Skip to main content
Use one Vonage Voice API WebSocket for each human participant and one PyAI Live Translation session for the conversation. Your server pairs the call legs, routes the audio and keeps the call record. Read the calling-platform integration guide first. Integration status: this recipe requires your own media bridge. PyAI does not currently provide a packaged interpretation adapter or a completed Vonage telephone acceptance test. The existing @pyai/twilio bridge serves Omni voice agents.

Connect each human separately

Configure your Voice API application’s answer and event webhooks. Return an NCCO connecting the customer to your bridge:
Create the agent’s separate outbound call with an answer NCCO pointing to /vonage/agent. These URLs belong to the bridge you implement. Bind each expected call UUID to the authorized conversation and participant. Keep each human’s source isolated from the other person’s playback. The authorization setting makes Vonage send a signed JWT during the WebSocket handshake; validate it using the documented signed-webhook procedure. Metadata inside headers does not authenticate a caller or authorize joining a room. See the NCCO reference.

Relay 16 kHz audio

Vonage sends binary audio and JSON control messages. Check the initial websocket:connected format. For the configuration above, binary frames carry mono signed little-endian PCM16 at 16 kHz, matching PyAI’s documented audio format. Reframe them as base64 audio.append events with the current leg epoch and contiguous sequence number; use frames of at most 200 ms. Decode PyAI audio.chunk.audio and send its PCM as binary messages only to the socket matching target_leg. Check target epoch, output generation and audio sequence before queuing. Generated speech must never enter either recognition source.

Track delivery and interruption

After the last binary frame for an utterance, send a unique playback marker:
A matching websocket:notify indicates the preceding queue completed. Report played to PyAI only when the utterance is fully generated, its current marker has completed and no cancellation intervened. Count original PyAI PCM samples, not bytes merely sent over the socket. On cancellation, retire pending markers, stop local playback sending, discard queued audio and send:
Await websocket:cleared before acknowledging a physical flush to PyAI. Serialize clear operations for each socket and fence late notifications from prior participants. For partial playback, report only the confirmed played prefix. Wait for PyAI’s input.resumed before accepting new source speech. These lowercase commands belong to the Voice API WebSocket protocol. See Vonage Voice WebSockets for message and playback semantics. Keep source/translated transcripts and delivery outcomes with the call UUIDs. Use the shared guide’s replacement sequence for transfers, including clearing both participant queues. A call or socket failure ends that translation session; do not replay previously sent speech automatically. Qualify playback, echo protection, transfers and teardown on actual telephone calls before rollout.