we have built a voicemail detect tool, but this to...
# ask-ai
g
we have built a voicemail detect tool, but this tool is being called in betten the call and because of that calls are getting croped in bw the session. how to solev this
t
Thanks for reaching out, ashutosh. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — that sounds frustrating. You're asking how to stop your voicemail detection tool from interrupting live calls and causing sessions to be cut off mid-call. You can prevent those interruptions by telling the tool to run without being cancelable while it performs its voicemail actions. What to do (short): • In your tool’s RunContext, call ctx.disallow_interruptions() at the start of the voicemail-handling sequence so user speech won’t cancel it. • After generating/playout of the voicemail message, wait for playout to finish if needed, then hang up the call cleanly (for example by deleting the room or using your normal hangup API). Example (conceptual Python):
Copy code
@function_tool
async def detected_answering_machine(self, ctx: RunContext):
    # Prevent user speech from interrupting this sequence
    ctx.disallow_interruptions()

    # Leave a message
    await self.session.generate_reply(instructions="Leave a brief message that you'll call back later.")

    # Optional: ensure audio finishes
    await ctx.wait_for_playout()

    # End the call for all participants
    await ctx.api.room.delete_room(room_id)
Why this helps: •
ctx.disallow_interruptions()
ensures the tool runs to completion even if the callee speaks, preventing mid-sequence cancellation that can truncate the call. • Waiting for playout avoids cutting audio mid-sentence. • Using the API to hang up (delete room or your telephony hangup) closes the call cleanly rather than leaving participants in a half-closed state. If you'd like, tell me: • Which SDK/language you’re using (so I can give exact code), and • Whether you already call any wait-for-playout or hangup functions today. I can provide a concrete code snippet for your environment and review where to place the disallow call in your current flow. Sources: Tool definition and use | LiveKit Documentation | Agents telephony integration | LiveKit Documentation | Agent speech and audio | LiveKit Documentation
g
async def detect_voice_mail(self, _context_: RunContext): """Call this immediately when you hear an automated voicemail greeting that mentions phrases like "forwarded to voicemail", "leave a message", "after the tone", "not available", or any automated recording asking to leave a message. This indicates a human is not on the line.""" # Update the agent's voice_mail_detected flag self.agent.voice_mail_detected = True await self.end_call_tool.end_call(context) this is the piece of code and also can you suggest a good description for the tool.
t
Thanks — this is helpful. I’ll respond to two things: (1) how to stop this tool from cutting calls off mid-session, based on the code you shared, and (2) a concise, user-friendly description you can use for the tool. Suggested code changes • Prevent interruptions at the start of the voicemail-handling flow by calling
ctx.disallow_interruptions()
. • Make sure any playout finishes before ending the call by awaiting a playout wait helper (for example
ctx.wait_for_playout()
if available). • Hang up cleanly using your room/hangup API (avoid abruptly terminating the session without waiting for playout). Example (adapted from your snippet — insert the correct room/hangup call for your environment):
Copy code
async def detect_voice_mail(self, context: RunContext):
    """Call this immediately when you hear an automated voicemail greeting."""
    # Ensure this sequence can't be interrupted by detected speech
    context.disallow_interruptions()

    # Mark voicemail detected for the agent logic
    self.agent.voice_mail_detected = True

    # Optional: if you play a message or generate a reply, do that here
    # await self.session.generate_reply(instructions="Leave a brief message...")

    # Wait for any playout to complete before hanging up
    try:
        await context.wait_for_playout()
    except AttributeError:
        # If wait_for_playout isn't available in your RunContext, you can use a short sleep
        import asyncio
        await asyncio.sleep(0.5)

    # End the call cleanly (replace with your actual hangup/delete_room call)
    await self.end_call_tool.end_call(context)
