Skip to main content
Field Guides

Avoiding crosstalk when multiple developers share a LiveKit project

How to prevent agent calls from landing on the wrong machine when your team runs agents locally against the same LiveKit Cloud project. Covers per-developer agent names, explicit dispatch, and when to reach for separate projects instead.

Last Updated:

Guide

When two or more developers run uv run agent.py dev within the same LiveKit Cloud project, every inbound call or room connection is routed to whichever agent picks up first. That means your test call may land on a teammate's laptop instead of yours. The industry term for this is crosstalk, and it's the most common frustration teams hit once they move past single-developer prototyping.

This guide covers two ways to fix it, one lightweight, one structural, and when to choose each.

Why it happens

In dev mode, your agent registers with LiveKit Cloud as an available worker. If multiple developers register agents with the same name (or no name at all), the dispatcher treats them as interchangeable instances of the same service and load-balances across them. From the server's perspective, this is correct behavior; it's how you scale agents in production. In development, it just means the wrong person's machine answers the phone.

Option 1: per-developer agent names

The fastest fix is to give each developer a unique agent_name. When you set agent_name, you switch from automatic dispatch to explicit dispatch, which means the agent only receives jobs that are dispatched to that specific name.

Set the agent name from an environment variable

Define a base agent name in code and append a developer-specific suffix from the environment. When the environment variable isn't set, the agent uses the base name, which is what you want in production:

1
import os
2
3
BASE_AGENT_NAME = "my-agent"
4
_dev_suffix = os.getenv("LIVEKIT_AGENT_SUFFIX", "")
5
AGENT_NAME = f"{BASE_AGENT_NAME}-{_dev_suffix}" if _dev_suffix else BASE_AGENT_NAME
6
7
@server.rtc_session(agent_name=AGENT_NAME)
8
async def entrypoint(ctx: JobContext):
9
# your agent code
10
...

Each developer sets the suffix in their own shell or .env file:

1
# Jack's machine
2
export LIVEKIT_AGENT_SUFFIX="jack"
3
4
# Jill's machine
5
export LIVEKIT_AGENT_SUFFIX="jill"

Jack's agent registers as my-agent-jack, Jill's as my-agent-jill. In production, where the variable isn't set, every instance registers as my-agent and the dispatcher load-balances across them as usual. No crosstalk in dev, no code changes for prod.

Dispatch to the right agent

Because explicit dispatch is now enabled, you need to tell LiveKit which agent to dispatch to. How you do that depends on your setup:

From the frontend (token-based dispatch): Include the agent name in the participant's access token. Use the same suffix logic so each developer's frontend dispatches to their own agent:

1
from livekit.api import AccessToken, RoomAgentDispatch, RoomConfiguration, VideoGrants
2
3
token = (
4
AccessToken()
5
.with_identity("test-user")
6
.with_grants(VideoGrants(room_join=True, room="my-room"))
7
.with_room_config(
8
RoomConfiguration(
9
agents=[
10
RoomAgentDispatch(agent_name=AGENT_NAME)
11
],
12
),
13
)
14
.to_jwt()
15
)

From a SIP dispatch rule: If you're testing telephony, set agent_name in your dispatch rule to match your personal agent name. See the caller dispatch rule docs for the full configuration.

From the CLI:

1
lk dispatch create \
2
--agent-name my-agent-jack \
3
--room my-room

Keep production clean

In production, simply don't set LIVEKIT_AGENT_SUFFIX. The code falls back to the base name (my-agent), so every instance registers identically and the dispatcher load-balances across them. No environment-specific code paths or conditional logic; the suffix is only present on developer machines.

Option 2: separate projects per developer

If you need full isolation, separate rooms, logs, and usage tracking per developer, give each developer their own LiveKit Cloud project. Every project has its own API key, secret, and server URL, so there's zero chance of crosstalk.

This is the right choice when:

  • You want completely independent logs and metrics per developer for debugging.
  • Your compliance requirements demand separate environments.
  • You prefer each developer to have their own sandbox without coordinating agent names.

For details on setting up multiple projects under a single subscription, see Structuring development and test environments.

The tradeoff is more projects to manage and more credential sets to distribute. For most teams, per-developer agent names (Option 1) are simpler to start with.

Console mode: no conflict by default

Developers running in console mode (uv run agent.py console) don't have this problem at all. Console mode runs entirely locally without connecting to LiveKit Cloud, so there's no dispatcher and no chance of crosstalk. Multiple developers can run console mode simultaneously without any coordination.

The limitation is that console mode can't interact with real rooms, SIP calls, or external systems that depend on a LiveKit connection. It's ideal for rapid iteration on prompt logic, tool definitions, and conversation flow — but when you need end-to-end testing with live infrastructure, switch to dev mode and use one of the approaches above.

Summary

ApproachIsolation levelEffortBest for
Per-developer agent_nameAgent dispatchLow — one env varSmall-to-medium teams sharing a project
Separate projectsFull (keys, rooms, logs)Medium — credential managementTeams wanting full isolation or compliance requirements
Console modeComplete (no server)NonePrompt/tool iteration only

Start with per-developer agent names. It takes one environment variable, zero infrastructure changes, and five minutes to set up across the team.

Related resources