ollie/doc/resources/misc.md

8.8 KiB

Ollie Technical Whitepaper

9P Filesystem: Everything is a File

The 9P namespace is the lowest-level interface to ollie. Everything — sessions, agents, prompts, tools, state — is a file. The o CLI wraps these operations, but the raw filesystem is the foundation.

Mounting

ollie-9p mount unix!/tmp/ns.$USER.$DISPLAY/ollie ~/mnt/ollie
cd ~/mnt/ollie
ls session/

Or connect remotely:

ollie-9p mount tcp!server:9564 ~/mnt/ollie

Raw session operations

# Create a session
echo "name={sname}" > session/new

# Submit a prompt
echo "fix the bug in main.go" > session/{sname}/agent/{aname}/prompt

# Stream the response
cat session/{sname}/agent/{aname}/chat

# Check state
cat session/{sname}/agent/{aname}/state

# Block until state changes
cat session/{sname}/agent/{aname}/statewait

# Read offset (byte position after user prompt)
cat session/{sname}/agent/{aname}/offset

Network transparency

9P is a network protocol. Mount the agent namespace from any machine and every session, tool, and config value is accessible as if local:

# From another machine:
9p -a 'tcp!server:5640' read session/{sname}/agent/{aname}/state

No SSH tunneling, no port forwarding, no API gateway.

Shell composability

Because operations are file I/O, they compose with the full Unix toolkit:

# Fan out a prompt to all agents
for s in session/*/agent/*/prompt; do echo "run tests" > "$s"; done

# Wait for all agents to finish
for s in session/*/agent/*/statewait; do cat "$s" > /dev/null; done

