doc: update documentation to reflect unified execute_code

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Levi Neely 2026-04-16 21:42:10 +02:00
parent 8aeefe43fa
commit 54af56c8d7
4 changed files with 41 additions and 35 deletions

View File

@ -62,22 +62,49 @@ Frontend
All tool calls go through one `tools.Dispatcher.Dispatch` path. Every registered server is a `tools.Server`; the dispatcher routes by name and is agnostic to how any server is implemented.
## Built-in Tools
## execute_code
One built-in tool via `execute.Server`:
`execute_code` is the only built-in tool. It is a unified primitive that handles simple execution, sequential composition, and parallel fan-out through a single `steps` array of pipeline stages.
| Tool | What it does |
|---|---|
| `execute_code` | Runs a pipeline of stages sequentially, piping stdout → stdin. Each stage is `{code}`, `{tool, args}`, or `{parallel:[...]}` for concurrent fan-out. Single stage = degenerate case, raw output. |
Each stage is one of:
- `{code, language}` — inline code (default: bash)
- `{tool, args}` — named script from `OLLIE_TOOLS_PATH`; language detected from shebang
- `{parallel: [...]}` — concurrent fan-out; each element is a `{code}` or `{tool}` step; outputs concatenated in submission order
`OLLIE_TOOLS_PATH` defaults to `~/.config/ollie/tools`. The directory can be a symlink or a mountpoint — `{tool}` steps in `execute_code` resolve scripts from this path.
Stages run sequentially, each stage's stdout fed to the next stage's stdin. A single simple stage is the degenerate case and returns raw output directly.
```
steps=[{code: "ls"}] — simple execution
steps=[{code: "grep error log"}, {code:"wc"}] — sequential pipeline
steps=[{parallel:[{code:"wc a"},{code:"wc b"}]}] — parallel fan-out
steps=[{parallel:[...]}, {code:"sort"}] — fan-out then transform
```
`OLLIE_TOOLS_PATH` defaults to `~/.config/ollie/tools`. `{tool}` steps resolve scripts from this path.
## Tool Scripts
Capabilities beyond `execute_code` are implemented as tool scripts in `OLLIE_TOOLS_PATH`. Scripts are invoked via `execute_code` `{tool}` steps. The agent discovers available scripts via `t/idx`.
All capabilities beyond `execute_code` itself are implemented as tool scripts in `OLLIE_TOOLS_PATH`, invoked via `{tool}` steps. The agent discovers available scripts via `t/idx`.
Examples from the default install: `file_read`, `file_write`, `file_edit`, `file_glob`, `file_grep`, `memory_remember`, `memory_recall`, `reasoning_think`, `task_plan`, `task_complete`, `subagent_spawn`.
## Sub-agents
Sub-agents are implemented as a tool script (`subagent_spawn`) on top of the `b/` batch namespace. The script writes a job spec to `b/new`, polls `b/{id}/status` per job in background subshells, joins on all, and concatenates results. The `b/` namespace (backed by `BatchStore`) handles agent lifecycle, cancellation, and result storage.
For heterogeneous parallel delegation (N agents, N different prompts), a `{parallel:[...]}` stage composes with `subagent_spawn` — each parallel step is one shell invocation with a distinct prompt:
```
execute_code {parallel} stage
├── subagent_spawn "prompt A" → b/{id-0}/result
├── subagent_spawn "prompt B" → b/{id-1}/result
└── subagent_spawn "prompt C" → b/{id-2}/result
↓
concatenated in submission order
```
The architecture boundary is clean: `execute_code` is the only built-in tool in `core`; everything else is a tool script; `b/` is a 9P namespace. No layer knows about the others.
## Planning
`task_plan` saves a markdown checklist to the plan directory (`pl/` in ollie-9p) as a `__todo.md` file. The agent then:
@ -89,27 +116,6 @@ Examples from the default install: `file_read`, `file_write`, `file_edit`, `file
`task_complete` takes the plan filename and a step title (substring match, case-insensitive). It errors if no matching unchecked step is found, so silent skips are caught.
Everything else — listing plans, inspecting a specific step, bulk operations — goes through `file_*` scripts or inline `execute_code`.
## Parallel Execution and Sub-agents
`execute_code` is a sequential pipeline: stages run in order, stdout piped to the next stage's stdin. A `{parallel:[...]}` stage fans out concurrently within the pipeline, concatenating results in submission order before passing them downstream. A single simple stage is the degenerate case and returns raw output.
Sub-agents are implemented as a tool script (`subagent_spawn`) on top of the `b/` batch namespace. The script writes a job spec to `b/new`, polls `b/{id}/status` per job in background subshells, joins on all, and concatenates results. The `b/` namespace (backed by `BatchStore`) handles agent lifecycle, cancellation, and result storage.
For heterogeneous parallel delegation (N agents, N different prompts), `execute_code` parallel steps compose with `subagent_spawn`: each step is one shell invocation of the script with a distinct prompt, all running concurrently. This is the fork-join pattern for agent-level work:
```
execute_code parallel steps
├── subagent_spawn "prompt A" → b/{id-0}/result
├── subagent_spawn "prompt B" → b/{id-1}/result
└── subagent_spawn "prompt C" → b/{id-2}/result
↓
joined in submission order
```
The architecture boundary is preserved: `execute_code` is the only built-in tool in `core`; everything else is a tool script; `b/` is a 9P namespace. No layer knows about the others.
## Typical Consumer Setup
```go

