LiveKit's SIP service (open-source on GitHub) acts as a bidirectional SIP-to-WebRTC bridge. It receives inbound SIP calls, converts them to WebRTC audio tracks in LiveKit rooms, and routes them to voice AI agent workers. This guide covers connecting every major open-source VoIP platform to LiveKit with production-ready configuration.
1. Architecture Overview
The LiveKit SIP integration follows a consistent pattern regardless of which PBX you use:
2. Platform Compatibility Matrix
| Platform | Method | Complexity | Inbound | Outbound | Notes |
|---|---|---|---|---|---|
| Twilio Elastic SIP | Direct SIP trunk | Easy | Best for cloud-first. No PBX needed. | ||
| Telnyx | Direct SIP trunk | Easy | Lower cost, good EU coverage. | ||
| Vonage / Nexmo | Direct SIP trunk | Easy | Strong APAC and EU presence. | ||
| Asterisk 20/21 | chan_pjsip SIP trunk | Medium | Route specific DIDs or all AI calls. | ||
| FreeSWITCH 1.10 | mod_sofia SIP gateway | Medium | ESL integration for event monitoring. | ||
| Kamailio 5.x | dispatcher module | Advanced | Load balancing + fraud detection before LiveKit. | ||
| OpenSIPS 3.x | SIP proxy routing | Advanced | Multi-tenant DID routing to LiveKit. | ||
| Any RFC-3261 PBX | Generic SIP trunk | Easy–Med | Any compliant SIP system works. |
3. Asterisk Configuration
Configure a PJSIP endpoint in Asterisk pointing to the LiveKit SIP service. Specific DID numbers are routed via dialplan:
pjsip.conf + extensions.conf
; pjsip.conf — Asterisk to LiveKit SIP trunk
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0
; LiveKit SIP service endpoint
[livekit-sip]
type=endpoint
transport=transport-udp
context=from-livekit
disallow=all
allow=ulaw,alaw,opus
aors=livekit-aor
outbound_auth=livekit-auth
[livekit-auth]
type=auth
auth_type=userpass
username=asterisk-trunk
password=your-strong-password
[livekit-aor]
type=aor
contact=sip:YOUR_LIVEKIT_SIP_HOST:5060
; ── Dialplan: route AI-destined calls to LiveKit ──
; extensions.conf
[from-internal]
; Route DID +15551234567 to LiveKit AI agent
exten => +15551234567,1,NoOp(Routing to LiveKit AI agent)
same => n,Dial(PJSIP/+15551234567@livekit-sip,,g)
same => n,Hangup()
; Route all calls starting with 1800 to LiveKit
exten => 1800.,1,NoOp(AI agent routing for 1800 numbers)
same => n,Dial(PJSIP/${EXTEN}@livekit-sip)
same => n,Hangup()4. FreeSWITCH Configuration
Define a FreeSWITCH SIP gateway pointing to LiveKit and add a dialplan extension. The mod_sofia profile handles media transcoding between PCMU/PCMA and Opus automatically:
external.xml gateway + dialplan
<!-- FreeSWITCH — sip_profiles/external.xml gateway to LiveKit -->
<gateway name="livekit-sip">
<param name="realm" value="YOUR_LIVEKIT_SIP_HOST"/>
<param name="proxy" value="YOUR_LIVEKIT_SIP_HOST:5060"/>
<param name="username" value="freeswitch-trunk"/>
<param name="password" value="your-strong-password"/>
<param name="from-user" value="freeswitch-trunk"/>
<param name="from-domain" value="YOUR_LIVEKIT_SIP_HOST"/>
<param name="register" value="false"/>
<param name="transport" value="udp"/>
</gateway>
<!-- dialplan/default.xml — route AI calls to LiveKit -->
<extension name="livekit-ai-route">
<condition field="destination_number" expression="^(+1800d+)$">
<action application="bridge" data="sofia/gateway/livekit-sip/$1"/>
</condition>
</extension>5. LiveKit SIP Trunk Setup via Python API
Create the inbound trunk, dispatch rule, and outbound trunk using the LiveKit Python SDK. Run this once during your infrastructure setup:
setup_sip.py — Complete trunk configuration
import asyncio
from livekit import api
async def setup_sip_integration():
lk_api = api.LiveKitAPI(
url="wss://YOUR-LIVEKIT-SERVER",
api_key="YOUR_API_KEY",
api_secret="YOUR_API_SECRET",
)
# 1. Create inbound SIP trunk — accepts calls FROM Asterisk
inbound_trunk = await lk_api.sip.create_sip_inbound_trunk(
api.CreateSIPInboundTrunkRequest(
trunk=api.SIPInboundTrunkInfo(
name="Asterisk-to-LiveKit",
numbers=["+15551234567", "+15559876543"],
allowed_addresses=["203.0.113.10"], # Asterisk server IP
auth_username="asterisk-trunk",
auth_password="your-strong-password",
)
)
)
print(f"Inbound trunk created: {inbound_trunk.sip_trunk_id}")
# 2. Create dispatch rule — route DID to AI agent room
dispatch_rule = await lk_api.sip.create_sip_dispatch_rule(
api.CreateSIPDispatchRuleRequest(
rule=api.SIPDispatchRule(
dispatch_rule_individual=api.SIPDispatchRuleIndividual(
room_prefix="ai-agent-",
),
trunk_ids=[inbound_trunk.sip_trunk_id],
)
)
)
print(f"Dispatch rule: {dispatch_rule.sip_dispatch_rule_id}")
# 3. Create outbound SIP trunk — LiveKit calls OUT through Asterisk
outbound_trunk = await lk_api.sip.create_sip_outbound_trunk(
api.CreateSIPOutboundTrunkRequest(
trunk=api.SIPOutboundTrunkInfo(
name="LiveKit-to-Asterisk-Outbound",
address="203.0.113.10:5060", # Asterisk server
numbers=["+15559876543"],
auth_username="livekit-outbound",
auth_password="outbound-password",
transport=api.SIPTransport.SIP_TRANSPORT_UDP,
)
)
)
print(f"Outbound trunk: {outbound_trunk.sip_trunk_id}")
asyncio.run(setup_sip_integration())6. SIP REFER — Transfer Caller Back to PBX
When the AI agent cannot resolve a query, transfer the caller to a human agent queue in Asterisk/FreeSWITCH via SIP REFER:
transfer.py — SIP REFER to Asterisk queue
# Transfer caller from LiveKit agent back to Asterisk queue
from livekit import api
async def transfer_to_human_agent(room_name: str, caller_identity: str):
lk_api = api.LiveKitAPI(
url="wss://YOUR-LIVEKIT-SERVER",
api_key="YOUR_API_KEY",
api_secret="YOUR_API_SECRET",
)
# SIP REFER — transfer the phone call to Asterisk queue extension
await lk_api.sip.transfer_sip_participant(
api.TransferSIPParticipantRequest(
room_name=room_name,
participant_identity=caller_identity,
# Route to Asterisk: the SIP REFER points to your PBX queue
transfer_to="sip:[email protected]",
play_dialtone=True, # Play ringback tone while transferring
)
)7. Kamailio / OpenSIPS as Front-End Proxy
For production deployments, place Kamailio or OpenSIPS in front of LiveKit to handle fraud detection, load balancing, and multi-tenant routing:
Kamailio Dispatcher to LiveKit
- 1.All inbound SIPs hit Kamailio
- 2.pike module blocks rate-exceeded IPs
- 3.Topology hiding strips internal IPs
- 4.dispatcher module selects LiveKit SIP
- 5.Human calls → Asterisk cluster
OpenSIPS Multi-Tenant Routing
- 1.DID prefix 1800 → AI agent room prefix 'ai-support'
- 2.DID prefix 1888 → AI agent room prefix 'ai-sales'
- 3.All other DIDs → Asterisk PBX cluster
- 4.Rate limiting via pike module
- 5.STIR/SHAKEN verification before routing
8. Production Security Checklist
IP allowlisting on LiveKit inbound trunk — restrict to known PBX/carrier IPs
SIP digest authentication (username + password) on all trunks
TLS for SIP signalling (port 5061) in production
SRTP for media encryption — enforced via trunk config
LiveKit SIP service behind firewall — not directly exposed to internet
Rate limiting at Kamailio/OpenSIPS layer before LiveKit
Prometheus alerts for SIP registration failures and call failure rates
CDR logging for all SIP legs — LiveKit webhooks + Asterisk CDR