Skip to main content

BYO VoiceAI

DialStack is agent-agnostic. Bring your own AI stack and plug it into the call. Two integration patterns cover every BYO scenario.

Two patterns​

PatternWhat your AI doesPrimitive
BYO ReceptionistAnswers the call, talks with the caller, decides what happens nextVoice App (Control) mode + attach action
BYO ObserverListens to the call for transcription / coaching / analytics, doesn't interrupt itVoice App (Notify) mode + Listeners API

Full Voice App semantics: Voice Apps, Call Control and Listeners.

Pattern 1: BYO Receptionist (bidirectional)​

The AI answers the call and talks with the caller. You run the prompt, the tools, and the transcription; DialStack handles telephony.

Flow​

Create the Voice App​

Bash
curl -X POST https://api.dialstack.ai/v1/voice-apps \
-H 'Authorization: Bearer sk_live_YOUR_KEY' \
-H 'DialStack-Account: acct_01h2xcejqtf2nbrexx3vqjhp41' \
-H 'Content-Type: application/json' \
-d '{
"name": "BYO Receptionist",
"url": "https://your-server.example.com/voice/webhook"
}'

Handle the webhook and attach audio​

TypeScript
import { DialStack } from '@dialstack/sdk-server';

const ds = new DialStack(process.env.DIALSTACK_API_KEY);

// POST /voice/webhook
app.post('/voice/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
// Throws on a bad signature: see receiving-webhooks.md#signature-verification
const event = DialStack.webhooks.constructEvent(
req.body,
req.header('x-dialstack-signature'),
process.env.VOICE_APP_SECRET
);

if (event.event === 'call.received') {
// Open the WebSocket for this call
await ds.calls.update(
event.call_id,
{
actions: [{ type: 'attach', url: 'wss://your-server.example.com/voice/stream' }],
},
{ dialstackAccount: event.account_id }
);
}

res.status(200).end();
});

The audio WebSocket​

Your service accepts a WebSocket at the URL you passed to attach, and sends agent audio back on the same socket. The audio format and messages are in the WebSocket API.

Vendor guides​

A relay server sits between the two WebSockets: DialStack's media socket on one side and your AI vendor's on the other. Step-by-step guides, each built on the same relay:

The same shape works for Vapi, Retell, or a self-hosted model — swap the outbound WebSocket and the frame format.

Routing​

Give the voice app an extension, or drop a Voice App (Control) node into any dial plan:

TypeScript
{
id: 'ai_reception',
type: 'voice_app',
config: { voice_app: 'va_01h2xcejqtf2nbrexx3vqjhp49', mode: 'control' }, // your voice app ID
}

Pattern 2: BYO Observer (one-way)​

The AI listens to calls for real-time transcription, coaching, or analytics. It never talks to the caller and doesn't affect call routing.

note

Notify nodes must reference a plain webhook voice app. The voice app managed by a Managed VoiceAI agent resource (/v1/ai-agents) is built to drive calls and cannot be used as a Notify target — dial-plan create/update will return 422.

Flow​

Create the listener​

TypeScript
if (event.event === 'call.notify') {
await ds.calls.createListener(
event.call_id,
{ url: 'wss://your-server.example.com/voice/listen' },
{ dialstackAccount: event.account_id }
);
}

Both parties on the call are unaware that a listener is attached, so you are responsible for obtaining any consent the law requires. Listeners stop automatically when the call ends. See Listeners.

Routing​

Put a Voice App (Notify) node ahead of the real routing. Its next is the node the call continues to:

TypeScript
{
id: 'transcribe',
type: 'voice_app',
config: { voice_app: 'va_01h2xcejqtf2nbrexx3vqjhp52', mode: 'notify', next: 'reception' },
}

Choosing between them​

  • Your AI should talk → Pattern 1 (Control mode + attach).
  • Your AI should listen → Pattern 2 (Notify mode + Listeners API).
  • Both → a dial plan can route through a Notify node first (transcription) and then to a Control node (Managed VoiceAI agent). Or the Control-mode AI can itself open a sidecar listener.

Compared to Managed VoiceAI​

DialStack ships a first-party AI receptionist via AI Scheduling / the Managed VoiceAI agents API. Reach for BYO when:

  • You already run an AI stack your team knows.
  • You need a specific model, voice, or data-control guarantee.
  • You want full control over the prompt, tools, and transcripts.

See also​

  • Voice Apps — creating a voice app, its webhooks and dial plan nodes.
  • Call Control — actions (attach, transfer, combined/sequenced).
  • Listeners — one-way audio streaming.
  • Dial Plans — how Voice App nodes slot into call routing.
  • WebSocket API — media-streaming protocol for both attach and Listeners.
  • AI Scheduling — the native alternative, when you don't need to bring your own.