Skip to main content
Extensions are optional pipeline components that address common outbound call challenges: navigating automated phone menus (IVR) and detecting whether a human or voicemail answered the call. Both are designed to slot into a standard Voxray pipeline with minimal wiring.

IVR Extension

Use case

When placing outbound calls to businesses or government services, your agent will often encounter an Interactive Voice Response (IVR) system before reaching a human — “Press 1 for billing, press 2 for support.” The IVR extension automates this navigation: it listens to the IVR audio, uses an LLM to decide what to do, sends DTMF keypad tones, and hands off cleanly to normal conversation mode once a human is reached.

How it works

The extension operates in two LLM modes managed by a single IVRProcessor:
  1. Classifier mode — active at call start. The LLM listens to audio and outputs one of two mode tags: <mode>conversation</mode> (human detected, hand off) or <mode>ivr</mode> (IVR system detected, enter navigation mode).
  2. IVR navigation mode — activated when the classifier fires ivr. The processor injects the IVR system prompt into the LLM context and adjusts VAD silence thresholds (shorter stop time so the agent doesn’t wait long between IVR prompts). The LLM then outputs DTMF tags (<dtmf>1</dtmf>) and status tags (<status>completed</status>) as it navigates the menu.
The processor sits downstream of the LLM and pushes control frames upstream to effect mode changes: LLMMessagesUpdateFrame to swap the system prompt, and VADParamsUpdateFrame to tighten the silence window during IVR navigation.

Key types

IVRProcessor — the core frame processor: IVRStatus — reported via OnIVRStatusChanged:

LLM command tags

The IVR system prompt must instruct the LLM to wrap commands in XML tags. The processor pattern-matches these tags in the streaming LLM output:
Text outside the XML tags is forwarded downstream as normal AggregatedTextFrame content. The LLM can still speak to the IVR system between DTMF presses — useful for spoken menu options that require voice input rather than keypad input.

Pipeline position

IVRNavigator wraps a [LLM, IVRProcessor] chain into a single pipeline node. The internal LLM context is automatically wired to IVRProcessor.SetSavedMessages so that when conversation mode is triggered, the full conversation history is available in the callback.

Setup

1

Import the extension package

2

Create the navigator

The second argument is the navigation goal injected into the IVR system prompt. The third is IVRVADStopSecs.
3

Register callbacks

4

Add to pipeline

Frames emitted


Voicemail Detection Extension

Use case

When placing outbound calls, you need to know whether a human or an answering machine picked up before your agent starts speaking. Delivering a full sales pitch to voicemail wastes the recording slot and sounds wrong. The voicemail detection extension holds the TTS output in a gate, classifies the audio using a fast LLM, and then either releases the buffered speech (human) or triggers a tailored voicemail response.

How it works

The detector inserts a parallel pipeline branch after STT. Both branches receive the transcribed audio simultaneously:
  • Conversation gate branch — passes frames through normally, but closes if voicemail is detected, preventing the main LLM from wasting compute on a recording.
  • Classifier branch — runs a dedicated fast LLM with a classification prompt. Its output is monitored by ClassificationProcessor, which fires one of two notifiers when it sees CONVERSATION or VOICEMAIL in the LLM response.
Downstream, a TTS gate buffers all TTS audio frames. When the classification notifier fires:
  • CONVERSATION → the gate opens and releases all buffered TTS frames. The caller hears the agent’s greeting with minimal delay.
  • VOICEMAIL → the gate discards buffered frames. The OnVoicemailDetected callback fires so your code can push a custom TTS message (e.g. “Please call us back at 555-0100”).

Components

Pipeline position

det.Detector() is the parallel pipeline node inserted after STT. det.Gate() is the TTS buffer inserted after TTS and before the transport sink.

Setup

1

Import the extension package

2

Create the detector

To customise the classification prompt:
3

Register callbacks

4

Add to pipeline

Classifier prompt requirements

The classifier LLM must respond with exactly CONVERSATION or VOICEMAIL as a complete response. Any other output is ignored and classification stalls until a valid token appears.
Do not instruct the classifier to explain its reasoning or hedge its answer. A response like “Based on the audio, I believe this is a CONVERSATION” will not match. The prompt must produce a bare single-word response.
Append voicemail.ClassifierResponseInstruction to any custom prompt — it contains the exact constraint text Voxray expects.

Integration with IVR

For outbound campaigns that encounter both voicemail screening and IVR systems, chain the two extensions: voicemail detection runs first, and on OnConversationDetected you start the IVR navigator:

Frames reference

Event hooks reference