Agent harness: zot & Colibri
← index
Architecture
Odjeljak naslovljen „Architecture”Two binaries with distinct roles:
- 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.
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.
AgentKind — single source of per-harness behavior
Odjeljak naslovljen „AgentKind — single source of per-harness behavior”AgentKind (crates/colibri-daemon/src/socket.rs) is an enum that resolves
a binary basename into the canonical CLI args, RPC stdin mode, runtime tag,
and credentials strategy. Three variants:
| Variant | Binary basename | CLI args | RPC? |
|---|---|---|---|
Zot | zot | rpc --provider deepseek --model deepseek-v4-flash (#344) | Yes |
Pi | pi | --mode json | No |
TestAgent | colibri-test-agent | --session-id <task_id> --step-ms 10 --hold-secs 1 | No |
Bare zot rpc defaults to openai-codex (429 rate limits). The --provider deepseek --model flags are the #344 fix — they live in AgentKind::Zot.args()
so both the autospawn and per-task spawn paths route correctly.
Runtimes
Odjeljak naslovljen „Runtimes”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
Odjeljak naslovljen „Autospawn”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:
COLIBRI_AUTOSPAWN_BINARY— defaults tozotCOLIBRI_AUTOSPAWN_ARGS— overrides the CLI args wholesale (zot default:rpc --provider deepseek --model deepseek-v4-flash, resolved viaAgentKind)COLIBRI_AUTOSPAWN_TASK— if set, sends a bootstrap prompt over theRpcSenderto the newly spawned agent
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.
On restart, stale agent rows from prior sessions are pruned before the
first scheduler tick (#348), so the scheduler never dispatches to a dead
agent. The same prune reclaims any tasks those agents held in-flight
(#351) — set back to queued so the next tick can re-dispatch them.
Where it lives
Odjeljak naslovljen „Where it lives”- Spawn contract,
rpc_stdin,RpcSender:crates/colibri-daemon/src/spawner.rs AgentKindenum (args, runtime, credentials):crates/colibri-daemon/src/socket.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
- 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 everycargo testviasample-pi-agent.py)
See also
Odjeljak naslovljen „See also”- task-dispatch-flow — the full submit → done chain
- naming-decisions — harness naming history
- hive-routing — capability-based task dispatch