ollie is a 9p-based generative agent surface
Go to file
Levi Neely 137d2c0e84 tools: add structured STATUS prefix signals for smaller model clarity
Addresses the loop/no-op problem where small models (e.g. devstral-small)
fail to interpret ambiguous prose output as terminal control signals.

Changes:
- file_write: prefix STATUS=done/no_change/error with STATE_CHANGED and RETRYABLE
- file_edit: same prefix scheme; also RETRYABLE=true for ambiguous match errors
- file_read: prefix STATUS=ok/empty/not_found/error to distinguish data absence from failure
- file_glob: prefix STATUS=ok/no_matches/error with MATCH_COUNT
- file_grep: prefix STATUS=ok/no_matches/error with MATCH_COUNT
- task_add: emit STATUS=ok ADDED=N TOTAL_TASKS=M
- task_check: emit STATUS=done TASK_COMPLETE=true/false REMAINING=N
- task_clear: emit STATUS=ok CLEARED=N REMAINING=N TASK_COMPLETE=true/false
- cascade: rewrite worker termination block as numbered mandatory rules;
  add explicit STATUS: error branch; clarify stop-after-write requirement
2026-05-19 10:15:08 +00:00
.beads agents: extract prompts to markdown, assemble via executable prompt 2026-04-26 15:00:46 +02:00
.kiro/settings sandbox: fix regression from simplification 2026-04-21 21:09:33 +02:00
9p@c1f02cdee1 fix: OLLIE_SESSION_ID available during prompt resolution 2026-05-18 12:31:53 +02:00
acme@c8e6c50e53 move t/ into s/{sid}/t/; two-layer tool restriction (allowExecutors/allowTools) 2026-05-16 23:55:25 +02:00
agents give execute_code to orcestrator 2026-05-18 22:41:34 +02:00
core@5efed7040d Update core and skills submodules; revise SYSTEM_PROMPT 2026-05-18 22:21:13 +02:00
doc add orchestrator/worker agents; update cascade defaults to deepseek v4 2026-05-17 15:04:06 +02:00
el@de3d08ce14 readme: add "What you get" section; update submodules 2026-05-03 22:03:01 +02:00
experiments Clarify Identity-Specific Rigor description 2026-05-02 14:30:21 +02:00
httpgw@292448c05d update httpgw and webui submodules 2026-04-26 15:54:38 +02:00
prompts improve system prompt 2026-05-18 22:39:07 +02:00
sandbox sandbox: add Qt, pnpm, pipx, aqt to rwx paths 2026-05-18 17:14:05 +02:00
scripts add orchestrator/worker agents; update cascade defaults to deepseek v4 2026-05-17 15:04:06 +02:00
skills@00e12bc15b Update core and skills submodules; revise SYSTEM_PROMPT 2026-05-18 22:21:13 +02:00
tools tools: add structured STATUS prefix signals for smaller model clarity 2026-05-19 10:15:08 +00:00
webui@700d0dae46 acme: add u/complete for AI ghost-text code completion 2026-05-03 13:30:26 +02:00
.gitignore gitignore: add __pycache__ 2026-04-29 10:17:28 +02:00
.gitmodules remove ollie-tui submodule 2026-05-01 10:17:36 +02:00
Containerfile add remote access via TCP: Containerfile, mount subcommand, docs 2026-04-16 23:32:37 +02:00
README.md README: update with cascade, orchestrator/worker, plan-first discipline 2026-05-17 18:18:58 +02:00
mkfile mkfile: add scripts/u/cascade and tools/cascade to installation 2026-05-17 14:16:30 +02:00

README.md

ollie

Ollie starts from a simple, slightly silly question: What might an AI agent look like in Plan 9? From there follow two more: What happens if agent primitives are exposed as an ordinary filesystem? and How much can we subtract from agent implementations while still being useful? The result is not a conventional "agent framework" but a small Go runtime and 9P‑backed filesystem surface that defines what an agent is, then exposes its state and behaviors as regular files and I/O streams, so that the surrounding environment (shell scripts, TUIs, web apps, cron, containers, and other OS facilities) can handle orchestration, scheduling, workflows, and interfaces instead. The same primitives scale from simple copilot use cases — u/complete manages a session per working directory for ghost‑text code completion in acme — through interactive shells and one‑shot pipelines, up to multi‑agent workflows coordinated by scripts, other agents, or both.