# Grep all agent plans
grep -r "TODO" session/*/plan

# Monitor costs
cat session/*/agent/*/cost

# Strip block markup from chat output
cat session/{sname}/agent/{aname}/chat | grep -vE '^\[\[\[.*'

Pipe agents into awk. Filter with grep. Schedule with cron. Orchestrate with a 10-line shell script instead of a framework.

Plan 9 patterns

  • /net/dns pattern — /complete, /generate, /route are stateless per-fid: write a request, read back the result
  • ctl files — control operations (stop, kill, rename, compact) are writes to a control file, not method calls
  • Blocking reads — statewait blocks until state changes, replacing event subscriptions with a simple cat
  • Multiplexing — multiple clients mount the same server simultaneously, each with an independent view through per-fid state

/generate — one-shot LLM

echo 'summarize this repo' | ollie-9p rdwr generate
cat main.go | ollie-9p rdwr generate
echo '{"prompt":"explain recursion"}' | ollie-9p rdwr generate

/complete — code completion

Fill-in-the-middle:

echo '{"file":"main.go","prefix":"func ","suffix":""}' | ollie-9p rdwr complete

/route — task routing

echo 'implement login page' | ollie-9p rdwr route
# backend=anthropic model=claude-sonnet-4-20250514

Key files per agent

File Mode Description
prompt write Queue a new turn
statewait read (blocking) Blocks until state changes
state read Current state
chat read Full conversation history
context read Full message history as JSONL
offset read Byte position after last user prompt
plan r/w Scratch space for agent planning
prompt.prev read The last submitted prompt
env read Session environment variables
cost read Cumulative cost in USD

Store Federation

OLLIE_TOOLS_PATH is an ordinary filesystem path. Because the server speaks 9P and any remote instance can be mounted locally, this var can point at a remote directory with no code changes — the OS handles the proxying transparently.

Centralized tool distribution

Host one authoritative tool set and point all machines at it:

# On each client machine:
ollie-9p mount toolserver:9564 ~/mnt/toolserver
export OLLIE_TOOLS_PATH=~/mnt/toolserver/t

Set it in ~/.config/ollie/env for persistence:

OLLIE_TOOLS_PATH=~/mnt/toolserver/t

Tool Discovery

Tools are executables in $OLLIE_TOOLS_PATH (default: ~/.config/ollie/tools/). At session startup, all .meta sidecar files are scanned and a compact listing (name + one-line description) is injected into the system prompt.

Metadata format

Each tool has a .meta JSON sidecar file alongside the executable:

{
  "description": "Short description (used in system prompt listing).",
  "prompt": "## my_tool\n\nFull documentation shown when tool is loaded.",
  "args": {"type":"object","required":["path"],"properties":{"path":{"type":"string","description":"File path"}}},
  "tier": "cold",
  "readOnly": true
}
Field Purpose
description One-liner shown in tool listing
prompt Full documentation injected when tool is loaded
args JSON Schema for tool input parameters
tier Result cacheability: cold, warm, or hot (default: hot)
readOnly Safe for parallel execution with other read tools
cmd Executable path or name override
sudo Requires root privileges; implies elevation
variants Conditional definitions for heterogeneous hosts

Runtime access

The full prompt for any tool is available on-demand:

echo 'file_edit' | 9p rdwr ollie/tools   # returns file_edit's full documentation

Adding a tool

Drop an executable and its .meta file in $OLLIE_TOOLS_PATH. The next session created will pick it up automatically. No restart required.

See doc/writing-tools.md for the full specification including host-conditional variants and privileged tools.


System Prompt Override

The default system prompt is compiled into olliesrv. To replace it — for models that need their own identity preamble — set the systemPrompt field in an agent config JSON to a file path:

{
  "systemPrompt": "~/.config/ollie/prompts/SYSTEM_PROMPT_QWEN.md",
  "prompt": ["$OLLIE_CFG_PATH/prompts/agent-coding.md"],
  "temperature": 0.7
}

The file is read at session creation time. If it doesn't exist, the embedded default is used. The override replaces only the base system prompt layer; the operational model (9P documentation), environment block, and agent-specific prompt commands are still appended on top.

Model-specific prompts live at ~/.config/ollie/prompts/SYSTEM_PROMPT_*.md. Create an agent config per model family and point systemPrompt at the appropriate file.


Context Inspection

The rendered context window for any session is readable at session/{sname}/agent/{aname}/context — the exact message array sent to the backend on the last turn. Combined with session/{sname}/agent/{aname}/systemprompt, this gives full visibility into what the model sees.


Predefined Workflows

When coordination logic is known in advance, a shell script can drive the entire write → review → test workflow using named sessions and statewait:

#!/bin/sh
cwd=${1:?usage: $0 <cwd>}

# Create named sessions with agent profiles
o write session/new "name=developer agent=developer cwd=$cwd"
o write session/new "name=reviewer  agent=reviewer  cwd=$cwd"
o write session/new "name=tester    agent=tester    cwd=$cwd"

# Discover agent names (first agent in each session)
agent_developer=$(o ls session/developer/agent | grep -v '^new$')
agent_reviewer=$(o ls session/reviewer/agent | grep -v '^new$')
agent_tester=$(o ls session/tester/agent | grep -v '^new$')

send() {
    sid=$1; shift
    aname=$1; shift
    exec 3< <(o readloop "session/$sid/agent/$aname/statewait" &)
    sleep 0.1
    o write "session/$sid/agent/$aname/prompt" "$*"
    until o read "session/$sid/agent/$aname/state" | grep -q idle; do sleep 0.5; done
    exec 3<&-
    offset=$(o read "session/$sid/agent/$aname/offset" | tr -d '[:space:]')
    o read "session/$sid/agent/$aname/chat" | tail -c +$((offset + 1))
}

reply=$(send developer "$agent_developer" "Implement a function that parses a JSON config file.")

while true; do
    review=$(send reviewer "$agent_reviewer" "Review the following code. Reply LGTM if ready, or PTAL with feedback.

$reply")

    if ! printf '%s' "$review" | grep -qi "LGTM"; then
        reply=$(send developer "$agent_developer" "Revise based on this feedback:

$review")
        continue
    fi

    result=$(send tester "$agent_tester" "Test the following code. Reply Approved if all tests pass, or Rejected with details.

$reply")

    if printf '%s' "$result" | grep -qi "Approved"; then
        printf '%s\n' "$reply"
        break
    fi

    reply=$(send developer "$agent_developer" "Fix the following test failures:

$result")
done

o kill developer
o kill reviewer
o kill tester

The script initializes the routing, but agents can discover other sessions via session/idx and write to their prompt files directly — coordination is a shared filesystem, not a master-slave topology. Each agent can use a different agent=, backend=, or model=.