View File

@ -18,4 +18,4 @@
**Passive memory** — Every session's chat history accumulates at `s/{id}/chat`, searchable with `grep`. An agent doesn't need to actively decide what to remember. This extends across sessions: an agent can search another session's chat for answers that have already been worked through.
**Sub-agents** — `subagent_spawn` implements fork-join over the `b/` namespace: spawn N specialized agents with a shared prompt, wait for all to complete, collect results in submission order. For heterogeneous parallel delegation (N agents, N different prompts), combine with `execute_code` parallel steps — each step calls `subagent_spawn` with a different prompt, all running concurrently.
**Sub-agents** — `subagent_spawn` implements fork-join over the `b/` namespace: spawn N specialized agents with a shared prompt, wait for all to complete, collect results in submission order. For heterogeneous parallel delegation (N agents, N different prompts), use a `{parallel: [...]}` stage in `execute_code` — each parallel step calls `subagent_spawn` with a different prompt, all running concurrently.

View File

@ -27,4 +27,4 @@ Each stage is one of:
Supported inline languages: `bash`, `python3`, `perl`, `lua`, `awk`, `sed`, `jq`, `ed`, `expect`, `bc`.
All parallel steps in a stage should produce the same output schema so their concatenated output is coherent for the next stage. Load the `execute-pipe` skill for pipeline patterns and the ETL pattern for disparate schemas.
All parallel steps in a stage should produce the same output schema so their concatenated output is coherent for the next stage. Load the `execute-pipe` skill for pipeline patterns and the ETL pattern for disparate output schemas.

View File

@ -12,7 +12,7 @@ Spawn when:
- A subtask is better handled by a different agent (different model, backend, or system prompt)
- You want to isolate a long-running or risky operation from the current session
Use `execute_code` parallel steps instead when the subtasks are single shell commands. Subagents are for agent-level work; parallel code steps are for parallel shell execution.
Use a `{parallel: [...]}` stage in `execute_code` instead when the subtasks are single shell commands. Subagents are for agent-level work; parallel stages are for parallel shell execution.
## How to use
@ -38,17 +38,17 @@ Prompt is all remaining arguments after flags.
## Heterogeneous fan-out
To run N subagents with N different prompts, combine with `execute_code` parallel steps — each step is one `subagent_spawn` shell invocation:
To run N subagents with N different prompts, use a `{parallel: [...]}` stage — each parallel step is one `subagent_spawn` shell invocation:
```
execute_code: steps=[
execute_code: steps=[{parallel: [
{code: "subagent_spawn 'Summarize core/pkg/agent/loop.go'"},
{code: "subagent_spawn 'Summarize core/pkg/backend/anthropic.go'"},
{code: "subagent_spawn 'Summarize 9p/internal/p9/server.go'"}
], timeout=300
]}], timeout=300
```
Three concurrent subagents, three different prompts. Results appear under `=== step N ===` headers from `execute_code`.
Three concurrent subagents, three different prompts. Results are concatenated in submission order.
Set `timeout` to at least 300 seconds when subagents are doing non-trivial work — the default 30 seconds is not enough.