Twilio Phone Calls
In deepeval, you can run a voice simulation against any agent that answers a phone number, by calling it through your own Twilio account. The connector places a real call with Twilio's API, and Twilio streams the call audio back to a small server deepeval runs on your machine, so the simulated caller can talk and listen at the same time.
No Twilio SDK is needed. If your agent runs on LiveKit, a LiveKitProvider calls it without a public URL.
Setting Up Your Credentials
Your account SID and auth token place the call. DeepEval autoloads .env.local then .env at import time (process env -> .env.local -> .env).
Recommended (local dev):
# .env.local
TWILIO_ACCOUNT_SID=<your-account-sid>
TWILIO_AUTH_TOKEN=<your-auth-token>Alternative (Shell/CI):
export TWILIO_ACCOUNT_SID=<your-account-sid>
export TWILIO_AUTH_TOKEN=<your-auth-token>Exposing the Audio Server
Twilio sends call audio over a Media Stream, which has to reach deepeval at a public wss:// address. deepeval listens on port 8765 by default, so expose that port with a tunnel such as ngrok:
ngrok http 8765Pass the https:// address the tunnel prints as public_url. On a server that's already reachable, pass its own address instead.
In Code
from deepeval.voice import PhoneConnector, TwilioProvider, VoiceConfig
voice_config = VoiceConfig(
connector=PhoneConnector(
"+14155550100",
caller_id="+14155550199",
provider=TwilioProvider(public_url="https://your-tunnel.ngrok.app"),
),
...,
)With Twilio, caller_id is required and must be a number on your Twilio account. PhoneConnector's other parameters, such as ring_timeout_s and silence_timeout_s, are listed in Phone Calls. There are ONE mandatory and FOUR optional parameters when creating a TwilioProvider:
public_url: A stringhttps://orwss://address that forwards todeepeval's port.- [Optional]
account_sid: A string Twilio account SID. Defaults toTWILIO_ACCOUNT_SID. - [Optional]
auth_token: A string Twilio auth token. Defaults toTWILIO_AUTH_TOKEN. - [Optional]
host: A string address the audio server listens on. Defaulted to"0.0.0.0". - [Optional]
port: An integer port the audio server listens on. Defaulted to8765.
If the call can't be placed or isn't answered, the run stops with the reason, such as a busy line, no answer, or a public_url that doesn't reach your machine.
Parallel Calls
Every simulated conversation places its own call, and all of them share the one audio server, so up to max_concurrent calls run at once. Calls are placed dial_interval_s apart because Twilio accepts one new call per second per account by default. Raise it in the Twilio console before running many calls in parallel.