If you’ve been following along, you’ve been creating beads without knowing it. When you started a session — that created a bead. When you sent mail — bead. When you cooked a formula — beads. When sling dispatched a wisp — bead. Beads are the universal work primitive in Gas City. Every trackable thing — tasks, messages, sessions, molecules, convoys — is a bead in the store. This tutorial peels back the layer and shows you what’s underneath. We’ll pick up where Tutorial 03 left off. You should haveDocumentation Index
Fetch the complete documentation index at: https://gascityinc-5c0069dd-work-default-pack-registry.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
my-city running with my-project rigged, and agents for mayor
and reviewer (along with the corresponding prompts):
agents/<name>/prompt.template.md.
The machine-local workspace identity and rig binding live in .gc/site.toml:
What is a bead
A bead is a unit of work with an ID, a title, a status, and a type. We use thebd tool to work with beads directly.
bd list renders a tree, with parent beads grouping their children.
The leading glyph is the bead’s status, followed by ID, priority (P2), and
title. Pass --flat for a single-level list and --all to include closed
beads.
Every bead has:
- ID — unique identifier prefixed with two letters derived from the city or
rig name (e.g.,
mc-194for a city named “my-city”,ma-12for a rig named “my-app”) - Title — human-readable name
- Status —
open,in_progress,blocked,deferred, orclosed - Type — what kind of bead it is
Bead types
The type determines what a bead represents:| Type | What it is | Created by |
|---|---|---|
| task | A unit of work | bd create, formula steps |
| message | Inter-agent mail | gc mail send |
| session | A running agent session | gc session new |
| molecule | Persistent formula instance | gc formula cook |
| wisp | Ephemeral formula instance | gc sling --formula |
| convoy | Container grouping related beads | gc convoy create, auto-created by sling |
Creating beads
Most beads are created indirectly:gc session new my-project/reviewercreates a session beadgc mail send mayor "Subject" "Body"creates a message beadgc formula cook reviewcreates molecule + step beadsgc sling mayor review --formulacreates a wisp bead + convoy
bd to create them manually:
Bead lifecycle
Beads move through a small set of states:- open — work hasn’t started yet. Discoverable by agents via hooks.
- in_progress — claimed by an agent, being worked on.
- closed — done.
- blocked — has an open
blocksdependency. Set automatically. - deferred — explicitly snoozed until a date.
blocked and deferred are derived states the system manages for you.
--status (--state is a different command for state
dimensions).
Beads as execution state
The bead store is effectively the execution state of the entire system. Every session that’s running, every message in flight, every formula step being worked on — all of it is a bead with a status. If you want to know what the city is doing right now, you query the store. The exact output depends on what is currently active in your city. For example:Labels
Labels are how beads get organized and routed:bd label add takes a single label per call — apply multiples one at a time.
Some labels have special meaning in Gas City:
gc:session— marks session beadsgc:message— marks mail beadsthread:<id>— groups mail messages into conversationsread— marks a message as read
Metadata
Beads carry arbitrary key-value metadata for structured state:session_name,
alias), routing (gc.routed_to), merge strategies, and formula references.
You can use it for anything you want to attach to a bead without changing its
title or description. Use --unset-metadata <key> to remove one.
Dependencies
Beads can depend on other beads. You’ve already seen this in formulas — when a step declaresneeds = ["design"], that’s a blocking dependency. The step bead
can’t start until the design bead closes. Dependencies are how Gas City enforces
ordering without a central scheduler: each bead knows what it’s waiting for, and
agents only see work that’s ready.
mc-xp7 won’t appear in any agent’s work query until mc-a4l is closed.
This is the same mechanism that makes formula step ordering work — needs
declarations become blocks edges between step beads.
The dependency types are blocks (must close before the other can start),
tracks (informational — “I care about this”), related (loose
association), parent-child (containment), and discovered-from (work
that surfaced while doing other work). Only blocks affects work visibility.
Beads also have a separate parent-child relationship — a bead can set a
parent_id linking it to a container. This is how convoys and molecules group
their children. The difference: dependencies express ordering (“do A before B”),
while parent-child expresses containment (“these beads belong to this group”). A
convoy’s children don’t depend on each other — they’re just members of the same
batch.
Convoys
If you’ve slung a formula, you’ve already created a convoy without knowing it — Gas City automatically wraps dispatched formula work in one. You’ll see them inbd list as beads with type convoy, and in gc convoy list with progress
summaries. They matter when you need to track a batch of related work as a unit:
“are all five of these tasks done yet?” is a convoy question.
You can also create them by hand to group arbitrary work — say, a set of beads
you want to track together as a sprint or a deploy:
convoy. The child beads are linked via their
ParentID — the same parent-child mechanism used by molecules, just for
grouping instead of step ordering.
Auto-close
When a bead closes, Gas City checks whether its parent is a convoy with all children now closed. If so, the convoy closes automatically. This happens in the background via theon_close hook — no polling, no manual intervention.
Convoys with the owned label skip auto-close. These are for workflows where
you want explicit control over when the convoy completes:
Adding beads and checking convoys
Sometimes work grows after a convoy is created — a new bug surfaces mid-sprint, or a dependency gets discovered after the plan is set. You can add beads to an existing convoy:Stranded work
To find open beads in convoys that have no assignee — work that’s stuck waiting for someone to pick it up:Convoy metadata
Convoys carry metadata that controls how grouped work behaves:convoy.owner— which agent manages this convoyconvoy.notify— who to notify when the convoy completesconvoy.merge— merge strategy for PRs (direct,mr,local)target— target branch inherited by child beads
How agents find work
This is where beads connect to the runtime. Routed agents discover work through the claim protocol rendered into their session startup prompt. The protocol asksgc hook for eligible work, claims one bead with bd update --claim, and then
the agent runs exactly that bead. The legacy Stop-hook form, gc hook --inject,
is silent compatibility behavior and no longer injects work into the agent.
The typical flow:
- Work is created (via
bd create,gc sling, formula cook, etc.) - Work is routed to an agent (via assignee or
gc.routed_tometadata) - Session startup runs the agent’s work query through
gc hook - The claim protocol atomically claims one ready bead
- The agent sees the claimed work and acts on it (GUPP: “if you find work on your hook, you run it”)
mc-xp7 is blocked by mc-a4l right now, this query won’t return
anything yet. That’s the point: blocked work is invisible to agent work
queries. Once mc-a4l closes, rerun the same query and mc-xp7 becomes
eligible.
This is the “pull” model — agents check for work rather than having work pushed
to them. It’s simple, crash-safe (queued work survives restarts), and scales
naturally.
The bead store
Beads are persisted in a store. Gas City supports several backends:- bd (default) — Dolt-backed database via the
bdCLI. Full-featured, good for production. - file — JSON file on disk. Simple, good for tutorials and small setups.
- exec — Delegates to a custom script. For integration with external systems.
city.toml:
You don’t usually work with beads directly. The higher-level commands —
gc session, gc mail, gc sling, gc formula — handle bead creation and
management for you. But when you want to query what work is outstanding across
the city, create ad-hoc tasks for agents, inspect the dependency graph of a
formula, or debug why an agent isn’t picking up work — that’s when you reach for
bd directly.
What’s next
- Orders — formulas and scripts on autopilot, triggered by time, schedule, conditions, or events