-
Notifications
You must be signed in to change notification settings - Fork 0
fix(claude-relay-plugin): stop printing workspace keys, use observer tokens #89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,13 +7,15 @@ AGENT_NAME="${RELAY_AGENT_NAME:-the assigned subagent name}" | |
| cat <<EOF | ||
| MANDATORY relay setup — complete these steps IN ORDER before any other work: | ||
|
|
||
| 1. Your task prompt contains a workspace key. Call \`set_workspace_key\` with that key to authenticate. Do not print the key. | ||
| 2. Call \`register_agent(name: "$AGENT_NAME", type: "agent")\` to register with the relay. | ||
| 3. Call \`check_inbox(as: "$AGENT_NAME")\` to get your task assignment. | ||
| 4. Send an ACK to your lead via \`send_dm(as: "$AGENT_NAME")\` when you understand the task. | ||
| 5. When finished, send a DONE message with a concise completion summary via \`send_dm(as: "$AGENT_NAME")\` before stopping. | ||
| 1. Call \`register_agent(name: "$AGENT_NAME", type: "agent")\` to register with the relay. | ||
| The workspace is already pinned to this project, so the relay MCP server resolves it | ||
| for you — you do NOT need a workspace key, and must never print or ask for one. | ||
| If this fails with "Workspace key not configured", report that to your lead. | ||
| 2. Call \`check_inbox(as: "$AGENT_NAME")\` to get your task assignment. | ||
| 3. Send an ACK to your lead via \`send_dm(as: "$AGENT_NAME")\` when you understand the task. | ||
| 4. When finished, send a DONE message with a concise completion summary via \`send_dm(as: "$AGENT_NAME")\` before stopping. | ||
|
|
||
| IMPORTANT: Include \`as: "$AGENT_NAME"\` on EVERY relay tool call to ensure correct message attribution. | ||
|
|
||
| Do NOT skip steps 1-2. Without them you cannot send or receive messages. | ||
| Do NOT skip step 1. Without it you cannot send or receive messages. | ||
|
Comment on lines
+10
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "Tracked files of interest:"
git ls-files | awk '
/plugins\/claude-relay-plugin\/hooks\/subagent-bootstrap\.sh$/ ||
/plugins\/claude-relay-plugin\/agents\/relay-worker\/agent\.md$/ ||
/plugins\/claude-relay-plugin.*agent.*\.md$/ ||
/plugins\/claude-relay-plugin.*\.sh$/
' | sort
echo
echo "subagent-bootstrap.sh relevant lines:"
if [ -f plugins/claude-relay-plugin/hooks/subagent-bootstrap.sh ]; then
nl -ba plugins/claude-relay-plugin/hooks/subagent-bootstrap.sh | sed -n '1,80p'
else
echo "missing plugins/claude-relay-plugin/hooks/subagent-bootstrap.sh"
fi
echo
echo "relay-worker agent.md relevant lines:"
if [ -f plugins/claude-relay-plugin/agents/relay-worker/agent.md ]; then
nl -ba plugins/claude-relay-plugin/agents/relay-worker/agent.md | sed -n '1,80p'
else
echo "missing plugins/claude-relay-plugin/agents/relay-worker/agent.md"
fi
echo
echo "Search for register_agent and workspace key failure wording:"
rg -n 'register_agent|Workspace key not configured|get_observer_url|Agent result|AgentResult|report|lead|retry' plugins/claude-relay-plugin || trueRepository: AgentWorkforce/skills Length of output: 696 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "subagent-bootstrap.sh lines:"
awk 'NR>=1 && NR<=120 { printf "%5d\t%s\n", NR, $0 }' plugins/claude-relay-plugin/hooks/subagent-bootstrap.sh
echo
echo "relay-worker agent.md lines:"
awk 'NR>=1 && NR<=120 { printf "%5d\t%s\n", NR, $0 }' plugins/claude-relay-plugin/agents/relay-worker/agent.md
echo
echo "Search for register_agent and workspace key failure wording:"
grep -RInE 'register_agent|Workspace key not configured|get_observer_url|Agent result|AgentResult|report|lead|retry' plugins/claude-relay-plugin || trueRepository: AgentWorkforce/skills Length of output: 15454 Define the out-of-band failure path for registration failures.
📍 Affects 2 files
🤖 Prompt for AI Agents |
||
| EOF | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,49 +11,45 @@ $ARGUMENTS | |
|
|
||
| ## How spawning works | ||
|
|
||
| Workers are spawned using Claude Code's built-in **Agent tool**, not the relay MCP tools. The relay is only used for communication between agents. | ||
| Workers are spawned with Claude Code's built-in **Agent tool**. The relay is only used for communication between agents. | ||
|
|
||
| - You **must** use `subagent_type: "relay-worker"` when spawning workers. Only `relay-worker` subagents get the Agent Relay MCP server, inbox-polling hooks, and the worker protocol. Regular subagent types (e.g. `researcher`, `general-purpose`) cannot communicate via relay. | ||
| - Run all workers in **background mode** (`run_in_background: true`) so they execute concurrently. | ||
| - Each worker's prompt **must include the workspace key** so the worker can authenticate. See the spawn example below. | ||
| - The `SubagentStart` hook automatically injects relay bootstrap instructions into every spawned worker. | ||
| - Do not introduce extra setup scripts or dependencies in this workflow. Use the existing plugin hooks, Agent Relay MCP tools, and `relay-worker` agent definition only. | ||
| - Use relay MCP tools (`send_dm`, `check_inbox`) to monitor worker progress. | ||
| - Use `subagent_type: "relay-worker"`. Only `relay-worker` subagents get the Agent Relay MCP server, the inbox-polling hooks, and the worker protocol. Other subagent types (`researcher`, `general-purpose`, …) cannot talk over the relay. | ||
| - Run all workers in **background mode** (`run_in_background: true`) so they work concurrently. | ||
| - Workers inherit the workspace automatically — the relay MCP server resolves the workspace pinned to this project. **Do not put the workspace key in a worker prompt.** It is an administrative credential, and copying it into N prompts puts it in N transcripts. If a worker reports no workspace, fix the pin (step 2) rather than pasting the key. | ||
| - The `SubagentStart` hook injects the relay bootstrap (register, check inbox, ACK, DONE) into every worker. | ||
| - Use the relay MCP tools (`send_dm`, `check_inbox`) to monitor progress. | ||
| - Do not add setup scripts or dependencies. Use the plugin's existing hooks, MCP tools, and `relay-worker` agent definition. | ||
|
|
||
| ## Protocol | ||
|
|
||
| 1. Pick a stable coordinator name such as `relay-lead`. On every relay tool call you make as the coordinator, include `as: "relay-lead"` so your messages, inbox checks, and reactions stay attributed to the lead. | ||
| 2. **Set up the workspace.** Try calling `register_agent` with a coordinator name like `relay-lead`. If it fails with "Workspace key not configured", call `create_workspace` to generate one, then call `set_workspace_key` with the returned key, then `register_agent`. Save the workspace key — you will pass it to every worker. | ||
| 3. **Tell the user they can follow along with the conversation.** Print the full observer URL with the real key value: `https://agentrelay.com/observer?key=<the actual key>`. Do not print a placeholder — print the real URL the user can click. This is mandatory. | ||
| 4. Confirm the work is truly parallelizable. Every worker should be able to finish without waiting on another worker's output. | ||
| 5. Decide the worker count from the task shape. Prefer 2 to 8 workers, but keep the count low enough that you can still monitor ACKs and completions reliably. | ||
| 6. Partition the work into independent units. Each unit should have its own files, target, or scope boundary and should not require shared intermediate state. | ||
| 7. Spawn one worker per unit using the Agent tool. **You must include the workspace key in the prompt**: | ||
| 1. Pick a stable coordinator name — `relay-lead`. Pass `as: "relay-lead"` on **every** relay tool call you make, so your messages, inbox reads, and reactions stay attributed to the lead. | ||
| 2. **Set up the workspace.** Call `register_agent` with `relay-lead`. If it fails with "Workspace key not configured", call `create_workspace`, then `register_agent` again. Both `create_workspace` and `set_workspace_key` pin the workspace to this project, which is how workers pick it up. | ||
| 3. **Give the user a link to follow along.** Call `get_observer_url` and print the URL it returns. It is backed by a read-only token that expires, so it is safe to share. Never build an observer URL from the workspace key, and never print the key. | ||
| 4. Confirm the work is genuinely parallelizable. Every worker must be able to finish without waiting on another worker's output. If that is not true, use the pipeline pattern instead. | ||
| 5. Pick the worker count from the task shape. Prefer 2–8, and stay low enough that you can still track every ACK and DONE. | ||
| 6. Partition the work into independent units — each with its own files, target, or scope boundary, and no shared intermediate state. | ||
| 7. Spawn one worker per unit with the Agent tool: | ||
| ``` | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Add language identifiers to the fenced examples.
🧰 Tools🪛 markdownlint-cli2 (0.23.1)[warning] 32-32: Fenced code blocks should have a language specified (MD040, fenced-code-language) 📍 Affects 3 files
🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||
| Agent( | ||
| subagent_type: "relay-worker", | ||
| run_in_background: true, | ||
| prompt: "You are relay-worker-N. Your lead is relay-lead. | ||
| Workspace key: <the actual key>. | ||
| CRITICAL: On every relay tool call, include as: \"relay-worker-N\". Without as, your messages can be attributed to another agent. | ||
| CRITICAL: pass as: \"relay-worker-N\" on every relay tool call, or your messages | ||
| can be attributed to another agent. | ||
| Your unit: [specific target/scope]. | ||
| Files: [list of files/directories]. | ||
| Deliver: [concrete output]." | ||
| Deliver: [concrete output]. | ||
| Do NOT release yourself when done — report DONE and stay idle for review." | ||
| ) | ||
| ``` | ||
| 8. Each worker's prompt must include: | ||
| - the workspace key | ||
| - the unit it owns | ||
| - the exact files, directories, or target it should handle | ||
| - its assigned relay name and who its lead is | ||
| - a reminder to use `as: "<worker-name>"` on every relay tool call | ||
| 9. Wait for ACK from every worker via relay inbox with `check_inbox(as: "relay-lead")`. Missing ACK means the worker is not ready. | ||
| 10. Let workers run independently. Only send follow-up DMs for blockers, missing ACKs, or a global decision that changes all units, always using `as: "relay-lead"` for coordinator messages. | ||
| 11. Collect all DONE messages, verify the outputs, and merge the final summary. Call out any units that finished partially or encountered blockers. | ||
| 8. Wait for an ACK from every worker with `check_inbox(as: "relay-lead")`. A missing ACK means that worker is not working — re-DM it. | ||
| 9. Keep a live worker table in your notes: name, unit, ACK, blocked, DONE. | ||
| 10. Let workers run independently. Only DM them for blockers, missing ACKs, or a global decision that changes every unit. | ||
| 11. Collect every DONE, verify the outputs yourself, and merge the summary. Call out units that finished partially or hit blockers. | ||
|
|
||
| ## Rules | ||
|
|
||
| - Do not use this pattern when stage N depends on stage N-1. That is a pipeline. | ||
| - Do not give multiple workers the same files unless duplicate review is intentional. | ||
| - Keep the task wording uniform so worker outputs are easy to compare and merge. | ||
| - Workers cannot spawn their own subagents — only the lead can spawn workers. | ||
| - Do not give two workers the same files unless duplicate review is the point. | ||
| - Keep the task wording uniform across units so the outputs are easy to compare and merge. | ||
| - Workers cannot spawn their own subagents — only the lead spawns. | ||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -11,57 +11,55 @@ $ARGUMENTS | |||||||||||
|
|
||||||||||||
| ## How spawning works | ||||||||||||
|
|
||||||||||||
| Workers are spawned using Claude Code's built-in **Agent tool**, not the relay MCP tools. The relay is only used for communication between agents. | ||||||||||||
| Workers are spawned with Claude Code's built-in **Agent tool**. The relay is only used for communication between agents. | ||||||||||||
|
|
||||||||||||
| - You **must** use `subagent_type: "relay-worker"` when spawning workers. Only `relay-worker` subagents get the Agent Relay MCP server, inbox-polling hooks, and the worker protocol. Regular subagent types (e.g. `researcher`, `general-purpose`) cannot communicate via relay. | ||||||||||||
| - Run pipeline stages in **foreground mode** (default) so you wait for each stage to complete before starting the next. | ||||||||||||
| - Each worker's prompt **must include the workspace key** so the worker can authenticate. See the spawn example below. | ||||||||||||
| - The `SubagentStart` hook automatically injects relay bootstrap instructions into every spawned worker. | ||||||||||||
| - Do not introduce extra setup scripts or dependencies in this workflow. Use the existing plugin hooks, Agent Relay MCP tools, and `relay-worker` agent definition only. | ||||||||||||
| - Use relay MCP tools (`send_dm`, `check_inbox`) to receive handoff artifacts from each stage. | ||||||||||||
| - Use `subagent_type: "relay-worker"`. Only `relay-worker` subagents get the Agent Relay MCP server, the inbox-polling hooks, and the worker protocol. Other subagent types (`researcher`, `general-purpose`, …) cannot talk over the relay. | ||||||||||||
| - Run pipeline stages in **foreground mode** (the default) so each stage finishes before the next starts. | ||||||||||||
| - Workers inherit the workspace automatically — the relay MCP server resolves the workspace pinned to this project. **Do not put the workspace key in a worker prompt.** It is an administrative credential, and copying it into N prompts puts it in N transcripts. If a worker reports no workspace, fix the pin (step 2) rather than pasting the key. | ||||||||||||
| - The `SubagentStart` hook injects the relay bootstrap (register, check inbox, ACK, DONE) into every worker. | ||||||||||||
| - Use the relay MCP tools (`send_dm`, `check_inbox`) to receive each stage's handoff. | ||||||||||||
| - Do not add setup scripts or dependencies. Use the plugin's existing hooks, MCP tools, and `relay-worker` agent definition. | ||||||||||||
|
|
||||||||||||
| ## Protocol | ||||||||||||
|
|
||||||||||||
| 1. Pick a stable coordinator name such as `relay-lead`. On every relay tool call you make as the coordinator, include `as: "relay-lead"` so your messages, inbox checks, and reactions stay attributed to the lead. | ||||||||||||
| 2. **Set up the workspace.** Try calling `register_agent` with a coordinator name like `relay-lead`. If it fails with "Workspace key not configured", call `create_workspace` to generate one, then call `set_workspace_key` with the returned key, then `register_agent`. Save the workspace key — you will pass it to every worker. | ||||||||||||
| 3. **Tell the user they can follow along with the conversation.** Print the full observer URL with the real key value: `https://agentrelay.com/observer?key=<the actual key>`. Do not print a placeholder — print the real URL the user can click. This is mandatory. | ||||||||||||
| 4. Break the task into ordered stages. Each stage must have a clear handoff artifact for the next stage: a summary, decision, file path, diff, or verified output. | ||||||||||||
| 5. Keep the number of stages low and explicit. Prefer 2 to 5 stages with distinct responsibilities. | ||||||||||||
| 6. Start stage 1. Spawn its worker using the Agent tool in foreground mode. **Include the workspace key**: | ||||||||||||
| 1. Pick a stable coordinator name — `relay-lead`. Pass `as: "relay-lead"` on **every** relay tool call you make, so your messages, inbox reads, and reactions stay attributed to the lead. | ||||||||||||
| 2. **Set up the workspace.** Call `register_agent` with `relay-lead`. If it fails with "Workspace key not configured", call `create_workspace`, then `register_agent` again. Both `create_workspace` and `set_workspace_key` pin the workspace to this project, which is how workers pick it up. | ||||||||||||
| 3. **Give the user a link to follow along.** Call `get_observer_url` and print the URL it returns. It is backed by a read-only token that expires, so it is safe to share. Never build an observer URL from the workspace key, and never print the key. | ||||||||||||
| 4. Break the task into ordered stages. Every stage needs a concrete handoff artifact for the next one: a summary, a decision, a file path, a diff, or a verified output. | ||||||||||||
| 5. Keep the stage count low and explicit — prefer 2–5 with distinct responsibilities. | ||||||||||||
| 6. Start stage 1. Spawn its worker with the Agent tool in foreground mode: | ||||||||||||
| ``` | ||||||||||||
| Agent( | ||||||||||||
| subagent_type: "relay-worker", | ||||||||||||
| prompt: "You are relay-stage-1. Your lead is relay-lead. | ||||||||||||
| Workspace key: <the actual key>. | ||||||||||||
| CRITICAL: On every relay tool call, include as: \"relay-stage-1\". Without as, your messages can be attributed to another agent. | ||||||||||||
| CRITICAL: pass as: \"relay-stage-1\" on every relay tool call, or your messages | ||||||||||||
| can be attributed to another agent. | ||||||||||||
| Your task: [stage 1 scope]. | ||||||||||||
| Files: [relevant files]. | ||||||||||||
| When done, send your lead a DONE message with: [handoff artifact description]." | ||||||||||||
| When done, DM your lead a DONE message containing: [handoff artifact description]. | ||||||||||||
| Do NOT release yourself when done — stay idle in case the stage needs a fix." | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: The new "Do NOT release yourself when done — stay idle" instruction conflicts with this skill's foreground mode. The pipeline spawns each stage with the Agent tool in foreground (blocking), and step 7 makes the lead wait for stage 1's DONE via check_inbox before spawning stage 2. If the stage worker stays idle instead of returning, the foreground Agent call never releases control, so the lead can never run check_inbox or spawn the next stage — the pipeline stalls after stage 1. This guidance is correct for team/fanout (background workers), but in a foreground pipeline the worker must release when done. Prompt for AI agents |
||||||||||||
| ) | ||||||||||||
| ``` | ||||||||||||
| 7. Wait for the stage 1 DONE message via relay inbox with `check_inbox(as: "relay-lead")`. Do not start downstream work on assumptions. | ||||||||||||
| 8. For each later stage, spawn a new worker with: | ||||||||||||
| - the workspace key | ||||||||||||
| - the original task context | ||||||||||||
| - the upstream DONE summary and handoff artifact | ||||||||||||
| - any produced files, decisions, or constraints from previous stages | ||||||||||||
| 7. Wait for stage 1's DONE with `check_inbox(as: "relay-lead")`. Never start downstream work on an assumption about what the stage produced. | ||||||||||||
| 8. For each later stage, spawn a worker carrying the original task context, the upstream DONE summary and handoff artifact, and any files, decisions, or constraints the earlier stages produced: | ||||||||||||
| ``` | ||||||||||||
| Agent( | ||||||||||||
| subagent_type: "relay-worker", | ||||||||||||
| prompt: "You are relay-stage-2. Your lead is relay-lead. | ||||||||||||
| Workspace key: <the actual key>. | ||||||||||||
| CRITICAL: On every relay tool call, include as: \"relay-stage-2\". Without as, your messages can be attributed to another agent. | ||||||||||||
| CRITICAL: pass as: \"relay-stage-2\" on every relay tool call. | ||||||||||||
| Previous stage completed: [DONE summary from stage 1]. | ||||||||||||
| Your task: [stage 2 scope using stage 1 output]. | ||||||||||||
| Files: [relevant files]." | ||||||||||||
| Your task: [stage 2 scope, using stage 1's output]. | ||||||||||||
| Files: [relevant files]. | ||||||||||||
| Do NOT release yourself when done — stay idle in case the stage needs a fix." | ||||||||||||
|
Comment on lines
+52
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: The stage 1 spawn template requires the worker to send a DONE message containing the handoff artifact, but the later-stage (stage 2+) template dropped this requirement — it only tells the worker not to self-release, without specifying what the final DONE message must contain. Downstream stages (and the final stage in particular) need an explicit handoff/evidence requirement so the lead isn't left validating an undefined deliverable. Prompt for AI agents
Suggested change
|
||||||||||||
| ) | ||||||||||||
|
Comment on lines
+44
to
54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "Files matching SKILL.md in relay-pipeline:"
fd -a 'SKILL\.md$' . | sed 's#^\./##' | grep 'plugins/claude-relay-plugin/skills/relay-pipeline/SKILL.md' || true
echo
echo "Relevant section:"
sed -n '1,140p' plugins/claude-relay-plugin/skills/relay-pipeline/SKILL.md
echo
echo "Search for handoff/DONE/evidence in skill files:"
rg -n "handoff|handoff artifact|DONE|final evidence|relay-stage|subagent_type|release|DM your lead" plugins/claude-relay-plugin/skills/relay-pipeline -SRepository: AgentWorkforce/skills Length of output: 8051 Require a handoff artifact from every later stage. Stage 1 enforces 🧰 Tools🪛 markdownlint-cli2 (0.23.1)[warning] 45-45: Fenced code blocks should have a language specified (MD040, fenced-code-language) 🤖 Prompt for AI Agents |
||||||||||||
| ``` | ||||||||||||
| 9. After each stage finishes, validate that the handoff is sufficient. If the output is ambiguous, ask the user for clarification before starting the next stage. | ||||||||||||
| 10. Continue until the final stage completes, then synthesize the end-to-end result and highlight where each handoff happened. | ||||||||||||
| 9. Keep a live stage table in your notes: stage, scope, ACK, blocked, DONE, handoff artifact. | ||||||||||||
| 10. After each stage, check the handoff is sufficient. If it is ambiguous, ask the user before starting the next stage. | ||||||||||||
| 11. When the last stage finishes, synthesize the end-to-end result and show where each handoff happened. | ||||||||||||
|
|
||||||||||||
| ## Rules | ||||||||||||
|
|
||||||||||||
| - Use pipeline only for genuine dependencies. If stages can run independently, switch to fan-out. | ||||||||||||
| - Handoffs must be explicit. A downstream worker should never need to guess what mattered from the previous stage. | ||||||||||||
| - If a stage fails or is blocked, stop the pipeline, resolve the blocker, and then resume from the blocked stage. | ||||||||||||
| - Workers cannot spawn their own subagents — only the lead can spawn workers. | ||||||||||||
| - Use a pipeline only for genuine dependencies. If the stages can run independently, switch to fan-out. | ||||||||||||
| - Handoffs must be explicit. A downstream worker should never have to guess what mattered upstream. | ||||||||||||
| - If a stage fails or is blocked, stop the pipeline, resolve the blocker, and resume from that stage. | ||||||||||||
| - Workers cannot spawn their own subagents — only the lead spawns. | ||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: The new registration-failure guidance says to "report that to your lead" on a 'Workspace key not configured' failure, but registration is a prerequisite for any relay messaging (send_dm/check_inbox). Since the worker can't message its lead over relay until it's registered, this instruction needs an explicit out-of-band failure channel (e.g., surfacing the failure via the Agent tool's result) rather than relying on relay messaging that hasn't been established yet.
Prompt for AI agents