Summary
Any relayflows workflow that sets swarm.channel fails at its first agent step when run in cloud:
[write-drafts] mcp-args --register failed (exit 1):
Error: register auth error: registration failed for 'writer' (401):
Agent token required (at_live_...) (code: unauthorized)
Remove the one line and the identical workflow passes. swarm.channel is a documented, first-class field used by most built-in templates, so this silently breaks a large share of cloud workflows.
Reproduction
Three cloud runs of a one-agent, one-step workflow. The only difference between them is the channel: line.
| run |
swarm.channel |
result |
4e40d810 |
(absent) |
PASS — agent ran in 12s |
48501c5f |
native-autopilot |
FAIL — 401 at register |
7d9f6eaa |
probe-unique-a91f3c (never used before) |
FAIL — 401 at register |
version: "1.0"
name: agent-register-probe
swarm:
pattern: dag
timeoutMs: 600000
channel: probe-unique-a91f3c # <-- remove this line and the run passes
agents:
- name: probe
cli: claude
role: "Says one word"
interactive: false
workflows:
- name: default
steps:
- name: say-hello
agent: probe
task: |
Print exactly the word OK and nothing else, then output /exit.
errorHandling:
strategy: fail-fast
Run 3 rules out the obvious theory that this is about joining a channel that already exists — a brand-new channel name fails exactly the same way.
What is established
The error message is specific. relaycast's packages/engine/src/auth/tokenKind.ts emits Agent token required (at_live_...) from exactly one place — validateTokenRequirement, when a token of a recognised but wrong kind hits an endpoint requiring agent. An unrecognised prefix would produce Invalid token format instead.
So the request carried a well-formed credential of the wrong kind, almost certainly the rk_live_ workspace key that cloud correctly supplies (run/route.ts sets relayApiKey = resolvedRelayWorkspace.relaycastApiKey).
That is odd, because the broker's register path only touches workspace-key endpoints:
| endpoint |
guard |
POST /v1/agents |
requireWorkspaceKey |
POST /v1/agents/:name/rotate-token |
requireWorkspaceKey |
Both accept rk_live_. The only requireAgentToken routes are GET /v1/agent and POST /v1/agent/node-token, which registration should not be calling.
What is still open
Which request actually 401s. Two things hide it:
map_register_agent_token_error in crates/broker/src/cli_mcp_args.rs flattens every 401/403 into register auth error, discarding the path. That alone turned this into a multi-hour investigation — including the failing URL would likely have made it a five-minute fix.
- In
@relayflows/core, the runner sets a channel either way — config.swarm.channel ?? wf-<name>-<shortid> — so this.channel is truthy in both the passing and failing runs. Whatever diverges is downstream of that, and cloud never reads swarm.channel itself (the field only reaches the runner inside the sandbox).
Suggested fixes
- Stop flattening the error so the failing request survives into the message. Worth doing regardless of the root cause.
- Whatever call needs an agent token during registration should use the
at_live_ token registration just minted, not the workspace key.
Impact
Found while running a customer proof of concept on cloud. It cost two full debugging cycles and was initially misattributed twice — first to a repair-agent quirk, then to channel reuse. Both were wrong, and the flattened error is why.
Workaround: omit swarm.channel and let the runner auto-generate one. That is fine for workflows whose agents hand off through files, and not fine for anything that relies on a stable channel name.
Related: AgentWorkforce/cloud#3115, #3116, #3117.
Summary
Any relayflows workflow that sets
swarm.channelfails at its first agent step when run in cloud:Remove the one line and the identical workflow passes.
swarm.channelis a documented, first-class field used by most built-in templates, so this silently breaks a large share of cloud workflows.Reproduction
Three cloud runs of a one-agent, one-step workflow. The only difference between them is the
channel:line.swarm.channel4e40d81048501c5fnative-autopilot7d9f6eaaprobe-unique-a91f3c(never used before)Run 3 rules out the obvious theory that this is about joining a channel that already exists — a brand-new channel name fails exactly the same way.
What is established
The error message is specific. relaycast's
packages/engine/src/auth/tokenKind.tsemitsAgent token required (at_live_...)from exactly one place —validateTokenRequirement, when a token of a recognised but wrong kind hits an endpoint requiringagent. An unrecognised prefix would produceInvalid token formatinstead.So the request carried a well-formed credential of the wrong kind, almost certainly the
rk_live_workspace key that cloud correctly supplies (run/route.tssetsrelayApiKey = resolvedRelayWorkspace.relaycastApiKey).That is odd, because the broker's register path only touches workspace-key endpoints:
POST /v1/agentsrequireWorkspaceKeyPOST /v1/agents/:name/rotate-tokenrequireWorkspaceKeyBoth accept
rk_live_. The onlyrequireAgentTokenroutes areGET /v1/agentandPOST /v1/agent/node-token, which registration should not be calling.What is still open
Which request actually 401s. Two things hide it:
map_register_agent_token_errorincrates/broker/src/cli_mcp_args.rsflattens every 401/403 intoregister auth error, discarding the path. That alone turned this into a multi-hour investigation — including the failing URL would likely have made it a five-minute fix.@relayflows/core, the runner sets a channel either way —config.swarm.channel ?? wf-<name>-<shortid>— sothis.channelis truthy in both the passing and failing runs. Whatever diverges is downstream of that, and cloud never readsswarm.channelitself (the field only reaches the runner inside the sandbox).Suggested fixes
at_live_token registration just minted, not the workspace key.Impact
Found while running a customer proof of concept on cloud. It cost two full debugging cycles and was initially misattributed twice — first to a repair-agent quirk, then to channel reuse. Both were wrong, and the flattened error is why.
Workaround: omit
swarm.channeland let the runner auto-generate one. That is fine for workflows whose agents hand off through files, and not fine for anything that relies on a stable channel name.Related: AgentWorkforce/cloud#3115, #3116, #3117.