# Gas Town Architecture Gas Town is a multi-agent workspace manager that coordinates AI coding agents working on software projects. It provides the infrastructure for running swarms of agents, managing their lifecycle, and coordinating their work through mail and issue tracking. ## Core Concepts ### Town A **Town** is a complete Gas Town installation - the workspace where everything lives. A town contains: - Town configuration (`config/` directory) - Mayor's home (`mayor/` directory at town level) - One or more **Rigs** (managed project repositories) ### Rig A **Rig** is a container directory for managing a project and its agents. Importantly, the rig itself is NOT a git clone - it's a pure container that holds: - Rig configuration (`config.json`) - Rig-level beads database (`.beads/`) for coordinating work - Agent directories, each with their own git clone This design prevents agent confusion: each agent has exactly one place to work (their own clone), with no ambiguous "rig root" that could tempt a lost agent. ### Agents Gas Town has four agent roles: | Agent | Scope | Responsibility | |-------|-------|----------------| | **Mayor** | Town-wide | Global coordination, swarm dispatch, cross-rig decisions | | **Witness** | Per-rig | Worker lifecycle, nudging, pre-kill verification, session cycling | | **Refinery** | Per-rig | Merge queue processing, PR review, integration | | **Polecat** | Per-rig | Implementation work on assigned issues | ### Mail Agents communicate via **mail** - JSONL-based inboxes for asynchronous messaging. Each agent has an inbox at `mail/inbox.jsonl`. Mail enables: - Work assignment (Mayor → Refinery → Polecat) - Status reporting (Polecat → Witness → Mayor) - Session handoff (Agent → Self for context cycling) - Escalation (Witness → Mayor for stuck workers) ### Beads **Beads** is the issue tracking system. Gas Town agents use beads to: - Track work items (`bd ready`, `bd list`) - Create issues for discovered work (`bd create`) - Claim and complete work (`bd update`, `bd close`) - Sync state to git (`bd sync`) Polecats have direct beads write access and file their own issues. ## Directory Structure ### Town Level ``` ~/ai/ # Town root ├── config/ # Town configuration (VISIBLE, not hidden) │ ├── town.json # {"type": "town", "name": "..."} │ ├── rigs.json # Registry of managed rigs │ └── federation.json # Remote machine config (future) │ ├── mayor/ # Mayor's HOME at town level │ ├── CLAUDE.md # Mayor role prompting │ ├── mail/inbox.jsonl # Mayor's inbox │ └── state.json # Mayor state │ ├── wyvern/ # A rig (project repository) └── beads/ # Another rig ``` ### Rig Level ``` wyvern/ # Rig = container (NOT a git clone) ├── config.json # Rig configuration ├── .beads/ # Rig-level issue tracking │ ├── beads.db # SQLite database │ └── issues.jsonl # Git-synced issues │ ├── polecats/ # Worker directories │ ├── Nux/ # Full git clone (BEADS_DIR=../.beads) │ ├── Toast/ # Full git clone (BEADS_DIR=../.beads) │ └── Capable/ # Full git clone (BEADS_DIR=../.beads) │ ├── refinery/ # Refinery agent │ ├── rig/ # Authoritative "main" clone │ ├── state.json │ └── mail/inbox.jsonl │ ├── witness/ # Witness agent (per-rig pit boss) │ ├── state.json # May not need its own clone │ └── mail/inbox.jsonl │ └── mayor/ # Mayor's presence in this rig ├── rig/ # Mayor's rig-specific clone └── state.json ``` **Key points:** - The rig root has no `.git/` - it's not a repository - All agents use `BEADS_DIR` to point to the rig's `.beads/` - Refinery's clone is the authoritative "main branch" view - Witness may not need its own clone (just monitors polecat state) ### Why Decentralized? Agents live IN rigs rather than in a central location: - **Locality**: Each agent works in the context of its rig - **Independence**: Rigs can be added/removed without restructuring - **Parallelism**: Multiple rigs can have active swarms simultaneously - **Simplicity**: Agent finds its context by looking at its own directory ## Agent Responsibilities ### Mayor The Mayor is the global coordinator: - **Swarm dispatch**: Decides which rigs need swarms, what work to assign - **Cross-rig coordination**: Routes work between rigs when needed - **Escalation handling**: Resolves issues Witnesses can't handle - **Strategic decisions**: Architecture, priorities, integration planning **NOT Mayor's job**: Per-worker cleanup, session killing, nudging workers ### Witness The Witness is the per-rig "pit boss": - **Worker monitoring**: Track polecat health and progress - **Nudging**: Prompt workers toward completion - **Pre-kill verification**: Ensure git state is clean before killing sessions - **Session lifecycle**: Kill sessions, update worker state - **Self-cycling**: Hand off to fresh session when context fills - **Escalation**: Report stuck workers to Mayor **Key principle**: Witness owns ALL per-worker cleanup. Mayor is never involved in routine worker management. ### Refinery The Refinery manages the merge queue: - **PR review**: Check polecat work before merging - **Integration**: Merge completed work to main - **Conflict resolution**: Handle merge conflicts - **Quality gate**: Ensure tests pass, code quality maintained ### Polecat Polecats are the workers that do actual implementation: - **Issue completion**: Work on assigned beads issues - **Self-verification**: Run decommission checklist before signaling done - **Beads access**: Create issues for discovered work, close completed work - **Clean handoff**: Ensure git state is clean for Witness verification ## Key Workflows ### Swarm Dispatch ``` Mayor Refinery Polecats │ │ │ ├─── [dispatch swarm] ────►│ │ │ ├─── [assign issues] ──────►│ │ │ │ (work) │ │◄── [PR ready] ────────────┤ │ │ (review/merge) │ │◄── [swarm complete] ─────┤ │ ``` ### Worker Cleanup (Witness-Owned) ``` Polecat Witness Mayor │ │ │ │ (completes work) │ │ ├─── [done signal] ───────►│ │ │ │ (capture git state) │ │ │ (assess cleanliness) │ │◄── [nudge if dirty] ─────┤ │ │ (fixes issues) │ │ ├─── [done signal] ───────►│ │ │ │ (verify clean) │ │ │ (kill session) │ │ │ │ │ │ (if stuck 3x) ───────────►│ │ │ │ (escalation) ``` ### Session Cycling (Mail-to-Self) When an agent's context fills, it hands off to its next session: 1. **Recognize**: Notice context filling (slow responses, losing track of state) 2. **Capture**: Gather current state (active work, pending decisions, warnings) 3. **Compose**: Write structured handoff note 4. **Send**: Mail handoff to own inbox 5. **Exit**: End session cleanly 6. **Resume**: New session reads handoff, picks up where old session left off ## Key Design Decisions ### 1. Witness Owns Worker Cleanup **Decision**: Witness handles all per-worker cleanup. Mayor is never involved. **Rationale**: - Separation of concerns (Mayor strategic, Witness operational) - Reduced coordination overhead - Faster shutdown - Cleaner escalation path ### 2. Polecats Have Direct Beads Access **Decision**: Polecats can create, update, and close beads issues directly. **Rationale**: - Simplifies architecture (no proxy through Witness) - Empowers workers to file discovered work - Faster feedback loop - Beads v0.30.0+ handles multi-agent conflicts ### 3. Session Cycling via Mail-to-Self **Decision**: Agents mail handoff notes to themselves when cycling sessions. **Rationale**: - Consistent pattern across all agent types - Timestamped and logged - Works with existing inbox infrastructure - Clean separation between sessions ### 4. Decentralized Agent Architecture **Decision**: Agents live in rigs (`/witness/rig/`) not centralized (`mayor/rigs//`). **Rationale**: - Agents work in context of their rig - Rigs are independent units - Simpler role detection - Cleaner directory structure ### 5. Visible Config Directory **Decision**: Use `config/` not `.gastown/` for town configuration. **Rationale**: AI models often miss hidden directories. Visible is better. ### 6. Rig as Container, Not Clone **Decision**: The rig directory is a pure container, not a git clone of the project. **Rationale**: - **Prevents confusion**: Agents historically get lost (polecats in refinery, mayor in polecat dirs). If the rig root were a clone, it's another tempting target for confused agents. Two confused agents at once = collision disaster. - **Single work location**: Each agent has exactly one place to work (their own `/rig/` clone) - **Clear role detection**: "Am I in a `/rig/` directory?" = I'm in an agent clone - **Refinery is canonical main**: Refinery's clone serves as the authoritative "main branch" - it pulls, merges PRs, and pushes. No need for a separate rig-root clone. ### 7. Rig-Level Beads via BEADS_DIR **Decision**: Each rig has its own `.beads/` directory. Agents use the `BEADS_DIR` environment variable to point to it. **Rationale**: - **Centralized issue tracking**: All polecats in a rig share the same beads database - **Project separation**: Even if the project repo has its own `.beads/`, Gas Town agents use the rig's beads instead - **OSS-friendly**: For contributing to projects you don't own, rig beads stay separate from upstream - **Already supported**: Beads supports `BEADS_DIR` env var (see beads `internal/beads/beads.go`) **Configuration**: Gas Town sets `BEADS_DIR` when spawning agents: ```bash export BEADS_DIR=/path/to/rig/.beads ``` **See also**: beads issue `bd-411u` for documentation of this pattern. ## Configuration ### town.json ```json { "type": "town", "version": 1, "name": "stevey-gastown", "created_at": "2024-01-15T10:30:00Z" } ``` ### rigs.json ```json { "version": 1, "rigs": { "wyvern": { "git_url": "https://github.com/steveyegge/wyvern", "added_at": "2024-01-15T10:30:00Z" } } } ``` ### rig.json (Per-Rig Config) Each rig has a `config.json` at its root: ```json { "type": "rig", "version": 1, "name": "wyvern", "git_url": "https://github.com/steveyegge/wyvern", "beads": { "prefix": "wyv", "sync_remote": "origin" // Optional: git remote for bd sync } } ``` The rig's `.beads/` directory is always at the rig root. Gas Town: 1. Creates `.beads/` when adding a rig (`gt rig add`) 2. Runs `bd init --prefix ` to initialize it 3. Sets `BEADS_DIR` environment variable when spawning agents This ensures all agents in the rig share a single beads database, separate from any beads the project itself might use. ## CLI Commands ### Town Management ```bash gt install [path] # Install Gas Town at path gt doctor # Check workspace health gt doctor --fix # Auto-fix issues ``` ### Agent Operations ```bash gt status # Overall town status gt rigs # List all rigs gt polecats # List polecats in a rig ``` ### Communication ```bash gt inbox # Check inbox gt send -s "Subject" -m "Message" gt inject "Message" # Direct injection to session gt capture "" # Run command in polecat session ``` ### Session Management ```bash gt spawn --issue # Start polecat on issue gt kill # Kill polecat session gt wake # Mark polecat as active gt sleep # Mark polecat as inactive ``` ## Future: Federation Federation enables work distribution across multiple machines via SSH. Not yet implemented, but the architecture supports: - Machine registry (local, ssh, gcp) - Extended addressing: `[machine:]rig/polecat` - Cross-machine mail routing - Remote session management ## Implementation Status Gas Town is being ported from Python (gastown-py) to Go (gastown). The Go port (GGT) is in development: - **Epic**: gt-u1j (Port Gas Town to Go) - **Scaffolding**: gt-u1j.1 (Go scaffolding - blocker for implementation) - **Management**: gt-f9x (Town & Rig Management: install, doctor, federation) See beads issues with `bd list --status=open` for current work items.