best-battery-56004
12/22/2025, 8:37 PMctx.wait_for_participant() doesn't wait for the actual user (standard or sip skin) to join.tall-airline-16756
12/22/2025, 8:38 PMtall-airline-16756
12/22/2025, 8:38 PMctx.wait_for_participant() to return too early.
Short answer: keep calling ctx.wait_for_participant() but filter out automated participant kinds (egress/agent) or check participant identity/metadata until you see a STANDARD or SIP user you expect.
Example pattern (conceptual Python):
participant = await ctx.wait_for_participant()
while participant.kind in (rtc.ParticipantKind.PARTICIPANT_KIND_EGRESS,
rtc.ParticipantKind.PARTICIPANT_KIND_AGENT):
participant = await ctx.wait_for_participant()
# Now participant is a user (STANDARD or SIP) — or add further checks for identity/metadata
Notes and options:
• If you need to match a specific user, also verify participant.identity or metadata and continue waiting until it matches.
• For SIP participants, treat SIP as a valid user kind (not egress).
• If your ops listener can be distinguished by identity or metadata, checking that is more robust than relying only on kind.
Would you like a version of the snippet in a different language or guidance on checking identity/metadata for your specific setup?
Sources: Job lifecycle | LiveKit docs | Using Noise Cancellation for SIP and WebRTC Participantsbest-battery-56004
12/22/2025, 8:42 PMwhile cause an infinite loop? Can I use kind= argument?tall-airline-16756
12/22/2025, 8:42 PMwhile loop can loop forever if no matching participant ever joins.
Use the kind= argument on ctx.wait_for_participant() instead — it waits asynchronously for a matching participant (and resolves immediately if one is already present) and avoids spinning:
# Wait only for a STANDARD participant
participant = await ctx.wait_for_participant(kind=rtc.ParticipantKind.STANDARD)
# Or wait for either STANDARD or SIP (example pattern)
participant = await ctx.wait_for_participant(kind=rtc.ParticipantKind.STANDARD)
if not participant:
participant = await ctx.wait_for_participant(kind=rtc.ParticipantKind.SIP)
Recommendations:
• Prefer kind= to filter automated participants like `EGRESS`/`AGENT`.
• If you need a specific identity or metadata, after wait_for_participant(kind=...) verify participant.identity or metadata and call wait_for_participant() again if it doesn't match.
• Add a timeout or cancellation around the await if there’s any chance no matching participant will ever join, to avoid waiting indefinitely.
Would you like a short example that waits for either STANDARD or SIP with a timeout?
Sources: Job lifecycle | LiveKit docs | Rooms, participants, and tracks | LiveKit docs | Managing participants | LiveKit docs