LiveKit Agents
In deepeval, you can run a voice simulation against a LiveKit agent. deepeval joins your agent's room as another participant and trades audio with it over WebRTC, so the agent has to be deployed and able to join a room.
Setting Up Your Credentials
A LiveKit agent has no id you can dial β it's a worker dispatched into a room. So instead of naming the agent, you give deepeval credentials for your LiveKit project and it mints a token and creates a room. DeepEval autoloads .env.local then .env at import time (process env -> .env.local -> .env).
Recommended (local dev):
# .env.local
LIVEKIT_URL=wss://your-project.livekit.cloud
LIVEKIT_API_KEY=<your-livekit-api-key>
LIVEKIT_API_SECRET=<your-livekit-api-secret>Alternative (Shell/CI):
export LIVEKIT_URL=wss://your-project.livekit.cloud
export LIVEKIT_API_KEY=<your-livekit-api-key>
export LIVEKIT_API_SECRET=<your-livekit-api-secret>Alternative (notebook):
If you're working in a notebook environment (Jupyter or Colab), set your credentials in a cell:
%env LIVEKIT_URL=wss://your-project.livekit.cloud
%env LIVEKIT_API_KEY=<your-livekit-api-key>
%env LIVEKIT_API_SECRET=<your-livekit-api-secret>In Code
Pass a LiveKitConnector to VoiceConfig, naming the agent to dispatch into the room:
from deepeval.voice import LiveKitConnector, VoiceConfig
connector = LiveKitConnector(
url="wss://your-project.livekit.cloud",
api_key="your-api-key",
api_secret="your-api-secret",
agent_name="restaurant-agent",
)
voice_config = VoiceConfig(
connector=connector,
...,
)There are ZERO mandatory and ELEVEN optional parameters when creating a LiveKitConnector.
- [Optional]
url: A string LiveKit server URL. Defaults toLIVEKIT_URL, and is required unlessroomis already connected. - [Optional]
api_key: A string LiveKit API key. Defaults toLIVEKIT_API_KEY, and is required to mint a token. - [Optional]
api_secret: A string LiveKit API secret. Defaults toLIVEKIT_API_SECRET, and is required to mint a token. - [Optional]
room: Anrtc.Roomto use instead of creating one, connected or not. Defaulted toNone. - [Optional]
token: A LiveKit access token you minted yourself, used instead ofapi_keyandapi_secret. Defaulted toNone. - [Optional]
room_name: A string naming the room to join. Defaulted toNone, which creates a room for the session. - [Optional]
identity: A string participant identity for the simulator. Defaulted to"deepeval-test". - [Optional]
agent_name: A string naming the agent to dispatch into the room. Defaulted toNone, which leaves your existing routing to place the agent there. - [Optional]
turn_detection: A string preset β"eager","balanced", or"patient"β controlling how long a pause has to last before your agent is considered finished speaking. Defaulted to"balanced". - [Optional]
connect_timeout_s: A float number of seconds to wait when establishing the room connection. Defaulted to15.0. - [Optional]
transcript_grace_s: A float number of seconds to wait after your agent stops speaking for its transcript to arrive. Defaulted to1.5.
room_name and agent_name are what actually find your agent. Omit room_name and the connector creates a room; set agent_name and LiveKit dispatches that agent into it.
Bringing Your Own Room
If your test setup already joined a room, hand that over instead and skip the credentials:
from livekit import rtc
from deepeval.voice import LiveKitConnector, VoiceConfig
room = rtc.Room()
await room.connect("wss://your-project.livekit.cloud", your_token)
voice_config = VoiceConfig(
connector=LiveKitConnector(room=room),
...,
)Concurrent conversations each get their own session, cloned from the connector you passed. A connector holding a room you connected yourself can't be cloned, so give VoiceConfig a zero-argument callable that builds a fresh connector instead of the connector itself.
deepeval publishes a microphone track, listens for the agent, and leaves the room as it found it β a room you connected stays connected afterwards, with just the simulated microphone removed. An unconnected room gets connected using the parameters above.
For how connectors fit into the simulation loop, and for turn detection in full, see Voice Connectors.