Skip to main content

Agent dispatch

Specifying how and when your agents are assigned to rooms.

Dispatching agents

Dispatch is the process of assigning an agent to a room. LiveKit server manages this process as part of the Agent server lifecycle. LiveKit optimizes dispatch for high concurrency and low latency, typically supporting hundred of thousands of new connections per second with a max dispatch time under 150 ms.

Automatic agent dispatch

By default, an agent is automatically dispatched to each new room. Automatic dispatch is the best option if you want to assign the same agent to all new participants.

Explicit agent dispatch

Explicit dispatch is available for greater control over when and how agents join rooms. This approach uses the same systems as automatic dispatch, allowing you to run agent servers in the same way.

To use explicit dispatch, set the agent_name field:

In Python, set the agent name in the @server.rtc_session decorator:

@server.rtc_session(agent_name="test-agent")
async def my_agent(ctx: JobContext):
# Agent entrypointcode...
const opts = new WorkerOptions({
...
agentName: "test-agent",
});
Requires explicit dispatch

If you set the agent_name property, you turn off automatic dispatch. Agents must be explicitly dispatched to a room.

Dispatch via API

You can explicitly dispatch an agent to a room using the AgentDispatchService API.

import asyncio
from livekit import api
room_name = "my-room"
agent_name = "test-agent"
async def create_explicit_dispatch():
lkapi = api.LiveKitAPI()
dispatch = await lkapi.agent_dispatch.create_dispatch(
api.CreateAgentDispatchRequest(
agent_name=agent_name, room=room_name, metadata='{"user_id": "12345"}'
)
)
print("created dispatch", dispatch)
dispatches = await lkapi.agent_dispatch.list_dispatch(room_name=room_name)
print(f"there are {len(dispatches)} dispatches in {room_name}")
await lkapi.aclose()
asyncio.run(create_explicit_dispatch())
import { AgentDispatchClient } from 'livekit-server-sdk';
const roomName = 'my-room';
const agentName = 'test-agent';
async function createExplicitDispatch() {
const agentDispatchClient = new AgentDispatchClient(process.env.LIVEKIT_URL, process.env.LIVEKIT_API_KEY, process.env.LIVEKIT_API_SECRET);
// create a dispatch request for an agent named "test-agent" to join "my-room"
const dispatch = await agentDispatchClient.createDispatch(roomName, agentName, {
metadata: '{"user_id": "12345"}',
});
console.log('created dispatch', dispatch);
const dispatches = await agentDispatchClient.listDispatch(roomName);
console.log(`there are ${dispatches.length} dispatches in ${roomName}`);
}
lk dispatch create \
--agent-name test-agent \
--room my-room \
--metadata '{"user_id": "12345"}'
func createAgentDispatch() {
req := &livekit.CreateAgentDispatchRequest{
Room: "my-room",
AgentName: "test-agent",
Metadata: "{\"user_id\": \"12345\"}",
}
dispatch, err := dispatchClient.CreateDispatch(context.Background(), req)
if err != nil {
panic(err)
}
fmt.Printf("Dispatch created: %v\n", dispatch)
}

The room, my-room, is automatically created during dispatch if it doesn't already exist, and the agent server assigns test-agent to it.

Job metadata

Explicit dispatch allows you to pass metadata to the agent, available in the JobContext. This is useful for including details such as the user's ID, name, or phone number.

The metadata field is a string. LiveKit recommends using JSON to pass structured data.

The examples in the previous section demonstrate how to pass job metadata during dispatch.

For information on consuming job metadata in an agent, see the following guide:

Job metadata

Learn how to consume job metadata in an agent.

Dispatch from inbound SIP calls

Agents can be explicitly dispatched for inbound SIP calls. SIP dispatch rules can define one or more agents using the room_config.agents field.

LiveKit recommends explicit agent dispatch for SIP inbound calls rather than automatic agent dispatch as it allows multiple agents within a single project.

Dispatch on participant connection

You can configure a participant's token to dispatch one or more agents immediately upon connection.

To dispatch multiple agents, include multiple RoomAgentDispatch entries in RoomConfiguration.

The following example creates a token that dispatches the test-agent agent to the my-room room when the participant connects:

from livekit.api import (
AccessToken,
RoomAgentDispatch,
RoomConfiguration,
VideoGrants,
)
room_name = "my-room"
agent_name = "test-agent"
def create_token_with_agent_dispatch() -> str:
token = (
AccessToken()
.with_identity("my_participant")
.with_grants(VideoGrants(room_join=True, room=room_name))
.with_room_config(
RoomConfiguration(
agents=[
RoomAgentDispatch(agent_name="test-agent", metadata='{"user_id": "12345"}')
],
),
)
.to_jwt()
)
return token
import { RoomAgentDispatch, RoomConfiguration } from '@livekit/protocol';
import { AccessToken } from 'livekit-server-sdk';
const roomName = 'my-room';
const agentName = 'test-agent';
async function createTokenWithAgentDispatch(): Promise<string> {
const at = new AccessToken();
at.identity = 'my-participant';
at.addGrant({ roomJoin: true, room: roomName });
at.roomConfig = new RoomConfiguration({
agents: [
new RoomAgentDispatch({
agentName: agentName,
metadata: '{"user_id": "12345"}',
}),
],
});
return await at.toJwt();
}
func createTokenWithAgentDispatch() (string, error) {
at := auth.NewAccessToken(
os.Getenv("LIVEKIT_API_KEY"),
os.Getenv("LIVEKIT_API_SECRET"),
).
SetIdentity("my-participant").
SetName("Participant Name").
SetVideoGrant(&auth.VideoGrant{
Room: "my-room",
RoomJoin: true,
}).
SetRoomConfig(&livekit.RoomConfiguration{
Agents: []*livekit.RoomAgentDispatch{
{
AgentName: "test-agent",
Metadata: "{\"user_id\": \"12345\"}",
},
},
})
return at.ToJWT()
}