Skip to main content

Gates (Async Coordination)

Gates are synchronization points in Gas Town workflows. When a molecule step needs to wait for an external condition -- a CI pipeline finishing, a human approving a change, or a timer elapsing -- it parks on a gate. The gate holds the workflow until the condition is met, then releases it to continue.


Why Gates?

AI agents work fast. But some things cannot be sped up:

  • CI pipelines take minutes to run
  • Humans need time to review and approve
  • External services have their own timelines
  • Timers enforce cooldown periods

Without gates, an agent would need to busy-wait (burning context and cost) or exit and lose its place. Gates solve this by parking the workflow and resuming it when the condition clears. This aligns with GUPP -- the workflow's progress is preserved, and it resumes forward when the gate opens.

Gate Types

Gas Town supports several gate types, each waiting on a different kind of external condition:

TypeAwait KeyConditionWho Closes It
TimertimerElapsed time since creation exceeds timeoutDeacon patrol (automatic)
GitHub Actionsgh:runGitHub Actions workflow run completesDeacon patrol (polls GitHub)
GitHub PRgh:prPull request reaches target stateDeacon patrol (polls GitHub)
Human ApprovalhumanA human explicitly approvesHuman via bd gate approve
MailmailA specific mail message arrivesMail system (automatic)

Timer Gates

Timer gates are the simplest type. They close automatically after a specified duration:

# Create a gate that opens after 30 minutes
bd gate create --type timer --timeout 30m --title "Cooldown before retry"

The Deacon's patrol cycle checks all timer gates and closes any that have elapsed:

# Deacon runs this automatically:
bd gate check --type=timer --escalate
Escalation on Expiry

Timer gates do not just silently close. When they expire, they escalate to the overseer for awareness. This ensures human oversight of timeout conditions.

GitHub Actions Gates

These gates wait for a GitHub Actions workflow run to complete:

# Wait for CI to pass on a specific commit
bd gate create --type gh:run --run-id 12345 --title "Wait for CI"

The Deacon polls GitHub during patrol cycles to check run status.

Human Approval Gates

Human gates require explicit human action to proceed. They are used for critical decisions that should not be automated:

# Create a gate requiring human approval
bd gate create --type human --title "Approve production deploy"

The gate stays open until a human explicitly approves it:

# Human approves the gate
bd gate approve gt-gate-123

Mail Gates

Mail gates close when a specific message arrives in an agent's mailbox:

# Wait for a MERGED notification
bd gate create --type mail --subject "MERGED polecat/toast" --title "Wait for merge"

Gate Lifecycle

StateMeaning
OpenWaiting for condition to be met
ClosedCondition met, workflow can resume
ExpiredTimer elapsed, escalated for attention

Gates in Molecules

Gates are typically embedded in molecule steps. When a step encounters a gate, the workflow pauses at that step until the gate closes.

Example: CI Gate in a Deploy Workflow

[[steps]]
id = "run-ci"
title = "Trigger CI and wait for results"
description = """
Trigger the CI pipeline and create a gate to wait for completion.

```bash
# Trigger CI
gh workflow run ci.yml --ref $(git branch --show-current)

# Create gate to wait for CI
bd gate create --type gh:run --run-id <run-id> --title "Wait for CI"

# Park on the gate
gt mol step park --gate <gate-id>

The Deacon will close this gate when CI completes. Your next patrol cycle (or a fresh session) will pick up from here. """


### Example: Human Gate Before Production Deploy

```toml
[[steps]]
id = "human-approval"
title = "Get human approval for production deploy"
description = """
Create a human gate and wait for approval.

```bash
bd gate create --type human --title "Approve deploy v2.3.1 to production"

# Notify the overseer
gt mail send mayor/ -s "APPROVAL NEEDED: Deploy v2.3.1" \
-m "Please review and approve: bd gate approve <gate-id>"

This step cannot proceed until a human runs bd gate approve. """


## Gate Evaluation by the Deacon

The Deacon is responsible for evaluating gates during its patrol cycle. The `gate-evaluation` step in the `mol-deacon-patrol` formula handles this:

1. **List all open gates**: `bd gate list --json`
2. **For each timer gate**: Check if `created_at + timeout < now`
3. **For each GitHub gate**: Poll the GitHub API for run/PR status
4. **Close ready gates**: `bd gate close <id> --reason "Condition met"`
5. **Notify waiters**: Send mail to agents blocked on the gate

After gate evaluation, the `dispatch-gated-molecules` step finds molecules that were blocked on now-closed gates and dispatches them:

```bash
# Find molecules ready to resume
bd mol ready --gated --json

# Dispatch each to the appropriate rig
gt sling <mol-id> <rig>/polecats

Commands

Creating Gates

# Timer gate
bd gate create --type timer --timeout 30m --title "Cooldown period"

# Human approval gate
bd gate create --type human --title "Approve deploy"

# GitHub Actions gate
bd gate create --type gh:run --run-id 12345 --title "Wait for CI"

# Mail gate
bd gate create --type mail --subject "MERGED" --title "Wait for merge"

Viewing Gates

# Show gate details
bd gate show <gate-id>

# List all open gates
bd gate list

# List gates as JSON
bd gate list --json

Closing Gates

# Close a gate (condition met)
bd gate close <gate-id> --reason "CI passed"

# Approve a human gate
bd gate approve <gate-id>

# Wake agents waiting on a gate
gt gate wake <gate-id>

Command Reference

CommandDescription
bd gate createCreate a new gate
bd gate show <id>Show gate details
bd gate listList all open gates
bd gate close <id>Close a gate (condition met)
bd gate approve <id>Approve a human gate
gt gate wake <id>Wake agents waiting on a gate

Use Cases

Waiting for CI

Human Approval Workflow

Timer-Based Retry

When to Use Gates

Use gates whenever your workflow needs to wait for something external. Prefer gates over busy-waiting (polling in a loop), which wastes context and compute. Gates let the agent exit cleanly and resume only when the condition is met.

  • Molecules & Formulas -- Gates are embedded within molecule steps, pausing the workflow at the gated step
  • Hooks -- When an agent parks on a gate and exits, the hook preserves the molecule state so a fresh session can check the gate and resume
  • Beads -- Gates are themselves beads with their own status lifecycle (open, closed, expired)
  • GUPP & NDI -- Gates respect GUPP: they pause forward progress but never move the system backward; when the gate opens, the workflow resumes from where it left off
  • Rigs -- The Deacon evaluates gates across all active rigs during its patrol cycle