Capture from Twilio
Twilio splits caller and agent onto separate channels only if you ask for it. Request dual-channel when the recording is made, then give capture the recording SID: it pulls and scores offline, or score a WAV you already have directly.
The recording you capture feeds a five-dimension conversation-test: separated caller and agent channels are what the Conversation (turn-taking) and Speech (timing) dimensions read, and the same file drops into hotato test run beside a transcript and trace for the Outcome and Policy checks.
| Stack | Automatic pull | Separate channels | Contract-grade default | Network use |
|---|---|---|---|---|
| Vapi | Yes: capture fetches by call id | Yes, out of the box | Yes | One call: fetch the recording |
| Twilio | Yes: capture fetches by recording SID | No by default: must request RecordingChannels=dual at creation | No, opt-in | One call: fetch the recording |
| Retell | Yes: capture fetches by call id | Yes, once call recording is turned on | Opt-in: enable recording first | One call: fetch the recording |
| LiveKit | No: egress runs in your own infra | Yes, if egress records both tracks | Opt-in: configure egress for two tracks | None from Hotato |
| Pipecat | No: the setup recorder runs in your pipeline | Yes, the scaffold writes caller ch0 / agent ch1 | Yes, once the recorder is added | None: local recorder, no network call |
Automatic pull: does hotato capture fetch it for you. Separate channels: is caller/agent separation what you get. Contract-grade default: is that separation on without extra setup. Network use: what capture calls out to, not your infrastructure.
Record dual-channel
- Ask for it when the recording is created:
RecordingChannels=dual(REST),<Record recordingChannels="dual">, or<Dial record="record-from-answer-dual">(TwiML). Caller and agent legs land on separate channels.
--allow-mono fallback): both voices collapse onto one track; overlap is visible but not attributable.Score it: auto-pull
Twilio credentials + recording SID: capture fetches the recording (only network call: that download), scores offline. --expect yield/hold = interruption vs. backchannel.
export TWILIO_ACCOUNT_SID=... export TWILIO_AUTH_TOKEN=... uvx hotato capture --stack twilio --recording-sid RE... # no credentials yet? prove the capture→score loop on a bundled call uvx hotato capture --stack twilio --demo
capture requests the dual-channel file explicitly (?RequestedChannels=2); mono-only recordings get a 400 and a plain stop message.
--allow-mono scores mono anyway, degraded: indicative only; no contract-grade talk-over attribution.
Or score a WAV you already have
Fetched it? Point Hotato at the file: caller on channel 0, agent on channel 1.
uvx hotato run --stereo call.wav --stack twilio --expect yieldCaller on channel 1 instead? Pass --caller-channel 1 --agent-channel 0.
Pulling more than one call?
hotato connect twilio --account-sid AC... --auth-token ... stores credentials once, locally (0600). hotato pull --stack twilio --since 7d bulk-fetches recordings via the same Recordings.json list endpoint; hotato sweep pulls, then ranks the worst turn-taking moments across all of them in one offline dashboard. Mono-only recordings in the batch still need --allow-mono and score degraded. Every stack’s pull support →
Conference channel order follows join order, not roles. Verify which channel holds the caller before trusting attribution.
--dump-frames shows activity per channel; --caller-channel/--agent-channel remap a flipped order.
Separated caller and agent audio is what makes overlap attributable; speech activity comes from exposed VAD thresholds, frame-inspectable. The scorer takes one two-channel WAV or two aligned mono WAVs.