Notes on placement and behavior • Call
context.disallow_interruptions()
immediately when you detect the voicemail greeting so downstream steps cannot be canceled by incoming speech. • If your detection triggers while the callee is speaking, disallowing interruptions prevents that speech from canceling the voicemail flow and causing a mid-call cutoff. • Waiting for playout (or a small sleep when playout waiting isn't available) prevents cutting off the final audio before the hangup. • Ensure
end_call_tool.end_call
performs a clean hangup (for example, uses your API to delete the room or call so participants are disconnected gracefully). Tool description suggestions Pick one that fits your UI tone; short and long options: • Short (UI label): "Voicemail Detection" • Short description: "Detects automated voicemail greetings and handles leaving a message without interrupting active calls." • Longer description (for tool listing or docs): "Automatically detects automated voicemail greetings (phrases like 'leave a message', 'after the tone', 'forwarded to voicemail') and runs a non-interruptible voicemail-handling sequence. The tool ensures audio playout completes and then ends the call cleanly so live calls are not cut off unexpectedly." If you want a version tailored to a specific audience (developer, product, or end-user), tell me which and I’ll adapt it. Next steps I can help with • Provide a version of the code for a specific SDK or language if you tell me which one you’re using. • Review your
end_call_tool.end_call
implementation to confirm it performs a graceful hangup. • Add an example where the tool also plays a short message before hanging up. Would you like the snippet converted to a specific SDK or to review your end_call implementation next?
g
actually, my current setup deleibrately triggers the voicemail although the actual user is presnt.
t
Thanks — that helps a lot. You're saying your system intentionally triggers voicemail detection even when a live person is on the line. That explains why calls are being cut off unexpectedly. I can help two ways: (A) stop the voicemail-handling sequence from interrupting calls once it starts, and (B) reduce false voicemail triggers so the sequence rarely starts when a real person is present. Before I give targeted suggestions, could you tell me a few details about how your voicemail detection currently works? The answers will let me recommend the most effective fixes. Please share: 1. How you detect voicemail today — brief summary (choose one or more): ◦ Keyword/phrase matching on speech-to-text (e.g., "leave a message", "after the tone") ◦ Acoustic/intonation models that recognize recorded greetings vs. live speech ◦ Tone detection (beep/after-tone) or silence patterns ◦ Heuristic rules (e.g., long continuous playback, lack of conversational back-and-forth) ◦ Something else (please describe) 1. If you use speech-to-text/keyword matching: what confidence thresholds or timing rules do you use? Do you require multiple keywords or just one match? 2. If you use acoustic models or heuristics: what features do you inspect (e.g., speaker energy, background noise, pause lengths, packet timing)? Any thresholds you can share? 3. How quickly does your code trigger the voicemail flow after hearing the greeting? (immediate on first match, after N seconds, after N phrases, etc.) 4. Do you have access to metadata like call direction (inbound vs outbound), carrier flags, or SIP/telephony headers that might indicate voicemail? 5. Would you prefer to accept a small delay to improve accuracy (for example wait 1–2 seconds to confirm), or is minimal latency more important? If you’d rather, paste the core detection snippet you’re using (the logic that decides voicemail vs human). Once I have this, I’ll suggest concrete changes to reduce false positives and show where to place
context.disallow_interruptions()
(or equivalent) so voicemail handling no longer cuts off live calls. Quick guidance you can consider right away • Debounce detection: require two independent indicators (e.g., keyword + acoustic pattern) before triggering. • Require multiple keyword matches or higher confidence thresholds instead of a single phrase. • Add a short confirmation window (e.g., 500–1500 ms) to watch for human-like responses before executing voicemail flow. • If you can, prefer metadata signals (carrier voicemail flags, SIP headers) to avoid audio-only false positives. • Always call
context.disallow_interruptions()
at the start of the voicemail-handling sequence so when it does run it won't be interrupted. Tell me which detection methods you use and whether you can accept a small confirm delay. I’ll provide tailored code changes and a suggested confidence/timeout policy.
g
currenlt we are dependent on the llm, based on the description llm trggers the tool
t
Thanks — this is clear and helpful. You mentioned the LLM is the trigger for the voicemail tool. I can help with two parallel tracks: • Make voicemail handling non-interruptible so it won’t cut calls off when it does run. • Reduce LLM false positives so the voicemail tool rarely triggers when a live person is present. To give precise, actionable changes I need one thing from you: the exact LLM prompt or the trigger text/description you currently use that tells the LLM to call the voicemail tool. With that I can suggest prompt edits and guardrails to reduce false triggers. While you paste the prompt, here are recommended changes you can apply now. Immediate fixes (stop cutting calls off) 1. At the start of your voicemail tool, call
context.disallow_interruptions()
so the sequence cannot be canceled by incoming speech. 2. If you play or generate any audio, wait for playout to finish—use
await context.wait_for_playout()
if available, or a short
await asyncio.sleep(0.5)
fallback—before hanging up. 3. Ensure your hangup path performs a clean disconnect (e.g.,
ctx.api.room.delete_room(room_id)
or your existing
end_call_tool.end_call
) so participants aren’t left in a half-closed state. Prompt + LLM-side guardrails (reduce false positives) • Require multiple signals: change the LLM prompt to only trigger voicemail when it sees both a clear voicemail phrase (e.g., "leave a message", "after the tone", "forwarded to voicemail") AND at least one additional indicator (long continuous playback, absence of conversational reply, or a carrier/SIP voicemail flag). • Raise confidence threshold: instruct the LLM to only call the tool when the predicted probability/confidence of "voicemail" is high (e.g., > 0.85), or when the same conclusion appears across N consecutive model inferences. • Add a confirmation window: after the LLM predicts voicemail, wait 500–1500 ms to see if any human-like speech/response occurs. If human speech is detected in that window, cancel the voicemail flow. • Require two independent detectors: have the LLM’s decision be validated by a secondary heuristic (e.g., keyword matcher or acoustic classifier) before triggering the tool. • Be conservative on single-keyword matches: don’t trigger on a single low-information phrase such as "not available" unless paired with other evidence. • Use explicit negative checks: instruct the LLM not to trigger if it detects conversational cues (questions, short answers, interruptions, or back-and-forth exchanges) in the recent audio. Suggested prompt patterns • Add a short checklist to the prompt: “Only call the voicemail tool if all of the following are true: 1) an automated greeting contains voicemail phrases, 2) audio shows long continuous playback or beep, 3) no human response occurs within 1 second, 4) confidence >= 0.85.” • Ask the LLM to output a structured decision object: {decision: "voicemail" | "human", confidence: 0.0-1.0, reasons: [..]} so your orchestrator can apply deterministic thresholds before invoking the tool. Concrete orchestration pattern 1. LLM processes audio and returns structured decision + confidence + reasons. 2. Orchestrator checks: if decision == "voicemail" AND confidence >= threshold AND at least one corroborating heuristic is true -> call voicemail tool. 3. If decision is borderline, buffer 500–1500 ms and re-evaluate with new audio before acting. 4. If voicemail tool is invoked, it starts with
context.disallow_interruptions()
and follows the playout/wait/hangup flow. Tool description suggestions (final) • Short label: "Voicemail Detection" • Short description: "Detects automated voicemail greetings and safely handles leaving a message without interrupting active calls." • Longer description: "Detects automated voicemail greetings (phrases like 'leave a message', 'after the tone', 'forwarded to voicemail') and runs a non-interruptible voicemail-handling flow that finishes audio playout and then ends the call cleanly. The tool is only triggered when multiple voicemail indicators are present to avoid false positives." Next step — please paste: 1. The exact LLM prompt or trigger text you currently use to instruct the model to call the voicemail tool. 2. If possible, the structured output your LLM currently provides (if any), and whether it returns a numeric confidence score. 3. Whether you can accept a 500–1500 ms confirmation delay. Once you share the prompt and answers, I’ll: • Propose a revised prompt with guardrails. • Show a small orchestrator snippet that applies the thresholds and confirmation window. • Optionally convert the voicemail tool snippet to your exact runtime/SDK if you tell me which one you use.