Can two cheap models check each other well enough to skip the frontier model?

Casey Holt

Casey Holt

October 7, 2026

Can two cheap models check each other well enough to skip the frontier model?

No. Two cheap models cannot check each other well enough to skip the frontier model on a tool call that sends, spends, or writes something you will not read yourself. They catch a missing field and, sometimes, a path that does not appear in the tool result. They agree on the plausible wrong edit. Agreement is not a check. If both are asked “is this good?”, you have paid for two yeses. A frontier model is still the gate when the cost of a wrong call is higher than the call. Two cheap models are enough only when the checker’s question is narrow, the evidence is in the packet, and a person still sees the diff.

The hope is reasonable. A second opinion feels like review. It is review only if the second model can see a mistake the first model’s habits hide. Cheap models share those habits.

The comment they both approved

The proposer was a small local model. The task was the rename I keep as a fixture: change the config key invoice_prefix to invoice_series, not the comment above it. The proposer called edit_file with the right path and the wrong old string. It selected the comment line, because that line contained the key’s name. The tool would have succeeded.

I did not run it. I sent the proposed call to a second small model, same size class, and asked it to say whether the edit was correct. It said yes. The reason was that the old string occurred in the file and the new string contained the new name. Both of those were true. Neither was the request. The checker had the same weakness as the proposer: a nearby string that looks like the target counts as the target.

I ran it again with a different small model, not the same weights, and a sterner prompt. It also approved. The disagreement I wanted — one model noticing the comment — did not show up. What showed up was shared taste. Plausible beats exact when the model is small and the prompt says to be helpful.

Two identical rubber stamps resting side by side on a document

Why a second cheap model rubber-stamps

They are trained to continue a reasonable story. A proposed tool call is a reasonable story. The checker sees a well-formed JSON blob, a path that exists, and a string that really is in the file. Rejecting that feels like pedantry, and pedantry is not what a short prompt produces unless you forbid every other answer.

They also share blind spots even across families, at the size you can run cheaply. Distinguishing a comment from a key is a small semantic gap. Distinguishing npm test at the repo root from “run the billing tests” is the same gap in disguise: the command is valid, the words “test” overlap, the failure is about which package. A second model that thinks npm test means the tests will not rescue a first model that thinks the same thing. You need a model that will look at the script name and stop, or you need a program that reads package.json and does not have an opinion.

Asking them to debate does not create that model. I let them exchange one round of objections. The checker invented a mild objection about formatting. The proposer agreed to add a trailing newline. The comment line was still the edit. Debate between two models that cannot see the bug becomes an edit to the part they can see.

The check that is actually a different job

The times a second cheap model earned its place, I had not asked “is this good?” I had asked a question a person could grade with a glance, and I had put the evidence in the packet.

“Does this path appear, character for character, in the search result I attached?” The checker had to answer yes or no, and no other text was accepted. On that question it was useful, because the failure was copying. The proposer dropped a directory. The checker said no. I could have done this with a string compare and no model at all. The model was a convenience where the path was buried in a noisy result and I did not want to write the parser that afternoon. It was not a substitute for judgment.

“Is the old string unique in the file snippet?” Same shape. Yes or no. The cheap checker handled it when the snippet was short. When the snippet was the whole file, it said yes on a string that appeared twice, because it sampled the top. I stopped calling that a check and rejected non-unique matches in the tool instead. A runtime error is a better second opinion than a small model skimming.

Schema checks belong in code. Required fields, types, enums. If you are spending a model to notice that a boolean arrived as the word “yes,” you have skipped the parser. Two models agreeing the word yes is fine is how that bug ships.

A red pencil mark on a printed page beside a laptop

Where I still pay for the frontier model

I skip the frontier model when three things are true. The tool cannot send, spend, or delete. I will read the diff before it lands. The second model is answering a yes/no against text I attached, not grading the plan. File edits inside a branch I review can live there. A directory listing can live there with no second model at all.

I do not skip it when the tool is shell on a machine with credentials, a mail send, a calendar invite, a payment call, or a write to a default branch. Two cheap approvals are correlated. The frontier model is not magic, but it is less correlated with the proposer on the exact-string and which-package mistakes, and I only need it on that call, with the original sentence beside the arguments. A second cheap model on those calls gave me comfort logs. The comfort was the failure.

There is a middle I tried and dropped. Cheap proposer, cheap checker, and the frontier model only if they disagree. They almost never disagreed on the bad edits. The frontier model stayed idle on the days I needed it and woke up on formatting nits. Disagreement is the wrong trigger if both models are weak in the same direction. Use the frontier model on the dangerous tool, not on the argument.

How to set the checker so it can fail

If you still want a cheap second pass, make a wrong answer possible. Give it the original sentence and the proposed arguments, and forbid it to rewrite them. Accept only match or mismatch. Mismatch must name the field. If it writes a paragraph, throw the result away and treat the call as unchecked. A paragraph is how “yes, but I would also” turns into a quiet approval.

Do not show it the proposer’s explanation. The explanation is persuasive and often false, and the checker will cite it. Show the tool result or the file hunk. If you cannot attach the evidence, you do not have a check. You have a vibe.

Score the pair on bugs you planted, not on a week of green runs. My planted set is the comment-versus-key edit, the root test script versus the package script, and a path with one directory missing. A cheap pair that approves any of those does not get to gate a send. I rerun the set when I change models. A new small model that is chattier will approve more, not less, until the format is this strict.

Same family or two vendors, same result

I wanted the second model to be a different product, on the theory that two vendors would not share a blind spot. On the planted comment edit, the second vendor approved it too. It praised the proposer for touching the line that mentioned the key. Different weights, same preference for the line that looked relevant over the line that defined the value. I am not claiming that every pair of small models will fail every fixture. I am saying I have not seen a cheap pair catch this class of miss often enough to trust them with a call I will not reread.

A larger gap sometimes appears when the checker is told it will be graded only on mismatches it can point at, and the proposer is not in the prompt at all. That is a different setup from “two agents reviewing each other.” The moment they can see each other’s reasoning, the gap closes and the approval comes back. If your architecture is a conversation between them, you built the rubber stamp.

What “skip the frontier model” is allowed to mean

It is allowed to mean: this call is reversible, I am looking at it, and the second pass is a mechanical comparison a small model happened to do. It is not allowed to mean: two inexpensive yeses are a review. They are two draws from the same kind of mistake.

Use the cheap pair to catch a path that is not in the search result. Use code to catch a schema violation. Use a frontier model, or yourself, when the tool can leave the machine or land unread. If you cannot afford the frontier model on that step, take the tool away. Do not replace it with a second model that will nod.

More articles for you