Interruption Handling

Handle barge-in on the Flux TTS WebSocket — stop playback, send Interrupt, and use the server’s text_spoken / text_remaining report to keep your LLM context in sync.

When a user speaks over the agent (a barge-in), you need to do two things: stop the audio immediately, and tell your LLM what the user actually heard so the conversation stays coherent. Flux TTS handles the second part for you — Interrupt returns the exact text that was spoken before the cut. This page covers the full pattern.

For the message references, see Interrupt and SpeechInterrupted.

The pattern

  1. Detect barge-in — typically from your STT (e.g. Flux STT’s StartOfTurn) or a VAD.
  2. Stop playback locally, now. Don’t wait for the server. The Interrupt round-trip is for context reconciliation, not for stopping audio.
  3. Send Interrupt with how far playback got, so the server can compute what was heard precisely.
  4. Discard in-flight audio — frames that arrive after you send Interrupt but before SpeechInterrupted were already on the wire. Drop them.
  5. Use SpeechInterrupted — append text_spoken to your LLM context so the next turn doesn’t repeat what the user already heard.

Sending Interrupt

Include playback_offset whenever you can — it’s how the server aligns text_spoken to the audio the user actually heard. Without it, the server can’t compute the split: SpeechInterrupted omits text_spoken and text_remaining, and audio_played_ms falls back to the server’s own generated-audio total.

1{
2 "type": "Interrupt",
3 "playback_offset": {"type": "time_ms", "value": 2340}
4}

playback_offset is measured from the start of the session’s audio, not the current turn, and each interrupt’s offset must advance past the position the previous interrupt established. An offset that doesn’t advance is rejected with an INVALID_INTERRUPT_OFFSET warning and the interrupt is ignored — track one session-wide playback counter rather than resetting per turn. Interrupt always cancels the currently-active turn — there is no per-turn targeting.

The response

1{
2 "type": "SpeechInterrupted",
3 "audio_played_ms": 2340,
4 "text_spoken": "Sure, I can help you cancel your subscription.",
5 "text_remaining": " Let me pull up your account.",
6 "metadata": { "speech_id": "dg_sp_a1b2c3d4e5f6", "audio_duration_ms": 2340, "...": "..." }
7}
  • text_spoken — what the user heard. Feed this back into the LLM context. Present only when your Interrupt carried a playback_offset.
  • text_remaining — what they didn’t hear. Useful if you want to resume or summarize what was cut. Present only when your Interrupt carried a playback_offset.
  • metadata — per-turn billing/timing, same shape as SpeechMetadata.

Interrupt does not reset the voice

Interrupt stops synthesis and clears the buffer, but it does not reset the model’s conversational state — so the agent’s voice stays consistent into the next turn. See Cross-Turn Context.

Edge cases

When you send InterruptWhat happens
While the turn is Generating (audio streaming)Synthesis stops; text_spoken / text_remaining are computed from your playback_offset.
Before any audio has been generated this sessionIgnored. The server emits a NO_AUDIO_GENERATED warning; no SpeechInterrupted is sent.
While an earlier Interrupt is still being processedIgnored, with an INTERRUPT_IN_PROGRESS warning. At most one interrupt is handled at a time.
With a playback_offset that doesn’t advance past the previous oneIgnored, with an INVALID_INTERRUPT_OFFSET warning.

In a voice agent loop

1async def handle_barge_in(stt_event, speak_conn, playback):
2 if stt_event.event == "StartOfTurn":
3 playback.stop() # stop audio locally, immediately
4 await speak_conn.send({
5 "type": "Interrupt",
6 "playback_offset": {"type": "time_ms", "value": playback.session_offset_ms()}
7 })
8 # On SpeechInterrupted: llm_context.append(assistant=text_spoken)

This snippet focuses on message flow. For the concrete SDK calls, see Getting Started and the template apps — the Python (deepgram-sdk) and JavaScript (@deepgram/sdk) SDKs expose a speak.v2 client for /v2/speak.