doc: MULTI_AGENT.md — coordination patterns enabled by agent-as-filesystem

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Levi Neely 2026-04-28 15:07:13 +02:00
parent b0514ea34f
commit 524cbde6d3
1 changed files with 148 additions and 0 deletions

148
doc/MULTI_AGENT.md Normal file
View File

@ -0,0 +1,148 @@
# Multi-Agent Coordination
ollie exposes agents as filesystem objects via the 9P protocol. This means
multi-agent coordination requires no framework, SDK, or message bus — it is
ordinary shell scripting against a mounted filesystem.
## The Namespace
Every session lives under `/s/{id}/`:
| Path | Purpose |
|------|---------|
| `/s/new` | Create a session (write `name`, `backend`, `model`, `agent`, `cwd`) |
| `/s/{id}/prompt` | Submit a prompt (dispatched async on close) |
| `/s/{id}/chat` | Cumulative conversation history (append-only read) |
| `/s/{id}/state` | Current state: `idle`, `thinking`, `calling:<tool>` |
| `/s/{id}/statewait` | **Blocking read** — returns when state changes |
| `/s/{id}/ctl` | Control commands: `stop`, `kill`, `compact`, model/backend switches |
| `/s/{id}/cfg` | Mutable session config (KV pairs) |
Utility files at the session root (`/s/`) provide higher-level operations:
| File | Purpose |
|------|---------|
| `/s/b` | One-shot: create, submit, wait, print result, kill |
| `/s/bfg` | Batch foreground: submit to existing session, wait, print |
| `/s/bbg` | Batch background: submit, return session path immediately |
| `/s/sh` | Interactive shell session |
Global namespaces are shared across all sessions:
| Path | Purpose |
|------|---------|
| `/t/{name}` | Tool scripts (read/write) |
| `/t/idx` | Synthesized tool index (descriptions + args) |
| `/a/{name}.json` | Agent configs (supports `mv`, `cp`, `rm`) |
| `/sk/{name}` | Skill files |
| `/p/{name}` | Prompt templates |
## Spawning Agents
From within an agent session, use `subagent_spawn`:
```sh
subagent_spawn [-name NAME] [-agent AGENT] [-backend BACKEND] [-model MODEL] [-cwd DIR] <prompt>
```
This creates a child session, writes the prompt, and returns the session path
(e.g. `s/my-session`). Child sessions carry the parent session ID in their name,
so the spawning tree is recoverable from session IDs alone.
## Coordination Patterns
### Hub-and-Spoke (Conductor)
A root agent reasons about a task and delegates subtasks to workers. Workers
report back via their chat history; the conductor reads `/s/{id}/chat` after
`statewait` unblocks.
```sh
# Conductor spawns two workers
worker_a=$(subagent_spawn -model haiku "analyse /src/a.go")
worker_b=$(subagent_spawn -model haiku "analyse /src/b.go")
# Wait for both
until [ "$(cat $worker_a/state)" = "idle" ]; do cat $worker_a/statewait; done
until [ "$(cat $worker_b/state)" = "idle" ]; do cat $worker_b/statewait; done
# Collect results
cat $worker_a/chat $worker_b/chat
```
The conductor and workers can run on different models. Mechanical analysis goes
to cheaper models; reasoning stays on the expensive one.
### Pipeline
Agent A produces output; agent B consumes it. Composition via `/tmp/` or direct
path passing.
```sh
step1=$(subagent_spawn "extract all TODOs from /src/ and write to /tmp/todos.txt")
until [ "$(cat $step1/state)" = "idle" ]; do cat $step1/statewait; done
subagent_spawn "prioritise the TODOs in /tmp/todos.txt and produce a plan"
```
### Scatter-Gather (Swarm)
Spawn N workers in parallel, collect when all reach `idle`. Because `statewait`
blocks until state changes, no polling loop is needed.
```sh
# Scatter
for f in /src/*.go; do
subagent_spawn "review $f for security issues" &
done
wait # wait for all subagent_spawn calls to return session paths
```
Or from within `execute_code` using parallel steps:
```json
{
"steps": [
{ "parallel": [
{ "code": "subagent_spawn 'task A'" },
{ "code": "subagent_spawn 'task B'" },
{ "code": "subagent_spawn 'task C'" }
]}
]
}
```
### Peer-to-Peer
Any agent can read any other agent's session directory. There is no privileged
orchestrator role — agents coordinate by reading each other's `chat` and `state`
files directly. A peer can wait on another peer's `statewait`, then act on what
it reads in `chat`.
### Reactive / Event-Driven
`statewait` is a proper synchronization primitive. A shell script (or another
agent) blocks on it and wakes exactly when the target agent transitions state.
This enables event-driven pipelines without polling:
```sh
# Block until agent finishes, then trigger downstream work
cat /s/worker-123/statewait
# agent is now idle — proceed
```
### Self-Directed Spawning
Agents can spawn sub-agents mid-task without human direction. If an agent
determines that parallelism or specialization would help, it calls
`subagent_spawn` on its own. No human prompt is required to initiate a
multi-agent workflow — the model decides.
## Design Principle
ollie imposes no coordination model. There is no built-in conductor, swarm
layer, or workflow engine. Orchestration is handled by the surrounding
environment — shell scripts, cron, systemd, containers, or another agent.
This is intentional. The filesystem namespace is the API. Any tool that can
read and write files can participate in a multi-agent workflow, which means the
full Unix toolchain is available as an orchestration layer.