Self-Hosted
Self-Hosted
Self-Hosted mode lets you bring your own agent infrastructure. Instead of Dial’s managed agent driving a call, Dial connects to a WebSocket server you host. It comes in two variants — one is active at a time, for all of your account’s calls:
- LLM (
"type": "llm") — Dial still handles the hard parts of voice: telephony, speech‑to‑text, text‑to‑speech, turn‑taking, and interruptions. Your server only answers one question, live: given the conversation so far, what should the agent say next? It speaks the Self-hosted LLM protocol — transcripts in, text turns out. - Audio (
"type": "audio") — Dial pipes the raw call audio to your server, full duplex, over the Self-hosted audio protocol. You bring the entire voice stack: a speech-to-speech model (OpenAI Realtime, Gemini Live, …) or your own STT → LLM → TTS chain. Audio formats are configurable per direction (G.711 or linear PCM at 8–24 kHz).
Either way, no voice-infrastructure details leak through — your server sees clean Dial-native protocols and Dial call ids only.
How it works
- You host a WebSocket endpoint and configure Self-Hosted with its
wss://URL and variant. - For each call, Dial opens a socket to
wss://<your-url>/<call_id>, signed so you can verify it’s from Dial. - LLM: Dial streams the live transcript and asks for the agent’s turns; your server streams back the words to speak. Audio: Dial streams the caller’s audio; your server streams back the agent’s audio.
While Self-Hosted is on, it drives all of your account’s calls — inbound and outbound.
Enable it
Set it up from the dashboard Self-Hosted page, or via the API. LLM and audio each have their own independent config — configure either without affecting the other.
Every change is a single POST with one action: save (persist a mode’s config; mints that
mode’s signing secret on the first URL), activate (save the config, then enable + route calls
through that mode — enable or switch), or disable.
save never changes which mode is active or whether Self-Hosted is on — it just persists that
mode’s config. Each mode has its own wsUrl and signing secret.
Copy that mode’s signing secret — from the dashboard, or
GET /api/v1/self-hosted/secret?mode=llm — and wire up your server’s signature verification with it
(each mode has its own secret). Then activate: the body is exactly a save (the mode’s
config), and it also enables Self-Hosted and routes all your calls (inbound and outbound) at
that mode’s server immediately — so make sure it’s ready:
To switch modes, activate the other one — its config comes along in the same body (affects new
calls only). To turn Self-Hosted off, disable:
Verify every connection
Each connection carries an X-Dial-Signature header (HMAC‑SHA256 over <timestamp>.<call_id>
with your signing secret) — the same scheme in both variants. Your server should verify it and
reject stale or mismatched signatures. The SDKs ship a helper for
exactly this, plus the full protocols as ready-made schemas and server helpers — start there rather
than hand‑rolling the message types.
Reference servers
Don’t start from scratch. The
OpenAI WebSocket server
in the Dial playbooks repo is a minimal, runnable LLM-variant server. It verifies the
X-Dial-Signature, drives each turn with the OpenAI SDK, echoes the ping_pong keepalive, and
focuses on transcript interrupts — cancelling the in‑flight reply when the caller speaks again so
the agent never talks over them. Run it, expose it with ngrok, and point
Self-Hosted at the tunnel’s wss:// URL:
While Self-Hosted is on, managed features do not apply: built‑in agent tools and any Context MCP connections are inert, because the agent driving the call is yours. In the audio variant this extends to everything voice: transcripts, recordings, and call summaries are not produced — Dial never hears the conversation. Turn Self-Hosted off to return to the managed agent.
Next steps
- Self-hosted LLM protocol — the LLM-variant WebSocket contract: connection, signing, messages, streaming, interrupts, and resumability.
- Self-hosted audio protocol — the audio-variant contract: formats, media frames, barge-in, checkpoints, and reconnection.
- SDKs — protocol schemas, server helpers, and the signature helper for Node and Python.