This page is the OpenAI-specific integration guide. For the general
speech-to-speech model, see
BYO Speech-to-Speech Models.
That page covers the shape of a
REALTIME agent, the other duplex providers,
and how to select duplex or a cascade.What you get
- Duplex audio. ClutchCall Voice opens the Realtime WebSocket on the first inbound audio frame. It forwards each PCM chunk. It streams the model’s spoken reply back onto the call. The runtime does the sample-rate conversion to and from the model’s expected rate. Thus the same agent works on a G.711 phone leg and an Opus web leg without changes.
- Server-side VAD. OpenAI does its own endpointing. It emits
speech-started / speech-stopped signals. A
REALTIMEagent uses these signals directly. You do not add a local turn detector. - Instant barge-in via truncate. When the caller talks over the agent, the runtime truncates the in-flight assistant turn at the model. It also drops the buffered audio that is already on its way to the caller. Details are below.
- Function calling and a spoken greeting. Both are on by default.
Configure the agent
1
Set a REALTIME entry node with provider openai
A duplex agent has a single node. Set
entry_node: REALTIME. Name openai
as the provider. Select a voice. The runtime passes the model id on the
dial URL, not in the session bootstrap. Leave the model unset to get the
current generally-available model.- agent-config.yml
- control-plane API (TS)
2
Supply the OpenAI API key
Each workspace supplies its own OpenAI key. The system stores the key per
tenant, seals it at rest, and never shares it across workspaces. Set the
key in the agent console at
agent.clutchcall.dev, or through the
control-plane API.3
Point a number at the agent and call it
Route a phone number or trunk at the agent. Place a call. On the first
inbound audio frame, the runtime dials OpenAI. If OpenAI refuses the
connection (bad key, retired model), the runtime logs the failure. The call
then degrades to a silent passthrough and does not drop.
How the session is bootstrapped
When the Realtime WebSocket connects, ClutchCall Voice sends a singlesession.update in OpenAI’s GA shape. Only after that does it start to stream
audio. Thus your voice and instructions are always in force before the model
speaks:
session.typeisrealtime.- The runtime sets turn detection under
audio.input.turn_detectionasserver_vad. You can tunethreshold,prefix_padding_ms, andsilence_duration_ms. - The runtime sets the voice under
audio.output.voice. instructionscarries your prompt.- The runtime caps
max_output_tokensfor each assistant turn. OpenAI defaults this value to “inf”. A voice turn is short. The cap stops a runaway response that generates minutes of speech and burns tokens.
Barge-in via truncate
OpenAI owns endpointing. Thus itsspeech_started signal fires barge-in. When
the caller interrupts, two actions occur together:
- The runtime sends a
conversation.item.truncatefor the assistant item that currently speaks. This tells OpenAI to stop generation of the rest of that turn. Without the truncate, the model continues to produce audio that you decided not to play. That wastes tokens. - The runtime emits a cancel downstream. This flushes the outbound audio buffer. Without the cancel, the caller would continue to hear the tail of the cancelled turn from the jitter buffer, even after the model stopped.
The truncate handshake, step by step
The truncate handshake, step by step
- OpenAI’s server-side VAD detects caller speech over the agent. It emits
speech_started(a server-initiated truncate). - The runtime responds with
conversation.item.truncate. The message carries the id of the in-flight assistant item. It also carries the number of milliseconds of that item’s audio that the caller heard. Thus the model’s conversation history matches the audio that was played. - At the same time, the runtime cancels the in-flight response locally. It drops all pre-fetched audio bytes that are queued toward the caller.
- The caller now has the floor. Their speech streams into the input buffer, and the model responds to it.
On a phone call, the media path has no acoustic echo cancellation. Thus a loud
agent can trip the model’s VAD. See
Turn Detection & Barge-In for the
turn-detection thresholds and the mic-gating that protect against this.
Greeting on inbound calls
Some carrier SBCs do not send you RTP until they hear your RTP. On an inbound call, the runtime asks the model to speak first. It issues an empty-input response request. The model then greets from yourinstructions, or from an
exact opening line that you pin. This opens the carrier’s media path. This
behavior is on by default for inbound direct-media calls. No extra config is
required.
Tools mid-conversation
The session bootstrap advertises your tools. Thus the model can call HTTP and MCP tools during a spoken turn. The sequence is:- The model emits a function call.
- The runtime runs the tool.
- The runtime returns the result as a
function_call_output. - The runtime requests the next response, and the model speaks the answer.
Session budgets
Every Realtime session is bounded. A stuck provider cannot run forever:- Connect timeout. The handshake gets a few seconds. After that, the runtime gives up and falls back to a silent passthrough.
- Per-turn token cap. The session bootstrap bounds it, as described above.
- Max session. The runtime closes sessions at a 15-minute ceiling, even if OpenAI did not close them. Tune lifetime, idle re-engage, and hangup budgets on Session Lifecycle.
Next steps
Speech-to-speech overview
The general duplex model, other providers, and duplex vs. cascade.
Turn detection
Tune barge-in, endpointing, and backchannel handling.
Tool calling
Let the model call HTTP and MCP tools during a spoken turn.
Gemini Live
Wire Google’s duplex model as an alternative realtime provider.

