TwilioAgentAdapter
Connects to a Twilio phone number over Media Streams (WebSocket) and drives a full inbound or outbound call. Supports DTMF detection and the full Twilio call-state lifecycle.
Constructor
import os
import scenario
adapter = scenario.TwilioAgentAdapter(
account_sid=os.environ["TWILIO_ACCOUNT_SID"],
auth_token=os.environ["TWILIO_AUTH_TOKEN"],
phone_number=os.environ["TWILIO_PHONE_NUMBER"],
http_port=8765,
)All arguments are keyword/option-named. Beyond the core ones:
public_base_url / publicBaseUrl, allowed_callers, on_dtmf,
http_port / httpPort (default 8765), role (default AgentRole.AGENT),
validate_signature (default True — set to False only when running against a
local test harness that can't sign webhook requests).
Test harness (recommended)
For end-to-end tests you need a public HTTPS URL that routes Twilio's webhook to this machine.
# Python: TwilioHarness spins up a cloudflared quick tunnel, configures the
# Twilio webhook for the lifetime of the `async with` block, and tears down on exit.
import os
from scenario.voice.testing import TwilioHarness
async with TwilioHarness(
account_sid=os.environ["TWILIO_ACCOUNT_SID"],
auth_token=os.environ["TWILIO_AUTH_TOKEN"],
phone_number=os.environ["TWILIO_PHONE_NUMBER"],
http_port=8766,
) as adapter:
# Pass `adapter` to `scenario.run(...)`.
...Capabilities
| streaming_transcripts | native_vad | dtmf | interruption | input_formats | output_formats |
|---|---|---|---|---|---|
| ❌ | ❌ | ✅ | ✅ | mulaw/8000 | mulaw/8000 |
DTMF tones: send them with scenario.dtmf("1") in your script step (same step
name in both SDKs).
VAD: Twilio has no native VAD; the SDK falls back to webrtcvad. See
Troubleshooting → VAD didn't fire.
Worked examples
- Python:
dtmf_ivr.py— DTMF-driven IVR menu test from dial-in to hang-up;twilio_inbound.py— inbound call test;twilio_outbound.py— dialer-side outbound test. - TypeScript: the Twilio tunnel + adapter path is covered by the
@ts-twilio-tunnelbinding inspecs/voice-agents.feature(real-phone demos are gated manual — they need a tunnel + a second number).
Common failures
- HTTP 401 code 20003 — auth token mismatch. See Troubleshooting → Twilio HTTP 401 code 20003.
