Skip to content

Re-registering an existing agent name fails with 401 from mcp-args --register #1594

Description

@khaliqgant

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:

  1. 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.
  2. 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

  1. Stop flattening the error so the failing request survives into the message. Worth doing regardless of the root cause.
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions