give complete guide on usage of TurnHandlingOption...
# ask-ai
b
give complete guide on usage of TurnHandlingOptions
✅ 1
t
Thanks for reaching out, Mohammed. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m responding to your request for a complete guide on using TurnHandlingOptions. Below is a concise, practical guide you can use to configure turn detection, endpointing, and interruption handling for LiveKit agents. Overview • TurnHandlingOptions controls how an agent detects when a user has finished speaking (turn detection), when the agent should end listening (endpointing), and how the agent treats user interruptions (barge-ins vs backchannel). • You pass it to AgentSession to control conversation flow and responsiveness. Quick example (Python)
Copy code
from livekit.agents import TurnHandlingOptions
from livekit.plugins.turn_detector.multilingual import MultilingualModel

turn_handling = TurnHandlingOptions(
    turn_detection=MultilingualModel(),
    endpointing={"min_delay": 0.5, "max_delay": 3.0},
    interruption={"mode": "adaptive", "enabled": True}
)

session = AgentSession(
    turn_handling=turn_handling,
    stt="deepgram/nova-3:multi",
    llm="openai/gpt-4.1-mini",
    tts="cartesia/sonic-3:...",
    vad=silero.VAD.load(),
)
1) Turn detection modes — how to choose • MultilingualModel(): context-aware model trained for conversational turn-taking. Good default for natural behavior; requires STT and VAD. • "realtime_llm": uses realtime model’s built-in activity detection (e.g., OpenAI Realtime or Gemini Live). When used, disable automatic detection on the realtime model if you want LiveKit to manage turns. • "stt": rely on STT end-of-speech signals (AssemblyAI, Deepgram, etc.). Combine with VAD for faster reactions. • "vad": use only voice-activity (silence) detection. Simple and low-cost. • "manual": you manage turns explicitly via
commit_user_turn()
,
interrupt()
, and
clear_user_turn()
. When to ask a clarifying question: • If you have multiple agents or realtime models in play, tell me which model and environment (Cloud or self-hosted) so I can recommend exact settings. 2) Endpointing — tuning delays for natural flow • Purpose: define how long silence must last before the system considers the user’s turn ended. • Key parameters: ◦
min_delay
— minimum silence time (seconds) before ending the turn (e.g., 0.5). ◦
max_delay
— cap for silence wait (seconds) to force a turn end (e.g., 3.0). ◦
mode
(
fixed
or
dynamic
, Python only) —
dynamic
adapts delays using pause stats to be more natural. • Node.js note: min/max delays are specified in milliseconds (e.g., 500, 3000). • Best practice: start with min_delay ~0.5s and max_delay ~2.5–3s and adjust based on user speech patterns. 3) Interruption handling — barge-ins vs backchannel • Purpose: decide if and how a user can interrupt agent speech. • Main options: ◦ `enabled`: true/false — allow interruptions. ◦ `mode`:
adaptive
(recommended) or
vad
. ▪︎
adaptive
uses acoustic/context cues to ignore backchannels while allowing true barge-ins. ▪︎
vad
flags any detected speech as interruption (simpler). ◦
min_duration
/ `min_words`: require a minimum speech duration or word count to treat as interruption (helps filter noise). ◦ `resume_false_interruption`: resume agent speech after a false interruption (e.g., cough) when appropriate. ◦ `false_interruption_timeout`: how long to wait before marking interruption as false. ◦ `discard_audio_if_uninterruptible`: drop audio if agent cannot be interrupted. • Recommendation: use
adaptive
with aligned STT transcripts when available for best UX. 4) Combined patterns & edge cases • Realtime LLM + LiveKit detection: if you use realtime LLM automatic detection, disable automatic detection on that model if you want LiveKit’s turn detector to handle endpointing. • STT-based detection: if you rely on STT for endpointing, set
endpointing.min_delay = 0
to avoid stacking delays (prevents added latency). • Always provide a VAD plugin even when using STT endpointing — improves responsiveness for interruptions. 5) Language & model considerations • MultilingualModel supports many languages (EN, ES, FR, DE, IT, PT, NL, ZH, JA, KO, ID, TR, RU, HI). • Adaptive interruption works best with STT that provides aligned transcripts. 6) Events to monitor • Listen for session events to observe turn/interrupt state: ◦
user_state_changed
— user started/stopped speaking. ◦
agent_state_changed
— agent speaking/thinking. ◦
user_interruption_detected
— when an interruption is detected. ◦
agent_false_interruption
— false interruption occurred; agent may resume. • Use these events to log behavior or adjust heuristics in real time. 7) Best practices / Recommendations • Default: Use
MultilingualModel
+
adaptive
interruption + VAD for robust natural conversations. • Tune endpointing
min_delay
and
max_delay
to your user population and use
dynamic
mode (Python) if you need adaptive timing. • Use
min_words
or
min_duration
if you see many short noises triggering interruptions. • For self-hosted deployments, note adaptive interruption quotas may apply. 8) Manual control (when you want full control) • Set
turn_detection="manual"
and call: ◦
session.interrupt()
— stop agent speech immediately. ◦
session.commit_user_turn()
— tell the system the user finished speaking and should be processed. ◦
session.clear_user_turn()
— discard current user audio. If you want, I can: • Provide a tailored example for Node.js (with millisecond endpointing) or for your exact STT/LLM/TTS stack. • Recommend starting values for
min_delay
,
max_delay
,
min_duration
, and
min_words
based on your use case (e.g., short Q&A vs. long-form conversation). • Show sample event handlers for logging or metrics. Would you like a Node.js example or a configuration tuned for short customer-support calls vs. long conversational flows? Sources: Turns overview | LiveKit Documentation | Agent session | LiveKit Documentation | LiveKit turn detector plugin | LiveKit Documentation | Gemini Live API plugin | LiveKit Documentation | Adaptive interruption handling | LiveKit Documentation, with interactive elements
b
so what happens if we do not provide interruption key itself in the TurnHandlingOptions also what is the class EndpointingOptions(TypedDict, total=False): """Configuration for endpointing. All keys are optional. Missing keys inherit from the session default (at the ``Agent`` level) or use the documented defaults (at the ``AgentSession`` level). """ mode: Literal["fixed", "dynamic"] """Endpointing mode. ``"fixed"`` for fixed delay, ``"dynamic"`` for dynamic delay. Defaults to ``"fixed"``.""" min_delay: float """Minimum time (s) since last detected speech before declaring the user's turn complete. Defaults to ``0.5``.""" max_delay: float """Maximum time (s) the agent waits before terminating the turn. Defaults to ``3.0``.""" fixed vs dynamic it looks like this is something new too
t
Thanks — I’m answering both parts: (1) what happens if you omit the
interruption
key in
TurnHandlingOptions
, and (2) clarification of
EndpointingOptions
and the difference between
fixed
and
dynamic
modes. 1) If you do NOT provide
interruption
in TurnHandlingOptions • The system uses the session/agent defaults for interruption behavior. • On LiveKit Cloud and dev mode the default is to allow interruptions with the
adaptive
strategy. That means adaptive interruption handling (which filters backchannels and small noises) will be used unless you explicitly disable or override it. • Practically this means: ◦ Users can barge in while the agent is speaking (adaptive barge-in). ◦ Short backchannels (e.g., “uh-huh”, “mm”) are less likely to stop the agent because adaptive mode attempts to distinguish those from true interruptions. • If you need different behavior, set
interruption
explicitly. Example options you can set: ◦
{"enabled": False}
to disable interruptions. ◦
{"mode": "vad"}
to use VAD-only interruptions (any detected speech is considered an interruption). ◦ Add
min_duration
,
min_words
,
resume_false_interruption
, or
false_interruption_timeout
to refine behavior. 2) EndpointingOptions — keys, defaults, and fixed vs dynamic • What the class represents: ◦
EndpointingOptions
configures how long the system waits after the user stops speaking before it declares the user’s turn complete (endpointing). ◦ All keys are optional; missing keys inherit from the Agent-level session defaults or use AgentSession defaults when not set. • Keys and defaults: ◦
mode: "fixed" | "dynamic"
— defaults to
"fixed"
. ◦
min_delay: float
— minimum silence time (seconds) before ending the user turn. Defaults to
0.5
. ◦
max_delay: float
— maximum time (seconds) to wait before forcing the turn to end. Defaults to
3.0
. • Fixed vs Dynamic: ◦ Fixed: ▪︎ Uses the configured
min_delay
and
max_delay
as static thresholds. ▪︎ The system will wait at least
min_delay
seconds of silence and no longer than
max_delay
before ending the turn. ▪︎ Good when you want predictable, consistent timing. ◦ Dynamic (Python-only): ▪︎ Adjusts the delay adaptively based on conversation pacing — the system computes an exponential moving average of inter-utterance pauses and adjusts the endpointing delay within the `min_delay`/`max_delay` bounds. ▪︎ Produces more natural timing for varied conversational styles (short Q&A vs. longer pauses). ▪︎ Use when you want endpointing to adapt automatically to the session’s rhythm. Notes and best practices • Node.js users: specify `min_delay`/`max_delay` in milliseconds (e.g.,
500
,
3000
). • If you rely on STT-based endpointing, set
endpointing.min_delay = 0
to avoid additive latency stacking with STT phrase endpointing. • Start with
min_delay = 0.5
and
max_delay = 2.5–3.0
and iterate based on real-user behavior. • Use
dynamic
when you want the system to tune timing automatically (Python only). If you want, I can: • Show a short Node.js and Python example that omits
interruption
(so you can see defaults) and one that explicitly sets interruption options. • Recommend concrete `min_delay`/`max_delay` and interruption thresholds for a specific use case (short support interactions vs. long interviews). Which scenario are you tuning for?, with interactive elements
b
give me example code for normal vad approach using the TurnHandlingOptions
t
Thanks — below are concise example snippets showing how to configure
TurnHandlingOptions
to use a normal VAD-based approach for both Python and Node.js. These examples show VAD for turn detection and VAD-based interruption handling. Python example
Copy code
from livekit.agents import TurnHandlingOptions, AgentSession
import silero  # example VAD plugin; replace with your VAD of choice

