boundless-author-7811
04/23/2026, 7:53 AMtall-airline-16756
04/23/2026, 7:53 AMtall-airline-16756
04/23/2026, 7:54 AMRoomAgentDispatch entries in a RoomConfiguration when generating a participant token to dispatch several agents to the same room.
• Call the AgentDispatchService API multiple times to create separate dispatches (same room or different rooms).
• For SIP inbound dispatch rules, include multiple agents via room_config.agents.
If you want, tell me whether you plan to (a) include multiple agents in a token, (b) create dispatches via the API at runtime, or (c) configure SIP dispatch rules — and I’ll provide a short example for that case.
Sources: Agent dispatch | LiveKit Documentation, with interactive elementsboundless-author-7811
04/23/2026, 7:56 AMawait asyncio.wait_for(
self.lkapi.agent_dispatch.create_dispatch(
CreateAgentDispatchRequest(
agent_name="outbound-call-agent",
room=room_name,
metadata=json.dumps(metadata)
)
),
timeout=10.0
)tall-airline-16756
04/23/2026, 7:56 AMcreate_dispatch multiple times (concurrently or sequentially). Example patterns:
1) Sequential (simple):
for agent in ["agent-a", "agent-b", "agent-c"]:
await asyncio.wait_for(
self.lkapi.agent_dispatch.create_dispatch(
CreateAgentDispatchRequest(
agent_name=agent,
room=room_name,
metadata=json.dumps(metadata)
)
),
timeout=10.0
)
2) Concurrent (faster):
tasks = [
asyncio.create_task(
self.lkapi.agent_dispatch.create_dispatch(
CreateAgentDispatchRequest(agent_name=agent, room=room_name, metadata=json.dumps(metadata))
)
)
for agent in ["agent-a", "agent-b", "agent-c"]
]
await asyncio.wait_for(asyncio.gather(*tasks), timeout=10.0)
Choose sequential if you need ordered creation or per-dispatch error handling; choose concurrent to speed up multiple dispatches. Do you want an example that includes per-dispatch retries or individual timeouts?
, with interactive elementsboundless-author-7811
04/23/2026, 7:57 AMtall-airline-16756
04/23/2026, 7:57 AMoutbound-call-agent-1, outbound-call-agent-2) so each dispatch is delivered to an available instance.
• If you want the single container to handle multiple dispatches concurrently, ensure the agent process supports multiple simultaneous connections and accepts multiple dispatches; then dispatching the same agent_name to multiple rooms can work (subject to your agent’s concurrency logic).
Which direction do you want to pursue?
• Scale horizontally (run multiple containers with different agent names) — I can show container/instance naming and dispatch patterns.
• Keep a single container and add concurrency support in the agent process — I can outline code patterns for handling multiple simultaneous dispatches.
• Or do you want an example of dispatching the same agent name to multiple rooms?, with interactive elementsboundless-author-7811
04/23/2026, 8:00 AMtall-airline-16756
04/23/2026, 8:00 AMoutbound-call-agent to multiple rooms concurrently
import asyncio
import json
from livekit import api
from livekit.api import CreateAgentDispatchRequest
async def dispatch_to_rooms(lkapi: api.LiveKitAPI, agent_name: str, rooms: list, metadata: dict):
tasks = []
for room in rooms:
req = CreateAgentDispatchRequest(
agent_name=agent_name,
room=room,
metadata=json.dumps(metadata)
)
tasks.append(lkapi.agent_dispatch.create_dispatch(req))
# run concurrently and await all results
results = await asyncio.gather(*tasks, return_exceptions=True)
# results contains responses or exceptions for each dispatch
return results
# usage
async def main():
lkapi = api.LiveKitAPI() # your instantiated client
rooms = ["room-a", "room-b", "room-c"]
metadata = {"user_id": "12345"}
results = await dispatch_to_rooms(lkapi, "outbound-call-agent", rooms, metadata)
for room, res in zip(rooms, results):
if isinstance(res, Exception):
print(f"dispatch to {room} failed: {res}")
else:
print(f"dispatched to {room}: {res}")
asyncio.run(main())
Important notes:
• Sending dispatches to multiple rooms with the same agent_name is allowed.
• Whether those dispatches are actually handled concurrently depends on your agent instance:
◦ If your single container supports multiple simultaneous agent connections and logic to handle them, it can accept multiple dispatches.
◦ If it only accepts one active connection, only one dispatch will be served at a time — others may queue or fail.
• If you need true parallel handling, run multiple agent instances (distinct identities or same name if your system allows multiple connections for that name) or make the agent process concurrent-capable.
Want a version that:
• uses per-dispatch timeouts/retries, or
• checks dispatch results and retries failed ones?, with interactive elementsboundless-author-7811
04/23/2026, 8:01 AMtall-airline-16756
04/23/2026, 8:01 AMimport asyncio
import json
from livekit import Room, RoomOptions # pseudocode imports
MAX_CONCURRENT = 5
semaphore = asyncio.Semaphore(MAX_CONCURRENT)
async def handle_dispatch(dispatch):
# dispatch contains agent_name, room, metadata, etc.
async with semaphore:
try:
# connect to LiveKit room (pseudo-code; use your SDK's connect)
room = await Room.connect(dispatch.room, token=dispatch.token, options=RoomOptions())
# perform agent work: publish/subscribe, handle tracks, signaling, SIP bridging, etc.
await run_agent_session(room, dispatch.metadata)
except Exception as e:
# handle/log error
raise
finally:
# ensure cleanup
await room.disconnect()
async def dispatch_consumer(dispatch_source):
# dispatch_source yields incoming dispatch objects
async for dispatch in dispatch_source():
asyncio.create_task(handle_dispatch(dispatch))
# Example run
asyncio.run(dispatch_consumer(my_dispatch_source))
Notes:
• Replace pseudo-code with the concrete LiveKit Python client calls you use to join rooms and manage tracks.
• If the SDK has blocking calls, run them in an executor: await loop.run_in_executor(...).
• Add per-dispatch timeouts (asyncio.wait_for) and retries as needed.
• Monitor resource usage (CPU, memory, sockets) and tune MAX_CONCURRENT accordingly.
Would you like a concrete example using your current dispatch creation flow and the exact LiveKit Python client calls you use to join rooms? If so, share how you connect to rooms in the agent (sync vs async and what client functions you call).
, with interactive elementsboundless-author-7811
04/23/2026, 8:06 AMawait asyncio.wait_for(
self.lkapi.agent_dispatch.create_dispatch(
CreateAgentDispatchRequest(
agent_name="outbound-call-agent",
room=room_name,
metadata=json.dumps(metadata)
)
),
timeout=10.0
)tall-airline-16756
04/23/2026, 8:06 AMawait asyncio.wait_for(...) call:
• await itself does not cause performance issues; it yields control while the HTTP request runs so your event loop can do other work.
• Using asyncio.wait_for(..., timeout=10.0) is good practice to avoid hangs.
• Sequentially awaiting many create_dispatch calls will be slower than issuing them concurrently. For better throughput, dispatch concurrently with asyncio.gather() or create tasks and await them, e.g.:
tasks = [
self.lkapi.agent_dispatch.create_dispatch(
CreateAgentDispatchRequest(agent_name="outbound-call-agent", room=r, metadata=json.dumps(metadata))
)
for r in rooms
]
results = await asyncio.gather(*tasks, return_exceptions=True)
• If your single container must handle multiple active dispatches, ensure the agent process is concurrency-capable (async handlers, semaphores to limit concurrency, or thread/executor for blocking work).
• Keep per-dispatch timeouts/retries and monitor resource usage; for very high volume, batch or rate-limit dispatches or scale horizontally.
If you want, I can:
• Show a concurrent example with per-dispatch timeouts/retries, or
• Convert your current wait_for pattern to a concurrent-safe version. Which would you like? Sources: Agent dispatch | LiveKit Documentation | Voice Agent Architecture: STT, LLM, and TTS Pipelines Explained | LiveKit, with interactive elements