docs/MOLECULES.md
This doc explains how beads structures and executes work. Start here if you're building workflows.
blocks = sequential. No dep = parallel.bd mol bond A B creates a dependency between work graphs.An agent picks up a molecule (epic with children). They execute ready children in parallel until everything closes:
epic-root (assigned to agent)
├── child.1 (no deps → ready) ← execute in parallel
├── child.2 (no deps → ready) ← execute in parallel
├── child.3 (needs child.1) → blocked until child.1 closes
└── child.4 (needs child.2, child.3) → blocked until both close
Ready work: bd ready shows issues with no open blockers.
Blocked work: bd blocked shows what's waiting.
| Type | Semantics | Use Case |
|---|---|---|
blocks | B can't start until A closes | Sequencing work |
parent-child | If parent blocked, children blocked | Hierarchy (children parallel by default) |
conditional-blocks | B runs only if A fails | Error handling paths |
waits-for | B waits for all of A's children | Fanout gates |
Non-blocking types: related, discovered-from, replies-to - these link issues without affecting execution.
Children are parallel by default. Only explicit dependencies create sequence:
# These three tasks run in PARALLEL (no deps between them)
bd create "Task A" -t task
bd create "Task B" -t task
bd create "Task C" -t task
# Add dependency to make B wait for A
bd dep add <B-id> <A-id> # B depends on A (B needs A)
An agent works through a molecule by:
bd ready)bd update <id> --claim)bd close <id>)If the molecule is blocked by another molecule:
Bonding enables compound execution: When you bond molecule A to molecule B, the agent can traverse both as one logical unit of work.
They're the same thing. A molecule is just an epic (parent + children) with workflow semantics.
| Term | Meaning | When to Use |
|---|---|---|
| Epic | Parent issue with children | General term for hierarchical work |
| Molecule | Epic with execution intent | When discussing workflow traversal |
| Proto | Epic with template label | Reusable pattern (optional) |
You can create molecules without protos - just create an epic and add children:
bd create "Feature X" -t epic
bd create "Design" -t task --parent <epic-id>
bd create "Implement" -t task --parent <epic-id>
bd create "Test" -t task --parent <epic-id>
bd dep add <implement-id> <design-id> # implement needs design
bd dep add <test-id> <implement-id> # test needs implement
Bond = create a dependency between two work graphs.
bd mol bond A B # B depends on A (sequential by default)
bd mol bond A B --type parallel # Organizational link, no blocking
bd mol bond A B --type conditional # B runs only if A fails
| Operands | What Happens |
|---|---|
| epic + epic | Creates dependency edge between them |
| proto + epic | Spawns proto as new issues, attaches to epic |
| proto + proto | Creates compound template |
Bonding lets agents traverse compound workflows. When A blocks B:
This is how orchestrators run autonomous workflows - agents follow the dependency graph, handing off between sessions, until all work closes.
Ordinary epics stay open when the last child closes. They become close-eligible work that can be closed explicitly once the parent outcome is actually done.
For reusable workflows, beads uses a chemistry metaphor:
| Phase | Name | Storage | Synced | Purpose |
|---|---|---|---|---|
| Solid | Proto | .beads/ | Yes | Frozen template |
| Liquid | Mol | .beads/ | Yes | Active persistent work |
| Vapor | Wisp | .beads/ (Wisp=true) | No | Ephemeral operations |
bd mol pour <proto> # Proto → Mol (persistent instance)
bd mol wisp <proto> # Proto → Wisp (ephemeral instance)
bd mol squash <id> # Mol/Wisp → Digest (permanent record)
bd mol burn <id> # Wisp → nothing (discard)
| Use Case | Phase | Why |
|---|---|---|
| Feature work | Mol (pour) | Persists across sessions, audit trail |
| Patrol cycles | Wisp | Routine, no audit value |
| One-shot ops | Wisp | Scaffolding, not the work itself |
| Important discovery during wisp | Mol (--pour) | "This matters, save it" |
bd create "Pipeline" -t epic
bd create "Step 1" -t task --parent <pipeline>
bd create "Step 2" -t task --parent <pipeline>
bd create "Step 3" -t task --parent <pipeline>
bd dep add <step2> <step1>
bd dep add <step3> <step2>
bd create "Process files" -t epic
bd create "File A" -t task --parent <epic>
bd create "File B" -t task --parent <epic>
bd create "File C" -t task --parent <epic>
bd create "Aggregate" -t task --parent <epic>
# Aggregate needs all three (waits-for gate)
bd dep add <aggregate> <fileA> --type waits-for
When the number of children isn't known until runtime:
# In a survey step, discover workers and bond arms dynamically
for worker in $(bd agent list); do
bd mol bond mol-worker-arm $PATROL_ID --ref arm-$worker --var name=$worker
done
Creates:
patrol-x7k (wisp)
├── preflight
├── survey-workers
│ ├── patrol-x7k.arm-ace (dynamically bonded)
│ ├── patrol-x7k.arm-nux (dynamically bonded)
│ └── patrol-x7k.arm-toast (dynamically bonded)
└── aggregate (waits for all arms)
Wrong: "Phase 1 comes before Phase 2" → bd dep add phase1 phase2
Right: "Phase 2 needs Phase 1" → bd dep add phase2 phase1
Use requirement language. Verify with bd blocked.
Numbered steps don't create sequence. Dependencies do:
# These run in PARALLEL despite names
bd create "Step 1" ...
bd create "Step 2" ...
bd create "Step 3" ...
# Add deps to sequence them
bd dep add step2 step1
bd dep add step3 step2
Blocked issues stay blocked forever if their blockers aren't closed. Always close completed work:
bd close <id> --reason "Done"
Wisps accumulate if not squashed/burned:
bd mol wisp list # Check for orphans
bd mol squash <id> # Create digest
bd mol burn <id> # Or discard
bd mol wisp gc # Garbage collect old wisps
bd mol wisp gc --closed --force # Purge all closed wisps
For reference, here's how the layers stack:
Formulas (JSON compile-time macros) ← optional, for complex composition
↓
Protos (template issues) ← optional, for reusable patterns
↓
Molecules (bond, squash, burn) ← workflow operations
↓
Epics (parent-child, dependencies) ← DATA PLANE (the core)
↓
Issues (Dolt, version-controlled) ← STORAGE
Most users only need the bottom two layers. Protos and formulas are for reusable patterns and complex composition.
bd ready # What's ready to work
bd blocked # What's blocked
bd update <id> --claim
bd close <id>
bd dep add <issue> <depends-on> # issue needs depends-on
bd dep tree <id> # Show dependency tree
bd mol pour <proto> --var k=v # Template → persistent mol
bd mol wisp <proto> # Template → ephemeral wisp
bd mol bond A B # Connect work graphs
bd mol squash <id> # Compress to digest
bd mol burn <id> # Discard without record