← back to writing
#AI Engineering · #Agentic AI · #Loop Engineering · #AI Safety · #Evaluation

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:

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.

A bounded autonomy loop. The maker creates a candidate, deterministic checks and an independent checker test it, and the breaker routes the result to repeat, stop, or human handoff. The maker cannot approve itself, and every path writes a receipt.

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:

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:

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 checker ladder orders evidence from cheapest and most objective to most expensive and judgment-heavy. Schema, build, tests, policy, and provenance run first; a stable rubric scores survivors; an independent model handles genuine judgment; and a human decides only reserved consequences or unresolved ties.

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:

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.

A checker verdict routing map. Pass completes with evidence. Revise returns specific failed criteria to the maker if budget remains. Deny terminates and records the reason. Awaiting human suspends the exact artifact until a decision, then resumes or rejects without regenerating approval scope.

One practical pattern: gate, score, escalate

For consequential work, I use this order:

  1. Gate: remove candidates that fail objective checks.
  2. Score: compare survivors against a stable rubric.
  3. 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.

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.

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.

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:

  1. Maker: who produces what artifact?
  2. Checker: what independent evidence must pass?
  3. Breaker: what exact limits end iteration?
  4. 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.