# Load a VAD plugin (example)
vad = silero.VAD.load()

turn_handling = TurnHandlingOptions(
    # Use VAD-only turn detection
    turn_detection="vad",

    # Endpointing in seconds (fixed mode by default)
    endpointing={
        "mode": "fixed",
        "min_delay": 0.5,   # wait at least 0.5s of silence
        "max_delay": 3.0    # but no more than 3.0s
    },

    # Use VAD for interruption handling as well
    interruption={
        "enabled": True,
        "mode": "vad",      # treat any detected speech as interruption
        # optional: require at least 0.2s of speech to count as interruption
        "min_duration": 0.2
    }
)

session = AgentSession(
    turn_handling=turn_handling,
    stt="deepgram/nova-3:multi",   # optional STT for transcripts
    llm="openai/gpt-4.1-mini",     # your LLM
    tts="cartesia/sonic-3:...",    # your TTS
    vad=vad                        # provide the VAD plugin
)

# Example event handlers (optional)
@session.on("user_state_changed")
def on_user_state_changed(ev):
    print("User state:", ev.new_state)

@session.on("user_interruption_detected")
def on_interruption(ev):
    print("Interruption detected at", ev.timestamp)
Node.js example
Copy code
const { TurnHandlingOptions, AgentSession } = require("livekit-agents");
// Example VAD plugin; replace with your VAD implementation
const silero = require("silero-vad");

