doc/IDEAS.md: polish predefined workflows; fix stale prompt reference

Update send() to use statewait (eliminates busy-wait polling race on
submit). Fix stale prompts/08_subagents.md ref → prompts/tools-subagent.md.
Remove redundant offset explanation from prose.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Levi Neely 2026-04-19 20:17:43 +02:00
parent 6516aacb8c
commit 186f935cbb
1 changed files with 15 additions and 7 deletions

View File

@ -17,13 +17,13 @@ Two distinct patterns apply depending on whether work is delegated to ephemeral
For one-off focused tasks, use `subagent_spawn`. The parent spawns one or more jobs via the `b/` namespace, blocks until all complete, and reads the results. The subagents are ephemeral — they exist for the duration of one job and are torn down automatically. This is the right pattern for parallelising independent subtasks within a single workflow.
See `prompts/08_subagents.md` and `skills/session-management/SKILL.md` for usage.
See `prompts/tools-subagent.md` and `skills/session-management/SKILL.md` for usage.
#### Concurrent sessions
For workflows where multiple long-lived agents work in parallel and need to coordinate, the mechanism is direct prompt passing. Each agent is told its own session ID and its peers' IDs at startup. When an agent finishes a step and wants to hand off, it writes the result to another session's `prompt` — a plain file write from within `execute_code`. Writing to `prompt` queues by default, so a busy agent will not drop a message.
When a peer needs to read back the response it triggered, it polls the target session's `state` until idle, then reads `offset` and extracts the new output: `tail -c +$((offset+1)) s/$peer/chat`. The server sets `offset` to the byte position immediately after the user prompt is appended, so everything from that position to EOF is exactly the model response for that turn.
When a peer needs to read back the response it triggered, it waits for `state` to return to idle, then reads `offset` and extracts the new output: `tail -c +$((offset+1)) s/$peer/chat`. The server sets `offset` to the byte position immediately after the user prompt is appended, so everything from that position to EOF is exactly the model response for that turn.
No external coordinator is needed after the initial kickoff. The agents themselves route work based on context in their prompts. A human can intervene at any time by writing to any session's `prompt`.
@ -31,7 +31,7 @@ Each agent can use a different backend, model, or tool configuration. The bounda
#### Predefined workflows
When the coordination logic is known in advance, a shell script can drive the entire workflow externally. Named sessions make routing unambiguous. The server updates `offset` to the byte position immediately after the user prompt is appended to chat. After the agent goes idle, `tail -c +$((offset+1))` yields exactly the model response for that turn.
When the coordination logic is known in advance, a shell script can drive the entire workflow externally. Named sessions make routing unambiguous; `statewait` eliminates polling races on submit.
```sh
#!/bin/sh
@ -43,13 +43,21 @@ echo "name=reviewer agent=reviewer cwd=$cwd" > s/new
echo "name=tester agent=tester cwd=$cwd" > s/new
# Send a prompt and return the model response.
# The server sets offset after the user prompt is appended to chat;
# everything from offset to EOF is the model response for that turn.
# Opens statewait before writing prompt so the "idle" baseline is snapshotted
# before the agent has a chance to start processing. The server sets offset to
# the byte position immediately after the user prompt is appended to chat;
# everything from that position to EOF is the model response for that turn.
send() {
sid=$1; shift
exec 3< s/$sid/statewait
printf '%s' "$*" > s/$sid/prompt
while [ "$(cat s/$sid/state)" = "idle" ]; do sleep 0.2; done
while [ "$(cat s/$sid/state)" != "idle" ]; do sleep 1; done
while true; do
read -r _ <&3 && { exec 3<&- 2>/dev/null; break; }
exec 3<&-
[ "$(cat s/$sid/state)" != "idle" ] && break
exec 3< s/$sid/statewait
done
until [ "$(cat s/$sid/state)" = "idle" ]; do sleep 0.5; done
tail -c +$(($(cat s/$sid/offset) + 1)) s/$sid/chat
}