gc does, from slinging a single task to running a fleet of pooled agents, is some combination of these nine. Read this page after the overview, or jump straight to the concept you need.
This is reference material, not a tutorial. Each section explains what a concept is, what it does for you, and shows one snippet you can copy-paste. For the guided, end-to-end path, start with the Tutorials.
The five primitives
A primitive is irreducible: you cannot rebuild it out of the other concepts, and removing it would make whole classes of orchestration impossible. There are exactly five.Session
A session is a single running instance of an agent — a live process (by default atmux pane) that Gas City can start, stop, prompt, and observe, regardless of which provider backs it.
Sessions are deliberately disposable. They come and go; the work they were doing survives them, because work lives in the Beads Store, not in the process. This is what lets the controller restart a stalled agent, replace a crashed one, or adopt a still-running one after the controller itself restarts — without losing anything.
A session’s identity is stable even though the process is not. The same agent always resolves to the same session name, so the controller can find, re-attach to, or replace it across restarts.
What it does for you: you never manage processes by hand:
- You declare agents in config
- The controller spawns, supervises, and reaps sessions to match
- When you need to look inside one, you address it by name (peek it, attach to its session, etc.).
Under the hood, the runtime boundary is a Provider interface with implementations for tmux (production), subprocess (remote), exec (script), Kubernetes, and a fake provider for tests. They all expose the same start/stop/prompt/observe surface, so nothing above the session layer cares which one is in use.
Beads Store
The Beads Store is the universal persistence substrate. The rule is absolute: everything is a bead. A bead is one row in one store, and tasks, mail messages, molecules, convoys, and epics are all beads that differ only by theirtype field.
A bead is a single unit of work with:
- an ID
- a title
- a status (
open→in_progress→closed) - a type
- an optional assignee
- parent/child links
- dependencies (
needs) - a description
- labels.
By default the store is backed by Dolt through thebdCLI, with one Dolt server per city. The city and its rigs share that server but stay logically separate byissue_prefix. See Beads Storage Topology for where the files live.
Event Bus
The event bus is the universal observation substrate: an append-only pub/sub log of everything that happens in the system. Events are immutable and carry a monotonically increasing sequence number, so observers can replay from any point and never miss or reorder an event. It has two tiers:- critical events on a bounded queue, for infrastructure that must not drop anything;
- optional, fire-and-forget events for audit and visibility.
--watch/--follow view.
Config
Config is TOML with progressive activation: capabilities switch on simply because a section is present, not because you flipped a feature flag. For instance, an emptycity.toml gives you the bare minimum; adding sections unlocks more.
Config is assembled from several sources:
city.toml— the root config file at the city directory root; the entry point the controller reads first and the file you always edit.- Fragment files — additional TOML files pulled in via an
includefield incity.toml. pack.toml— reusable configuration directories (packs) that define agents and prompts.agents/<name>/agent.toml— one file per agent; optional per-agent overrides (provider, rig scope, model, pool size). Lives under theagents/directory of any pack — the city root (yes, a city is also a pack, called the root pack), an imported pack, or a rig-level import.formulas/*.toml— one file per formula; can live at the city root (<city-root>/formulas/) or inside a pack (<pack-dir>/formulas/).orders/*.toml— one file per order (a formula with an Event Bus gate condition); same placement rules as formula files.
city.tomlis the operational config: which agents run, how many, on which provider, health thresholds, mail settings, etc. It is the desired state the controller reconciles toward — change it and the controller notices (it watches the file) and drives reality to match, no restart required for most changes.pack.tomlis the behavioral config: what agents do — their prompts. Packs are reusable and can be shared across cities.agents/<name>/agent.tomlis the per-agent config: how one agent diverges from the defaults — its provider, rig scope, model, or pool size. Optional; omit it and the agent inherits everything.- Formula and order files are the workflow config: the step-by-step definitions that instantiating a molecule or firing an order consumes at runtime. They can live at the city root or inside a pack.
city.toml is where you say how your city runs; packs and their agents/<name>/agent.toml files are where you define which agents exist and what each one does; formula and order files are where you define the workflows they run. Together they form the full picture of your city’s desired state, with no separate state file to maintain.
A minimal two-agent city declares each agent as its own directory under
agents/. Scaffold them with gc agent add:
agents/<name>/ directory with a starter prompt. The
result is a tree where city.toml holds the operational defaults the agents
inherit:
mayor and worker run on claude because they inherit the workspace
default; neither needs an agent.toml until it diverges from it.
Prompt Templates
A prompt template is a Gotext/template written in Markdown that defines what an agent does.
It is the entire behavioral specification for a session — the SDK contains zero hardcoded roles, so a “mayor” or a “reviewer” is nothing more than the prompt you wrote for it.
Templates are rendered at spawn time with context about:
- the city
- the agent
- the rig
- git metadata.
{{ .AgentName }}, {{ .RigName }}, {{ .RigRoot }}, {{ .WorkDir }}, {{ .WorkQuery }}, {{ .IssuePrefix }}, {{ .CityRoot }}, and {{ .DefaultBranch }}.
Prompt file discovery prefers prompt.template.md (with prompt.md and prompt.md.tmpl accepted for compatibility).
The four derived mechanisms
A derived mechanism is one that is composed from the primitives above — it needs no new storage, no new runtime, no new infrastructure. Each one below is just a particular combination of Session, Beads Store, Event Bus, and Config.Messaging
Messaging is how agents talk to each other. It is two things, neither of which is a new primitive:- Mail is a bead with
type: message. An agent’s inbox is a query for open message beads addressed to it; archiving a message is closing that bead. Mail is therefore just the Beads Store. Mail is not instantaneous: the recipient reads it the next time theUserPromptSubmit(or equivalent) agent provider’s hook fires (which runsgc mail check --injectto inject pending messages into the agent’s next prompt). If you need the agent to act before that, pair a mail with a nudge. - Nudge is text typed directly into a running agent’s session to prod it. It is fire-and-forget and uses just the Session layer.
Formulas & Molecules
A formula is a reusable, multi-step workflow written as TOML. A molecule is a formula instantiated at runtime: one root bead plus child step beads in the Beads Store, with progress tracked by closing those beads. A wisp is an ephemeral molecule that auto-closes and is garbage-collected after a configurable time-to-live (TTL). Instantiating a molecule from a formula is pure composition from the primitives: Config supplies the formula definition (aformulas/*.toml file), and the Beads Store holds the resulting root bead and step beads. Steps declare dependencies on each other with needs, so the store’s readiness queries naturally schedule them in the right order.
What it does for you: instead of slinging work one piece at a time, you describe a whole workflow once and dispatch it as a unit. The steps fan out and join automatically based on their dependencies.
dry and wet have no dependencies and can run in parallel; combine waits for both. See Tutorial 05 for the full walkthrough.
Dispatch (Sling)
Dispatch — invoked withgc sling — is the routing mechanism that turns “do this work” into a running agent.
It composes the primitives end to end:
- find or spawn an agent (Session)
- select a formula if one applies (Config)
- create the work bead or molecule (Beads Store)
- hook it to the agent (Beads Store)
- nudge the session (Session)
- optionally create a convoy to group related work (Beads Store)
- log an event (Event Bus).
Health Patrol
Health patrol keeps the fleet alive. Like Dispatch it composes the primitives end to end:- probe sessions for liveness (Session)
- compare what it finds against thresholds (Config)
- publish stalls to the Event Bus
- restart unhealthy sessions with backoff (Session).
agents/<name>/ directory would break supervision, that would be a bug.
What it does for you: stalled and crashed sessions recover automatically. You declare the health thresholds in config; the controller does the probing, restarting, and backoff. When you want to check the system’s health yourself:
A note on design principles
These nine concepts are not an arbitrary list — they are the minimal set that makes multi-agent orchestration possible. Three rules keep the boundary honest:- Atomicity. If a capability can be decomposed into the five primitives, it is a derived mechanism, not a new primitive. That is why Messaging, Formulas, Dispatch, and Health Patrol are composed, not built.
- Bitter Lesson. Every primitive must become more useful as models improve, never less. Gas City adds no heuristics or decision trees that a better model would outgrow.
- ZFC (Zero Framework Cognition). Go handles transport, not reasoning. If a line of Go contains a judgment call, it is a violation — the decision belongs in a prompt template, not in code.
Where to go next
- Architecture Overview — the top-down view these primitives compose into.
- Tutorials — the guided, end-to-end path through every concept above.
- Tutorial 06: Beads — go deeper on the Beads Store that underpins everything here.
- Beads Storage Topology — how a city and its rigs share one store under the hood.
- Reference — command, config, formula, and provider lookup.