Skip to main content
To the device gateway, a phone line is just a SIP connection, using the same capabilities as SIP conferencing endpoints: an incoming call is a regular user in the channel, and can talk with a SAI Agent or enter an SMeeting meeting. No dedicated telephony hardware is needed— a carrier SIP trunk or the customer’s existing IP-PBX connects directly.
Routing by called number, DTMF forwarding, and immediately rejecting the incoming call when the platform declines it require device gateway 1.3.5 or later.

How it works

The key is the agent_join callback: the gateway only hands the called number (no) and caller (name) to the platform. Your backend decides which channel the call joins and whether to answer it.

Three connection options

Dialing in to a meeting (entering the meeting ID after the call connects) needs an IVR to collect digits, which the customer’s PBX does before forwarding to the gateway; the gateway itself has no voice menu. AI calls don’t need digit collection—the conversation starts as soon as the call connects.

Gateway configuration

Configuration lives in the device gateway’s options.xml; restart the gateway after changes.

Listening and public address

Open the SIP port and RTP port range in the firewall; see Network and port requirements. When UseRtpAddress is true, the gateway sends voice back to the address the peer actually sends RTP from, so the peer can hear audio even behind NAT.

Which app incoming calls go to

The prefix matches the called number. For carrier numbers, use the number itself (or its number block) as the prefix.

Register to a carrier or PBX (optional)

Incoming-call IP allowlist (required for lines over the public internet)

Once the SIP port is exposed to the internet, it keeps receiving scanning calls. The gateway has a built-in automatic blocklist (an IP is blocked after more than 5 attempts in 30 seconds), so scans never reach the join flow. With a carrier line, the peer IP is fixed, so also turn on the allowlist to accept calls only from the line side:
Supports single IPs, IP ranges, and CIDR; IPv4 only.

Your backend: one channel per call

On the AI phone app, configure callbacks and subscribe to agent_join. When the callback arrives:
  1. Check whether it’s a phone call: type is 2 (SIP), and no is the called number
  2. Generate a unique channel name for the call, for example phone- plus a random string
  3. Call Get a channel join token with the uid from the callback to get the device’s sid
  4. Start the agent in the same channel asynchronously—don’t wait for the agent to join before returning
  5. Return {"code": 0, "data": "<sid>"} from the callback; any non-zero return rejects the call, and the gateway responds with 603
agent_join is a synchronous callback. The platform waits about 5 seconds, and a timeout counts as failure. Do slow work such as starting the agent and loading models after the callback returns.
For field descriptions and the response format, see the Event callbacks guide. The agent should only hear the phone’s audio: when the MCU is deployed, the platform publishes a composite stream (uid __mcu__) in the channel for SIP devices, and it includes the agent’s own voice. If the agent subscribes to all audio, filter by sender and feed only the device uid’s audio (the uid in the agent_join callback) into speech recognition; otherwise the agent hears itself and interrupts itself.

DTMF

When the gateway receives a keypress, it sends a custom message to the channel as the device: In the Python SDK, receive it with on_custom_msg, for example to hand it to a pipecat pipeline:

Hang-up

  • The caller hangs up: the device leaves the channel, and the agent ends the session when it receives the user-left event
  • Your side hangs up (for example, after the AI says goodbye): call the Remove a user from the channel endpoint to remove the device uid from the channel, and the platform tells the gateway to send BYE on the line

FAQ

For SIP conferencing endpoint setup, see SIP / H.323 endpoints; for the AI side, see pipecat integration.