agent pool — design
Class:
design· Function axis:f0the fleet-as-data surface (the whole) ·f1theAgentPoolRPC ·f2thedwarves agentsverb (fat + thin) ·f3the jera reuse seam Strict: this file states only what the agent-pool surface IS — its parts and why. Sibling how-to: agent-pool-guide.md; zero-knowledge walkthrough: agent-pool-for-idiots.md.
The agent pool surface exposes the worker fleet the forge dispatches to — every registered agent (id, group, capabilities, cores/mem, liveness) — as data, over the wire and from the CLI. It closes the D1-wishlist gap "AgentPool … remain open" and is the enabling wire for the parity §4b "Agents view — the live fleet." Before this, Show/History carried pipelines + runs but the fleet was invisible over gRPC.
The system as one — the function map (f0)
| part | lives in | what it is |
f1 AgentPool RPC |
crates/dwarves/src/server.rs · proto/dwarf.proto |
DwarfSvc::agent_pool reads the shared jera Scheduler → AgentPoolReply{ repeated AgentRow } |
f2 dwarves agents verb |
crates/dwarves/src/main.rs |
fat = the local single-machine pool; thin = the server's live pool over AgentPool |
f3 reuse seam |
jera (edda) | Scheduler::state_json() — the ONE fleet-as-data contract, consumed not twinned |
Why it is shaped this way
- Reuse jera's fleet contract (Law #1). dwarves owns no scheduler of its own — the
Agent/Scheduler/worker-group machinery lives injera::agent(edda). The RPC handler readsScheduler::state_json()(the documented{agents:[{id,group,caps, cores,mem_mb,state}]}shape jera already ships for exactly this "feed a UI Agents pane" purpose) and maps each row onto the wire — no internal accessor, no twin fleet model. The fat CLI reads the samestate_json()from the local default pool, so fat and thin print an identical listing. - One surface, single→multi machine. The pool is
LocalAgentsingle-machine today (scheduler_with_local_defaultseedslocal-0in groupdefault, capcargo). AGrpcAgentfleet registers into the SAMEScheduler, soAgentPoolreports a real multi-machine fleet with no change to this surface — the lazy-but- seam-honest discipline the parity spec mandates for distribution. - Additive + gated like every RPC. The
AgentPoolRPC +thin_agentsclient compile only under--features server(proto codegen + tonic); the fatdwarves agentsneeds onlyagent_bridge(always compiled). nornir's lean path-dep pulls nothing new. - Observed as data (L4). The handler is drive-and-assert tested (a fresh server's pool is exactly
local-0/default/cargo/idle, RED-when-broken) with adwarves::server / agent_pooltestmatrix cell. No new UI surface ⇒ no robot row (the fleet-as-data contract is the assertion, same as theBadgeRPC).
Place in the nordisk constellation
This is a dwarves-owned control-plane surface reading a shared jera primitive. It mirrors the constellation's "expose the fleet as data so a robot/matrix can assert it" law: nornir, dwarves and holger all get multi-machine awareness from the one jera crate, and each surfaces its pool the same way. The eventual Agents pane (facett-jobview-adjacent) consumes this RPC behind the same state_json shape.
Deferred
- No Agents UI pane yet. The RPC + CLI land the wire; mounting a live Agents pane in
dwarves-gui(over this RPC or a fixture) is a follow-up, mirroring the Status-board build-out. - Single in-process agent. Only the default
LocalAgentis registered today; theGrpcAgentremote-registration path (a<host> dwarves agent --group …joining the server's scheduler over gRPC) is the tracked multi-machine leg — this surface already reports whatever the scheduler holds, so it needs no change when that lands. - PDFs (
docs/*.pdf) left for the Loki bencher'snornir docs bookrender.