polite-oil-10264
12/16/2025, 4:14 PMtall-airline-16756
12/16/2025, 4:14 PMtall-airline-16756
12/16/2025, 4:15 PMparticipant_identity when starting the session. Omitting that option lets the agent receive audio from multiple participants.
• Example (RoomIO):
await session.start(
room=ctx.room,
agent=MyAgent(),
room_options=room_io.RoomOptions(audio_input=True)
)
1. Agent audio output is broadcast by default
• The agent’s TTS is published as a track in the room and is available to all participants unless subscriptions/permissions restrict it. No extra setting is required for the agent to speak to everyone.
1. If you need agents to hear each other (multi-agent rooms)
• Include AGENT in participant_kinds so agents process other agents’ audio:
RoomInputOptions(
participant_kinds=[
rtc.ParticipantKind.PARTICIPANT_KIND_STANDARD,
rtc.ParticipantKind.PARTICIPANT_KIND_AGENT,
],
)
1. Optional: customize behavior by speaker identity
• Use events like user_input_transcribed or user_state_changed to inspect participant.identity and tailor responses when needed.
If you’d like, tell me which SDK/language you’re using (Python, Node.js, etc.) and whether multiple agents are in the room — I can provide a concise code example for your setup.
Sources: Agent session | LiveKit docs | Realtime media | LiveKit Docs | How to test your agent using another agent | How to Enable Agent-to-Agent Speech Detection in LiveKitpolite-oil-10264
12/16/2025, 4:16 PMtall-airline-16756
12/16/2025, 4:16 PMpolite-oil-10264
12/16/2025, 4:18 PMtall-airline-16756
12/16/2025, 4:19 PMsession.say() for the chosen participant.
Notes:
• Omit participant_identity so the agent listens to everyone.
• Use RoomInputOptions.participant_kinds if you need agents to hear other agents.
• Replace STT/LLM/TTS initializers with your preferred implementations.
from livekit import rtc
from livekit.agents import cli, JobContext, WorkerOptions
from livekit.agents.voice import VoiceAssistant
from livekit.agents.voice.room_io import RoomIO, RoomInputOptions
import asyncio
class SelectorAgent:
"""
Listens to all participants and responds only to the participant
matching custom criteria (e.g., identity or keyword).
"""
def __init__(self, session: VoiceAssistant = None):
self.session = session
async def decide_whether_to_respond(self, text: str, participant_identity: str) -> bool:
# Example decision logic:
# - respond if identity equals "target_user"
# - or if text contains "hey bot"
if participant_identity == "target_user":
return True
if "hey bot" in (text or "").lower():
return True
return False
async def on_user_transcribed(self, evt):
"""
Handler for user transcription events. The event object typically
contains text and participant metadata — adjust field names to match your SDK version.
"""
user_text = getattr(evt, "text", None) or getattr(evt, "transcript", None) or ""
participant_identity = getattr(evt, "participant_identity", None) or "unknown"
should_respond = await self.decide_whether_to_respond(user_text, participant_identity)
if not should_respond:
# ignore
return
# Generate or send a reply targeted to the chosen participant.
reply_text = f"Hello {participant_identity}, I heard you: \"{user_text}\""
# Publish TTS reply into the room so everyone can hear; session.say() publishes the agent's audio
await self.session.say(reply_text)
async def entrypoint(ctx: JobContext):
# Connect and auto-subscribe to audio so the agent hears participants
await ctx.connect(auto_subscribe=rtc.AutoSubscribe.AUDIO_ONLY)
# Listen to all participant kinds (optional; include AGENT if agents should hear other agents)
room_input_options = RoomInputOptions(
participant_kinds=[
rtc.ParticipantKind.PARTICIPANT_KIND_STANDARD,
rtc.ParticipantKind.PARTICIPANT_KIND_SIP,
rtc.ParticipantKind.PARTICIPANT_KIND_AGENT,
]
)
# Create RoomIO without specifying participant_identity (listens to all)
room_io = RoomIO(ctx.room, input_options=room_input_options)
# Create assistant (use your STT/LLM/TTS implementations)
assistant = VoiceAssistant(
vad=await rtc.VAD.load(),
stt=await rtc.STT.create(),
llm=await rtc.LLM.create(),
tts=await rtc.TTS.create(),
)
# Create session bound to room_io
session = assistant.create_session(room=ctx.room, room_io=room_io)
await session.start()
# Attach selector logic
selector = SelectorAgent(session=session)
# Hook into transcription events. Adjust event registration to match your SDK:
# Many SDKs expose an event like `on_user_speech` or `on_transcription`.
# Here we assume session.context.on("user_speech", handler) style; adapt if needed.
try:
session.context.on("user_speech", selector.on_user_transcribed) # type: ignore
except Exception:
# Fallback: if the SDK exposes a different event name, adapt accordingly
session.context.on("user_input_transcribed", selector.on_user_transcribed) # type: ignore
# Keep running
await ctx.wait_for_shutdown()
if __name__ == "__main__":
cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint))
If you want, I can:
• Convert this to a minimal runnable sample tailored to your STT/LLM/TTS choices.
• Show how to respond privately to a single participant (instead of broadcasting). Sources: How to test your agent using another agent | Agents Framework | livekit/livekit_composite | DeepWiki | Job lifecycle | LiveKit docs | Rooms, participants, and tracks | LiveKit docs | How to set a fixed participant for agent audio processing