- The on-device VAD never fires.
- The mic gate that protects the agent from its own echo also blocks the caller.
- The runtime cannot cancel the downstream provider after the request starts.
- The end-of-turn timer is too short, so the agent starts to talk in the caller’s pause.
This page is about an agent that does not yield. If the opposite occurs, and
the agent stops on background noise or a cough, use the sensitivity tuning in
Turn detection & barge-in. Do not
use this page for that problem.
Symptom → cause → fix
Isolate the cause
Do these steps in order. Answer one question at a time:- Did the VAD see the caller?
- Was the caller gated out?
- Can the provider stop?
1
Confirm the interrupt is even detected
Pull the turn-taking trace for the call. The runtime records every
speech-onset, pending-barge, confirm, and cancel event. The workspace shows
these events per call.
See Barge-in debugging.
- No onset logged while the caller clearly speaks → the VAD gate is too high. Go to step 2.
- Onset logged, but no confirm → the caller spoke, but not long enough to
clear
barge_confirm_msorresponse_min_speech_ms. Go to step 3. - Confirm logged, but the agent continued to talk → detection is correct. The provider could not cancel. Go to step 4.
2
Lower the VAD gate (thresholds too high)
On a noisy trunk, a higher Start at the
threshold rejects background noise. But if the
value is too high, the caller’s real speech never crosses the gate. Then no
onset is armed.0.5 default. Increase it only in small steps. Check that onsets
still fire after each step. If the line is very noisy, the durable fix is a
cleaner trunk, or the ingress noise suppression on the browser/WebRTC leg. A
higher gate also rejects the caller.3
Lower the confirm and over-agent floors (won't yield to short interrupts)
Two settings decide if a detected onset becomes a confirmed barge. Both
defaults are high on purpose, so that backchannels do not cancel the agent:
params.barge_confirm_ms(default300) — the time that over-talk must continue before the interrupt fires.params.response_min_speech_ms(default600) — the shortest burst that counts as a real interruption over the agent. Shorter bursts count as continuers, for example “mhm”.
barge_confirm_ms: 0 for an instant cut.4
Confirm the provider can cancel mid-flight (timeout-only barge)
If the runtime confirms the interrupt but the agent completes its sentence,
the downstream provider is the limit, not your tuning. A non-streaming HTTP
LLM cannot stop generation after the request starts. The runtime can only
silence the local playback. The response still completes server-side, and the
provider still bills for it.Check the provider path against the
barge scorecard.
Streaming TTS, streaming ASR, and realtime speech-to-speech providers cancel
within a frame. Move the failing node to one of these paths.
5
Check the end-of-turn timer if the agent replies into a pause
In this case, the caller did not interrupt. The agent decided the turn was
over. If
silence_duration_ms is shorter than the caller’s natural pauses
between words, end-of-turn fires early. The agent then starts to reply while
the caller still thinks. To the caller, this feels the same as an agent that
does not yield.Raise silence_duration_ms (default 500) toward 700–800 for slow,
deliberate callers. Do this before you change other settings.The TTS mic gate and no-AEC legs
The telephony media path has no acoustic echo cancellation. On a phone call, the agent’s own TTS leaks back through the caller’s microphone. Without a guard, that leaked audio trips the VAD, and the agent barges on itself. To prevent this, the runtime raises the during-speech mic gate,params.margin_while_tts, while the agent talks. On PSTN, the gate rises to
match the quiet-line gate (params.margin). The agent’s voice then cannot
cancel the agent. Realtime telephony sessions apply this automatically.
But the caller’s speech must cross that same gate to barge in. If you set the
gate too high, it rejects the echo and also rejects the caller.
When the provider owns the turn
If your agent’s entry node is a realtime speech-to-speech provider, the provider does its own endpointing (server_vad). The on-device VAD never
runs. In that mode, the provider emits the barge signal. The stop speed is the
provider’s budget, not yours.
- OpenAI Realtime, Gemini Live — these providers emit clean speech-start / speech-stop events. The runtime forwards the interrupt/truncate, and the session stops generation. This is the tightest path.
- Self-hosted models with no server VAD — nothing detects the turn on the provider side. The runtime falls back to a local detector that drives an explicit commit. Barge-in still works, and you tune it with the same settings above. See Bring your own speech-to-speech.
- External vendor bridge (LiveKit / Vapi / Twilio) — the vendor’s adapter sets the quality of the interrupt. For the tightest budgets, keep media on the native SIP/RTP, browser, or WebRTC-fallback path.
Still stuck?
1
Reproduce with the defaults
Set the agent’s
turn_detection block back to empty. Then reproduce the
problem. The defaults are phone-safe. If barge-in works with no config, one of
your overrides is the cause. Add the overrides back one at a time.2
Diff the browser and phone legs
If barge-in fails on only one transport, the difference is the TTS mic gate
(above) or the provider path. The caller is not the difference.
3
Read the trace, don't guess
The turn-taking events show which stage failed: onset, confirm, or provider
cancel. If you change settings without the trace, you usually move the problem
to a different place.
Related
Turn detection & barge-in
The full model: VAD modes, the timing settings, and the barge scorecard by
provider and transport.
Barge-in debugging
Trace onset, pending-barge, confirm, and cancel events on a live call.
Runtime configuration
Where
turn_detection lives in the agent config, and how to push it.High latency
If the agent yields but the full turn is slow, start here instead.

