Having trouble with agent dispatch — second agent ...
# ask-ai
t
Having trouble with agent dispatch — second agent in same project not receiving calls I have two agents deployed in the same LiveKit Cloud project (i've created a worktree locally). The first agent works fine. The second one registers successfully but never receives job requests when calls come in. - Worker logs show "registered worker" but no "received job request" ever appears - Dashboard shows "Agent dispatch errors" under the agent's graph - Dispatch rule is scoped to the correct trunk ID and points to the correct agent name - Trunk and dispatch rule all look correct via lk sip dispatch list and lk sip inbound list Using @alert-easter-19258/agents@1.0.48 (Node.js). Has anyone run into dispatch issues when running multiple agents in the same project? Any ideas what could cause dispatch errors when the worker is registered and the rule looks correct?
t
Thanks for reaching out, Ishil. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I’m sorry you’re running into this. You’ve given good detail; I’m responding to the parts about the second agent registering but never receiving job requests, the “Agent dispatch errors” on the dashboard, and your dispatch rule/trunk checks. Short answer: when you run multiple agents in the same project and an agent has an explicit
agent_name
, LiveKit requires explicit dispatch rules that target that agent name. Agents with an explicit
agent_name
are excluded from automatic dispatch, so they won’t receive jobs unless the dispatch rule’s
agents
array names them. What to check (quick list) • Dispatch rule’s agents list — Confirm the SIP dispatch rule’s
roomConfig.agents
includes the exact
agentName
used by the second agent. Example:
Copy code
"roomConfig": {
  "agents": [
    { "agentName": "second-agent-name" }
  ]
}
• No default unnamed agent — If a default (unnamed) agent exists, it can consume incoming requests. Only agents explicitly named in the rule will be routed when
agent_name
is set on agents. • Worker registration state — Ensure the worker stays in a healthy registered state (you should see
registered worker
and not
draining worker
or repeated reconnects). • Credentials & clock skew — Token validation or clock skew can prevent proper dispatch even if registration looks successful. Confirm system time is in sync and tokens are valid. • SDK version — You're on @LiveKit/agents@1.0.48. Consider upgrading to a newer Agents SDK (1.3.0+ recommended) to avoid known dispatch jitter after rejections and get the latest dispatch behavior. Targeted troubleshooting steps 1. Show me the exact
agentName
that the second agent is using (copy-paste from your agent config or logs). 2. Share the
agents
portion of the dispatch rule (redact secrets). I can quickly verify the names match and the rule is scoped properly to the trunk. 3. If names match but dispatch still fails: ◦ Check the dashboard timeline for the exact dispatch error messages and paste the error text you see under “Agent dispatch errors.” ◦ Confirm the agent process logs for any token errors or repeated reconnects near the time of incoming calls. If you prefer, paste the
agentName
and the
agents
array from your dispatch rule and I’ll examine them for mismatches or common mistakes. Sources: Server options | LiveKit Documentation | Agent dispatch | LiveKit Documentation | Deployment reliability on LiveKit Cloud | LiveKit | Troubleshooting 401 Unauthorized and Token Errors | LiveKit | Why do jobs stop after agent rejection? | LiveKit
t
Agent name (from code): agentName: 'phone-ordering-realtime' Dispatch rule agents array (from lk sip dispatch list and API): { "sipDispatchRuleId": "SDR_tgiyyCBvksN2", "name": "Phone Ordering Realtime Dispatch", "trunkIds": ["ST_Ty4jg4NRE4qN"], "roomConfig": { "agents": [ { "agentName": "phone-ordering-realtime" } ] } } Names match exactly. Worker stays registered (no draining/reconnects in logs). The first agent (phone-ordering) in the same project works fine with the same pattern. One question — you mention upgrading to 1.3.0+, but is that available for the Node.js SDK? We're on @livekit/agents@1.0.48 which appears to be the latest on npm.
t
Thanks — this is really helpful detail. I’m responding to the parts where you confirmed the names match, the worker stays registered, the first agent works, and you asked whether a newer Node.js SDK exists. Short answer: • Your dispatch rule and
agentName
match exactly, and your agent stays registered, so the basic configuration is correct. • You’re on
@livekit/agents@1.0.48
. The Node.js Agents SDK received the relevant dispatch improvements starting at v1.0.19, and v1.0.48 is newer than that, so you already have the JS updates that address dispatch behavior. There isn’t a separate “1.3.0” Node release you need to install. Next steps — targeted checks to find why the second agent isn’t getting jobs 1. Confirm the trunk receiving the incoming call is the same trunk ID in the dispatch rule. ◦ Even though the rule lists
ST_Ty4jg4NRE4qN
, please confirm incoming calls are arriving on that exact trunk (check SIP logs or trunk inbound history). 1. Inspect agent logs for silent rejection or token issues. ◦ Look for any job acceptance/rejection messages, token validation errors, or authorization warnings around incoming-call times. You mentioned seeing only
registered worker
— also check for any lines about rejecting jobs, missing capabilities, or expired tokens. 1. Verify there’s no unnamed/default agent intercepting traffic. ◦ If an unnamed (default) agent exists in the same project, it can receive automatic dispatch. Named agents only receive jobs when explicitly targeted by the dispatch rule. Confirm there’s no competing rule or default agent consuming the job. 1. Confirm the job routing payload includes the
agents
targeting. ◦ On the call arrival path, the dispatch request should route to the SIP dispatch rule you listed. If possible, capture the dispatch request (or check the dashboard trace) and confirm it references the dispatch rule and the
agents
array that targets
phone-ordering-realtime
. 1. Compare the working agent’s metadata/registration vs the non-working one. ◦ Compare the registration payloads and runtime logs of
phone-ordering
(working) and
phone-ordering-realtime
. Look for differences in: ▪︎ agent capability flags or features advertised at registration ▪︎ environment/time drift or token TTLs ▪︎ any additional config fields (e.g.,
room
,
capabilities
) that might affect eligibility What I can do if you share two small items • Paste the exact registration log lines (redact secrets) for
phone-ordering-realtime
around the time of registration and an incoming call. • Paste the dashboard dispatch error text that appears under “Agent dispatch errors” for that agent. With those I’ll look for: • Token validation or clock skew indicators • Job-rejection messages or capability mismatch clues • Whether the dispatch request is targeting the rule but failing assignment If you prefer, start by confirming the trunk match and pasting the dispatch error text — that often points directly to why a job isn’t assigned. Sources: Improved End-of-Turn Model Cuts Voice AI Interruptions 39% | Server lifecycle | LiveKit Documentation | Agents telephony integration | LiveKit Documentation | Deployment reliability on LiveKit Cloud | LiveKit | Why do jobs stop after agent rejection? | LiveKit
t
1. Registration logs for phone-ordering-realtime: {"level":40,"time":...,"version":"1.0.48","msg":"custom loadThreshold is not supported when deploying to Cloud, using defaults"} {"level":30,"time":...,"version":"1.0.48","msg":"starting worker"} {"level":30,"time":...,"msg":"Server is listening on port 8081"} {"level":30,"time":...,"version":"1.0.48","id":"CAW_xxxxx","server_info":{"edition":"Cloud","version" :"1.9.12","protocol":16,"region":"US East B","nodeId":"NC_xxxxx","debugInfo":"","agentProtocol":0},"msg":"registered worker"} That's it — no job requests, no rejections, no token errors, no capability warnings. Just registers and then silence. No other log lines appear when calls come in. 2. Dashboard dispatch errors: The dashboard just shows "Agent dispatch errors: 4" on the graph — there's no expandable error text or detail. It's just a count on the metrics chart. Notable: agentProtocol: 0 in the registration — could that be relevant? The working agent (phone-ordering) is on the same SDK version. Also, the very first deployment of this agent DID receive a job successfully ("received job request" with "agentName":"phone-ordering-realtime"), but after redeploying it stopped.
t
Thanks — this is very helpful detail. I’m responding to the parts where you showed the registration log (registered worker + agentProtocol: 0), the dashboard showing only a dispatch error count, and the fact the agent worked once but stopped after redeploy. Summary of what the logs show • The agent successfully registers (you see "registered worker"), so connectivity and token validation look OK from the agent side. • There are no job request or rejection logs when calls arrive — the agent never sees the dispatch attempt. • The dashboard shows a count of dispatch errors but no expanded error text. • Crucial clue:
agentProtocol: 0
in the registration info and the agent worked once before failing after redeploy. Why this matters •
agentProtocol: 0
is unusual and suggests a protocol negotiation mismatch or compatibility/registration metadata issue. If the server considers the agent protocol unsupported or incompatible, it may count a dispatch error server-side and never deliver the job to the agent (hence no job logs). • The fact the agent worked initially but stopped after redeploy strongly points to deployment/configuration drift rather than a dispatch-rule naming mismatch (your names match). What to check next (concise, actionable steps) 1. Compare registration info from the working agent ◦ Get the same registration log lines from the working agent (
phone-ordering
). Does it show a non-zero
agentProtocol
value or different
server_info
fields (region, nodeId, protocol)? Paste those lines (redact secrets) and I’ll compare. 1. Redeploy cleanly / restart agents in isolation ◦ Temporarily stop the working agent (
phone-ordering
) and then redeploy or restart
phone-ordering-realtime
. If
phone-ordering-realtime
begins receiving jobs, that indicates routing contention or load-balancing preference between similarly-named agents. ◦ Alternatively, do a full redeploy of
phone-ordering-realtime
ensuring no build cache or leftover state (clear image cache / remove local worktree artifacts). 1. Inspect the exact registration payload your agent is sending ◦ If you can log the full registration/server_info payload emitted at registration (beyond the brief line), look for differences in
agentProtocol
,
version
,
agentProtocol
fields, capability flags, or any extra config that could make the agent ineligible for jobs. 1. Verify for silent filtering logic ◦ If your worker code implements any
request
filter or
requestFunc
that accepts/rejects jobs, confirm it isn’t silently skipping or rejecting incoming requests. Add temporary logging in the request handler to ensure nothing short-circuits acceptance. 1. Check deployment environment differences ◦ Confirm environment variables, Node versions, and container image build steps match between the working agent and the problematic one. The log about "custom loadThreshold is not supported when deploying to Cloud" suggests some self-hosted configs are present — ensure those don’t alter runtime behavior in Cloud. 1. Gather the dashboard trace / timestamps ◦ Note exact timestamps when you see the dispatch error count increase in the dashboard and the corresponding times of incoming calls. Provide those timestamps and the registration log around the same times so I can correlate server-side timing with your agent logs. If you share these two items I can analyze the next level: • The registration log lines from the working agent (same format as you pasted). • One or two timestamped examples where an incoming call was made + the dashboard shows dispatch error (so I can correlate times). If you prefer a quick test now: • Stop the working agent, make a test call to the trunk, and watch
phone-ordering-realtime
logs. Report whether it receives the job or whether the dashboard still increments dispatch errors without agent logs. I’ll stay with you through the steps — paste the working agent’s registration log and one example timestamp and I’ll help interpret the differences and recommend the exact fix. Sources: Agent dispatch | LiveKit Documentation | Agent deployment overview | LiveKit Documentation | Server options | LiveKit Documentation | Agents telephony integration | LiveKit Documentation | Deployment reliability on LiveKit Cloud | LiveKit
t
Working agent (phone-ordering) registration: {"version":"1.0.48","id":"CAW_xxxxx","server_info":{"edition":"Cloud","version":"1.9.12","protocol":1 6,"region":"US East B","nodeId":"NC_xxxxx","debugInfo":"","agentProtocol":0},"msg":"registered worker"} Non-working agent (phone-ordering-realtime) registration: {"version":"1.0.48","id":"CAW_xxxxx","server_info":{"edition":"Cloud","version":"1.9.12","protocol":1 6,"region":"US East B","nodeId":"NC_xxxxx","debugInfo":"","agentProtocol":0},"msg":"registered worker"} They're identical — same agentProtocol: 0, same SDK version, same Cloud version, same region. The working agent successfully receives jobs with this exact same registration. No unnamed/default agents exist, no request filters in the code. For the dashboard dispatch errors — there's no expandable error text, just a count on the metrics graph. I don't have access to more detailed error messages. The only difference between the two agents is the agentName and the realtime model used (Google beta realtime vs cascaded pipeline). Could the dispatch error be related to something server-side rather than agent-side?
t
Thanks — this is very useful. I’m responding to the part where both agents show identical registration (including
agentProtocol: 0
), the working agent still receives jobs, there are no request filters or unnamed agents, and you’re wondering whether the dispatch errors could be server-side. Short summary of where we are • Registration looks identical for both agents (same SDK, same Cloud server_info, same region). Connectivity and registration are healthy. • The dispatch rule and
agentName
are correct and match. • The working agent receives jobs; the other one does not — and the dashboard only shows a dispatch-error count with no agent-side logs when calls come in. • You’ve ruled out request filters and unnamed/default agents. What this means • Because registration is valid and one agent receives jobs while the other does not, the most likely causes are either: ◦ Server-side dispatch routing decisions (e.g., the dispatch attempt is rejected or fails before reaching the agent), or ◦ A subtle eligibility mismatch between the two agents that isn’t obvious in the registration snapshot (capabilities, runtime metadata, or how the realtime model affects job acceptance). Actionable next steps — targeted and quick checks 1. Confirm the dispatch rule’s full JSON (including any capability or metadata filters) ◦ Please paste the full dispatch rule JSON (you already shared the core, but include any other fields such as
capabilities
,
metadata
, or
selector
if present). If there are hidden filters, they can cause server-side rejections before the agent sees the job. 1. Reproduce in isolation and capture timing ◦ Stop the working agent (
phone-ordering
) and trigger an inbound call to the trunk so only
phone-ordering-realtime
is eligible. ◦ Watch the non-working agent’s logs during that call window. If it still receives nothing and the dashboard error count increments, that confirms server-side rejection/routing that never reaches the agent. 1. Compare runtime metadata at registration ◦ Although the registration lines look identical, there may be other registration metadata sent slightly later. Add verbose logging to capture the full registration payload (all fields) for both agents and paste both payloads here (redact secrets). I’ll compare for any subtle differences like
capabilities
,
tags
, or
metadata
. 1. Check model/capability requirements ◦ You mentioned the non-working agent uses a realtime model (Google beta realtime) vs a cascaded pipeline on the other agent. Does your dispatch rule or job creation logic require specific capability flags (for example, a flag indicating support for realtime audio processing)? If so, ensure those flags are present in the agent registration metadata. If you don’t have such flags, confirm that the job request payload doesn’t include a capability requirement tied to the model. 1. Collect timestamps for correlation ◦ When you make a test call, note the exact timestamp (UTC) and include it here. Provide the registration log lines around that time. I’ll correlate the event timing with your logs and the dashboard error increments to narrow whether dispatch attempts are failing server-side. 1. Temporary experiment: rename agent ◦ As an experiment, deploy the realtime agent with a different
agentName
(e.g.,
phone-ordering-realtime-test
) and update the dispatch rule to include that name. Then trigger a call. This isolates whether something about the
phone-ordering-realtime
name or its previous job history/state is affecting routing. If you can do steps 1–3 now (paste the full dispatch rule JSON and the full registration payloads), I’ll compare them and point out any mismatches. If you prefer the isolation test, tell me the timestamp of a test call after you stop the working agent and I’ll help interpret the results.
t
this is not helpful 🙂
but i will try renaming!
t
Thanks — I hear you, and I appreciate you trying the rename experiment. Quick acknowledgement: you were right to be frustrated — you’ve done the right checks (names match, identical registration, no request filters), and the problem looks like a subtle server-side routing/eligibility issue. Renaming the agent and updating the dispatch rule is a good, fast isolation test. Here’s a short, exact plan to run the test and what to report back so I can help interpret results quickly: 1) Rename the agent locally and in your agent config • Change agentName to something unique, e.g.,
phone-ordering-realtime-test
. 2) Update the dispatch rule to target the new name • Replace the
agents
entry with:
Copy code
"roomConfig": {
     "agents": [
       { "agentName": "phone-ordering-realtime-test" }
     ]
   }
