docs(wiki): rewrite agent-harness — technical explanation, not commit log #273

Merged
clawdie merged 1 commit from fix/rewrite-agent-harness-wiki into main 2026-06-28 12:06:10 +02:00
2 changed files with 80 additions and 78 deletions

View file

@ -1,56 +1,58 @@
# Agent harness: pi, zot & Colibri
# Agent harness: zot & Colibri
← [index](./index.md)
## Decision
## Architecture
Two binaries, not one (Sam rejected merging them, 13.jun.2026):
Two binaries with distinct roles:
- **zot**_the agent_ (front door to the model). Go binary; acts.
- **Colibri**_the control plane_ (supervisor). Rust; watches agents via
glasspane, runs the task board, owns cost. It **observes** zot/pi; it does not
contain them.
- **zot**the agent (model frontend). Go binary; executes tasks, calls
providers, emits JSONL events on stdout.
- **Colibri** — the control plane (supervisor). Rust daemon; observes agents
via glasspane, runs the task board, owns cost tracking.
Canonical statement: `AGENTS.md` (lines ~1832). `clawdie-ai` (TS) is being
pruned; surviving features move to zot/Colibri.
> There is **no** `ADR-agent-harness-consolidation.md` (it was referenced in the
> past; those references have since been cleaned up). Treat `AGENTS.md` as the ADR.
Colibri **observes** zot; it does not embed it. The two communicate through
the spawner's stdout JSONL contract and, for RPC agents, a piped stdin
channel.
## Runtimes
Glasspane normalizes events from both harnesses into one taxonomy via
`AgentRuntime { Pi, Zot, Local }``crates/colibri-glasspane/src/lib.rs`
(`zot_event_type()` maps zot's events onto the pi-style names).
Glasspane normalizes events from all harnesses into one taxonomy via
`AgentRuntime { Pi, Zot, Local }` — see `crates/colibri-glasspane/src/lib.rs`
(`zot_event_type()` maps zot's event structure onto the standard agent
lifecycle names).
## Autospawn + the RPC driver (colibri#143)
## Autospawn
The spawner's contract: spawn the agent, read stdout JSONL.
When `COLIBRI_AUTOSPAWN=YES`, the daemon spawns an agent at startup so the
node is immediately ready for task work. The agent binary and arguments are
configurable:
- **pi** self-drives (`pi --mode json`) with `stdin` null — fits directly.
- **zot**'s only structured persistent mode is `zot rpc`, a request/response
peer that **reads stdin**. So the spawner pipes stdin for RPC agents and the
daemon sends the prompt over an `RpcSender`.
- `COLIBRI_AUTOSPAWN_BINARY` — defaults to `zot`
- `COLIBRI_AUTOSPAWN_ARGS` — defaults to `rpc` for zot, `--mode json` for
other harnesses
Where it lives:
The spawner pipes stdin for RPC agents; the daemon sends a bootstrap prompt
over an `RpcSender` if `COLIBRI_AUTOSPAWN_RPC_PROMPT` is set.
- spawn contract + `rpc_stdin` + `RpcSender`: `crates/colibri-daemon/src/spawner.rs`
- autospawn binary-aware argv (`zot → rpc`, pi → `--mode json`):
`crates/colibri-daemon/src/socket.rs` (`default_agent_args`,
`autospawn_agent_if_configured`)
- wire format (verified against real zot): [agent-events-reference](./agent-events-reference.md)
- end-to-end proof, zot: `crates/colibri-daemon/tests/zot_rpc_driver.rs`
(`#[ignore]`, `ZOT_BIN`-gated — needs the real zot binary)
- end-to-end proof, pi: `crates/colibri-daemon/tests/pi_spawn_live.rs`
(unignored, runs in every `cargo test` — uses `sample-pi-agent.py` which
emits colibri-pi-events taxonomy verified against real pi)
- autospawn argv contract: `crates/colibri-daemon/src/socket.rs`
(`default_agent_args` unit tests — zot→rpc, pi→--mode json)
After spawn, the agent is registered in the local SQLite store with
capabilities detected by `probe_capabilities()` (OS, ollama, llama.cpp,
blender — see `clawdie-system-probe --capabilities` or the built-in fallback
in `crates/colibri-daemon/src/socket.rs`). The scheduler can then route
queued tasks to it.
OOTB default harness is **zot**; pi remains a supported fallback
(`COLIBRI_AUTOSPAWN_BINARY=pi`).
## Where it lives
- Spawn contract, `rpc_stdin`, `RpcSender`: `crates/colibri-daemon/src/spawner.rs`
- Autospawn, capability probe, agent registration: `crates/colibri-daemon/src/socket.rs`
(`default_agent_args`, `autospawn_agent_if_configured`, `probe_capabilities`)
- Wire format: [agent-events-reference](./agent-events-reference.md)
- End-to-end test, zot: `crates/colibri-daemon/tests/zot_rpc_driver.rs`
(auto-finds zot in PATH, skips gracefully if absent)
- End-to-end test, pi: `crates/colibri-daemon/tests/pi_spawn_live.rs`
(runs in every `cargo test` via `sample-pi-agent.py`)
## See also
- [naming-decisions](./naming-decisions.md) — the `pi → zot` neutral-naming work
- [quality-gates](./quality-gates.md) — how a half-finished rename reached `main`
- [naming-decisions](./naming-decisions.md) — harness naming history
- [hive-routing](./hive-routing.md) — capability-based task dispatch

View file

@ -1,60 +1,60 @@
---
title: "Agentska vprega: pi, zot & Colibri"
description: "Dve binarni datoteki, ne ena — zot (agent, Go) in Colibri (krmilna ravnina, Rust)."
title: "Agentska vprega: zot & Colibri"
description: "Dve binarni datoteki z različnima vlogama — zot (agent, Go) in Colibri (krmilna ravnina, Rust)."
---
← [kazalo](./index.md)
## Odločitev
## Arhitektura
Dve binarni datoteki, ne ena (Sam je zavrnil združitev, 13. junij 2026):
Dve binarni datoteki z različnima vlogama:
- **zot**_agent_ (vhodna vrata do modela). Binarna datoteka Go; deluje.
- **Colibri**_krmilna ravnina_ (nadzornik). Rust; opazuje agente prek
glasspane, poganja tablo opravil, upravlja stroške. **Opazuje** zot/pi; ne
vsebuje ju.
- **zot**agent (vhod v model). Binarna datoteka Go; izvaja opravila, kliče
ponudnike, oddaja dogodke JSONL na stdout.
- **Colibri** — krmilna ravnina (nadzornik). Proces v ozadju Rust; opazuje
agente prek glasspane, poganja tablo opravil, upravlja stroške.
Kanonična izjava: `AGENTS.md` (vrstice ~1832). `clawdie-ai` (TS) se krči;
preživele funkcije se selijo v zot/Colibri.
> **Ni** dokumenta `ADR-agent-harness-consolidation.md` (v preteklosti je bil
> omenjen; te reference so bile od takrat očiščene). Obravnavaj `AGENTS.md`
> kot ADR.
Colibri **opazuje** zot; ne vsebuje ga. Oba komunicirata prek pogodbe stdout
JSONL zaganjalnika in, za agente RPC, prek cevovoda stdin.
## Izvajalna okolja
Glasspane normalizira dogodke iz obeh oprem v eno taksonomijo prek
`AgentRuntime { Pi, Zot, Local }``crates/colibri-glasspane/src/lib.rs`
(`zot_event_type()` preslika zotove dogodke na imena v slogu pi).
Glasspane normalizira dogodke iz vseh oprem v eno taksonomijo prek
`AgentRuntime { Pi, Zot, Local }` — glej `crates/colibri-glasspane/src/lib.rs`
(`zot_event_type()` preslika zotovo strukturo dogodkov na standardna imena
življenjskega cikla agenta).
## Samodejni zagon + gonilnik RPC (colibri#143)
## Samodejni zagon
Pogodba zaganjalnika: zaženi agenta, beri stdout JSONL.
Ko je `COLIBRI_AUTOSPAWN=YES`, proces v ozadju ob zagonu zažene agenta, tako
da je vozlišče takoj pripravljeno na delo z opravili. Binarna datoteka in
argumenti agenta so nastavljivi:
- **pi** se sam poganja (`pi --mode json`) s `stdin` null — ustreza
neposredno.
- Edini strukturirani trajni način **zot** je `zot rpc`, vrstnik
zahteva/odgovor, ki **bere stdin**. Zato zaganjalnik napelje stdin za RPC
agente in proces v ozadju pošlje poziv prek `RpcSender`.
- `COLIBRI_AUTOSPAWN_BINARY` — privzeto `zot`
- `COLIBRI_AUTOSPAWN_ARGS` — privzeto `rpc` za zot, `--mode json` za druge
opreme
Kje živi:
Zaganjalnik napelje stdin za agente RPC; proces v ozadju pošlje zagonski
poziv prek `RpcSender`, če je nastavljen `COLIBRI_AUTOSPAWN_RPC_PROMPT`.
- pogodba zaganjalnika + `rpc_stdin` + `RpcSender`: `crates/colibri-daemon/src/spawner.rs`
- argv samodejnega zagona, ki se zaveda binarne datoteke (`zot → rpc`, pi → `--mode json`):
`crates/colibri-daemon/src/socket.rs` (`default_agent_args`, `autospawn_agent_if_configured`)
- žični format (preverjen proti pravemu zot): [agent-events-reference](./agent-events-reference.md)
- dokaz od konca do konca, zot: `crates/colibri-daemon/tests/zot_rpc_driver.rs`
(`#[ignore]`, `ZOT_BIN`-pogojen — potrebuje pravo binarno datoteko zot)
- dokaz od konca do konca, pi: `crates/colibri-daemon/tests/pi_spawn_live.rs`
(ne-ignoriran, teče v vsakem `cargo test` — uporablja `sample-pi-agent.py`, ki
oddaja taksonomijo colibri-pi-events, preverjeno proti pravemu pi)
- pogodba argv samodejnega zagona: `crates/colibri-daemon/src/socket.rs`
(testi enot `default_agent_args` — zot→rpc, pi→--mode json)
Po zagonu je agent registriran v lokalni shrambi SQLite z zmožnostmi, ki jih
zazna `probe_capabilities()` (OS, ollama, llama.cpp, blender — glej
`clawdie-system-probe --capabilities` ali vgrajeno rezervno zaznavanje v
`crates/colibri-daemon/src/socket.rs`). Načrtovalnik lahko nato usmeri
čakajoča opravila k njemu.
Privzeta vprega OOTB je **zot**; pi ostaja podprta rezerva
(`COLIBRI_AUTOSPAWN_BINARY=pi`).
## Kje živi
- Pogodba zaganjalnika, `rpc_stdin`, `RpcSender`: `crates/colibri-daemon/src/spawner.rs`
- Samodejni zagon, zaznavanje zmožnosti, registracija agenta: `crates/colibri-daemon/src/socket.rs`
(`default_agent_args`, `autospawn_agent_if_configured`, `probe_capabilities`)
- Žični format: [agent-events-reference](./agent-events-reference.md)
- Preizkus od konca do konca, zot: `crates/colibri-daemon/tests/zot_rpc_driver.rs`
(samodejno najde zot v PATH, se elegantno preskoči, če ga ni)
- Preizkus od konca do konca, pi: `crates/colibri-daemon/tests/pi_spawn_live.rs`
(teče v vsakem `cargo test` prek `sample-pi-agent.py`)
## Glej tudi
- [naming-decisions](./naming-decisions.md) — nevtralno poimenovanje `pi → zot`
- [quality-gates](./quality-gates.md) — kako je napol dokončano preimenovanje doseglo `main`
- [naming-decisions](./naming-decisions.md) — zgodovina poimenovanja oprem
- [hive-routing](./hive-routing.md) — usmerjanje opravil na podlagi zmožnosti