miniature-nail-35141
07/10/2025, 4:18 PMtall-airline-16756
07/10/2025, 4:19 PMtall-airline-16756
07/10/2025, 4:20 PMcreate_sip_participant
, you should listen for participant events and attribute changes. The status changes to active
when the SIP call is connected. Here’s a Python example (similar approaches are available for other SDKs):
def on_participant_attributes_changed(changed_attributes, participant):
if participant.kind == rtc.ParticipantKind.PARTICIPANT_KIND_SIP:
if 'sip.callStatus' in changed_attributes:
if changed_attributes['sip.callStatus'] == 'active':
print('SIP participant is now connected')
Listen to the participant_attributes_changed
event and check for sip.callStatus == 'active'
to confirm the SIP connection. Additional SIP-specific attributes such as sip.callID
and sip.phoneNumber
are also available on the participant object for detailed monitoring.
For more complete code samples and details on SIP participant monitoring, refer to the LiveKit participant event and attribute documentation.
Sources: Making outbound calls | LiveKit Docs | SIP participant | LiveKit Docs | src/room/Room.ts | Core API primitives | LiveKit Docs | Making calls using SIP | LiveKit Docsminiature-nail-35141
07/10/2025, 4:24 PMtall-airline-16756
07/10/2025, 4:24 PMminiature-nail-35141
07/10/2025, 4:26 PMtall-airline-16756
07/10/2025, 4:26 PMdef on_participant_attributes_changed(changed_attributes, participant):
if participant.kind == rtc.ParticipantKind.PARTICIPANT_KIND_SIP:
if 'sip.callStatus' in changed_attributes:
if changed_attributes['sip.callStatus'] == 'active':
# SIP participant has connected
# Remove the local participant as requested
await livekit_api.room.remove_participant(
api.RoomParticipantIdentity(
room=your_room_name, # Use your actual room name here
identity=local_participant # Replace with the identity you want to remove
)
)
Quick heads up: Depending on how your event framework works, you might need to get a bit creative with async functions. No worries, though – you can easily schedule the coroutine if needed!
def on_participant_attributes_changed(changed_attributes, participant):
if participant.kind == rtc.ParticipantKind.PARTICIPANT_KIND_SIP:
if 'sip.callStatus' in changed_attributes:
if changed_attributes['sip.callStatus'] == 'active':
asyncio.create_task(livekit_api.room.remove_participant(
api.RoomParticipantIdentity(
room=your_room_name,
identity=local_participant
)
))
And just like that, you'll smoothly remove the specified local participant the moment the SIP participant connects. Easy peasy!miniature-nail-35141
07/10/2025, 4:27 PMtall-airline-16756
07/10/2025, 4:28 PM@room.on("participant_attributes_changed")
def on_participant_attributes_changed(changed_attributes: dict[str, str], participant: rtc.Participant):
print("Changed attributes:", changed_attributes)
print("Current participant attributes:", participant.attributes)
Quick Tips:
• changed_attributes
is like a snapshot of just what's different - only the attributes that recently changed.
• Want the full picture? participant.attributes
gives you all the current details about that participant.
• Pro tip: If an attribute gets deleted, it'll show up as an empty string in changed_attributes
.
This handy event handler is your friend for keeping track of who's doing what and making sure you've got all the info you need. Pretty cool, right?
Sources: Participant attributes and metadata | LiveKit Docs | livekit-rtc/livekit/rtc/room.py | callback.go | livekit-android-sdk/src/main/java/io/livekit/android/events/ParticipantEven... | Job lifecycle | LiveKit Docsminiature-nail-35141
07/10/2025, 4:33 PMtall-airline-16756
07/10/2025, 4:34 PMfrom livekit import rtc
room = rtc.Room()
Now comes the fun part - you can set up event listeners to catch all the cool things happening in your room. For example, tracking participant attribute changes is a breeze:
@room.on("participant_attributes_changed")
def on_participant_attributes_changed(changed_attributes: dict[str, str], participant: rtc.Participant):
print("Changed attributes:", changed_attributes)
If you're working with LiveKit Agents, it gets even simpler - the room
object is right there waiting for you as ctx.room
in your JobContext:
async def entrypoint(ctx):
room = ctx.room
With this setup, you'll be able to manage all your room and participant events like a pro. Trust me, it's going to make your development process so much smoother!
Sources: livekit-protocol/livekit/protocol/room.py | Inside a session | LiveKit Docs