Bring Your Own Turn Detection
Streaming:Flux
Flux detects the end of a turn natively, and for most voice agents that is the right default. But if you have already invested in a turn detection stack — a VAD, an endpointing model, push-to-talk, or your own detector — you can keep it and adopt Flux for transcription without ripping out that logic. This guide shows the recipe for taking full ownership of turn endings.
The recipe
Section titled “The recipe”Two settings put you in control:
- Set
eot_thresholdto1.0. This suppresses Flux’s naturalEndOfTurnevents — the model will not end a turn on its own confidence. - Leave
eager_eot_thresholdunset. Eager end-of-turn is off by default; keep it off so noEagerEndOfTurnevents fire.
Then send a ForceEndTurn message whenever your own detector decides the turn is over. Flux ends the turn and emits an EndOfTurn with "trigger": "manual".
import json
import websockets
url = (
"wss://api.deepgram.com/v2/listen?model=flux-general-en"
"&eot_threshold=1.0" # suppress natural end-of-turn
"&eot_timeout_ms=30000" # safety-net backstop (see below)
)
headers = {"Authorization": "Token YOUR_DEEPGRAM_API_KEY"}
async with websockets.connect(url, additional_headers=headers) as ws:
# When your turn detector fires:
await ws.send(json.dumps({"type": "ForceEndTurn"}))How it works
Section titled “How it works”- Send audio as usual. Flux transcribes continuously and emits
StartOfTurnandUpdateevents. Witheot_threshold=1.0, it never emitsEndOfTurnon its own. - Your detector decides the turn is over. A push-to-talk release, a VAD silence event, a DTMF tone — whatever signal you rely on.
- Send
ForceEndTurn. Flux ends the turn and emitsEndOfTurnwith the transcript decoded so far and"trigger": "manual". - Dispatch the transcript. Treat the
EndOfTurntranscript as final and hand it to your agent.turn_indexincrements and Flux is ready for the next turn.
What still ends a turn
Section titled “What still ends a turn”With eot_threshold=1.0, three things can still end a turn:
ForceEndTurn— your explicit signal ("trigger": "manual").eot_timeout_ms— a safety net. If this much silence passes, Flux force-ends the turn with"trigger": "timeout". Set it high enough that it only fires when your own detection has failed. The maximum is60000(60 seconds).CloseStream— closes the connection without finalizing the active turn. NoEndOfTurnis emitted for it; treat the most recentUpdateas the last transcript for that turn.
Example
Section titled “Example”This loop wires an external detector to Flux. When your detector fires, it sends a ForceEndTurn; Flux replies with an EndOfTurn you treat as final.
// Send audio frames to Flux as you receive them.
function onAudioFrame(frame) {
ws.send(frame);
}
// Your existing turn detector fires -> force the turn to end.
function onTurnDetected() {
ws.send(JSON.stringify({ type: "ForceEndTurn" }));
}
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type !== "TurnInfo") return;
if (data.event === "EndOfTurn") {
// trigger is "manual" for ForceEndTurn, "timeout" for the backstop.
console.log(`Turn ended (${data.trigger}):`, data.transcript);
dispatchToAgent(data.transcript);
}
};When to use this
Section titled “When to use this”- You already have turn detection you trust and don’t want to migrate off it to adopt Flux.
- Your turn-end signal is external and definitive — push-to-talk, DTMF, a UI action.
- You are migrating from Nova-3 and want to keep your existing endpointing while gaining Flux transcript quality. See Migrating from Nova-3 to Flux.
If you don’t already have a turn detection stack, prefer Flux’s native detection — it is purpose-built for conversational turn-taking. See End-of-Turn Detection Parameters.
Related Resources
Section titled “Related Resources”- Force End Turn - The control message reference
- End-of-Turn Detection Parameters - Tune
eot_threshold,eager_eot_threshold, andeot_timeout_ms - Understanding the Flux State Machine - Turn events and state transitions
- Migrating from Nova-3 to Flux - Migration guide