176 lines
5.4 KiB
Markdown
176 lines
5.4 KiB
Markdown
# Ollie Technical Whitepaper
|
|
|
|
The full 9P filesystem reference has been moved to [`9p.md`](9p.md).
|
|
|
|
## 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:
|
|
|
|
```sh
|
|
# 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:
|
|
|
|
```json
|
|
{
|
|
"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 bypass |
|
|
| `variants` | Conditional definitions for heterogeneous hosts |
|
|
|
|
### Runtime access
|
|
|
|
The full prompt for any tool is available on-demand:
|
|
|
|
```sh
|
|
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](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:
|
|
|
|
```json
|
|
{
|
|
"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`:
|
|
|
|
```sh
|
|
#!/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
|
|
o write "session/$sid/agent/$aname/prompt" "$*"
|
|
# Block until agent returns to idle
|
|
while [ "$(o read "session/$sid/agent/$aname/statewait")" != "idle" ]; do :; done
|
|
}
|
|
|
|
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
|
|
|
|
session=developer o ctl kill
|
|
session=reviewer o ctl kill
|
|
session=tester o ctl kill
|
|
```
|
|
|
|
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=`. |