nice-electrician-78642
02/13/2026, 8:56 PMtall-airline-16756
02/13/2026, 8:56 PMtall-airline-16756
02/13/2026, 8:56 PMnice-electrician-78642
02/13/2026, 9:00 PMtall-airline-16756
02/13/2026, 9:01 PMnice-electrician-78642
02/13/2026, 11:24 PMtall-airline-16756
02/13/2026, 11:25 PMivr_detection=True does.
Short answer: ivr_detection is a boolean AgentSession option that, when set to True, enables LiveKit’s IVR/answering‑machine detection capabilities for server‑side Agents. It does not guarantee perfect classification, but it enables detection signals and behaviors that help your agent handle IVR flows more intelligently.
What enabling ivr_detection=True provides
• Activates IVR/answering‑machine detection logic at the session level so the agent can look for cues of automated systems (for example, structured prompts, lack of natural speech, repetitive audio patterns).
• Lets your agent take IVR‑specific actions such as navigating IVR menus (DTMF), detecting voicemail greetings, and handling call termination or message leaving flows more appropriately.
• Is intended for outbound scenarios where the agent may encounter phone systems before reaching a human.
What it is not
• It is not a perfect human-vs‑robot classifier that always identifies LVR/IVR with 100% accuracy. You should treat its output as a signal that can be combined with other logic.
• It does not automatically perform every IVR interaction without additional logic; enabling detection lets you integrate IVR responses (like DTMF or alternative prompts) or routing decisions in your session flow.
How teams typically use it (recommended patterns)
• Combine ivr_detection=True with silence/VAD signals and timing heuristics to form a confidence score before deciding to repeat a long intro.
• If the session is flagged as IVR, trigger a short recap or IVR navigation routine rather than the full intro.
• After a transfer, re-check for human signals (longer, variable turns) before replaying long content — use the IVR flag to decide whether to play a short recap first.
If you’d like, I can:
• Provide example server‑side pseudocode showing how to read the IVR flag and combine it with VAD/silence thresholds, or
• Suggest concrete thresholds and a two‑stage playback flow (short recap → full intro) you can implement with your AgentSession.
Which would you prefer?
Sources: Agent session | LiveKit Documentation | Building an Automated IVR Menu Caller | LiveKit Documentationnice-electrician-78642
02/13/2026, 11:26 PMSuggest concrete thresholds and a two‑stage playback flow (short recap → full intro) you can implement with your AgentSession.tall-airline-16756
02/13/2026, 11:26 PMivr_detection flag. If true, treat system as “likely IVR” initially.
1. Stage 1 — Short recap:
◦ Play a short, one‑line recap (<=5s) with interruptions allowed.
◦ Start a 1.5s listening window for user speech.
◦ If user speaks >=1.5s, assume human and stop; continue normal dialog.
1. If no human speech detected:
◦ Play full intro (15–20s) with interruptions allowed.
◦ After full intro, wait for human speech (use same 1.5–2.0s minimum).
1. Post‑playback:
◦ If still no human signal after full intro and repeated attempts, mark as voicemail/IVR and take fallback action (leave message, hang up, or schedule retry).
Server‑side pseudocode (conceptual)
• This pseudocode assumes you can:
◦ read an ivr_detection boolean,
◦ call session.say(text, allow_interruptions=True) returning a handle with wait_for_playout() and interruption metadata,
◦ listen for VAD / user_start events and measure continuous speech duration,
◦ use timeouts.
# Configurable thresholds
SHORT_RECAP_MAX = 5.0
FULL_INTRO_MAX = 20.0
INTERRUPTION_WINDOW = 1.5
SILENCE_TIMEOUT = 5.0
MIN_HUMAN_SPEECH = 1.5
async def on_transfer(session):
# Small buffer to ignore trailing IVR audio
await asyncio.sleep(0.8)
# Use ivr_detection as an initial signal
ivr_flag = session.agent_session_options.get("ivr_detection", False)
# Stage 1: short recap
recap_text = "You are now connected to a specialist. One moment please."
recap_handle = session.say(text=recap_text, allow_interruptions=True, max_duration=SHORT_RECAP_MAX)
# Wait for playout to finish or interruption
await recap_handle.wait_for_playout()
# If user interrupted during recap, treat as human (check interrupted speech length)
if recap_handle.interrupted:
if session.last_user_speech_duration >= MIN_HUMAN_SPEECH:
return # user engaged; continue conversation
# Short listening window for immediate user response
if await wait_for_user_speech(timeout=INTERRUPTION_WINDOW, min_duration=MIN_HUMAN_SPEECH):
return # human confirmed
# Stage 2: full intro (play only if needed)
full_intro_text = "Hi, I'm Alex from Billing. I see there was an issue with your last payment. How can I help today?"
intro_handle = session.say(text=full_intro_text, allow_interruptions=True, max_duration=FULL_INTRO_MAX)
await intro_handle.wait_for_playout()
# After full intro, wait for human speech for a short period
if await wait_for_user_speech(timeout=5.0, min_duration=MIN_HUMAN_SPEECH):
return # human confirmed
# If still no human speech, treat as IVR/voicemail fallback
handle_voicemail_or_retry(session)
Helpful implementation notes
• Allow interruptions on both recap and intro so a real person can jump in quickly.
• Use min_interruption_duration or equivalent VAD metric to avoid reacting to brief noise or DTMF tones. Require ~1.5s of continuous speech to count as human.
• Keep a session flag like played_recap to avoid repeating the recap on every internal transfer between humans.
• If ivr_detection was true earlier in the call, bias toward short recap first; if it was false, consider skipping recap unless transfer count > 1.
• Consider a short confirmation prompt after recap if you want to minimize risk of missing the leading message, e.g., “Can you confirm you can hear me?” (very short, low friction).
• Pre-generate or cache TTS audio for recap/intro to reduce latency during transfer.
Questions to fine‑tune thresholds for your environment
1. Do you receive an explicit transfer/call_state event from your telephony integration when transfer happens? If so, we can tie this flow directly to that event.
2. How long is your current full intro today (seconds)? That helps pick the exact full_intro cap.
3. Do you see lots of short exchanges between humans that would be disrupted by a recap? If yes, raise the barrier to play the recap (require ivr_flag true + transfer count > 1).
If you want, I can:
• Provide a concrete Node.js or Python code sample tailored to the AgentSession API you’re using, or
• Recommend exact values for the speech detection thresholds after you tell me your current full intro length and whether you can access transfer events.
Which would you prefer?
Sources: Agent speech and audio | LiveKit Documentation | Uninterruptable Agent | LiveKit Documentation | VAD and turn detection configuration guide | LiveKit | Silero VAD plugin | LiveKit Documentation | Handling payments with PCI compliance | LiveKitacoustic-lunch-30313
02/17/2026, 2:28 PMtall-airline-16756
02/17/2026, 2:28 PMivr_detection=True so the session treats the call as “likely IVR” when automated cues are present. This biases your agent to use navigation logic instead of immediately playing a long intro.
• While inside the IVR, send DTMF tones programmatically (to select menu options) and/or collect DTMF input from the remote system (if you need digits).
• After you finish IVR navigation and the callee is transferred, use the two‑stage playback (short recap → full intro) plus VAD/speech checks to avoid missing the caller’s leading message or over‑repeating the long intro.
Concrete components and recommended behavior 1) Enable IVR detection on the session
• Set ivr_detection=True in the AgentSession options to enable IVR/answering‑machine signals. Treat that flag as an initial hint, not a final decision.
2) Navigate IVR menus by sending DTMF
• Use the session/room participant method to publish DTMF tones when you need to press menu keys (e.g., press "1" for sales).
• Send tones programmatically after detecting the IVR prompt or by instruction from your workflow/LLM.
3) Collect DTMF input from the remote side
• Use a DTMF collection helper (e.g., GetDtmfTask) to listen for keypad tones and validate input when you need digits from the caller or to confirm menu choices.
4) Two‑stage playback after transfer (so you don’t miss caller context)
• Stage 1 (short recap): Play a 3–5s recap immediately after transfer. Allow interruptions.
• Listen for 1.5–2.0s of continuous human speech; if detected, skip the full intro.
• Stage 2 (full intro): If no human detected, play the full intro (cap 15–20s). Allow interruptions here too.
• If still no human speech after the full intro, mark as voicemail/IVR fallback (leave message, hang up, retry).
Suggested thresholds (practical)
• Short recap: <= 5s
• Full intro: 15–20s
• Interruption window after recap: 1.5s
• Minimum continuous speech to count as human: 1.5–2.0s
• Silence timeout for voicemail detection: 5.0s
• Require 2 supporting signals (VAD + variable turn length or DTMF absence) before flipping classification to “human”
Example flow tying it together (concept)
1. Outbound call answers → IVR detection may be true.
2. If ivr_detection or audio patterns indicate IVR:
◦ Run DTMF navigation steps (send tones as needed).
◦ Optionally collect DTMF from the remote system if you expect keypad responses.
1. When you detect the IVR has finished (silence patterns, known prompt end, or transfer event):
◦ Wait ~0.8–1.0s to drop trailing IVR audio.
◦ Run two‑stage playback: recap → listen 1.5s → full intro if needed.
1. If the call is transferred and you detect human speech during the recap, skip full intro and continue conversation. If not, play full intro once and then fallback.
Minimal code sketch (conceptual)
• Send DTMF:
◦ Call session.room.local_participant.publish_dtmf(digit='1') when you need to press 1 for a menu option.
• Collect DTMF:
◦ Use GetDtmfTask to wait for numeric input and confirm.
• Two‑stage playback:
◦ Play recap with session.say(..., allow_interruptions=True), wait up to 1.5s for user_started_speaking event and measure continuous speech. If not present, play full intro.
Practical tips and edge cases
• If IVR plays a long menu before transfer, use audio fingerprinting (if possible) to detect the menu end and only then do recap logic.
• Some IVRs use short tones or very brief speech; require ~1.5s continuous speech to reduce false positives from tones/DTMF.
• Cache or pre‑synthesize recap/intro TTS to avoid latency during transfer.
• Maintain a session flag (e.g., played_recap) to avoid repeating recap between internal human transfers.
• If your environment must avoid sending audio to external services, keep detection heuristic‑based (VAD + timing) rather than ML classification.
If you’d like, I can:
• Provide a concrete Python or Node.js snippet using your AgentSession API showing how to call publish_dtmf(), run GetDtmfTask, and wire up the two‑stage playback with VAD events; or
• Draft a decision tree that maps common IVR flows (press 1 → transfer, press 2 → human) to automated DTMF actions you can plug into your workflow.
Which would be most helpful — a code example for your language (Python/Node), or a decision tree mapping for your typical IVR targets?