rapid-honey-43838
02/28/2026, 10:04 AMtall-airline-16756
02/28/2026, 10:04 AMtall-airline-16756
02/28/2026, 10:04 AMnumbers.
Good news: you can create multiple inbound trunks without numbers as long as each trunk is unique in another configurable property — specifically allowed_addresses. Create each SIPInboundTrunkInfo with a distinct allowed_addresses list (and a unique name if helpful). That satisfies the uniqueness check and gives you IP-based separation for inbound traffic.
Recommended approach (high level):
• For each logical trunk you want, set:
◦ `name`: a unique identifier (e.g., "trunk-region-a")
◦ `numbers`: omit or leave empty if you don’t need phone numbers
◦ `allowed_addresses`: list of IPs you want that trunk to accept
• Create the trunks via the LiveKit API or CLI using create_sip_inbound_trunk (or equivalent).
Example (Python-like pseudocode):
trunk1 = create_sip_inbound_trunk({
"name": "Trunk-Region-A",
"numbers": [], # empty
"allowed_addresses": ["203.0.113.10", "203.0.113.11"]
})
trunk2 = create_sip_inbound_trunk({
"name": "Trunk-Region-B",
"numbers": [], # empty
"allowed_addresses": ["198.51.100.20", "198.51.100.21"]
})
A few quick notes and checks:
• Ensure each trunk’s allowed_addresses lists are disjoint (no overlapping IPs) so each trunk only accepts its intended sources.
• If you run into a uniqueness error when creating trunks, make sure name and any other trunk fields aren’t identical between trunks.
• Once created, reference these trunks in your routing/dispatch rules as needed.
If you want, I can:
• Show the exact API request payload for the language/SDK you’re using (Python, Go, CLI, etc.)
• Help verify why a trunk creation may be failing if you share the error message or the request payload you tried. Which SDK or method are you using to create the trunks? Sources: sip | livekit/livekit_composite | DeepWiki | Python SDKs | livekit/livekit_composite | DeepWiki | How to do call transfers with Five9 | LiveKit | examples/voice_agents | livekit/livekit_composite | DeepWikirapid-honey-43838
02/28/2026, 10:21 AMtall-airline-16756
02/28/2026, 10:21 AMsip.callStatus, sip.phoneNumber, and sip.trunkID.
• How it works: LiveKit will POST signed event payloads to your webhook endpoint whenever SIP-related events occur.
• When to use: You need reliable delivery, logging, or processing outside of an active room (e.g., billing, analytics, CRM updates).
• Implementation notes:
◦ Configure your webhook URL in your LiveKit settings (or server config).
◦ Verify the signature on incoming webhooks using your API secret.
◦ Inspect participant attributes in the webhook payload to read SIP fields (e.g., sip.callStatus).
2) In-room event listeners / agent listeners — real-time, in-process events
• What you get: Immediate events in the room such as participant_connected, participant_disconnected, and participant_attributes_changed. You can read SIP-specific attributes on the participant (including call status transitions like dialing, ringing, active, hangup, automation).
• How it works: An agent or backend connected to the room registers handlers for room/participant events and reacts immediately (logging, routing, updating UI, etc.).
• When to use: You need low-latency handling while the call is active (e.g., live routing, IVR automation, agent desktop updates).
• Implementation notes:
◦ Listen for participant connect/disconnect and attributes-changed events.
◦ Check participant.kind == "SIP" (or the SDK’s SIP participant kind) and read participant.attributes["sip.callStatus"], sip.phoneNumber, etc.
Which should you choose?
• Choose webhooks if you need durable, out-of-room notifications and easy integration with web services.
• Choose in-room listeners if you need immediate, live reactions while the call/room is running.
• You can use both: webhooks for durable audit/logging and in-room listeners for real-time behavior.
If you want, I can:
• Show an exact webhook handler example in the language you use (Python/Node/Go) and how to verify signatures.
• Show sample code for in-room event listeners for the SDK/agent you’re using (Python, JS, or the Agent framework).
Which environment/SDK do you want the example for, and are you aiming for webhooks, in-room listeners, or both?
Sources: sip | livekit/livekit_composite | DeepWiki | SIP Lifecycle Management Agent | LiveKit Documentation | Best practices for managing webhook event streams | LiveKit | Python SDKs | livekit/livekit_composite | DeepWikirapid-honey-43838
02/28/2026, 10:23 AMparticipant_attributes_changed published and how can I consume it ?tall-airline-16756
02/28/2026, 10:23 AMparticipant_attributes_changed event is published and how to consume it — I’ll explain both clearly and show how to use it for SIP call state updates.
When the event is published
• The event is fired whenever a participant's attributes are updated. That includes:
◦ Server-side updates (e.g., calling the server API to update participant attributes).
◦ Client SDK calls to set attributes (for that participant or others, as permitted).
◦ SIP lifecycle updates (attributes such as sip.callStatus, sip.phoneNumber, sip.trunkID being changed as the call progresses).
• The event is propagated asynchronously. In distributed deployments, attribute updates may arrive slightly later to participants connected to different SFU nodes, so rely on the event rather than immediate property reads to observe changes.
What the event delivers
• The handler receives a map/dictionary of only the attributes that changed (not the full attribute set).
• Typical SIP attribute keys you might see: sip.callStatus (values like dialing, ringing, active, hangup, automation), sip.phoneNumber, sip.trunkID.
• Always check participant.kind (or SDK-specific participant type) to ensure you’re processing SIP participants.
How to consume it
1) In a backend agent or server process (Python example)
@ctx.room.on("participant_attributes_changed")
def on_participant_attributes_changed(changed_attributes: dict, participant):
# Only the changed attributes are provided
if participant.kind == "SIP":
if "sip.callStatus" in changed_attributes:
new_status = changed_attributes["sip.callStatus"]
print(f"SIP participant {participant.identity} status -> {new_status}")
if "sip.phoneNumber" in changed_attributes:
print(f"Phone number updated: {changed_attributes['sip.phoneNumber']}")
2) In a web client (TypeScript / JS example)
room.on(RoomEvent.ParticipantAttributesChanged, (changedAttributes, participant) => {
if (participant.kind === "SIP" && changedAttributes["sip.callStatus"]) {
console.log(`SIP call status changed: ${changedAttributes["sip.callStatus"]}`);
}
});
3) Best practices and notes
• Use the event handler rather than polling participant.attributes, because the event provides the precise changes and avoids race conditions.
• Expect asynchronous propagation; your handler should tolerate short delays.
• If you need the current full attribute map after a change, read participant.attributes inside the handler (it will reflect latest state after the event).
• For SIP workflows, react to sip.callStatus transitions (for example, perform routing or UI updates on ringing → active → hangup).
If you want, I can:
• Provide the exact code for the SDK you’re using (JS, Python, Go, or an Agent framework).
• Show a small end-to-end example that listens for sip.callStatus changes and triggers a follow-up action (e.g., update a CRM, notify an agent UI).
Which SDK/environment should I tailor the example to?
Sources: Handling asynchronous metadata updates in LiveKit | LiveKit | Server-side | livekit/livekit_composite | DeepWiki | How to detect when an agent has finished speaking | LiveKit | SIP Lifecycle Management Agent | LiveKit Documentation | Job lifecycle | LiveKit Documentationrapid-honey-43838
02/28/2026, 10:38 AMtall-airline-16756
02/28/2026, 10:38 AMrapid-honey-43838
02/28/2026, 10:48 AMtall-airline-16756
02/28/2026, 10:48 AMrapid-honey-43838
02/28/2026, 1:49 PMtall-airline-16756
02/28/2026, 1:50 PMrapid-honey-43838
02/28/2026, 2:05 PM