microscopic-dress-75199
12/18/2025, 2:24 AMtall-airline-16756
12/18/2025, 2:24 AMtall-airline-16756
12/18/2025, 2:24 AMmicroscopic-dress-75199
12/18/2025, 2:24 AMtall-airline-16756
12/18/2025, 2:25 AMroom_io.set_participant(identity) to target a specific participant’s audio. `RoomIO`’s simplified API is typically for one target at a time. To subscribe to both a SIP participant and another agent simultaneously, either run multiple sessions (each targeting one participant) or use the lower-level Room/RemoteParticipant subscription APIs to manage multiple subscriptions yourself.
4) Cross-Session Communication AgentSession instances are isolated — one agent cannot directly call methods on another agent’s session. Use RPC/data channels (or LiveKit data messages/topics) for cross-agent communication and to request actions like interrupts or reply generation.
5) Muting Participants Programmatically You can mute a remote participant’s published audio via server-side APIs that act with room admin privileges (e.g., using room.local_participant.mute_published_track() or the RoomService mute functionality). An agent can mute others only if it has the necessary room/admin permissions; otherwise perform the mute from a backend process that holds those privileges.
6) Silent Agent Pattern Recommended: disable TTS for the observer by setting tts=None (or equivalent) on the AgentSession so it does not publish audio. You don’t need a dummy TTS; disabling TTS avoids creating/publishing an audio track.
7) Agent Subscribing to Another Agent's Audio Yes. An agent can subscribe to another agent’s published audio track using standard LiveKit subscription mechanics. With RoomIO you can target the other agent via set_participant() (or use low-level participant events/subscriptions for more control).
8) Detecting Agent Turn Completion Watch agent_state_changed transitions (e.g., from "speaking" to "listening"/"thinking") to detect turn completion. You can also await the SpeechHandle returned by say() or generate_reply() to know when the speech finishes.
9) Update Chat Context from External Source You cannot directly manipulate another session’s chat context from outside. Have the observer signal the main agent via data messages/RPC; the primary agent then injects the system/user message into its own context and continues the flow.
10) Agent Dispatch vs Same-Process Creation
• Creating a second AgentSession in the same entrypoint: runs both agents in one worker process — good for tight coupling, shared memory, simpler coordination.
• Using `api.agent_dispatch.create_dispatch()`: spawns a separate agent worker — provides isolation, independent scaling, and fault isolation.
Choose same-process for low-latency, tightly integrated agents; choose dispatch when you need independent scaling, resilience, or strict isolation.
If you want, I can:
• Show a short Python example for creating two AgentSessions in one process, or
• Show how to mute a participant via the RoomService API, or
• Outline a simple data-channel RPC pattern for agent-to-agent commands. Which would you like next? Sources: Virtual avatar plugins | LiveKit Docs | Job lifecycle | LiveKit docs | How to set a fixed participant for agent audio processing | Agents Framework | livekit/livekit_composite | DeepWiki | Bringing AI avatars to voice agentsmicroscopic-dress-75199
12/18/2025, 2:29 AMtall-airline-16756
12/18/2025, 2:29 AMctx.api.room.mute_published_track() only if that agent’s session has the necessary room admin permissions (i.e., it is authorized to perform server-side mute actions). If the agent does not hold those privileges, perform the mute from a backend process that has room admin rights using the LiveKit Server (RoomService) API from Python.
• In practice: if your agent process is granted admin-level scopes/credentials, calling ctx.api.room.mute_published_track() from within the agent is fine. If not, call the RoomService mute endpoint from a privileged backend.
Data-channel pattern for agent-to-agent commands
1. Overview
• Use LiveKit data messages/topics to send JSON commands between agents.
• Observer publishes a data message to the room with a command payload; the Main Agent subscribes to data messages and handles commands.
1. Minimal pattern (conceptual Python pseudocode)
Observer agent sends command:
cmd = {"action": "interrupt", "hint": "urgent safety issue"}
await ctx.room.publish_data(json.dumps(cmd).encode(), kind="reliable")
Main agent receives and handles:
# set up a data message handler when session/room connects
def on_data_message(message, participant):
payload = json.loads(message.data.decode())
if payload.get("action") == "interrupt":
# trigger interrupt handling within this agent
await agent_session.interrupt()
# optionally send ack back
ack = {"action": "ack", "for": payload}
await ctx.room.publish_data(json.dumps(ack).encode(), kind="reliable")
ctx.room.on("data_received", on_data_message)
Notes and best practices
• Use kind="reliable" for control messages that must arrive; use kind="lossy" for non-critical events.
• Include sender identity and correlation IDs in the payload for authorization and tracing.
• Validate incoming commands to avoid unauthorized actions.
• For richer RPC behavior, implement request/response with unique IDs and timeouts (observer sends {id, action}, main agent replies with {id, result}).
If you want, I can produce a more complete code example that wires handlers into AgentSession lifecycle and shows request/response with timeouts. Would you like that?