> ## 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.

Voice Mail Detection automatically detects when outbound calls are routed to voicemail, so the agent does not speak to a recording or wait for a person who is not there.

Voice Mail Detection lets you:

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

## Setup

Import `VoiceMailDetector` and put it on the `Pipeline`, alongside the providers. Give it an `llm` to classify with, and the runtime runs the detector when the session is started with `zeroruntime.invoke()`.

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

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

  pipeline = Pipeline(
      stt=DeepgramSTT(),
      llm=OpenAILLM(),
      tts=CartesiaTTS(),
      turn_detector=TurnDetector(model="echo-large"),
      denoise=AICousticsDenoise(model_id="quail-vf-2.2-l-16khz"),
      voice_mail_detector=VoiceMailDetector(
          llm=OpenAILLM(),
          duration=5,
      ),
  )


  class OutboundAgent(Agent):
      def __init__(self):
          super().__init__(
              agent_id="outbound",
              instructions="You are calling to confirm an appointment.",
              pipeline=pipeline,
          )

      async def on_voicemail(self) -> None:
          """Awaited, so anything said here finishes before the call ends."""
          print("Voice Mail detected, Shutting down the agent")
          await self.hangup(reason="reached voicemail")
  ```

  ```typescript title="Node JS" Node JS theme={null}
  import { Agent, Pipeline, VoiceMailDetector } from '@zeroruntime/js-sdk';
  import { OpenAILLM, DeepgramSTT, CartesiaTTS } from '@zeroruntime/js-sdk/plugins';
  import { AICousticsDenoise, TurnDetector } from '@zeroruntime/js-sdk/inference';

  const pipeline = Pipeline({
    stt: DeepgramSTT(),
    llm: OpenAILLM(),
    tts: CartesiaTTS(),
    turn_detector: TurnDetector({ model: 'echo-large' }),
    denoise: AICousticsDenoise({ model_id: 'quail-vf-2.2-l-16khz' }),
    voice_mail_detector: VoiceMailDetector({
      llm: OpenAILLM(),
      duration: 5,
    }),
  });


  class OutboundAgent extends Agent {
    constructor() {
      super({
        agent_id: 'outbound',
        instructions: 'You are calling to confirm an appointment.',
        pipeline,
      });
    }

    async on_voicemail() {
      // Awaited, so anything said here finishes before the call ends.
      console.log('Voice Mail detected, Shutting down the agent');
      await this.hangup('reached voicemail');
    }
  }
  ```
</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). Detection is handled by the runtime, which calls the agent's `on_voicemail` back
when it fires. Pass `callback=` on the detector instead to route it to a plain function.

## Parameters

| Parameter       | Type              | Default    | Description                                                                          |
| --------------- | ----------------- | ---------- | ------------------------------------------------------------------------------------ |
| `llm`           | `LLM`             | *required* | LLM instance used to classify the opening transcript as human vs. voicemail.         |
| `callback`      | `Callable`        | `None`     | Runs on detection. `None` calls the agent's `on_voicemail` method.                   |
| `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. |
| `enabled`       | `bool`            | `True`     | Set `False` to carry the configuration without turning detection on.                 |

## 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>
