Deterministic gates standard
Shell checks decide pass or fail, never an LLM judge, and a failure carries its reason into the next prompt.
The problem
An LLM asked "does this pass?" can be wrong, flattered, or tired. On a cheap model it is also another paid call. Whether the formatter is clean and the tests are green is a fact about the repo, not an opinion.
The pattern
Let a shell command decide. The gate runs the formatter, the linter and the tests, and its exit code is the verdict. No model sits in the judging seat.
A gate that only says "fail" teaches the next attempt nothing. So the failure's output goes into the next prompt, and the implementer sees why it was sent back.
Anthropic's agent guidance makes the same point about grounding: agents should "gain 'ground truth' from the environment at each step." Its multi-agent write-up also pairs model judgment with deterministic safeguards such as retries and checkpoints.
Three rules make this shape work, and each was learned by watching it not work.
**The implement edge is pass, never always.** An always edge routes a failed implement into the reviewer, which then approves work that was never written. A real run marked a spec completed with no commit behind it that way.
The check sits before the reviewer. Code that does not build never reaches review. Without that order, the reviewer writes up the breakage and the spec is marked completed anyway, because routing keys on the run's status, not on its prose.
Auto-fixing commands must not bounce work. Run the formatter in rewrite mode, which fixes, not in check mode, which fails. Only genuine breakage should route back to implement.
Use it for essentially everything. Start here and add shape only when a specific failure justifies it.
What we saw
The lab runs cheap, unreliable models with tight quota. Its standard loop puts the gates before any reviewer, so a reviewer's quota is never spent on code that does not compile.
The lab has not measured how much this saves. It is a design choice, not a benchmark.
Handing plans down
A plan from one node to the next travels through spec notes, not files. A designer node writes its plan with spec_note_write instead of a temp file no later node can find, and a verify step checks the notes file for the plan's heading. Every agent prompt already carries the notes, so nothing needs deleting and nothing goes stale.
In Canopy
A check node holds the command. Edges route pass forward and fail back to the implementer. In spec-loop, the gate and its two edges look like this:
{
"from_node": "full-gates",
"to_node": "reviewer",
"condition": "pass"
},
{
"from_node": "full-gates",
"to_node": "implementer",
"condition": "fail"
}
The implementer's preset reads {{previous_feedback}} and must address every point in it, which is how a failure's reason reaches the next attempt.
The cargo-gates node is the Rust version of the gate, from nodes/cargo-gates/node.json:
"config": {
"command": "cargo fmt --all && cargo clippy --all-targets -- -D warnings && cargo test"
}
In spec-loop, the gate command is a failing placeholder. Replace it with your project's own commands.
Try it
canopy graph install spec-loop
canopy node install cargo-gatesSources
- Building effective agents (Anthropic), ground truth from the environment
- How we built our multi-agent research system (Anthropic), deterministic safeguards
Implemented by
- spec-loopOfficialgraph
canopy graph install spec-loopThe lab's proven spec loop: implement, gate, review-and-commit, verify the commit, and collect a human verdict, with every failure routed back to the implementer. - cargo-gatesOfficialnode
canopy node install cargo-gatesDeterministic Rust gates: formatter, linter, and tests in one check command.