subagent: add -name flag, document roster convention

subagent_spawn now passes -name through to b, letting the parent assign
predictable session IDs. Updated coordination docs: parent passes full
peer roster in seeding prompts, names prefixed with parent session ID
for global uniqueness. Noted silent failure on duplicate names.
This commit is contained in:
Levi Neely 2026-04-26 20:34:27 +02:00
parent 6d635b9180
commit b33a411427
2 changed files with 22 additions and 14 deletions

View File

@ -14,6 +14,7 @@ execute_code: steps=[{tool: "subagent_spawn", args: ["-n", "N", "-agent", "A", "
| Flag | Default | Description |
|---|---|---|
| `-n N` | 1 | Number of parallel subagents, all receiving the same prompt (homogeneous fan-out) |
| `-name NAME` | auto | Session name; predictable IDs let you build a roster before agents start |
| `-agent A` | server default | Agent config name |
| `-backend B` | server default | Backend override |
| `-model M` | server default | Model override |
@ -53,10 +54,13 @@ general mandate.
entry tracking the overall work. This is the one field the parent must always
provide.
**Peers** can be discovered by convention. All sessions live under `s/` and
are named by session ID. Subagents spawned with `-n N` have predictable IDs.
Rather than listing exact peers, describe how to discover them — e.g., "other
subagents working in `$CWD`" — and let the child query `s/` if needed.
**Peers** are known at spawn time. The parent creates the full roster and
assigns `-name` to each subagent, so every peer ID is known before any agent
starts. Pass the complete roster (name → task mapping) in each seeding prompt
so agents can communicate directly without discovery. Names must be globally
unique (they become directories under `s/`); prefix with the parent session ID
to avoid collisions — e.g. `-name ${OLLIE_SESSION_ID}-impl`. Note: duplicate
session names fail silently due to 9P client limitations.
**Rendezvous** is implicit. Every session has a `prompt` file at
`s/{sid}/prompt`. Writing to another session's prompt file always works:
@ -74,21 +78,24 @@ fork-join; the prompt-based completion model is the intended direction.
**Example coordination prompt**:
```
You are the test-writer subagent. Spawned by session $PARENT_SESSION_ID.
Shared task: beads issue #42 ("add auth middleware").
A peer subagent is writing pkg/auth/middleware.go concurrently.
When that file exists, write its tests to pkg/auth/middleware_test.go and run them.
When done, write your result to s/$PARENT_SESSION_ID/prompt.
You are the test-writer subagent (session: ${OLLIE_SESSION_ID}-test-writer).
Parent: $OLLIE_SESSION_ID. Shared task: beads issue #42 ("add auth middleware").
Roster:
${OLLIE_SESSION_ID}-impl — writing pkg/auth/middleware.go
${OLLIE_SESSION_ID}-test-writer (you) — writing pkg/auth/middleware_test.go
When impl's file exists, write tests and run them.
When done, write your result to s/$OLLIE_SESSION_ID/prompt.
```
## Heterogeneous fan-out
To run N subagents with N *different* prompts, use a `{parallel: [...]}` stage. Each entry is an independent `subagent_spawn` call with its own prompt — use this when the subtasks differ:
To run N subagents with N *different* prompts, use a `{parallel: [...]}` stage. Each entry is an independent `subagent_spawn` call with its own prompt and `-name` — use this when the subtasks differ and agents need to know about each other:
```
execute_code: steps=[{parallel: [
{tool: "subagent_spawn", args: ["Summarize core/pkg/agent/loop.go"]},
{tool: "subagent_spawn", args: ["Summarize core/pkg/backend/anthropic.go"]},
{tool: "subagent_spawn", args: ["Summarize 9p/server.go"]}
{tool: "subagent_spawn", args: ["-name", "${OLLIE_SESSION_ID}-impl", "-agent", "coding", "-keep", "You are impl. Parent: $OLLIE_SESSION_ID. Roster: ${OLLIE_SESSION_ID}-impl (you) — write middleware, ${OLLIE_SESSION_ID}-test-writer — write tests. Task: beads #42. Write pkg/auth/middleware.go."]},
{tool: "subagent_spawn", args: ["-name", "${OLLIE_SESSION_ID}-test-writer", "-agent", "qa", "-keep", "You are test-writer. Parent: $OLLIE_SESSION_ID. Roster: ${OLLIE_SESSION_ID}-impl — write middleware, ${OLLIE_SESSION_ID}-test-writer (you) — write tests. Task: beads #42. When pkg/auth/middleware.go exists, write and run its tests."]}
]}], timeout=300
```

View File

@ -1,6 +1,6 @@
#!/usr/bin/env bash
# description: Spawn N subagents with a shared prompt, wait for all to complete, return concatenated results (fork-join).
# Args: [-n N] [-agent A] [-backend B] [-model M] [-cwd DIR] [-keep] <prompt...>
# Args: [-n N] [-name NAME] [-agent A] [-backend B] [-model M] [-cwd DIR] [-keep] <prompt...>
# Output: concatenated results from all subagents, in submission order. With -n > 1, results are separated by === {id} === headers.
set -euo pipefail
@ -13,6 +13,7 @@ n=1; args=()
while [ $# -gt 0 ]; do
case $1 in
-n) n=$2; shift ;;
-name) args+=(-name "$2"); shift ;;
-agent) args+=(-agent "$2"); shift ;;
-backend) args+=(-backend "$2"); shift ;;
-model) args+=(-model "$2"); shift ;;