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 optionsFromEnv → resolveWorkspaceSessionKey() (: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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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