# 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 `/session/{name}/` where `{name}` is the session's **mutable human-readable name** (not the immutable UUID — see `id` and `name` files). Session directories are keyed by Name; renaming a session via writing to its `name` file moves the entire directory subtree. | Path | Purpose | |------|---------| | `/session/new` | Create an empty session (write `name=...`, read back name) | | `/session/{name}/agent/new` | Create an agent within a session (write `cwd=... backend=...`) | | `/session/{name}/env` | Session environment variables | | `/session/{name}/id` | Immutable session UUID | | `/session/{name}/name` | Mutable session name (write to rename) | | `/session/{name}/agent/{aname}/prompt` | Submit a prompt | | `/session/{name}/agent/{aname}/chat` | Streaming chat (filtered text) | | `/session/{name}/agent/{aname}/plan` | Agent-scoped markdown checklist | | `/session/{name}/agent/{aname}/cfg` | Agent config KV: backend, model, agent, cwd, params | | `/session/{name}/agent/{aname}/statewait` | **Blocking read** — returns when state changes | | `/session/{name}/agent/{aname}/ctl` | Control commands: `stop`, `kill`, `compact`, `rn ` | | `/session/{name}/agent/{aname}/id` | Immutable agent ID (uname) | | `/session/{name}/agent/{aname}/name` | Mutable display name (write to rename) | Global request-response files provide stateless operations without sessions: | File | Purpose | |------|---------| | `/generate` | Write prompt, read response (one-shot generation) | Global namespaces are shared across all sessions: | Path | Purpose | |------|---------| | `/session/idx` | Session index (id, state, cwd, backend, model) | | `/session/{name}/agent/{aname}/plan` | Agent checklist | | `/session/{name}/agent/{aname}/chat` | Streaming filtered text | ## Spawning Agents From within an agent session, use `subagent_spawn`: ```sh subagent_spawn [-name NAME] [-agent AGENT] [-backend BACKEND] [-model MODEL] [-cwd DIR] ``` This creates a child session + agent atomically, writes the prompt, and returns the session path (e.g. `session/my-session`). Child sessions carry the parent session ID in their name, so the spawning tree is recoverable from session IDs alone. ### Explicit Two-Step Creation Session creation can be split into two phases for advanced orchestration scenarios: 1. **Create empty session**: `echo "name=my-session" | ollie-9p rdwr session/new` 2. **Add agent**: `echo "cwd=/home/user agent=default backend=openai model=gpt-4o" | ollie-9p rdwr session/my-session/agent/new` Empty sessions (`Core=nil`) are valid — they appear in `session/idx`, have no running agent, and can be killed or renamed. This enables pre-provisioning session directories before the agent environment is ready. ## Coordination Patterns ### Hub-and-Spoke (Conductor) ```mermaid flowchart TB ROOT["Root Agent\n(reasoning)"] W1["Worker A\n(cheap model)"] W2["Worker B\n(cheap model)"] ROOT -- "subagent_spawn" --> W1 ROOT -- "subagent_spawn" --> W2 W1 -- "statewait → read chat" --> ROOT W2 -- "statewait → read chat" --> ROOT ``` A root agent reasons about a task and delegates subtasks to workers. Workers report back via their log; the conductor reads `/session/{name}/agent/{aname}/log` 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 ```mermaid flowchart LR A["Step 1\nExtract TODOs"] B["Step 2\nPrioritise"] A -->|"/tmp/todos.txt"| B ``` 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) ```mermaid flowchart TB P["Parent"] S1["Worker 1"] S2["Worker 2"] S3["Worker N"] P --> S1 P --> S2 P --> S3 S1 --> P S2 --> P S3 --> P ``` 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 `shell`: ```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 /session/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.