Skip to content

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-only. Beyond the three above: public_base_url, allowed_callers, on_dtmf, http_port (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, use TwilioHarness — it 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_transcriptsnative_vaddtmfinterruptioninput_formatsoutput_formats
mulaw/8000mulaw/8000

DTMF tones: send them with scenario.dtmf("1") in your script step.

VAD: Twilio has no native VAD; the SDK falls back to webrtcvad. See Troubleshooting → VAD didn't fire.

Worked examples

Common failures