Ratatosk
Platform session runtime for the Willow fleet — the process that runs agent
turns on any node (desk, laptop, Termux phone) and speaks MCP to willow-mcp.
Role
Ratatosk is not memory (Nestor), not the desk (Grove). It is the session process: prompt → tools → loop, Grove lifecycle events, JSONL working set, tier-0 deposit sync.
Install
pip install "willow-ratatosk[mcp,cloud,local]"
# development
pip install -e ".[dev]"
Run
ratatosk --local
ratatosk --mcp
ratatosk --mcp --listen
ratatosk --mcp --deposit
--onescript — the one script's model seat
ratatosk --onescript --served served.json --out proposals.jsonl \
[--model gemma3:4b] [--rung ollama] [--ctx 4096] "<task>"
# the desk's cloud turn on a card the chain could not close
ratatosk --onescript --class flowering --served piece.json --out proposals.jsonl "<task>"
One local model turn over a document serve wrote. It is a different program
sharing the entry point: no MCP, no Grove events, no session JSONL, no hooks,
no CLAUDE.md or repo file in the prompt, none of the built-in tools. The
model sees one fixed system prompt, the served document as framed data in the
user turn, and one tool.
| Rule | What it means |
|---|---|
| Local rungs only | A rung is local when its base_url is loopback and its dialect is ollama or openai (an OpenAI-compatible server such as llama.cpp). A cloud rung, a cloud model name, or a ladder with no local rung is refused with exit 2 before any request. |
--class flowering |
The one way past local-only: the ladder's flowering class names the rungs, models and order (free tiers only). A rate limit, overload, timeout or transport failure before any row is written steps to the next rung; the summary line gains stepped=rung:end,…. --rung and --model are refused beside it. Every other rule here holds. |
| One tool, one write | propose(path, data, cites, claim) appends one line {"path", "data", "cites", "claim"} to --out. That file is the only thing written. Any other tool name is refused and recorded in the transcript, never run. A malformed call (absolute or .. path, non-list cites, over-size field) is handed back as refused: and not written. At most 16 proposals per run. |
| Three states | populated, empty and unreachable reach the model as themselves. A missing, unreadable or non-served file is unreachable; serve's own empty stays empty. < is escaped so served text cannot close the frame, and serve's return line is carried through. |
| Budget | The served block is sized from the model's context: --ctx, else the rung's own answer (Ollama /api/show num_ctx, llama.cpp /props), else 4096 (the phone budget), minus the frame, the task and an answer reserve. Over budget the block becomes empty ("narrow the stack"). It is never truncated. For Ollama the measured window is sent as num_ctx, so the budget is the window the model runs with. |
| Bounded | --max-turns (default 4) and --wall-clock seconds (default 180). A cap or a timeout ends the turn with a recorded reason. |
| No path | The served file's path is read by code and goes nowhere else: not into the prompt, not into the summary line. |
The last line printed is the summary: [onescript] model=… rung=… ctx=… (flag|rung|default) served=… proposals=N turns=T end=….
-v prints the transcript (including refused tool calls) to stderr; nothing is written for it.
End reasons: done, turn_cap, wall_clock, timeout, provider_error:<kind>, crash:<Class>.
Exit status: 0 the model finished, 1 the turn ended early, 2 refused before any request.
--out is created empty when the run starts, so "ran, proposed nothing" differs from "never ran".
Environment
| Var | Default | Purpose |
|---|---|---|
RATATOSK_GROVE_CHANNEL |
(disabled) | Grove channel for session events |
RATATOSK_MCP_COMMAND |
python -m willow_mcp |
MCP server command |
RATATOSK_APP_ID |
ratatosk |
MCP app_id |
WILLOW_HOME |
$WILLOW_HOME or XDG share |
Session data under $WILLOW_HOME/ratatosk/ |
OLLAMA_URL |
http://localhost:11434 |
Local inference |
ANTHROPIC_API_KEY |
— | Cloud mode |
willow-mcp registration
Ratatosk is a platform session identity, not a dispatch specialist. Install
its manifest under $WILLOW_HOME/mcp_apps/ratatosk/manifest.json (example in
docs/mcp-manifest.example.json). Without this, Grove tools deny with
app_id=ratatosk.
Org home
Canonical repo: willow-memory/ratatosk (Platform face, sibling to
willow-mcp and kartikeya).
Playground launcher: safe-app-store-public/apps/ratatosk.
Metadata
Release files for willow-ratatosk 1.16.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| willow_ratatosk-1.16.0.tar.gz | 304.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| willow_ratatosk-1.16.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 444.1 kB
Release files / willow_ratatosk-1.16.0.tar.gz
| Download URL | willow_ratatosk-1.16.0.tar.gz |
|---|---|
| Size | 304.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b39269eb0361b4a77716ad3b52533bbd07d6500faa85429e1224a75cc11f6855
|
|
BLAKE2b-256 checksum How to use checksums |
415db629ce0559e402551a393a7022d6aad708dc88db82ac6564766e1a62bc26
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.
Transparency logRelease files / willow_ratatosk-1.16.0-py3-none-any.whl
| Download URL | willow_ratatosk-1.16.0-py3-none-any.whl |
|---|---|
| Size | 139.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d9c3a25cf7a613be912563844e4d14013f412bd8890281e7b8bb69fb3bd6ad3e
|
|
BLAKE2b-256 checksum How to use checksums |
74933a29ffff1dd617a6f19d0d7d04e26aa93426c3256fe77abf3858ca9c649a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.
Transparency log