Live call routing and IVR (ONC-016)
Bring your own telephony: register a Twilio or Vonage number you own, attach a call flow, and point the number's voice webhook at the notifier path /voice/inbound/{number_id} (shown as webhook_path on the number). Requires the ManageOnCall permission.
API
POST|GET /v1/orgs/{org}/voice/flows,GET|PUT|DELETE /v1/orgs/{org}/voice/flows/{id}POST|GET /v1/orgs/{org}/voice/numbers,GET|PATCH|DELETE /v1/orgs/{org}/voice/numbers/{id}
The number's auth_token (Twilio auth token, Vonage signature secret) is sealed on write and never returned, logged or audited. Another org's flow or number is a 404.
Flow graph
{start, nodes[]} with at most 50 nodes. Node types:
type | fields | next |
|---|---|---|
|
|
|
|
| by digit; after the retries, |
|
| by local time |
|
| rings up to 5 current on-call targets in order; |
|
| the voice agent below; an empty link hangs up |
|
| the provider records; the recording URL and caller become a note on a new alert. We store no audio |
|
Every node must be reachable, and a cycle must pass through a menu or ai_agent (both wait for the caller).
AI voice agent
The ai_agent node speaks to a responder who calls the line. The caller must be verified twice:
Twilio reports a STIR/SHAKEN
Aattestation (StirVerstat); Vonage reports none, so on Vonage numbers the node only offers escalation.The caller number must be the verified voice contact of a user who was notified of an open page.
The agent then speaks that page and, on request, the project's change events of the last 24 hours. The text is written by the organization's own model key: the project's summary binding, else the org BYO key. It never uses the operator key, and it counts against the org's monthly AI cap. Without a key, with AI disabled or on any model error it speaks a plain template. Incident text goes to the model as data and the model only returns text to speak; it has no tools.
The caller answers by keypad or speech: 1 or "acknowledge", 2 or "escalate", 3 or "what changed?". Only Watchtower code maps the answer to an action. Ack and escalate run as that user through the same internal page actions as keypad acknowledgements, so the user's role is checked and the action is audited, and the call then follows on_ack or on_escalate. A caller who is not verified hears no incident details; "escalate" only follows on_escalate. Unclear answers and "what changed?" count towards retries; then the call follows on_timeout. Agent outcomes add voice.call.agent_ack and voice.call.agent_escalate (with _failed variants) to the call history.
Security and history
A request that fails the provider signature (Twilio X-Twilio-Signature, Vonage signed JWT) gets 403 and no flow runs. Interpreter state travels in signed callback URLs that expire after 10 minutes. Each call writes voice.call.inbound, voice.call.routed and voice.call.voicemail; the caller is masked to the last four digits unless the number has keep_caller set. Callers do not use on-call seats.