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:
Levi Neely 2026-04-25 08:37:33 +02:00
parent 2148c8c668
commit c3df30df3c
1 changed files with 203 additions and 0 deletions

View File

@ -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: