Write the building block once; compose it anywhere
A capability is a reusable building block — a small sub-workflow that does one thing (your create_pr, your verify-tests) behind a typed input/output contract. A larger workflow that wires several capabilities together is the orchestrator; it hands each one its inputs and collects its outputs. Fix a bug in create_pr once and every orchestrator that uses it inherits the fix. Break its contract and every dependent fails at load time, not in production.
workflows:
cap.verify.workspace-green: # a capability: one job, reusable
snippet: # the snippet block IS its typed contract
inputs: { repo: { type: string } }
outputs: { green: { type: boolean } }
# ... its own state machine
flow.add-feature: # an orchestrator: composes capabilities
states:
verifying:
transitions:
verify:
target: done
executor:
kind: workflow
definitionId: cap.verify.workspace-green
use:
inputs: { repo: "$.context.repo" }
outputs: { green: "$.context.green" }
Layer the rules; don’t fork the policy
The reason you’d fork create_pr in the first place is a per-repo rule — this project squash-merges, that one needs two reviewers. Instead of three copies, the rules layer: your personal defaults, your project’s rules, your team’s rules — stacked, so a project tweak overrides one rule without forking the whole block. The shared create_pr stays one definition; each layer only declares what it changes.
The cheapest sufficient model, per step
The model is chosen per step. A trivial classification can run on a small local model; a hard refactor can escalate to a frontier model; a deterministic step needs no model at all. You stop paying frontier prices for work that doesn’t need frontier reasoning. Name a model directly, or tag the step with an affinity: and let models.yaml resolve which model fills it — so swapping models is one file, not a find-and-replace across workflows.
triaging:
transitions:
triage:
target: triaged
executor:
kind: llm
model: anthropic:claude-sonnet-4-6 # cheapest sufficient for this step
prompt_template: |
Classify the issue in $.context.issue_body. Pick one transition.
max_iterations: 3