> ## Documentation Index
> Fetch the complete documentation index at: https://assemblyai.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Turn detection and interruptions

> How the Voice Agent API decides when the user has finished speaking and when they're interrupting. On by default, no tuning required.

Turn detection and barge-in are on by default and based on what the user actually said, not just silence or volume. There's nothing to wire up.

<Note>
  **Leave it on default.** With no `turn_detection` config, the agent adapts to each speaker's pace and automatically slows down to capture values your tools need, like a phone number or email. The way to make turn-taking better is **good tool descriptions**, not VAD knobs. Tune the raw thresholds only as a last resort.
</Note>

## What you get by default

* **Semantic end-of-turn.** The agent decides you're done from the meaning of what you said, so it won't cut you off mid-thought or sit on a long pause once you've clearly finished.
* **Smart waiting for tool values.** When a tool parameter expects a phone number, email, date, or other entity, the agent waits for the whole value before ending your turn, instead of jumping in after the first pause.
* **Adaptive pacing.** If a speaker pauses a lot, the agent gives them more room; if they're crisp, it replies faster. This gets better over the call.
* **Semantic barge-in.** Back-channels like "uh-huh" or "makes sense" don't interrupt; "wait, stop" does.

A normal user turn emits [`input.speech.started`](/voice-agents/voice-agent-api/events-reference#inputspeechstarted) → [`transcript.user.delta`](/voice-agents/voice-agent-api/events-reference#transcriptuserdelta) (partials) → [`input.speech.stopped`](/voice-agents/voice-agent-api/events-reference#inputspeechstopped) → [`transcript.user`](/voice-agents/voice-agent-api/events-reference#transcriptuser) (final) → [`reply.started`](/voice-agents/voice-agent-api/events-reference#replystarted). You never signal end-of-turn yourself.

## Get better turn-taking with tool descriptions

The agent waits for a complete value when it knows one is coming. It learns that from your tool's parameters, so describe the important ones well. No turn-detection config involved — just add the tool when you create the agent:

<CodeGroup>
  ```bash cURL expandable theme={null}
  curl -X POST https://agents.assemblyai.com/v1/agents \
    -H "Authorization: $ASSEMBLYAI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Account Assistant",
      "system_prompt": "You verify callers. Ask for their phone number, then call verify_account.",
      "voice": { "voice_id": "ivy" },
      "tools": [
        {
          "name": "verify_account",
          "description": "Look up a customer by phone number.",
          "parameters": {
            "type": "object",
            "properties": {
              "phone": {
                "type": "string",
                "description": "The caller'\''s phone number, including country code.",
                "examples": ["+14155552671"]
              }
            },
            "required": ["phone"]
          }
        }
      ]
    }'
  ```

  ```python Python expandable theme={null}
  # pip install requests
  import os
  import requests

  resp = requests.post(
      "https://agents.assemblyai.com/v1/agents",
      headers={"Authorization": os.environ["ASSEMBLYAI_API_KEY"]},
      json={
          "name": "Account Assistant",
          "system_prompt": "You verify callers. Ask for their phone number, then call verify_account.",
          "voice": {"voice_id": "ivy"},
          "tools": [
              {
                  "name": "verify_account",
                  "description": "Look up a customer by phone number.",
                  "parameters": {
                      "type": "object",
                      "properties": {
                          "phone": {
                              "type": "string",
                              "description": "The caller's phone number, including country code.",
                              "examples": ["+14155552671"],
                          }
                      },
                      "required": ["phone"],
                  },
              }
          ],
      },
  )
  resp.raise_for_status()
  print(resp.json())
  ```

  ```javascript Node.js expandable theme={null}
  // Node 18+ has fetch built in
  const res = await fetch("https://agents.assemblyai.com/v1/agents", {
    method: "POST",
    headers: {
      Authorization: process.env.ASSEMBLYAI_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      name: "Account Assistant",
      system_prompt: "You verify callers. Ask for their phone number, then call verify_account.",
      voice: { voice_id: "ivy" },
      tools: [
        {
          name: "verify_account",
          description: "Look up a customer by phone number.",
          parameters: {
            type: "object",
            properties: {
              phone: {
                type: "string",
                description: "The caller's phone number, including country code.",
                examples: ["+14155552671"],
              },
            },
            required: ["phone"],
          },
        },
      ],
    }),
  });
  const data = await res.json();
  console.log(data);
  ```
</CodeGroup>

With this, when the agent asks for the phone number it waits for all the digits instead of cutting in after "my number is four one five…". A clear `description` (plus optional `examples` or `pattern`) is what drives it. See [parameter hints](/voice-agents/voice-agent-api/tools/overview#parameter-hints-improve-accuracy).

## Interruptions

When the user truly interrupts, the server emits:

* [`reply.done`](/voice-agents/voice-agent-api/events-reference#replydone) with `status: "interrupted"`
* [`transcript.agent`](/voice-agents/voice-agent-api/events-reference#transcriptagent) with `interrupted: true` and `text` trimmed to what the user actually heard.

On that signal, stop and clear your queued audio so the user doesn't keep hearing stale speech:

```javascript theme={null}
ws.onmessage = ({ data }) => {
  const m = JSON.parse(data);
  if (m.type === "input.speech.started") flushPlayback();   // snappiest barge-in
  if (m.type === "reply.done" && m.status === "interrupted") flushPlayback();
};
```

See [Handling interruptions](/voice-agents/voice-agent-api/audio-format#handling-interruptions) for the full audio-flush pattern.

## Override the defaults (rarely needed)

If you must tune sensitivity, set the VAD knobs in `input.turn_detection`. All fields are optional; send only what you change. Set them on the stored agent when you create it:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://agents.assemblyai.com/v1/agents \
    -H "Authorization: $ASSEMBLYAI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Support Assistant",
      "system_prompt": "You are a friendly support agent. Keep replies under two sentences.",
      "voice": { "voice_id": "ivy" },
      "input": {
        "turn_detection": {
          "vad_threshold": 0.5,
          "min_silence": 1000,
          "max_silence": 3000,
          "interrupt_response": true
        }
      }
    }'
  ```

  ```python Python theme={null}
  # pip install requests
  import os
  import requests

  resp = requests.post(
      "https://agents.assemblyai.com/v1/agents",
      headers={"Authorization": os.environ["ASSEMBLYAI_API_KEY"]},
      json={
          "name": "Support Assistant",
          "system_prompt": "You are a friendly support agent. Keep replies under two sentences.",
          "voice": {"voice_id": "ivy"},
          "input": {
              "turn_detection": {
                  "vad_threshold": 0.5,
                  "min_silence": 1000,
                  "max_silence": 3000,
                  "interrupt_response": True,
              }
          },
      },
  )
  resp.raise_for_status()
  print(resp.json())
  ```

  ```javascript Node.js theme={null}
  // Node 18+ has fetch built in
  const res = await fetch("https://agents.assemblyai.com/v1/agents", {
    method: "POST",
    headers: {
      Authorization: process.env.ASSEMBLYAI_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      name: "Support Assistant",
      system_prompt: "You are a friendly support agent. Keep replies under two sentences.",
      voice: { voice_id: "ivy" },
      input: {
        turn_detection: {
          vad_threshold: 0.5,
          min_silence: 1000,
          max_silence: 3000,
          interrupt_response: true,
        },
      },
    }),
  });
  const data = await res.json();
  console.log(data);
  ```
</CodeGroup>

Configuring inline over the WebSocket instead? Set the same [`turn_detection`](/voice-agents/voice-agent-api/session-configuration#turn-detection) object under `session.input` in a `session.update`:

```json theme={null}
{
  "type": "session.update",
  "session": {
    "input": {
      "turn_detection": {
        "vad_threshold": 0.5,
        "min_silence": 1000,
        "max_silence": 3000,
        "interrupt_response": true
      }
    }
  }
}
```

| Field                | Description                                                      |
| -------------------- | ---------------------------------------------------------------- |
| `vad_threshold`      | Speech detection sensitivity (0.0–1.0). Lower is more sensitive. |
| `min_silence`        | Minimum silence for a confident end-of-turn, in ms.              |
| `max_silence`        | Maximum silence before forcing end-of-turn, in ms.               |
| `interrupt_response` | Set `false` to disable barge-in entirely.                        |

<Warning>
  Setting `min_silence` or `max_silence` turns off the adaptive pacing and entity-aware waiting described above for the rest of the session. Prefer leaving them unset.
</Warning>

<Note>
  If the agent keeps interrupting itself, the mic is picking up its own TTS. Use headphones or a [browser-based client](/voice-agents/voice-agent-api/browser-integration) (which has echo cancellation). See [Troubleshooting](/voice-agents/voice-agent-api/troubleshooting#agent-interrupts-itself-echo--feedback-loop).
</Note>
