docs: add multi-agent workflows and store federation to USAGE.md
Promote IDEAS.md content to concrete how-to documentation: subagent delegation via subagent_spawn, concurrent sessions with direct prompt passing (prompt/statewait/offset), predefined shell-script workflows, self-generating workflows, and store federation via OLLIE_TOOLS_PATH and OLLIE_TRANSCRIPT_PATH pointing at 9pfuse-mounted remote dirs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2148c8c668
commit
c3df30df3c
203
doc/USAGE.md
203
doc/USAGE.md
|
|
@ -168,6 +168,209 @@ prompt=$($OLLIE/u/optimize "translate this to Spanish" 2>/dev/null)
|
|||
cat document.txt | $OLLIE/s/bfg "$prompt"
|
||||
```
|
||||
|
||||
## Multi-agent workflows
|
||||
|
||||
Two patterns cover most multi-agent use cases: ephemeral subagent delegation for
|
||||
independent parallel subtasks, and persistent concurrent sessions for workflows that
|
||||
need coordination or long-lived state.
|
||||
|
||||
### Subagent delegation
|
||||
|
||||
`subagent_spawn` is a tool script that forks N ephemeral agents with a shared prompt,
|
||||
waits for all to finish, and returns their results concatenated in submission order. It
|
||||
is the right tool when work can be split into independent subtasks that don't need to
|
||||
talk to each other.
|
||||
|
||||
The agent invokes it via `execute_code`:
|
||||
|
||||
```json
|
||||
{
|
||||
"steps": [{"tool": "subagent_spawn", "args": "-n 3 summarize this module"}]
|
||||
}
|
||||
```
|
||||
|
||||
Or from a shell step:
|
||||
|
||||
```sh
|
||||
subagent_spawn -n 3 "review this diff for security issues"
|
||||
subagent_spawn -n 1 -agent reviewer -cwd /path/to/repo "check for style violations"
|
||||
```
|
||||
|
||||
**Flags**
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `-n N` | Number of subagents to spawn (default: 1) |
|
||||
| `-agent A` | Agent config for each subagent |
|
||||
| `-backend B` | Backend override |
|
||||
| `-model M` | Model override |
|
||||
| `-cwd DIR` | Working directory for subagents (default: `pwd`) |
|
||||
| `-keep` | Do not remove sessions after collecting results |
|
||||
|
||||
With `-n 1` (the default) the result is just the single agent's output. With `-n > 1`
|
||||
results are separated by `=== {id} ===` headers.
|
||||
|
||||
### Concurrent sessions
|
||||
|
||||
For workflows where multiple long-lived agents work in parallel and hand off to each
|
||||
other, the mechanism is direct prompt passing via the filesystem. Each agent has a
|
||||
`prompt` file that accepts writes; writing to it queues a new turn, so a busy agent
|
||||
will not drop a message.
|
||||
|
||||
**Create named sessions:**
|
||||
|
||||
```sh
|
||||
printf 'name=writer\ncwd=%s\n' "$PWD" > $OLLIE/s/new
|
||||
printf 'name=reviewer\ncwd=%s\n' "$PWD" > $OLLIE/s/new
|
||||
```
|
||||
|
||||
**Send a prompt and read the response:**
|
||||
|
||||
```sh
|
||||
# Queue a prompt on a named session
|
||||
printf '%s\n' "Draft a design doc for the new cache layer." > $OLLIE/s/writer/prompt
|
||||
|
||||
# Wait for the turn to finish (statewait blocks until state changes)
|
||||
until [ "$(cat $OLLIE/s/writer/statewait)" = "idle" ]; do :; done
|
||||
|
||||
# Read only the new output (offset marks the byte position after the user prompt)
|
||||
tail -c +$(($(cat $OLLIE/s/writer/offset) + 1)) $OLLIE/s/writer/chat
|
||||
```
|
||||
|
||||
**Key files per session:**
|
||||
|
||||
| File | Mode | Description |
|
||||
|---|---|---|
|
||||
| `prompt` | write | Queue a new turn; writes are enqueued if agent is busy |
|
||||
| `statewait` | read (blocking) | Blocks until state changes; returns new state |
|
||||
| `state` | read | Current state: `idle`, `running`, `failed: <reason>` |
|
||||
| `chat` | read | Full conversation transcript |
|
||||
| `offset` | read | Byte position in `chat` immediately after the last user prompt |
|
||||
|
||||
Reading `offset` before writing `prompt`, then extracting `chat[offset:]` after the
|
||||
turn completes, isolates exactly the model's response for that turn.
|
||||
|
||||
### Predefined workflows
|
||||
|
||||
When coordination logic is known in advance, a shell script can drive the entire
|
||||
workflow. Named sessions make routing unambiguous; `statewait` eliminates polling
|
||||
races. No external coordinator process is needed — the script is the coordinator.
|
||||
|
||||
The following example implements a write → review → test loop. The developer agent
|
||||
revises until the reviewer approves, then the tester validates:
|
||||
|
||||
```sh
|
||||
#!/bin/sh
|
||||
cwd=${1:?usage: $0 <cwd>}
|
||||
cd $OLLIE
|
||||
|
||||
printf 'name=developer\nagent=developer\ncwd=%s\n' "$cwd" > s/new
|
||||
printf 'name=reviewer\nagent=reviewer\ncwd=%s\n' "$cwd" > s/new
|
||||
printf 'name=tester\nagent=tester\ncwd=%s\n' "$cwd" > s/new
|
||||
|
||||
# Send a prompt to a named session and return the model's response.
|
||||
# Opens statewait before writing the prompt so the idle baseline is captured
|
||||
# before the agent starts processing. offset marks the byte position after the
|
||||
# user prompt in chat; everything from that position to EOF is the model response.
|
||||
send() {
|
||||
sid=$1; shift
|
||||
exec 3< s/$sid/statewait
|
||||
printf '%s' "$*" > s/$sid/prompt
|
||||
while true; do
|
||||
read -r _ <&3 && { exec 3<&-; 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
|
||||
}
|
||||
|
||||
reply=$(send developer "Implement a function that parses a JSON config file.")
|
||||
|
||||
while true; do
|
||||
review=$(send reviewer "Review the following code. Reply LGTM if ready, or PTAL with feedback.
|
||||
|
||||
$reply")
|
||||
|
||||
if ! printf '%s' "$review" | grep -qi "LGTM"; then
|
||||
reply=$(send developer "Revise based on this feedback:
|
||||
|
||||
$review")
|
||||
continue
|
||||
fi
|
||||
|
||||
result=$(send tester "Test the following code. Reply Approved if all tests pass, or Rejected with details.
|
||||
|
||||
$reply")
|
||||
|
||||
if printf '%s' "$result" | grep -qi "Approved"; then
|
||||
printf '%s\n' "$reply"
|
||||
break
|
||||
fi
|
||||
|
||||
reply=$(send developer "Fix the following test failures:
|
||||
|
||||
$result")
|
||||
done
|
||||
|
||||
rm -r s/developer s/reviewer s/tester
|
||||
```
|
||||
|
||||
The agents have no knowledge of each other — the script holds all the routing logic.
|
||||
A human can intervene at any time by writing directly to any session's `prompt`.
|
||||
Each agent can use a different `agent=`, `backend=`, or `model=` — set them in the
|
||||
`s/new` spec lines.
|
||||
|
||||
### Self-generating workflows
|
||||
|
||||
Because agents have access to `execute_code`, a session can write and run a workflow
|
||||
script without any human involvement. Given a task description and knowledge of the
|
||||
filesystem layout, an agent can decompose the work, create the named sessions, write
|
||||
the coordination script to a temp file, and execute it — all in a single turn.
|
||||
|
||||
The architecture documents (`ARCHITECTURE.md`, `USAGE.md`) and tool descriptions
|
||||
(available via `t/idx`) are the agent's reference. No additional scaffolding is needed.
|
||||
|
||||
## Store federation
|
||||
|
||||
`OLLIE_TOOLS_PATH` and `OLLIE_TRANSCRIPT_PATH` are ordinary filesystem paths. Because
|
||||
`olliesrv` speaks 9P and any remote instance can be mounted locally via `9pfuse`, these
|
||||
vars can point at remote directories with no code changes — the OS handles the proxying
|
||||
transparently.
|
||||
|
||||
### Centralized tool distribution
|
||||
|
||||
Host one authoritative tool set and point all machines at it:
|
||||
|
||||
```sh
|
||||
# On each client machine:
|
||||
olliesrv mount toolserver:9564 ~/mnt/toolserver
|
||||
export OLLIE_TOOLS_PATH=~/mnt/toolserver/t
|
||||
```
|
||||
|
||||
Every agent on every host now uses the same tool scripts. Update tools in one place;
|
||||
all clients pick up the change immediately.
|
||||
|
||||
### Centralized transcript archive
|
||||
|
||||
Collect transcripts from all hosts in one place:
|
||||
|
||||
```sh
|
||||
olliesrv mount archivehost:9564 ~/mnt/archive
|
||||
export OLLIE_TRANSCRIPT_PATH=~/mnt/archive/tr
|
||||
```
|
||||
|
||||
Sessions started after this change write their transcripts to the remote host.
|
||||
Existing sessions are unaffected.
|
||||
|
||||
Both vars can be combined. Set them in `~/.config/ollie/env` for persistence:
|
||||
|
||||
```
|
||||
OLLIE_TOOLS_PATH=~/mnt/toolserver/t
|
||||
OLLIE_TRANSCRIPT_PATH=~/mnt/archive/tr
|
||||
```
|
||||
|
||||
## Alternative front-ends
|
||||
|
||||
The 9P filesystem is the lowest level interface to ollie. All interfaces are simply wrappers around filesystem operations, and `s/sh` is the standard chat interface. A couple of other front-ends are also provided:
|
||||
|
|
|
|||
Loading…
Reference in New Issue