Skip to content

Multi-Stage Pipelines

Break a continuous delivery workflow into discrete stages — each with its own model, cadence, and responsibility. A common pattern is triage → design → execute, where each stage runs as a separate cron job.

When to Use

  • Continuous workflows where quality requires distinct phases (planning before implementing)
  • Different stages need different model capabilities (opus for design, sonnet for dispatch, codex for implementation)
  • Handoffs between stages should be tracked via external state (GitHub labels, issue status) rather than in-session context

Architecture

┌──────────────┐     status:triaged    ┌──────────────────┐     status:ready    ┌──────────────┐
│  Triage      │ ─────────────────▶   │  Design Unlocker  │ ─────────────────▶ │  Executor     │
│  (opus, 1h)  │                       │  (opus, 4h)       │                     │  (sonnet, 3h) │
│  labels +    │                       │  writes design    │                     │  dispatches   │
│  priorities  │                       │  spec as comment  │                     │  coder agents │
└──────────────┘                       └──────────────────┘                     └──────────────┘

Key Design Points

  • External state as handoff mechanism. Use GitHub labels (e.g., status:triagedstatus:ready) as the contract between stages. Each stage reads its input label, does work, and writes its output label. Local state files drift; external state is always current.
  • Design must complete before implementation. Never run design and implementation stages in parallel. The implementation agent needs the design spec to work from — running them simultaneously means the implementation has nothing to follow.
  • Each stage has its own model. Triage needs judgment (opus). Design needs deep reasoning (opus). Execution is dispatch logic (sonnet). Implementation is code generation (codex). Match model to the cognitive demands of the stage.
  • Label format must be consistent. Colon-separated (status:ready) vs slash-separated (status/ready) must match between producer and consumer. Verify existing label format before creating new labels.
  • Both input and output labels must be explicit in the cron prompt. Ambiguity between stages (e.g., "triaged" vs "ready") causes zero throughput — the consumer finds no work because it's looking for the wrong label.

Failure Modes

  • Label mismatch — producer writes status:triaged, consumer reads status/triaged. Zero throughput.
  • Parallel design+implement — implementation starts before design exists. Output is architecturally unsound.
  • Local state drift — stages use local JSON files to track what's been processed. Files diverge from reality. Use external state (GitHub labels, issue status) as the source of truth.
  • Duplicate dispatch — executor picks up the same issue twice in one run. Fix: claim the issue (update label) before dispatching, not after.
  • Context loss at handoff — each stage is stateless. The design spec must be written as a GitHub comment or file, not held in session memory.

Built with OpenClaw 🤖