How a gate works
A gate is a bead like any other: created open, it blocks its waiters through a normal dependency edge, and the step becomes ready the moment the gate closes. Gates close in one of two ways:- Manually —
bd gate resolve <gate-id>(human gates always close this way). - Via
bd gate check— evaluates open timer and GitHub gates against the real world and closes the ones whose condition is met.
Gate types
| Type | Waits for | Closed by |
|---|---|---|
human | a person’s decision | bd gate resolve only |
timer | a duration after gate creation | bd gate check once the timeout elapses |
gh:run | a GitHub Actions workflow to complete successfully | bd gate check (uses gh run view) |
gh:pr | a pull request to merge | bd gate check (uses gh pr view) |
bead | a bead in another rig to close | currently unresolvable — multi-rig routing was removed, so bd gate check reports these gates as uncheckable |
30m, 1h, 24h (there is no d unit —
write 24h, not 1d).
Gates in formulas
A formula step declares a gate with a[steps.gate] block. When the formula
is instantiated, bd creates the gate issue and wires it as a blocker of that
step. The schema has four fields: type, id, await_id, and timeout.
This is the release gate from beads’ own release formula — the step that
waits for the GitHub release workflow:
Creating gates outside formulas
bd gate create attaches a gate to existing work:
Fan-in: waiting on other steps
Waiting on other steps is not a gate — it’s a dependency. Useneeds to
fan in on named steps, and waits_for when a step must wait for
dynamically-created children:
Working with gated molecules
bd gate check on a schedule (cron, CI, or an
orchestrator loop) so timer and GitHub gates close without a human in the
loop; keep human gates for the decisions that should never auto-close.