The machinery underneath
Three pieces of role-agnostic plumbing run the primitives, and you configure no role around any of them.
None of this machinery knows what your agents do. It’s the substrate the six
primitives sit on. Notice the shape of the loop: the orchestrator acts on
sessions — spawning, stopping, restarting them — but reads their progress from
the bead store and event bus rather than being called back directly. The loop
closes through shared state, which is why work survives a crash on either side.
The six primitives
Agent
An agent is who does the work — a worker a pack defines as a prompt plus a scope and a provider. The prompt template is its entire behavioral spec; because the platform has no hardcoded roles, a “reviewer” or a “planner” is nothing more than the prompt you wrote for it. When an agent is running it is a session — a live process the platform can start, stop, prompt, and observe. The engine backing that session is its provider; when the orchestrator restarts, it adopts the live sessions it finds — creating a session bead for each — rather than respawning them. A single agent can be scaled into a pool of identical workers sharing one queue: each tick the orchestrator runs the agent’sscale_check query to measure
demand and sizes the pool to it — up to max_active_sessions, never below a
min_active_sessions floor — retiring sessions that fall idle. Sessions are
disposable; the work they did survives them, because work lives in beads.
Bead
A bead is what the work is — one unit with an ID, title, status, and type, movingopen → in_progress → closed. Beads are also the universal store:
tasks, inter-agent mail, running sessions, and convoys are all beads that differ
only by type, sharing one query interface. A convoy is a container bead
that groups related work so you track a batch as a unit. Dependencies are
blocking needs edges: a bead with an open blocker is invisible to agents until
that blocker closes — which is how ordering happens with no central scheduler.
Because work persists in beads, the system converges: if an agent dies, its beads
stay open and a fresh agent picks up the same work.
Formula
A formula is how a job gets done — a reusable, written-down method, a TOML file of steps and their dependencies. Applying it compiles the steps into a graph and materializes them as beads; from that moment a run is independent of the file and of any session. The orchestrator drives the run outside your session, fanning ready steps out to many agents at once and gating each on its dependencies. Sling (gc sling) is the dispatch op that creates and routes
in one motion. An Order automates when a formula runs, pairing a trigger
(cooldown, cron, condition, event, or manual) with the formula to fire — no human
runs a verb. Health patrol is one kind of order: each tick the orchestrator
evaluates due triggers and fires them.
Rig
A rig is where the work happens — an external project, usually a git repo, registered with the city withgc rig add <path>. A rig carries a repo, its own
bead namespace, and an agent scope. Its directory can live anywhere on
disk, inside or outside the city. Isolation is by bead-ID prefix, not a separate
database: the city and all its rigs share one underlying store, and reads and
writes are filtered to the current scope’s prefix. Work slung in one rig stays
logically isolated from the others, and rig-scoped agents are instantiated once
per rig.
Pack
A pack is what configures the system — a directory with apack.toml that
declares agents, formulas, and orders, plus the support files they need. The
local (root) pack is your City: the pack rooted at the city directory, where
the city keeps its own definitions alongside its deployment settings. Imports
are named dependencies on shared packs; an imported pack’s agents, formulas, and
orders read exactly like locally declared ones, so a city reuses behavior defined
elsewhere without copying files. The same engine becomes a different orchestrator
purely by swapping which packs it loads.
Event
An event is how you observe what’s happening — an immutable, append-only record fired by city activity, not something the other primitives consume. Every event carries a monotonically increasing sequence number, so a watcher can replay the stream from any point. Beads firebead.created / bead.closed, sessions fire session.woke /
session.crashed, convoys fire convoy.created / convoy.closed, and orders
fire order.fired / order.completed. Humans watch the stream with bd show --watch, the gc events --follow CLI, or the dashboard; agents and bd hooks
observe and emit too. Events also close the automation loop: an event-triggered
order reads the stream to decide when its formula runs — so the same
notifications humans watch can drive the fleet, with no specific agent role
required.
Where to go next
- Tutorials — the guided, end-to-end path through every primitive above.
- Understanding Formulas — the full guide to formulas, runs, sling, and orders.
- Understanding Packs — how packs, cities, and imports compose.
- Reference — command, config, formula, and provider lookup.