Skip to main content

AI Voice Agents via sip_forward

You can point an Orbit DID at any third-party AI voice platform that exposes a SIP endpoint — callers.ai, Retell, Vapi, and most other agent providers do. Orbit handles the carrier termination, billing, and recording; the AI provider runs the conversation logic. This guide walks through wiring up an inbound sip_forward route end to end. The same shape works for self-hosted PBX targets — see the SIP trunk reference for the trunk-mode alternative.

How it works

  1. Orbit owns the DID and accepts the inbound INVITE from the carrier.
  2. Orbit’s SBC (Jambonz) re-INVITEs the call to the AI provider’s SIP URI on your behalf, terminating TLS at our edge.
  3. RTP media is bridged through RTPengine — the AI provider never sees the carrier directly, and the carrier never sees the AI provider.
  4. Hangup, DTMF, and recording are surfaced over the same Orbit webhook contract regardless of which AI vendor terminates the call.

Step 1 — Buy a number

Pick a number for the agent. Toll-free numbers tend to work better for contact-center scenarios because A2P 10-DLC restrictions don’t apply to inbound voice. First, list available numbers for the country and capability you want:
Each entry in the response’s numbers array has a phone_number field. Copy the E.164 value (e.g. +14155550123) of the one you want, then buy that specific number:
The response carries the phone_number field — the E.164 phone number (e.g. +14155550123) you’ll use in the next step. Inbound routing is keyed by the E.164 number, not the id (num_…): export it as PHONE_NUMBER so the path below resolves correctly.

Step 2 — Configure inbound routing → sip_forward

You can omit sipUsername / sipPassword if the AI provider doesn’t require digest auth on the inbound INVITE — most do not.

Provider URI examples

Each AI provider publishes a slightly different SIP URI shape. Use the example for your vendor verbatim — only the token / agent ID changes.

callers.ai

The <token> is the agent token from your callers.ai dashboard (Settings → Phone → SIP).

Retell

<retell-sip-host> is the host published in your Retell dashboard under “Phone Numbers → BYO SIP” — it’s region-specific (Retell publishes a per-account SIP host such as <account-hash>.sip.<provider>.example; copy the exact value from your dashboard rather than hard-coding).

Vapi

The <assistant_id> is the assistant’s ID from the Vapi dashboard (Assistants → ID → Copy). Vapi’s SIP endpoint accepts unauthenticated INVITEs by default; configure an inbound credential under “SIP Trunks” if your security posture requires digest auth.

DTMF

Orbit forwards DTMF events to the AI provider as RFC 4733 in-band RTP. All three providers above support this out of the box — no extra configuration needed. SIP INFO DTMF is not forwarded; if your agent only supports SIP INFO, contact support and we’ll enable the DTMF translator on your account.

Audio codec compatibility

Orbit’s SBC re-negotiates codecs on the way out, so the AI provider sees only the codec it’s comfortable with even if the carrier offered something exotic.

Troubleshooting

Signature 401 on inbound INVITE

The AI provider’s SIP gateway rejected your INVITE with a 401 Unauthorized and you don’t see the call in your provider dashboard. The two common causes:
  1. Wrong token / agent_id. Re-copy from the provider dashboard; tokens are case-sensitive.
  2. Trunk auth required. Some providers (Retell on production tier, Vapi if “Allow only authorized SIP origins” is on) need digest auth. Set sipUsername and sipPassword on the route config to credentials issued by the provider — Orbit stores them encrypted at rest.

Audio one-way

You can hear the caller, but the caller can’t hear the agent (or vice versa). This is almost always a codec mismatch on the AI provider side — the AI is sending Opus but Orbit re-INVITEd as G.711. Open a ticket with the provider and ask them to advertise G.711 µ-law in their SDP answer; Orbit will negotiate down to whatever both ends agree on.

Calls drop at exactly 32 seconds

Classic NAT keep-alive timeout: the carrier or RTPengine isn’t seeing media in one direction, so the SBC tears the call down at the 32s default. The fix lives on the AI provider’s side — they need to send RTP keep-alives during periods of silence (e.g. while waiting on the LLM). All three providers above support this; check their “send RTP during silence” setting. If the drop happens earlier (< 5s), it’s usually the carrier rejecting the re-INVITE — open a support ticket with your call SID and we’ll pull the SBC trace.

See also

  • SIP Trunks — the trunk-mode alternative to inline sip_forward. Use this when one trunk fans out to many DIDs.
  • Inbound routing — full reference for every route type (agent, softphone_user, softphone_register, ivr, voicemail, queue, sip_forward, transfer, conference, decline, ring_group, shared_line, dispatch_to_voicemail_box, webhook).
  • Webhooks — receive call.initiated, call.answered, and call.completed events for calls forwarded to an AI agent.