3.6 KiB
Architectural Evolution
How the Ollie system-of-systems emerged and evolved. This is a study log: it records important transitions, including discarded approaches, while describing the architecture that remains.
1. The filesystem became the control plane
Ollie began as a collection of components with a conventional programmatic API. The decisive change was to represent agent primitives as files over 9P. Sessions became directories; prompting became a write to prompt; state and conversation became readable files; statewait supplied blocking observation.
This made the control plane protocol-agnostic. A shell, editor, GUI, or another agent can operate Ollie with ordinary file operations.
2. Tool execution moved out of the core
The tool design went through external MCP servers, scripts, and a single built-in execution path. The current design keeps tools outside the agent loop in toolsrv, a separate 9P process. Executables describe themselves with metadata, and the registry discovers and loads them lazily.
This removed built-in-tool and prompt-bloat pressure. File, code-intelligence, memory, reasoning, and web capabilities use the same external-tool boundary. OptMem became the owner of persistent memory rather than Ollie maintaining a competing memory directory.
3. Planning became session state
Planning moved through several namespaces and tool-specific task APIs. The surviving form is the session-scoped plan file: an agent-controlled Markdown checklist that survives context compaction without imposing a separate planning service.
4. Multi-agent work used the same primitives
Subagents, generated agents, cascades, observers, and feed agents were added as orchestration patterns. They create ordinary sessions and agents, then communicate through 9P files. This avoided introducing a separate coordination protocol.
5. Security became process and policy isolation
Execution initially had no sandbox. Landrun/Landlock policy was introduced for tool processes, followed by per-process isolation and a policy-controlled bypass broker for approved operations. An SSH-agent proxy and separate privilege adapter were removed because they expanded the trust boundary without improving the core model.
6. Frontends stayed clients
A terminal UI and several adapter experiments were tried. The durable frontends are shell scripts, Acme, KDE integrations, and other 9P clients. They create sessions and observe files rather than duplicating the agent loop.
The earlier D-Bus control-plane experiment was also removed from the current architecture. Desktop integrations use the 9P service/client boundary instead of maintaining a second session store.
7. The great flattening
The core was simplified after the major features stabilized. Unused interfaces, manager/dispatcher indirections, duplicate execution packages, and dead exported code were removed. The fs.Tree became the session collection, package functions replaced the manager object, and context.Context replaced ad-hoc interruption paths.
The result is a single Go module with direct boundaries:
9P client → olliesrv → fs/session → agent loop → provider
└→ toolsrv → sandbox/bypass
Current lesson
Ollie keeps one small runtime and makes capabilities composable through files and external executables. The architecture has changed repeatedly, but the durable principles are now clear: 9P is the integration contract, tools are replaceable processes, state is observable through files, and orchestration should be built from the same primitives as a single agent.