Loop Engineering, Part 2: Maker, Checker, Breaker
A safe agent loop separates three jobs: making the work, checking the evidence, and stopping the run. Let one model own all three and confidence quietly becomes control.
I asked the same agent to write the draft and review it. It approved its own mistake.
This pattern is easy to create: ask an agent to produce an answer, then ask the same agent whether the answer is good.
It feels like verification. It is not.
The model remembers why it made every shortcut, so it is sympathetic to them. I have seen this in code, architecture notes, and research. The maker says, “Done.” The reviewer says, “Comprehensive and well-structured.” A test, a missing source, or a human with fresh eyes finds the hole in minutes.
The problem is not that models cannot review. They can. The problem is role collapse: one actor does the work, defines success, interprets the evidence, and decides whether it gets another attempt.
The fix is not a smarter model. It is separating those powers.
Three jobs, not one clever agent
The smallest useful control structure has three roles:
- Maker: produce a candidate.
- Checker: decide whether the candidate meets the contract.
- Breaker: decide whether the loop may continue.
A human sits outside the cycle for decisions the loop is not allowed to make.
The breaker is the part I most often find missing. It is what turns repeated generation into bounded autonomy.
These roles can be different programs, different agents, or different layers of one system. What matters is that their authority is separate.
The maker should not rewrite the rubric after seeing its score. The checker should not quietly repair the artifact it is judging. The breaker should not accept “one more try” just because the maker sounds close.
The maker owns the attempt
The maker’s job is creative and local: take the current goal, state, tools, and constraints, then produce the next candidate.
Good maker instructions are specific about the output but do not reveal every detail of the held-out check. If the maker knows the exact scoring tricks, it can optimise for the appearance of success instead of the outcome.
Give the maker:
- the goal and current state;
- the permitted tools and write boundary;
- the output contract;
- the evidence it must return;
- the budget for this attempt.
Do not give it the right to declare the entire loop complete. “I finished” is a claim submitted to the checker.
The checker owns the verdict
The checker asks a colder question: what evidence would make this candidate safe to accept?
The best checker rail is layered.
Start with deterministic gates
Run the checks that do not care how persuasive the candidate sounds:
- schema validation;
- compilation;
- tests;
- lint and policy checks;
- link validation;
- allowlists and security rules;
- required fields and provenance.
If a candidate cannot pass the objective floor, do not spend a model call debating its style. Reject it cheaply and return useful evidence to the maker.
Then apply the rubric
Some work cannot be reduced to a boolean test. A design may need to be coherent, a research note may need balanced coverage, and a blog may need a strong argument rather than merely valid Markdown.
Use a rubric with observable dimensions. “High quality” is not a dimension. “Every material claim has a source, the opening creates a concrete tension, and each section advances the argument” is.
Keep the scoring criteria stable during the run. A moving rubric turns iteration into negotiation.
Use a second model where judgment is genuinely needed
An independent checker can catch omissions and contradictions the maker misses. Diversity helps: a different model, persona, context, or temperature is more likely to make a different error.
But independence is not magic. A second model is still weaker evidence than a passing executable check. Put machine judgment after deterministic evidence, not instead of it.
The breaker owns permission to continue
The checker decides whether the latest candidate passed. The breaker decides whether the loop has earned another attempt.
That distinction matters because failure does not automatically justify another attempt.
candidate = maker.run(state)
verdict = checker.evaluate(candidate)
if verdict.passed:
return complete(candidate, verdict)
if verdict.denied:
return terminate(candidate, verdict)
if budget.exhausted() or verdict.requires_human:
return handoff(candidate, verdict)
state = record_failure_and_prepare_next_attempt(candidate, verdict)
A breaker should understand at least four stop conditions:
Budget exhausted
Maximum attempts, tokens, money, or wall-clock time. A loop without a cost ceiling can turn a small problem into an expensive ritual.
No measurable improvement
If the score has plateaued, another mutation is not automatically progress. For hill-climbing loops, keep a candidate only on strict improvement. “Different” is not “better.”
Repeated failure class
Three failures on the same missing permission are not three creative attempts. They are one blocked path repeated three times. A fourth attempt is not persistence. It is an expensive way of not noticing.
Consequence requires a human
Production changes, external communication, destructive actions, money movement, or policy exceptions should suspend at a precise gate.
The distinction that changed how I build these systems is simple: failed and waiting are not the same state.
A failed run is done. A waiting run holds the exact candidate and approval request a human still needs to see. It resumes from that decision. It does not quietly generate a different artifact and assume the old approval still covers it.
Approval belongs to the exact thing a human saw.
A checker is not a critic
This was an important correction in my own thinking. I used to picture the checker as a senior reviewer writing comments. That is only part of the job.
A useful checker returns a machine-actionable verdict:
passrevisewith evidencedenyawaiting_human
It should also return the failing criteria and the evidence used. That gives the next iteration something firmer than “make it better.”
For example:
{
"verdict": "revise",
"failed": ["source_coverage", "acceptance_test"],
"evidence": {
"uncited_claims": 2,
"test": "test_resume_after_approval",
"exit_code": 1
}
}
The maker can act on that. The record can preserve it. The breaker can count it. A dashboard can explain it.
“Needs improvement” does none of those things.
One practical pattern: gate, score, escalate
For consequential work, I use this order:
- Gate: remove candidates that fail objective checks.
- Score: compare survivors against a stable rubric.
- Escalate: ask a stronger model or a human only when evidence cannot settle the decision.
This keeps the expensive judgment focused on the small set of cases that deserve it. It also makes failure legible. The candidate did not lose because another model “felt better.” It failed the build, missed a source, scored below the threshold, or reached a decision reserved for a person.
What this looks like in real agent platforms
Maker, checker, and breaker are roles in the control system, not product names. You can build the pattern with the agent platforms people already use.
Microsoft Foundry Agent Service
Imagine a Foundry agent that prepares a customer-facing architecture recommendation.
- Maker: a prompt agent or hosted agent drafts the recommendation using approved tools and grounded enterprise data.
- Checker: deterministic code validates the response schema, required citations, customer constraints, and policy rules. Your application can then use a Foundry evaluation for qualities that need model judgment, such as groundedness and relevance.
- Breaker: the workflow around the agent counts attempts, detects repeated failure classes, enforces cost and time budgets, and routes high-impact recommendations to a person. Foundry tracing preserves the evidence behind each decision.
The important part is not deploying three Foundry agents and naming them Maker, Checker, and Breaker. The breaker is usually deterministic orchestration code. It should not be another model deciding whether to spend more money.
GitHub Copilot coding agent
Suppose you assign Copilot coding agent an issue to repair an authentication bug.
- Maker: Copilot works in its own environment, changes the code, runs its available checks, and opens a pull request.
- Checker: required GitHub Actions checks run the test suite, linting, security scanning, and repository policies. A human reviewer or Copilot code review can add judgment, but that review does not replace the executable checks.
- Breaker: repository automation or the supervising human limits revision cycles. If three revisions fail because the agent cannot access a required service, the PR is marked blocked and handed over. It is not sent back to Copilot indefinitely with “try again.”
The pull request is the candidate. A green check is evidence. Merge permission remains outside the maker.
Anthropic Claude Code
Now imagine Claude Code refactoring a service.
- Maker: one Claude Code session works in a dedicated branch or worktree and returns the diff plus test evidence.
- Checker: the test runner evaluates objective behavior first. A separate Claude Code subagent, with its own context and read-only tools, adds rubric-based judgment.
- Breaker: the calling script or Agent SDK caps turns, cost, and elapsed time. Claude Code hooks can block prohibited tool calls or require approval, while the outer controller records repeated failures and decides whether to stop or wait for a person.
Asking the original Claude session, “Are your changes correct?” is still self-review. A reviewer subagent improves context independence, but it does not become objective evidence merely because it runs separately. Tests and an external attempt budget remain stronger controls.
Across all three platforms, the shape is the same:
agent produces candidate
↓
objective checks run
↓
independent judgment only if needed
↓
controller completes, retries, stops, or waits for a human
The tools change. The separation of authority does not.
Design your first bounded loop
Take one task you already repeat and write four lines:
- Maker: who produces what artifact?
- Checker: what independent evidence must pass?
- Breaker: what exact limits end iteration?
- Human: what decision can the loop never make alone?
If one actor currently owns all four lines, split the authority before you add more autonomy.
The goal is not to make agents distrust themselves. It is to stop confidence from becoming permission.
A capable maker produces better work. A skeptical checker catches more mistakes. The breaker is what lets you leave the room, because it knows when the next attempt is no longer deserved.
Next in the series: State, Recovery, and the Right to Continue - how a loop survives restarts without repeating side effects or learning from the wrong signal.