delightful-airline-96880
03/13/2026, 12:30 PMtall-airline-16756
03/13/2026, 12:30 PMtall-airline-16756
03/13/2026, 12:30 PMsip.callID. You can read it from the participant’s attributes dictionary (for example inside your participant_connected handler) after the SIP participant has connected.
Example (async event handler):
async def async_on_participant_connected(participant: rtc.RemoteParticipant):
# Only SIP participants will have sip.* attributes
if participant.kind == rtc.ParticipantKind.PARTICIPANT_KIND_SIP:
call_id = participant.attributes.get('sip.callID', None)
if call_id:
<http://logger.info|logger.info>(f"SIP Call ID for {participant.identity}: {call_id}")
else:
<http://logger.info|logger.info>(f"No sip.callID present for {participant.identity}")
Notes and tips:
• Ensure the participant is a SIP participant (PARTICIPANT_KIND_SIP). Non-SIP participants will not have sip.* attributes.
• sip.callID is populated when the call is established through a SIP trunk.
• If you meant a custom tag (not the built-in sip.callID), tell me where that tag is stored (participant identity, metadata, or custom attributes) and I’ll show how to read it.
If you’d like, share a short snippet of your current event handler or how you’re receiving participants and I’ll adapt the example to match your code.
Sources: SIP Lifecycle Management Agent | LiveKit Documentationdelightful-airline-96880
03/13/2026, 12:31 PMtall-airline-16756
03/13/2026, 12:31 PMparticipant.kind == PARTICIPANT_KIND_SIP)?
• The exact code you use to read participant.attributes (or the event handler snippet).
• A small sample (sanitized if needed) of the participant.attributes dictionary you’re seeing right now — e.g. the keys/values that include the "CALL TAG".
• How that "CALL TAG" is being set: is it coming from your SIP gateway, a webhook, or are you setting it as a custom attribute/metadata somewhere in your app?
Quick checks you can try right away:
• Confirm participant kind:
print(participant.kind, participant.identity)
• Dump the attributes to inspect keys:
print(participant.attributes)
What to expect:
• If this is a SIP participant created through a SIP trunk, the SIP call ID should appear under sip.callID.
• If you see another key like callTag, call_tag, or a custom CALL TAG value, that means something in your flow (gateway or app) is adding a custom attribute instead of the Sip-specific sip.callID.
Send the code snippet and the attributes output and I’ll show exactly how to extract the SIP call ID or how to map your CALL TAG to the SIP callID.delightful-airline-96880
03/13/2026, 12:31 PMsip.callID -- this returns data like SCL_asdasd which is livekit autogenerated call tag, but I need SIP CALL IDtall-airline-16756
03/13/2026, 12:32 PMsip.callID values (like SCL_asdasd) but need the original SIP protocol Call-ID from the INVITE. I’ll address that and give practical next steps.
Short answer
• LiveKit’s sip.callID is a LiveKit-generated identifier. The original SIP protocol Call-ID header is not exposed as a documented participant attribute in the SDK, so you cannot read the raw SIP Call-ID directly from participant.attributes in the Python SDK.
Why this happens
• LiveKit assigns SIP participant attributes such as sip.callID, sip.callStatus, sip.phoneNumber, etc. The sip.callID you see is LiveKit’s internal tag, not the original SIP Call-ID header from the SIP INVITE.
What you can try next
• Check your SIP trunk/provider: Some providers can forward the original SIP Call-ID in a custom SIP header or map it into metadata. Ask your provider if they can include the original Call-ID in a header that can be forwarded to LiveKit or included in the gateway-to-app payload.
• Inspect webhook events: Enable and log LiveKit webhook payloads for SIP lifecycle events (e.g., participant_connected or sip_call_status). Log the full webhook body to see if the original Call-ID appears there (some gateway setups surface extra fields in webhooks even if SDK attributes do not).
• Log full participant/event objects: In your agent, log the entire participant or event object at connection time to check for undocumented fields:
async def async_on_participant_connected(participant: rtc.RemoteParticipant):
<http://logger.info|logger.info>(f"Full participant object: {participant}")
<http://logger.info|logger.info>(f"Attributes dump: {participant.attributes}")
If any additional SIP headers are present they may show up in the raw logged event.
• Map a custom attribute upstream: If your SIP gateway can read the SIP Call-ID, configure it to pass that value into a custom attribute (e.g., attributes['sip_orig_call_id']) when provisioning the participant into LiveKit. Then read that attribute from participant.attributes.
If the original SIP Call-ID is critical
• The documented LiveKit flows do not expose raw SIP headers. If your provider cannot forward the Call-ID and you cannot find it in webhooks or the raw participant object, the practical options are to:
◦ Get the SIP provider to include the Call-ID in a custom header or translated attribute that LiveKit receives.
◦ Use webhooks or your SIP gateway logs to correlate calls using the original Call-ID outside of LiveKit.
◦ Request that LiveKit expose raw SIP headers (if this is a feature you need, I can help prepare details and explain where it would be most useful in your flow).
If you want, share:
• A sanitized dump of the full participant.attributes or webhook payload you’re seeing.
• Which SIP provider/gateway you’re using (e.g., Twilio, Telnyx, etc.).
With that I can suggest the next concrete step (exact header name to request from the vendor, or where to look in the webhook payload).
Sources: SIP Lifecycle Management Agent | LiveKit Documentation | sip | livekit/livekit_composite | DeepWiki | Agents telephony integration | LiveKit Documentation