What you get

  • Interactive AI shell — s/sh gives you a readline prompt that resumes your last session per directory, with streaming output and live model/backend switching
  • One-shot queries that compose with Unix pipes — cat error.log | s/bfg "what caused this?" | s/bfg "suggest a fix"
  • Parallel fan-out — s/bfg -parallel 4 spawns N agents on the same prompt and collects results
  • Multi-agent workflows in plain shell — create named sessions, pass prompts between them via files, coordinate with statewait; no framework or SDK
  • Subagent delegation — agents can fork ephemeral subagents that run independently and return results
  • Model cascading for 90% cost reduction — cascade delegates mechanical work to cheaper models, keeping expensive reasoning for high-level planning
  • Orchestrator/worker system — specialized agents for task decomposition (orchestrator) and mechanical execution (worker)
  • Any model, any backend — Ollama (local), OpenAI, Anthropic, OpenRouter, GitHub Copilot, Kiro; switch per-session with one write
  • Sandboxed execution — every tool call runs inside a Landlock sandbox with configurable filesystem access
  • Extensible via plain scripts — drop executables into a directory and the agent picks them up; built-in tools cover file I/O, LSP (go-to-definition, references, rename, diagnostics), persistent memory, web search, browser screenshots, and task tracking
  • Domain skills — teach the agent your project's conventions with a markdown file; loaded on demand
  • AI code completion — u/complete reads a prefix from stdin and prints the completion to stdout; plug it into any editor that can shell out
  • Multiple frontends — terminal (s/sh), acme (ollie-acme + Kmpl), Emacs (ellie), and a browser-based web UI; all talk to the same 9P server
  • Remote access — mount a remote server's namespace locally with 9pfuse, or use the HTTP gateway with curl or the web UI
  • Store federation — point tools or transcripts at a remote 9P mount to share across machines
  • Prompt optimization — u/optimize generates N candidate prompts in parallel, then judges them to return the best one
  • Automatic context compaction — long conversations are summarized transparently when approaching the model's context limit
  • Plan‑first discipline — agents write checklists before acting, reducing wasted steps and improving reliability

Getting Started

Clone with submodules:

git clone --recurse-submodules https://github.com/lneely/ollie.git

Or after cloning:

git submodule update --init --recursive

Build and install everything from the monorepo root:

mk

Or build specific components:

mk core    # Build core library
mk 9p      # Build 9p filesystem server
mk httpgw  # Build HTTP gateway
mk webui   # Build web UI (requires Node.js + npm)

For Emacs Lisp, copy el/ellie.el into your own Emacs configuration directory, and:

(require 'ellie)

See doc/USAGE.md for usage instructions.

Configuration

Environment: ~/.config/ollie/env

OLLIE_BACKEND=openai           # ollama | openai | anthropic | copilot | kiro (default: ollama)
OLLIE_OLLAMA_URL=              # base URL for Ollama (default: http://localhost:11434)
OLLIE_OPENAI_URL=https://openrouter.ai/api
OLLIE_OPENAI_KEY=sk-or-...
OLLIE_ANTHROPIC_KEY=sk-ant-...
OLLIE_COPILOT_TOKEN=...
OLLIE_KIRO_TOKEN=...           # bearer token or sqlite:// path (auto-detected from Kiro CLI if unset)
OLLIE_MODEL=qwen/qwen3-235b-a22b
OLLIE_TOOLS_PATH=~/.config/ollie/tools    # directory for tool scripts ({tool} steps)
OLLIE_MEMORY_PATH=~/.config/ollie/memory  # directory for memory files (ollie/m)
OLLIE_ELEVATE_SOCKET=${XDG_RUNTIME_DIR}/ollie/elevate.sock  # socket path for x/elevate adapter (default: $XDG_RUNTIME_DIR/ollie/elevate.sock)
OLLIE_COMPLETE_BACKEND=ollama             # backend for u/complete (required)
OLLIE_COMPLETE_MODEL=qwen3:latest         # model for u/complete (required)

Shell environment variables take precedence over the env file.

Remote Access

Two approaches: mount the 9P namespace directly with 9pfuse, or reach it over HTTP via ollie-httpgw.

9P mount

Because olliesrv speaks 9P over TCP, a remote instance can be mounted into the local namespace using 9pfuse. Agent sessions, tools, and all other filesystem state on a remote host become ordinary local files — no special client needed.

# On the remote host:
olliesrv start -tcp :9564

# Locally:
olliesrv mount remotehost:9564 ~/mnt/remotehost
ls ~/mnt/remotehost      # s/, ...

Sessions created under ~/mnt/remotehost/s/ run on the remote host, so tool calls execute close to the remote filesystem rather than over the wire.

HTTP gateway

ollie-httpgw translates HTTP to 9P, letting any HTTP client interact with olliesrv without a 9P library. It's also the backend for the web UI.

# Connect to local server:
ollie-httpgw

# Connect to remote server:
ollie-httpgw -net tcp -addr remotehost:9564

See doc/USAGE.md for full details on the gateway and web UI.

Container

A Containerfile is included for running a self-contained remote server:

podman build --network=host -t olliesrv .
podman run --network=host -e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY olliesrv

Then mount locally or point httpgw at it:

olliesrv mount localhost:9564 ~/mnt/container-ollie
# or
ollie-httpgw -net tcp -addr localhost:9564

Development

Update all submodules to latest:

git submodule update --remote

Credits

Many sources of inspiration:

  • Plan 9 from Bell Labs — for an interesting system
  • @9fans — for the Plan 9 port
  • Suckless — for articulating good software development principles
  • @simonfxr — for a solid agent baseline to "borrow" from, and other nifty ideas
  • @aws — for a solid open-source agent implementation

License

GPLv3