Skip to content

Concurrent relay teams in one checkout cross workers through the shared project workspace pin #1587

Description

@willwashburn

Split out of review on AgentWorkforce/skills#89, where the plugin skills stopped copying the workspace key into every worker prompt and now rely on the project pin instead. That removed a real credential leak, but it surfaced this: the pin is a single last-writer-wins slot, so it cannot safely serve two concurrent relay teams in the same checkout.

Problem

A spawned worker has no way to be told which workspace to join except the project pin.

  • persistWorkspaceSession writes the pin via writeProjectWorkspaceKey — one slot per project (packages/cli/src/cli/lib/workspace-session.ts:73,102).
  • Both MCP entry points write it: create_workspace (packages/cli/src/cli/agent-relay-mcp.ts:803) and set_workspace_key (:867).
  • A worker's MCP server resolves it through optionsFromEnvresolveWorkspaceSessionKey() (:1486).

So with two Claude sessions running relay teams from the same directory:

  1. Lead A calls create_workspace → pin = W1.
  2. Lead B calls create_workspace → pin = W2.
  3. Lead A spawns a worker → the worker resolves W2 and registers in lead B's workspace.

The worker is live and healthy, just in the wrong place. Lead A never sees it.

This is the same mechanism as #1440, which shows the damage an unintended pin overwrite already causes in practice — nightcto-sf, nightcto-finn, nightcto-barry and relayauth-finn-0803 all ended up in an auto-provisioned workspace and became invisible to fleet tooling. That issue is about node up overwriting the pin; this one is about two writers racing for it. Same slot, different trigger.

Why the obvious fixes don't work

  • Put the key back in the worker prompt. This is what skills#89 removed. It trades a rare cross-workspace bug for a guaranteed one: an administrative credential copied into N prompts and N transcripts on every run. Closely related to Broker passes live workspace key and agent tokens as plaintext argv to every spawned agent #1570.
  • Have the lead pass the workspace some other way. A lead's only channel to a subagent is the prompt, so anything it passes lands in the transcript. There is no run-scoped handoff today.

Current mitigation (skills#89)

Documented as a constraint rather than fixed — one relay team per checkout, use separate checkouts or worktrees for concurrent teams. The failure is at least loud now: a worker in the wrong workspace finds no assignment in check_inbox and cannot ACK, and it reports that out-of-band instead of guessing at the work. Previously it failed silently.

What would actually fix it

A run- or session-scoped workspace handoff that doesn't route through the prompt and doesn't collide across concurrent sessions. Rough shapes, not a recommendation:

  • A scoped, short-lived spawn token the lead mints per worker, redeemable once for workspace context.
  • Keying the pin by session/run id rather than by project alone, so concurrent leads get separate slots.
  • An env-based handoff on the spawn boundary, if the harness gives the parent a way to set child environment.

Acceptance

  • Two leads running relay teams from the same checkout can each spawn workers that register into their own workspace.
  • No workspace key appears in any worker prompt or transcript.
  • Covered by a test that runs two concurrent leads against one project directory.

Refs AgentWorkforce/skills#89, #1440, #1570

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions