gentle-dream-14103
08/19/2025, 8:18 AMtall-airline-16756
08/19/2025, 8:18 AMtall-airline-16756
08/19/2025, 8:19 AMSIPDispatchRuleIndividual
.
• The rooms get named with the caller's phone number plus a little random suffix to keep things unique.
• You can also add a special prefix to the room name with the roomPrefix
option if you like.
async def create_individual_dispatch_rule():
lk_api = LiveKitAPI(url=livekit_url, api_key=livekit_api_key, api_secret=livekit_api_secret)
dispatch_rule_request = CreateSIPDispatchRuleRequest(
trunk_ids=[inbound_trunk.sip_trunk_id],
rule=SIPDispatchRule(
dispatch_rule_individual=SIPDispatchRuleIndividual(room_prefix="call")
),
)
dispatch_rule = await lk_api.sip.create_sip_dispatch_rule(dispatch_rule_request)
2. Rooms Based on Called Number:
• Create rooms based on the phone number the call was made to using SIPDispatchRuleCallee
.
• Rooms are named with the called phone number plus an optional prefix to keep things clear.
• If you want, you can add a random suffix for each caller by setting randomize
to true.
async def create_callee_dispatch_rule():
lk_api = LiveKitAPI(url=livekit_url, api_key=livekit_api_key, api_secret=livekit_api_secret)
dispatch_rule_request = CreateSIPDispatchRuleRequest(
trunk_ids=[inbound_trunk.sip_trunk_id],
rule=SIPDispatchRule(
dispatch_rule_callee=SIPDispatchRuleCallee(
room_prefix="number-",
randomize=False
)
),
)
dispatch_rule = await lk_api.sip.create_sip_dispatch_rule(dispatch_rule_request)
So, depending on what feels right for your setup—whether you want to pinpoint the exact number that was called (go with SIPDispatchRuleCallee
) or just want unique rooms for each caller (try SIPDispatchRuleIndividual
)—you've got options that make it easy to manage your calls.
Sources: SIP dispatch rule | LiveKit Docs | SIP dispatch rule | LiveKit Docs | Agents telephony integration | LiveKit Docs | Creating SIP Inbound Trunks and Dispatch Rules with Python SDKgentle-dream-14103
08/19/2025, 9:18 AMtall-airline-16756
08/19/2025, 9:19 AMSIPDispatchRuleCallee
with automatic room creation. This should make things a bit easier for you:
from livekit import api
from livekit.protocol import sip
async def create_callee_dispatch_rule():
# Initialize the LiveKit API client
livekit_api = api.LiveKitAPI(
url="your-livekit-url",
api_key="your-api-key",
api_secret="your-api-secret"
)
try:
# Create a SIPDispatchRuleCallee for automatic room creation
dispatch_rule_info = sip.SIPDispatchRuleInfo(
rule=sip.SIPDispatchRule(
dispatch_rule_callee=sip.SIPDispatchRuleCallee(
room_prefix="number-", # Optional prefix for room names
pin="", # Optional PIN protection
randomize=False # Set to True for unique rooms per caller
)
),
name="Callee Dispatch Rule",
metadata="Routes calls based on called number",
trunk_ids=[], # Empty means all trunks
hide_phone_number=False
)
# Create the dispatch rule
request = sip.CreateSIPDispatchRuleRequest(
dispatch_rule=dispatch_rule_info
)
response = await livekit_api.sip.create_sip_dispatch_rule(request)
print(f"Created dispatch rule: {response.sip_dispatch_rule_id}")
return response
finally:
await livekit_api.aclose()
# Usage example
import asyncio
async def main():
# Let's create that dispatch rule!
result = await create_callee_dispatch_rule()
print(f"Dispatch rule created with ID: {result.sip_dispatch_rule_id}")
if __name__ == "__main__":
asyncio.run(main())
Quick heads-up on the key settings:
• `room_prefix`: This adds a little prefix to your room name, like "number-".
• `randomize`: Flip this to True
if you want a random suffix, so each caller gets a unique room.
• `pin`: You can set an optional PIN if you want to add a bit of extra security.
So, with this setup, LiveKit will automatically create rooms based on the number being called. For example, if the called number is +15551234567
and you set room_prefix="number-"
, the room name will end up as number-+15551234567
. Pretty neat, right?
Sources: SIP dispatch rule | LiveKit Docs | livekit-protocol/livekit/protocol/sip.pygentle-dream-14103
08/19/2025, 9:22 AMtall-airline-16756
08/19/2025, 9:23 AMSIPDispatchRuleCallee
, here’s a friendly Python example to help you connect to and keep an eye on those rooms:
import asyncio
from livekit import api
class CalleeRoomHandler:
def __init__(self, api_key: str, api_secret: str, host: str):
self.livekit_api = api.LiveKitAPI(host, api_key, api_secret)
async def connect_to_callee_room(self, called_number: str, room_prefix: str = "number-"):
"""Connect to a room created by SIPDispatchRuleCallee"""
room_name = f"{room_prefix}{called_number}"
try:
# First, let's check if the room exists
rooms = await self.livekit_api.room.list_rooms(
api.ListRoomsRequest()
)
room_exists = any(room.name == room_name for room in rooms.rooms)
if room_exists:
print(f"Found callee room: {room_name}")
# Now, let's see who’s in the room
participants = await self.livekit_api.room.list_participants(
api.ListParticipantsRequest(room=room_name)
)
print(f"Participants in {room_name}: {len(participants.participants)}")
return room_name
else:
print(f"Room {room_name} does not exist yet")
return None
except Exception as e:
print(f"Oops! There was an error connecting to the callee room: {e}")
raise
# Here’s a quick example of how to use this
async def main():
handler = CalleeRoomHandler(
api_key="your_api_key",
api_secret="your_api_secret",
host="your_livekit_host"
)
# Let’s connect to a room using the called number
called_number = "+15105550123"
await handler.connect_to_callee_room(called_number)
if __name__ == "__main__":
asyncio.run(main())
Key Steps:
• Create the room name by combining the prefix and the called number (like number-+15105550123
).
• Check if the room exists using list_rooms
.
• Get the list of participants in the room with list_participants
.
This example shows you how to easily connect to and monitor rooms created by SIPDispatchRuleCallee
. If you have any questions or want to dive deeper, just let me know—I’m here to help!
Sources: telephony/sip_lifecycle.py | Dispatching agents | LiveKit Docs | SIP dispatch rule | LiveKit Docsgentle-dream-14103
08/19/2025, 9:29 AMtall-airline-16756
08/19/2025, 9:32 AMSIPDispatchRuleCallee
, connect to each one, listen to published tracks, and publish your own, here’s a friendly Python example to get you started:
import asyncio
from livekit import api, rtc
from typing import List
class SIPRoomManager:
def __init__(self, room_prefix: str = "number-", randomize: bool = False):
self.room_prefix = room_prefix
self.randomize = randomize
self.active_rooms = {}
def get_room_name(self, phone_number: str) -> str:
return f"{self.room_prefix}{phone_number}"
async def connect_to_callee_rooms(self, phone_numbers: List[str], identity_prefix: str = "bot"):
tasks = []
for phone_number in phone_numbers:
room_name = self.get_room_name(phone_number)
identity = f"{identity_prefix}-{phone_number.replace('+', '').replace('-', '')}"
task = asyncio.create_task(self.connect_and_handle_room(room_name, identity))
tasks.append(task)
await asyncio.gather(*tasks)
async def connect_and_handle_room(self, room_name: str, identity: str):
room = rtc.Room()
@room.on("track_subscribed")
def on_track_subscribed(track, publication, participant):
print(f"Track subscribed in {room_name}: {publication.sid}")
token = (
api.AccessToken()
.with_identity(identity)
.with_grants(api.VideoGrants(room_join=True, room=room_name))
.to_jwt()
)
try:
await room.connect("your-livekit-url", token)
print(f"Connected to room: {room_name}")
self.active_rooms[room_name] = room
await self.publish_tracks_to_room(room)
await self.monitor_room(room, room_name)
except Exception as e:
print(f"Oops, failed to connect to room {room_name}: {e}")
async def publish_tracks_to_room(self, room):
video_source = rtc.VideoSource(width=1280, height=720)
video_track = rtc.LocalVideoTrack.create_video_track("video", video_source)
audio_source = rtc.AudioSource(sample_rate=48000, num_channels=2)
audio_track = rtc.LocalAudioTrack.create_audio_track("audio", audio_source)
await room.local_participant.publish_track(video_track)
await room.local_participant.publish_track(audio_track)
print(f"Published tracks to room: {room.name}")
async def monitor_room(self, room, room_name):
try:
while room.isconnected():
await asyncio.sleep(1)
except Exception as e:
print(f"Room {room_name} monitoring error: {e}")
finally:
if room_name in self.active_rooms:
del self.active_rooms[room_name]
# Example usage
async def main():
room_manager = SIPRoomManager(room_prefix="number-", randomize=True)
phone_numbers = ["+15551234567", "+15559876543"]
await room_manager.connect_to_callee_rooms(phone_numbers, "sip-bot")
if __name__ == "__main__":
asyncio.run(main())
Here’s what this does for you:
• Creates room names based on the called number and a prefix, making it easy to organize.
• Connects to each room and listens for any tracks being published.
• Publishes your own audio and video tracks into the room.
• Keeps an eye on room activity and handles disconnections smoothly.
Hope this helps you manage multiple rooms effortlessly! If you have any questions or want to tweak this further, just give me a shout—I’m here to help!
Sources: SIP APIs | LiveKit Docs | SIP dispatch rule | LiveKit Docs | examples/room_example.py | test/lktest/livekit.go