const vad = silero.load();

const turnHandling = new TurnHandlingOptions({
  // VAD-only turn detection
  turn_detection: "vad",

  // Endpointing in milliseconds for Node.js
  endpointing: {
    mode: "fixed",
    min_delay: 500,   // 500 ms
    max_delay: 3000   // 3000 ms
  },

  // VAD-based interruption handling
  interruption: {
    enabled: true,
    mode: "vad",
    min_duration: 0.2  // seconds; if your API expects ms, convert accordingly
  }
});

const session = new AgentSession({
  turn_handling: turnHandling,
  stt: "deepgram/nova-3:multi",
  llm: "openai/gpt-4.1-mini",
  tts: "cartesia/sonic-3:...",
  vad: vad
});

session.on("user_state_changed", (ev) => {
  console.log("User state:", ev.new_state);
});

session.on("user_interruption_detected", (ev) => {
  console.log("Interruption detected at", ev.timestamp);
});
Notes and recommendations • VAD-only mode is simple and low-latency but will treat any detected speech as an interruption unless you add thresholds (
min_duration
,
min_words
) to filter noise/backchannels. • Provide a
vad
plugin to the session to ensure responsive detection. • Tune `min_delay`/`max_delay` for your users; Node.js uses milliseconds for those values. • If you later want to ignore short backchannels, switch
interruption.mode
to
adaptive
and use STT with aligned transcripts. Would you like a variant that: • Uses
min_words
instead of
min_duration
, or • Demonstrates disabling interruptions entirely?, with interactive elements
b
aec_warmup_duration explain in detail what exactky is this, how does this help?
t
Thanks — I’m responding about your question on
aec_warmup_duration
. I don’t have a precise internal definition for that exact parameter in the docs I can access, but I can explain what it most commonly means, how it typically helps, and what to check next. If you share where you saw the option and your platform (browser WebRTC, Node, iOS, Android, Agent config, SDK version), I’ll tailor the guidance and recommend concrete values. What
aec_warmup_duration
likely is • It most commonly means “Automatic Echo Canceller warm-up duration.” It’s the amount of time (seconds or milliseconds) you give the AEC algorithm to stabilize and adapt to the acoustic environment before treating its output as fully reliable. • During this warm-up the AEC: ◦ Learns the echo path (how speaker output couples into the microphone). ◦ Builds or updates its filter coefficients or adaptive models. ◦ Measures playback vs. mic timing and any buffering/latency so it can subtract playback from the captured mic signal more accurately. Why a warm-up window helps • Faster/stronger echo suppression: Adaptive AECs need an initial period to converge their filter coefficients. Allowing warm-up reduces residual echo once the agent starts speaking or playback begins. • Reduced false detections: Better AEC adaptation lowers the chance that the system interprets echoed agent speech as user speech (important for interruption detection and endpointing). • Stable behavior across devices: Different speaker/mic couplings (headset vs. laptop speakers vs. mobile) require different adaptation times; warm-up lets the algorithm adjust. • Improves voice quality: Cleaner mic signal after warm-up leads to improved STT accuracy and better downstream model behavior. How it’s usually used in practice • Set a short warm-up when you expect immediate interaction (e.g., 0.5–2s) for responsive scenarios. • Use a longer warm-up (a few seconds to tens of seconds) when the acoustic path is complex (e.g., loud rooms, smartphone loudspeakers) to improve cancelation quality. • Some systems start AEC warm-up as soon as playback starts; others start when the microphone is first opened. Confirm which event triggers warm-up in your environment. Typical trade-offs • Latency to reliable audio processing: Longer warm-up improves suppression but delays the period where AEC output is trusted. • User experience: Very long warm-up may cause poor initial audio quality; very short warm-up may leave noticeable echo. • CPU and power: Some adaptive algorithms do heavier processing during adaptation—monitor resource usage if running on constrained devices. Practical recommendations • If you want low-latency interactive voice (e.g., voice assistants, short dialogs): start with a small warm-up, e.g., 500 ms–2 s, and test if residual echo is acceptable. • For conference/meeting scenarios or when using loudspeakers: test 3–10 s and increase if you see persistent echo. • If your pipeline supports it, start warm-up when playback begins (or when both playback and mic are active), not just on session start. • Log AEC convergence if available (some implementations expose metrics); use that to pick the smallest duration that reaches acceptable suppression. • Combine with other measures: good automatic gain control (AGC), noise suppression (NS), and correct buffer/latency settings reduce load on AEC and shorten warm-up needs. What I need to give a precise answer Please tell me: • Where you saw
aec_warmup_duration
(SDK/library name + version or config file). • Platform/language (browser WebRTC, Node, Android, iOS, self-hosted agent). • The current/default value you observed (and its units, ms vs s). • Your use case (agent voice prompts, meetings, recordings) and target priorities (lowest latency vs highest suppression). With that I’ll give a concrete recommendation (exact units, sensible defaults, and a sample config) or pull the authoritative definition and best-practice values for your platform. , with interactive elements