polite-oil-10264
02/25/2026, 9:12 PMtall-airline-16756
02/25/2026, 9:12 PMtall-airline-16756
02/25/2026, 9:13 PMparticipant_kinds parameter when you start an agent session.
• If you want an agent to process audio from a specific participant, you can set a fixed participant identity in the RoomIO constructor so the agent processes that participant’s audio stream.
If you want next steps
• Do you want the Python multi‑agent example link and a short walkthrough of its key files?
• Or do you want help configuring participant_kinds or RoomIO for a specific scenario (e.g., agents + SIP callers, or one agent monitoring multiple live participants)?
Tell me which option fits your use case and I’ll provide the relevant example snippets and configuration guidance.
Sources: Examples | livekit/livekit_composite | DeepWiki | How to Test Your Agent Using Another Agent | LiveKit | How to set a fixed participant for agent audio processing | LiveKitpolite-oil-10264
02/25/2026, 9:24 PMtall-airline-16756
02/25/2026, 9:24 PMparticipant_kinds and RoomIO configuration.)
5. Any preferred LLM/STT/TTS providers to include in the sample (for example OpenAI for LLM, Whisper for STT, etc.)?
6. Do you prefer asyncio style examples and any platform constraints (Linux/macOS)?
If you want a quick start now, here’s a minimal multi‑agent Python skeleton you can use while you answer the questions above. It shows how to configure an agent session to listen to other agents using `RoomOptions.participant_kinds`:
from livekit import rtc
from livekit.agents import JobContext, AgentSession, RoomOptions
@server.rtc_session(agent_name="evaluation-agent")
async def entrypoint(ctx: JobContext):
await ctx.connect()
session = AgentSession(
# add your stt/llm/tts/vad configs here
)
await session.start(
agent=EvaluationAgent(),
room=ctx.room,
room_options=RoomOptions(
participant_kinds=[
rtc.ParticipantKind.PARTICIPANT_KIND_AGENT,
],
),
)
What I’ll provide next after you answer the questions:
• A complete, runnable example (minimal text OR audio) with required package imports and setup steps.
• Guidance on configuring participant_kinds and RoomIO if you need the agent to process audio from a specific participant identity.
• Notes on running multiple agents in one process vs separate processes.
Tell me your preferences for items 1–6 and I’ll return the tailored example and run instructions.
Sources: How to Test Your Agent Using Another Agent | LiveKitpolite-oil-10264
02/25/2026, 9:32 PMtall-airline-16756
02/25/2026, 9:32 PMRoomIO (or equivalent) to subscribe to participant audio and identify which participant each audio segment belongs to,
◦ Uses VAD to detect speech boundaries per participant,
◦ Sends speech segments to STT, tags transcripts with participant identity, forwards text to an LLM for response generation,
◦ Synthesizes the LLM reply with TTS and plays it back into the room so the agent can “speak” naturally.
1. Key configuration details:
◦ RoomOptions.participant_kinds to ensure the agent listens to human participants (and agents if desired),
◦ How to set a participant identity (if you want the agent to monitor a specific user),
◦ How to run multiple agents (single process vs separate processes/containers).
1. Notes about reliability and latency trade-offs and suggested parameters (short VAD timeouts, chunk size for STT, etc.).
If you’re ready, tell me:
• Full audio or minimal text example?
• Preferred providers (or “use placeholders”)?
I’ll then return the complete Python example and step‑by‑step run instructions.polite-oil-10264
02/25/2026, 9:35 PMtall-airline-16756
02/25/2026, 9:36 PM.env with keys:
LIVEKIT_URL=<your_livekit_url>
LIVEKIT_API_KEY=<your_api_key>
LIVEKIT_API_SECRET=<your_api_secret>
DEEPGRAM_API_KEY=<your_deepgram_key>
OPENAI_API_KEY=<your_openai_key>
ELEVENLABS_API_KEY=<your_elevenlabs_key>
2) Install dependencies:
pip install "livekit-agents[silero,deepgram,openai,elevenlabs]" python-dotenv
3) Save this as multi_agent.py and run python multi_agent.py dev (or console for a local console mode).
Code (complete example):
import asyncio
import logging
from dotenv import load_dotenv
import os
from livekit.agents import (
AgentServer,
JobContext,
AgentSession,
Agent,
)
from livekit.plugins import silero, deepgram, openai, elevenlabs
# Load env
load_dotenv()
# Logging
logging.basicConfig(level=<http://logging.INFO|logging.INFO>)
logger = logging.getLogger("multi-voice-agent")
# Create the agent server
server = AgentServer()
# Pre-warm VAD to reduce latency
def prewarm(proc):
proc.userdata["vad"] = silero.VAD.load()
server.setup_fnc = prewarm
class MultiParticipantAgent(Agent):
def __init__(self):
super().__init__(
instructions=(
"You are a friendly assistant in a group conversation. "
"When a participant speaks, transcribe and respond naturally. "
"Address participants by name if available and keep responses concise."
)
)
async def on_enter(self):
# Optional greeting when the agent joins the room
await self.session.say("Hi everyone — I'm here to help. Feel free to speak.")
async def on_participant_speaking(self, participant_id, transcript, final):
"""
Hook-like conceptual handler. The AgentSession below will route
transcripts to the agent's LLM. This method illustrates intent:
you can implement participant-aware behavior by inspecting `participant_id`.
"""
# You can implement participant-specific logic here
<http://logger.info|logger.info>("Spoke: %s final=%s text=%s", participant_id, final, transcript)
# Entrypoint for rtc session
@server.rtc_session(agent_name="multi-voice-agent")
async def entrypoint(ctx: JobContext):
ctx.log_context_fields = {"room": ctx.room.name}
# Build the session with full pipeline:
session = AgentSession(
# VAD: preloaded instance (on-device Silero) for per-participant speech segmentation
vad=ctx.proc.userdata.get("vad"),
# STT: Deepgram real-time transcription (interim + final)
stt=deepgram.STT(api_key=os.environ.get("DEEPGRAM_API_KEY"), model="nova-2-general"),
# LLM: OpenAI responses (gpt-4o or similar)
llm=openai.responses.LLM(api_key=os.environ.get("OPENAI_API_KEY"), model="gpt-4o"),
# TTS: ElevenLabs to synthesize replies
tts=elevenlabs.TTS(api_key=os.environ.get("ELEVENLABS_API_KEY"), voice="21m00Tcm4TlvDq8ikWAM"),
# Behavior flags:
preemptive_generation=True, # can start generating before user finishes if helpful
allow_interruptions=False, # prevents the agent from interrupting a speaker
)
agent = MultiParticipantAgent()
# Start the session — the session will:
# - subscribe to participant audio streams
# - use VAD to find speech segments per participant
# - send segments to STT tagged with participant identity
# - forward transcript to the agent/LLM
# - generate TTS and publish audio when replying
await session.start(agent=agent, room=ctx.room)
# Connect the server/job context (lifecycle)
await ctx.connect()
if __name__ == "__main__":
# Run the server in "dev" mode to connect to real LiveKit rooms.
# Use "console" to simulate a simple local test.
from livekit.agents import cli
cli.run_app(server)
How the example detects and attributes speech:
• Silero VAD segments incoming audio and indicates speech activity per participant stream.
• AgentSession subscribes to each participant’s audio and tags STT requests with that participant’s identity, so transcripts are associated with who spoke.
• The LLM receives transcripts (with participant context) and you can instruct it to include participant names or reference turn-taking in prompts.
Tuning tips:
• VAD sensitivity and pre-warming: Preload VAD in the process to reduce first-response latency.
• STT chunking: Use short chunks (200–700 ms) for low-latency interim transcripts; ensure finalization for accurate context before replying.
• Turn-taking: Keep allow_interruptions=False for polite behavior; set preemptive_generation=True if you want the agent to prepare replies while the speaker is finishing.
• Participant identity: If participants provide names as metadata, include that when building LLM prompts so replies can address them personally.
Next steps / I can help with:
• Swap the providers for Whisper/OpenAI STT, another LLM, or a different TTS — tell me which and I’ll update the example.
• Add explicit prompt templates showing how to include participant names, last N utterances, or conversation history for context.
• Show a sample run demonstrating how transcripts arrive tagged with participant IDs and how the agent responds.
Would you like me to:
• Provide a variant using Whisper (OpenAI) STT, or
• Expand the example to show the actual prompt template passed to the LLM that includes per-participant history?
Tell me which and I’ll send the updated code.
Sources: Agents (Python) | livekit/livekit_composite | DeepWiki | An open source stack for real-time multimodal AI | Simple Call Answering Agent | LiveKit Documentation | Pipeline Translator Agent | LiveKit Documentation | An open source stack for real-time multimodal AIpolite-oil-10264
02/25/2026, 11:01 PMtall-airline-16756
02/25/2026, 11:02 PMrtc.ParticipantKind.PARTICIPANT_KIND_STANDARD.
◦ If you create RoomIO manually, start it with participant_kinds=[rtc.ParticipantKind.PARTICIPANT_KIND_STANDARD].
1. Preload VAD and attach it so you can detect speech per participant stream.
2. Add room event handlers:
◦ On participant_started_speaking (or on a data-track event / audio activity event), call await room_io.set_participant(participant.identity) if that participant is different from the current linked one.
◦ Optionally add a debounce or grace period so the agent doesn’t flip focus too fast.
1. Keep allow_interruptions=False if you want polite behavior; set to True if you want preemptive interruption.
Example snippet (adapt to your code):
# after creating session
room_io = RoomIO(session, room=ctx.room)
# start RoomIO so it can subscribe to STANDARD participants
await room_io.start(participant_kinds=[rtc.ParticipantKind.PARTICIPANT_KIND_STANDARD])
# handler example (pseudo)
@ctx.room.on("participant_speaking")
async def on_speaking(participant_id):
if participant_id != room_io.linked_participant.identity:
await room_io.set_participant(participant_id)
If you prefer the diarization path
• Use an STT plugin/provider that supports speaker diarization (Speechmatics or similar).
• Send the mixed audio to that STT and receive transcripts with speaker labels.
• Use those labels in prompts (e.g., "Participant Alice said: ...") so the LLM can generate appropriate replies.
Next steps I can help with
• I can update your existing agent code to the switch‑focus pattern (I’ll provide a concrete patch that integrates RoomIO.set_participant and VAD‑driven switching). Please paste the agent file you’re running or tell me which example you started from.
• Or I can provide a diarization example using a specific STT provider (Speechmatics or others). Tell me which STT provider you prefer and I’ll return code showing how to send mixed audio and parse diarized transcripts.
Which path do you want to try first — switch‑focus (lower latency) or diarization (true multi‑speaker)? Also paste the current agent code (or tell me which example file you’re running) and I’ll give you an updated, runnable snippet you can drop in immediately.
Sources: Agent session | LiveKit Documentation | How to set a fixed participant for agent audio processing | LiveKit | TTS Comparison | LiveKit Documentation | Speechmatics STT plugin guide | LiveKit Documentation | How to Test Your Agent Using Another Agent | LiveKit