skill
ornithopter
Specialized-agent harness that lets a lightweight local reasoning model (ornith:9b via Ollama) carry out long, autonomous tasks. Inspired by Claude Code managed subagents.
Set up
Skills are installed by placing their folder where your agent loads skills.
The download comes from github.com/zepef/ornithopter itself, not from our server, so what you get is exactly what its author published.
Install instructions come from the README
README
synced Oct 26, 2026Ornithopter
A specialized-agent harness that lets a lightweight local reasoning model carry out long, autonomous tasks.
An ornithopter stays aloft not by raw power but by continuous beats. The bet
here is the same: a small model (ornith:9b, a 9B Qwen3.5 reasoning model served
by Ollama) can accomplish long tasks that its raw reasoning couldn't in one shot —
if the harness around it is good enough. Persistence, tight tool feedback,
context compaction, and verify-before-finish discipline do the load-bearing work.
This is a research harness, not a product. The question it exists to answer:
How much of a large agent's competence is the model, and how much is the harness? Can careful scaffolding lift a 9B to usefully autonomous long tasks?
The idea: specialized agents, not one generic loop
Inspired by Claude Code's managed subagents, each agent is a definition — a role, a restricted tool set, and model/budget attributes — and the harness specializes itself to that agent at run time:
- only the agent's allowed tools are exposed (a read-only
reviewernever even learnswrite_fileexists); - the agent's role instructions are injected into the system prompt;
- its own sampling temperature and step budget are applied.
Definitions are Markdown files with Claude-Code-style frontmatter, in agents/:
---
name: coder
description: Implements and modifies code, then proves it works by running it.
vibe: Ships the smallest change that works, then proves it with a real run.
tools: shell, read_file, write_file, list_dir, scratchpad, finish
model: ornith:9b
max_steps: 90
category: engineering
success_criteria: |
- The change is implemented and the file contains it.
- You RAN the code/tests and it passes (command + exit code shown).
---
## Identity
You are a meticulous software engineer...
The persona schema (vibe, success_criteria, sectioned body) is borrowed — as a
reference — from msitarzewski/agency-agents;
see docs/authoring-agents.md.
Built-in agents:
| agent | category | scope | tools |
|---|---|---|---|
generalist | general | open-ended tasks, full tool set | files + shell |
coder | engineering | implement + run/verify code | files + shell |
debugger | engineering | reproduce → root-cause → fix → prove | files + shell |
test-writer | engineering | write focused tests, run them green | files + shell |
refactorer | engineering | improve structure, behavior-preserving | files + shell |
reviewer | engineering | read-only code review | read-only |
researcher | research | investigate → write report.md | read + report |
orchestrator | coordination | plan → delegate to specialists → verify | delegate-only |
Drop your own *.md into ./.ornithopter/agents/ or ~/.ornithopter/agents/
to add or override agents. Validate them with ornithopter lint.
How the loop works
system prompt (protocol + this agent's specialization + only its tools)
task
loop until finish / step budget:
model turn ──► parse the single JSON action
execute the tool (sandboxed to the run's workspace)
feed the observation back
on finish ──► if the agent has success_criteria, verify each once, then accept
(every step is journalled to disk; context is compacted when it grows)
Design choices that matter for a small model:
- One action per turn, always followed by an observation. No speculative chains.
- Empty-content recovery. Reasoning models emit
thinkingbeforecontent, both counting againstnum_predict. If a turn burns its whole budget thinking, the harness retries once with a larger budget, then nudges. - Context compaction. When the transcript grows past a threshold, the middle is summarized into a running "progress so far" note so the small context stays focused.
- Resumable. Each run is a directory (
runs/<id>/) withjournal.jsonl,meta.json, ascratchpad.md, and a sandboxedworkspace/.resumereplays it. - Sandboxed tools. File ops can't escape the workspace; shell runs there with a
timeout and an approval gate (opt out with
--yes). - Verify-before-finish. An agent with
success_criteriais challenged once when it first callsfinish— it must re-check each criterion with evidence before the run is accepted as done. - Delegation (opt-in). An
orchestratorcan hand a subtask to a specialist via the privilegeddelegatetool; the sub-agent runs with its own restricted tools and budget in a nested sub-run that shares the workspace. Depth-bounded.
The core harness has no third-party dependencies — standard library only.
Delegation
An orchestrator (or any agent granted the privileged delegate tool) can hand a
self-contained subtask to a specialist. The sub-agent runs with its own
restricted tools and step budget, in a nested sub-run that shares the parent's
workspace, so files it produces are visible to the parent:
orchestrator ──delegate("coder", "create fizzbuzz.py")──────► coder (own tools/budget)
──delegate("test-writer", "run and verify it")─► test-writer
runs/<id>/
journal.jsonl parent turns + delegation / delegation_result events
workspace/fizzbuzz.py written by coder, read by test-writer (shared)
sub/1-coder/ nested run — its own journal, meta, scratchpad
sub/2-test-writer/
delegate is privileged: it is never granted by the * wildcard. An agent must
list it explicitly, name its specialists in delegates_to, and stay under
ORNITHOPTER_MAX_DELEGATION_DEPTH (default 1). Least-privilege is preserved — a
sub-agent only ever gets its own declared tools.
Install
git clone https://github.com/zepef/ornithopter
cd ornithopter
pip install -e . # exposes the `ornithopter` command
# or just: export PYTHONPATH=src && python3 -m ornithopter ...
You need Ollama running with the model pulled:
ollama pull ornith:9b
From WSL, the Windows host Ollama is at http://172.28.160.1:11434 (the default).
Override via OLLAMA_HOST. See .env.example for all knobs.
Use
ornithopter check # verify Ollama + model, list agents
ornithopter agents # describe the specialized agents (by category)
ornithopter lint # validate agent persona files
# run an agent on a task
ornithopter run -a coder "add a --json flag to cli.py and show it works" -y
ornithopter run -a researcher -f task.md
ornithopter run -a reviewer "review the diff on this branch"
ornithopter run -a orchestrator "build fizzbuzz.py and have it reviewed" -y
ornithopter list # past runs
ornithopter resume 20260701-085034-coder
-y auto-approves shell commands; without it you confirm each one. --no-stream
hides the live token stream. --max-steps N overrides an agent's default budget.
Examples
Three runnable, self-contained examples in examples/, in increasing
collaboration — solo → pair → team:
01-simple— one agent (coder) does a task end to end.02-two-agents-cooperate— a leadpair-coderdelegates a review toreviewer(peer cooperation, no orchestrator; also shows a project-local agent).03-orchestrated-team— anorchestratorfans a task out tocoder,test-writer, andreviewer.
cd examples/01-simple && ./run.sh
Layout
agents/ specialized agent definitions (editable)
src/ornithopter/
config.py env-driven configuration
llm.py dependency-free streaming Ollama client
protocol.py robust JSON-action parser
tools.py sandboxed tool registry
agents.py AgentSpec + frontmatter loader (the specialization layer)
prompts.py system prompt = shared protocol + agent role
run.py per-run persistence / resume
agent.py the loop, verify-before-finish gate, delegation
cli.py command-line interface (check/agents/lint/run/resume/list)
tests/ model-independent tests (protocol, tools, agents, loop, lint)
docs/ authoring-agents guide
examples/tasks/ sample tasks
runs/<id>/ per-run artifacts: journal, workspace, sub-runs (gitignored)
Status
Early but real. The harness runs end-to-end on ornith:9b: coder builds and
verifies FizzBuzz, and an orchestrator delegates to specialists (coder,
test-writer) in nested sub-runs. Eight built-in personas, a verify-before-finish gate, a lint, and a
model-independent test suite. What it's for now is measuring where a 9B holds up
over long horizons and where the harness has to carry it.
Credits
Persona schema and authoring discipline are adapted — used purely as a reference (their "Use as Reference" path) — from msitarzewski/agency-agents (MIT). The harness itself (per-agent tool restriction, budgets, loop, delegation) is ours.
License
MIT — see LICENSE.