> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zeroruntime.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Voicemail Detection

> Detect voicemail systems on outbound calls and respond with a callback.

Voice Mail Detection automatically detects when outbound calls are routed to voicemail and triggers a callback so your agent can leave a message or end the call, preventing the agent from speaking or waiting unnecessarily.

Voice Mail Detection lets you:

* Detect voicemail systems automatically.
* Control how your agent responds.
* End calls cleanly after voicemail handling.

## Setup

Import `VoiceMailDetector`, attach it to your agent's `Pipeline`, and register a callback that defines how voicemail should be handled. The runtime runs the detector and fires your callback when the session is started with `zrt.invoke()`.

<Note>
  To set up outbound calling and routing rules, check out [Handling Calls](/telephony/managing-calls/handling-calls).
</Note>

<CodeGroup>
  ```python title="main.py" Python theme={null}
  from zrt import Pipeline, VoiceMailDetector
  from zrt.plugins import OpenAILLM, DeepgramSTT, CartesiaTTS, TurnDetector
  from zrt.inference import AICousticsDenoise

  async def voice_mail_callback(event):
      # event: the detection payload (e.g. transcript, confidence)
      await agent.session.say("We tried to reach you. Please call us back.")

  voicemail = VoiceMailDetector(
      llm=OpenAILLM(),
      callback=voice_mail_callback,
      duration=5,
      auto_hangup=True,
  )

  pipeline = Pipeline(
      stt=DeepgramSTT(),
      llm=OpenAILLM(),
      tts=CartesiaTTS(),
      turn_detector=TurnDetector(model="echo-large"),
      voice_mail_detector=voicemail,
      denoise=AICousticsDenoise(model_id="quail-vf-2.2-l-16khz"),
  )
  ```
</CodeGroup>

## How it works

The detector buffers the opening speech on an outbound call for `duration` seconds, then
asks the `llm` to classify the transcript as a human or a voicemail greeting (a one-word
yes/no). If it's classified as voicemail, your `callback` runs so you can leave a message or
hang up cleanly.

## Parameters

| Parameter             | Type              | Default    | Description                                                                                                    |
| --------------------- | ----------------- | ---------- | -------------------------------------------------------------------------------------------------------------- |
| `llm`                 | `LLM`             | *required* | LLM instance used to classify the opening transcript as human vs. voicemail.                                   |
| `callback`            | `Callable`        | *required* | Called when a voicemail is detected, with the detection event payload (transcript, confidence). Sync or async. |
| `duration`            | `float` (seconds) | `2.0`      | How long to buffer the opening speech before classifying.                                                      |
| `custom_prompt`       | `str`             | `None`     | Override the built-in classifier system prompt for custom voicemail-detection logic.                           |
| `auto_hangup`         | `bool`            | `False`    | Automatically end the session when a voicemail is detected.                                                    |
| `detection_threshold` | `float`           | `1.0`      | Confidence threshold for gating detection.                                                                     |

## What's Next

<CardGroup cols={2}>
  <Card title="DTMF Events" icon="hashtag" href="/build/telephony/dtmf">
    Capture caller key presses.
  </Card>

  <Card title="Call Transfer" icon="phone-arrow-right" href="/build/telephony/call-transfer">
    Move a live call to another number.
  </Card>
</CardGroup>

## References

<Tabs>
  <Tab title="Python">
    #### SDK Reference

    <CardGroup cols={2}>
      <Card title="Voice Mail Detector" icon="voicemail" href="/api-reference/python/core/tools-and-mcp#voicemaildetector">
        VMD in the Python API reference.
      </Card>
    </CardGroup>
  </Tab>
</Tabs>
