Skip to content

SIP integrations

Status: Current | Last reviewed: 2026-08-11

How each carrier and contact-center integration reaches ai-orchestrator. They share the same downstream pipeline; what differs is the protocol they speak upstream.

The integrations

Integration Mode Service Protocol upstream Downstream
Genesys Cloud (BYOC) SIP carrier + AudioHook genesys-connector-go SIP via kamailio + AudioHook WebSocket media-proxy → ai-orchestrator
Genesys Cloud (server-side WebRTC) WebRTC agent genesys-agent-go WebRTC over WSS to Genesys direct gRPC to ai-orchestrator
Webex Contact Center (BYOVA) Custom voice agent webex-connector-go Webex BYOVA WebSocket media-proxy → ai-orchestrator
Five9 VoiceStream five9-voicestream-connector-go Five9 WebSocket media-proxy → ai-orchestrator
Amazon Connect KVS + emulator WebRTC connect-kvs-connector + ai-manager Reads Kinesis Video Stream; starts web contacts for emulator tests gRPC to ai-orchestrator / browser Chime audio
Salesforce SCV (BYOT) Telephony partner connect-scv-translator SCV API (HTTP + Socket.IO) dispatches to Genesys / Connect / demo

What they have in common

All produce frames that look like:

{
  conversation_id: <uuid>,
  audio: <PCM, sample rate, channels>,
  metadata: { caller_number, called_number, attributes... }
}

ai-orchestrator does not care which integration produced the frame. It looks up the agent for called_number → tenant → agent, builds a pipeline, and runs it.

They also share the CCaaS allow-list gate: every inbound call that carries CCaaS identification (Genesys org id, Amazon Connect source ARN) is validated by ari-controller against ccaas_pipeline_integrations — the agent must be explicitly enabled for the calling integration or the call is rejected (default-deny). Operators control this per agent from the publish dialog's CCaaS Availability section in ai-manager. See ari-controller.

What is different per integration

Genesys (BYOC)

SIP trunk into kamailio (5060/5061). Calls land in asterisk via PJSIP, hand off to ari-controller, bridge to media-proxy. AudioHook is a parallel realtime audio stream Genesys sends over WebSocket — used for transcription and analytics by some customers, terminated by genesys-connector-go for orchestration.

City dev environments require per-city TLS certs and a trunk ACL allowlisting the city's NAT egress IP. See city-dev-environments.md.

Genesys (server-side WebRTC)

A pure-Go service (genesys-agent-go) logs into Genesys as a WebRTC agent. It receives audio over WebRTC and forwards to ai-orchestrator. No SIP stack involved on our side. Used for outbound campaigns and WebRTC-only Genesys orgs.

UI for triggering: hidden at /agent-simulation in ai-manager.

Webex BYOVA

Webex Contact Center treats us as a "virtual agent". Audio arrives over their BYOVA WebSocket protocol. The Go connector terminates the protocol and forwards.

A separate service, webex-app-manager, handles OAuth lifecycle, datasource registration, and webhook delivery for the management plane.

Five9 VoiceStream

Five9 emits real-time audio over their VoiceStream WebSocket. The Go connector terminates and forwards.

Amazon Connect (KVS)

Connect publishes call audio to Kinesis Video Stream. connect-kvs-connector (Java) reads KVS, decodes, and forwards stereo PCM to ai-orchestrator.

For session metadata (DNIS, ANI, contact attributes), connect-session-start-lambda bridges Connect's Contact Flow to the connector.

The standalone ai-manager /emulator also supports an Amazon Connect WebRTC dial mode. That path does not dial PSTN or SIP. Instead, ai-manager lists contact flows for the selected Connect instance, calls StartWebRTCContact, and the browser joins the returned Chime meeting. Amazon Connect treats the session as an inbound web contact that starts the selected flow.

Configuration lives on an Amazon-sourced integration with the telephony capability:

  • source_arn is the Amazon Connect Instance ARN. Runtime helpers parse both the Connect instance ID and region from it.
  • Optional default_contact_flow_id to preselect a flow in the emulator.
  • Optional outbound_contact_flow_id, outbound_source_phone_number, outbound_queue_id for workflow-originated outbound calls (below).
  • Optional voice_connector_id — the Chime Voice Connector id, matched against the X-VoiceConnector-ID header when an arriving leg carries no Connect ARN.
  • Optional encrypted access_key_id, secret_access_key, and session_token. If omitted, the AWS SDK default credential chain is used. All three are secret: true, so each shows Leave blank to keep unchanged on edit; every reader resolves secrets first and falls back to config, so a row still holding a plaintext access_key_id keeps working. session_token is only for temporary STS credentials — it is read by every service that signs an AWS request, so a stale value breaks all of them at once when it expires.
  • In ai-manager, Discover AWS resources fills every discoverable field from the current credentials: Connect instances (source_arn), then — once an instance is resolved — contact flows (both default_contact_flow_id and outbound_contact_flow_id), STANDARD queues (outbound_queue_id), and claimed phone numbers (outbound_source_phone_number, stored as the E.164 number, not the phone-number id). Chime Voice Connectors (voice_connector_id) come from a separate hand-signed GET voice-chime.<region>.amazonaws.com/voice-connectors — the Chime SDK Voice signing name is chime, not chime-sdk-voice, and only some regions host that endpoint, so an integration elsewhere gets a warning naming the region instead of an opaque DNS failure. Each list is a separate IAM action and runs in its own try, so one missing permission empties one dropdown rather than all of them. Every field stays typable — the manual input under each dropdown always shows the stored value.

Outbound is the other direction, and Connect owns it. Connect exposes no trunk we can originate on, so a workflow's Start Conversation node does not call ari-controller for a Connect integration — it calls StartOutboundVoiceContact, and the contact flow transfers the answered leg back to us over the Chime Voice Connector, where it arrives as an ordinary inbound Connect call subject to the allow-list gate above. Only Genesys BYOC dials through our own SIP edge.

The emulator sends participant display name and contact attributes such as name, ani, caller_id_number, caller_id_name, and any custom keys entered by the tester. The backend validates attribute keys and payload size before forwarding them to Connect.

Salesforce SCV BYOT

Salesforce Service Cloud Voice (BYOT) treats us as a telephony partner. The SCV partner package is at sfdc/trueserve-scv/.

connect-scv-translator is the backend. Its dispatch layer routes to:

  • Genesys (for customers with Genesys carriers).
  • Amazon Connect (for customers with Connect).
  • Demo mode (in-house simulation for testing).

The dispatch is server-side based on TELEPHONY_PROVIDER env var; the SCV LWC sees a single API.

CES (Cloud Engagement Suite) session routing

Some integrations layer Google's Cloud Engagement Suite on top. CES gives a session ID per conversation. We map CES's Mcp-Session-Id to our internal conv_id via Redis (mcp:el_mapping:<ces_session>), TTL 1h.

There are two ways to bind tenant variables:

  1. REST runSession inputs[].variables — works once per session. Used at session start.
  2. OpenAPI tools with $context.session_id substitution — works every call. Used for runtime tool invocations.

See agent memory ces-session-variable-binding and ces-openapi-session-routing for the gotchas.

SIP trace logging

When a call fails, capture SIP traces:

docker exec -it tsf-local-kamailio kamcmd tm.t_dump_uac
docker exec -it tsf-local-asterisk asterisk -rx "pjsip set logger on"

For cluster deploys, see troubleshooting voice.

See also