Skip to content
Conduit

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.

zepef/ornithoptercommunitylistedunreviewed

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

Skills do not use an MCP config. Follow the steps in the README below.

README

synced Oct 26, 2026

Ornithopter

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 reviewer never even learns write_file exists);
  • 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:

agentcategoryscopetools
generalistgeneralopen-ended tasks, full tool setfiles + shell
coderengineeringimplement + run/verify codefiles + shell
debuggerengineeringreproduce → root-cause → fix → provefiles + shell
test-writerengineeringwrite focused tests, run them greenfiles + shell
refactorerengineeringimprove structure, behavior-preservingfiles + shell
reviewerengineeringread-only code reviewread-only
researcherresearchinvestigate → write report.mdread + report
orchestratorcoordinationplan → delegate to specialists → verifydelegate-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 thinking before content, both counting against num_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>/) with journal.jsonl, meta.json, a scratchpad.md, and a sandboxed workspace/. resume replays 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_criteria is challenged once when it first calls finish — it must re-check each criterion with evidence before the run is accepted as done.
  • Delegation (opt-in). An orchestrator can hand a subtask to a specialist via the privileged delegate tool; 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 lead pair-coder delegates a review to reviewer (peer cooperation, no orchestrator; also shows a project-local agent).
  • 03-orchestrated-team — an orchestrator fans a task out to coder, test-writer, and reviewer.
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.

↑↓ navigate openesc close