# Barge-in Not Working

> The agent talks over the caller or does not stop when the caller interrupts. Find the cause in the VAD thresholds, the TTS mic gate, or the provider path, and fix it.

Most reports describe the same symptom: **the caller starts to talk and the
agent continues.** Sometimes the agent talks over a real interruption.
Sometimes the agent replies in the caller's own pause, before the caller
completes a sentence. Both look like the agent does not yield.

Almost every case has one of four causes:

- 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.

Work through the table below from top to bottom. The first three rows cover
most real tickets.

> **NOTE:**
> 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](/modalities/voice/concepts/turn-detection). Do not
> use this page for that problem.

## Symptom → cause → fix

| What you hear | Likely cause | Fix |
|---------------|--------------|-----|
| The caller speaks clearly over the agent. The agent never stops | The VAD gate is too high. A high `threshold` for a noisy trunk makes real speech read as background | Lower `threshold` toward `0.5`. Check that the caller's speech crosses it (see [debugging](/modalities/voice/observability/barge-in-debugging)) |
| The agent ignores short interruptions ("wait—", "no") but yields to long ones | The over-agent floor is too high. `params.response_min_speech_ms` is set higher than the length of a real interjection | Lower `response_min_speech_ms` (default `600`) toward `300`. It is intentionally higher than the answering floor to reject backchannels |
| The interrupt fires only after long, obvious over-talk | The hold-and-confirm window is too long. `params.barge_confirm_ms` is set high | Lower `barge_confirm_ms` (default `300`). Set `0` **only** on echo-cancelled legs (browser) |
| The agent does not yield on a phone call, but it yields in the browser | The TTS mic gate blocks the caller. A high `params.margin_while_tts` gates out the caller *while the agent speaks* | Lower `margin_while_tts` on that agent, or move to a leg with client-side echo cancellation. See [below](#the-tts-mic-gate-and-no-aec-legs) |
| Playback goes quiet when the caller speaks. Then the agent continues and completes its sentence | The provider cannot cancel an active request. This is a non-streaming HTTP LLM. The runtime detects the barge, but it only silences the local playback | Move that node to a streaming or realtime provider. See the [scorecard](/modalities/voice/concepts/turn-detection#where-barge-in-actually-works) |
| The agent replies in the caller's natural pause. It sounds like the agent talks over the caller | The end-of-turn timer is too short. `silence_duration_ms` fires on the gaps between words | Raise `silence_duration_ms` (default `500`) toward `800` for deliberate callers |

## 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](/modalities/voice/observability/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_ms` or `response_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 `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.

```json
{
  "turn_detection": {
    "type": "silero",
    "threshold": 0.5
  }
}
```

Start at the `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` (default `300`) — the time that over-talk must
  **continue** before the interrupt fires.
- `params.response_min_speech_ms` (default `600`) — the shortest burst that
  counts as a real interruption *over* the agent. Shorter bursts count as
  continuers, for example "mhm".

If callers report that the agent ignores short, urgent interjections, lower
both values. For a browser agent with client-side echo cancellation, you can
set `barge_confirm_ms: 0` for an instant cut.

```json
{
  "turn_detection": {
    "params": {
      "barge_confirm_ms": 150,
      "response_min_speech_ms": 350
    }
  }
}
```

> **WARNING:**
> Do not set `barge_confirm_ms: 0` on a PSTN agent with no echo cancellation.
> The agent's own TTS bleeds back through the caller's mic. This triggers a
> barge on the first frame, and the agent cuts itself off constantly. Use `0`
> on echo-cancelled legs only.

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](/modalities/voice/concepts/turn-detection#where-barge-in-actually-works).
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.

| Leg | Echo cancellation | `margin_while_tts` guidance |
|-----|-------------------|-----------------------------|
| SIP / RTP (PSTN trunk) | None — the media path has no AEC | Keep the guard high enough to reject echo. Lower it in small steps, and test that the agent does not self-barge |
| Browser (media-over-QUIC) | Client-side (browser AEC) | Safe to lower for a faster, more sensitive barge |
| WebRTC fallback leg | Client-side (browser AEC) | Same as browser |

> **TIP:**
> If barge-in works in the browser but not on phone calls, this gate is almost
> always the cause. The browser cancels the echo, so a low `margin_while_tts`
> is safe there. The phone line has no echo cancellation, so the same low value
> lets the caller through *and* lets the agent's echo through. Tune the two legs
> separately. Do not copy a browser-tuned agent config to a PSTN agent.

## 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](/modalities/voice/runtime/byo-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](/modalities/voice/concepts/turn-detection)** — The full model: VAD modes, the timing settings, and the barge scorecard by
provider and transport.
- **[Barge-in debugging](/modalities/voice/observability/barge-in-debugging)** — Trace onset, pending-barge, confirm, and cancel events on a live call.
- **[Runtime configuration](/modalities/voice/runtime/configuration)** — Where `turn_detection` lives in the agent config, and how to push it.
- **[High latency](/modalities/voice/troubleshooting/high-latency)** — If the agent yields but the full turn is slow, start here instead.