3) Redeploy only the renamed agent • Leave the original
phone-ordering
running so you can compare behavior, or stop it if you want to force routing to the test agent. 4) Make a single test inbound call (note exact UTC timestamp) • Trigger one call and watch the test agent logs. 5) Tell me the outcome with minimal info: • Did the test agent receive the job? (yes / no) • If yes: include the log line showing "received job request" (redact secrets). • If no: include the UTC timestamp of the test call and whether the dashboard dispatch error count incremented. If the test agent receives jobs, that proves the original agent name or some internal state tied to it was causing the issue and renaming is a viable workaround while we dig deeper. If the test agent still does not receive jobs and the dashboard error increments, that confirms a server-side rejection unrelated to agent name. In that case I’ll walk you through: • Capturing the exact timestamps for a few failed attempts so I can correlate them, • A minimal verbose registration payload from the test agent (all fields, redact secrets), • Stopping the working agent and retrying once to confirm whether routing is preferential. Thanks again for trying the rename — tell me what happens and I’ll help analyze the result immediately.
t
why is the agent not picking up naming in dash?
t
Thanks — I hear you. You’re asking why the dashboard is showing an agent ID (like CA_hysrnhEagPeQ) instead of the agentName you set, and why that might relate to dispatch not routing to the agent. Quick acknowledgement • I see the dashboard screenshot: the agent card shows an internal agent ID (CA_...) with RUNNING and 0 concurrent sessions. That view is from the Cloud agents listing and shows the deployed instance’s ID and runtime info — not necessarily the
agentName
you configured for dispatch. Why the dashboard can show an ID instead of your
agentName
• The dashboard lists the deployed worker instance (internal agent ID) and deployment metadata, not the dispatch-facing
agentName
. This is expected: the UI focuses on instances and deployment state, whereas
agentName
is a logical name used by dispatch rules to target eligible agents. • An agent can register under an internal instance ID while also advertising a distinct
agentName
for dispatch. The dashboard tile won’t always display that
agentName
. Why that matters for dispatch • Seeing the internal ID in the UI alone does not mean the agent won’t be targeted — what matters is the agent advertising the correct
agentName
during registration and the dispatch rule targeting that same
agentName
. • Since you’ve confirmed the dispatch rule includes
{ "agentName": "phone-ordering-realtime" }
and the agent previously received jobs, the dashboard card showing CA_... is not by itself a cause of routing failure. Next focused checks (fast, prioritized) 1. Confirm the agent advertises the
agentName
at registration ◦ Add one short log line immediately after registration to print the agentName your worker is using (for example: Agent registered as agentName="phone-ordering-realtime"). This removes ambiguity between instance ID and logical name. 1. Redeploy with the rename test (you mentioned trying this) ◦ If you renamed to
phone-ordering-realtime-test
and updated the dispatch rule, did the agent receive jobs? Report yes/no and a sample “received job request” log line if yes. 1. If rename test fails, run isolated test ◦ Stop the working agent (phone-ordering) and trigger a single call to the trunk while watching the realtime agent logs. If the dashboard increments dispatch errors and the realtime agent still sees nothing, the dispatch attempt is failing server-side before agent delivery. 1. Capture timestamps for failed attempts ◦ When you test and see the dashboard count increase, note the exact UTC timestamp (to the second). Provide that timestamp and the realtime agent registration log around that time. With timestamps I can correlate events and point out server-side timing issues. If you want, I can provide the exact log line to add to your agent startup to confirm the advertised name. Example (Node.js): • After your worker connects, log: Agent registered with agentName="phone-ordering-realtime" (redact any secrets). Final note • The dashboard showing CA_... is not inherently a problem. The critical thing is what the agent advertises for
agentName
when it registers and whether the dispatch rule targets that name. If you prefer, paste the startup log after adding the single agentName log and I’ll verify the registration payload for you.
t
why does it show the name on the other one
t
Thanks — I hear the question: “Why does the dashboard show the friendly name for one agent (phone-ordering) but only the internal ID (CA_...) for the other?” Short answer • The dashboard shows whichever label the agent advertises at registration. If an agent sends a user-friendly
agentName
(like
phone-ordering
), the UI can display that name. If the agent does not advertise a friendly name (or the name isn’t present in the registration payload), the UI falls back to showing the internal instance ID (CA_...). • So the difference you see means the working agent is advertising a display name in its registration metadata, while the realtime agent is not — or the friendly name isn’t being included where the dashboard expects it. What to check (fast, exact steps) 1. Log the advertised name the agent registers with ◦ Add a single log line right after the worker connects that prints the value you pass for
agentName
(or the registration payload). Example message: Agent registered as agentName="phone-ordering-realtime" ◦ Redeploy and confirm that line appears in the realtime agent logs. 1. Compare the full registration payloads ◦ Capture the full registration/server_info payload for both agents (the working and the realtime) and compare fields beyond the small summary line. Look for a
name
,
agentName
,
displayName
,
metadata
, or similar field that the dashboard could use. 1. Verify where
agentName
is set in your code ◦ Ensure the realtime agent actually sets
agentName
in the worker creation/registration call and that no env var or build step overwrote it during redeploy. 1. Quick experiment ◦ Temporarily set the realtime agentName to the same friendly name as the working agent (e.g.,
phone-ordering-test
) and redeploy. If the dashboard displays that friendly name, it confirms the dashboard is simply reflecting whatever the agent advertises. Why this matters for dispatch • Dashboard display alone doesn’t cause dispatch failures. The important part is the
agentName
the agent advertises for dispatch matching the dispatch rule. But if the agent isn’t advertising the name in its registration payload, that can also explain why it’s not being targeted for jobs. If you want, paste the small log line you add after registration (or the full registration payload for the realtime agent) and I’ll confirm whether the agent is advertising the name the dashboard expects.
t
doesn't that affect dispatch rules?
t
Short answer: Yes — dispatch matches the logical
agentName
that the agent advertises when it registers. The dashboard’s visual label is just a UI convenience; what actually controls routing is the
agentName
in the registration/registration payload. If an agent doesn’t advertise the expected
agentName
, the dispatch rule that targets that name will not match and the agent will not receive jobs. What this means for your situation • The dashboard showing CA_... for one agent and a friendly name for the other is a sign that the realtime agent is not advertising a friendly display name in the registration metadata the dashboard reads. • If the realtime agent is not actually advertising the same
agentName
your dispatch rule targets at registration time, the server-side dispatch attempt will not deliver the job to that agent — you’ll see dispatch error counts but no job logs on the agent. Concrete checks and fixes (do these now — each is quick) 1. Log the advertised name on registration ◦ Add one log line immediately after your worker connects that prints the
agentName
you set. Example Node.js: log Agent registered with agentName="phone-ordering-realtime". ◦ Redeploy and confirm the agent logs that exact line. 1. Capture full registration payload ◦ Capture or print the full registration payload/server_info your agent sends (all fields) so we can compare with the working agent. Look specifically for fields named
agentName
,
name
,
displayName
,
metadata
, or similar. 1. Ensure agentName is set in code and not overwritten ◦ Confirm the code path that constructs the worker registration sets
agentName
deterministically (env var, config file, or literal) and that no build step or runtime env is overriding it during redeploy. 1. Quick isolation test ◦ Redeploy the realtime agent with a unique test name (e.g.,
phone-ordering-realtime-test
) and update the dispatch rule to target that name. Trigger a test call. If it receives jobs, that proves the issue was the advertised name/state; if it still doesn’t, the problem is likely server-side routing/eligibility. 1. Correlate timestamps if tests fail ◦ If you still see dispatch errors and the agent receives nothing, note exact UTC timestamps for the test calls and paste registration logs around those times so we can correlate failure timing. Why the dashboard may show different labels • The UI prefers a friendly name if the registration contains it; otherwise it falls back to the internal instance ID (CA_...). The display difference itself doesn’t change dispatch behavior — the server uses the registration metadata (the truth) for routing. If you want, paste the single added registration log line (or the full registration payload) from the realtime agent and I’ll confirm whether it’s advertising the expected
agentName
and point out any mismatches.
t
is there a way to get human support
or to log a ticket
t
I don't have the answer you're looking for. You could also try asking your question: • in one of the other Slack channels or • to https://deepwiki.com/livekit/livekit_composite which is trained on all LiveKit source code If you find the answer, please post it here to help others!