August 2026 · 4 min read
The Hard Part Was Teaching It Not to Help
I built the compare skill from the last post and tested it against a plain model with no skill. The plain model caught every bug that mattered. What it couldn't do was stop correcting them, and that turned out to be the whole job.
I built a tool this month that finds mistakes. Finding them turned out to be the easy part. Teaching it to stop once it had was the whole job.
You know the paper that comes back from a teacher drowned in red pen. Every wrong answer crossed out and the right one written in above it. A grade at the top. You didn’t learn much from that paper, because there was nothing left for you to do. The work of finding the mistakes had already been done, and finding the mistakes was the work.
The tool is a compare skill. It runs the compare step of the apprenticeship loop I wrote about last time. A junior commits to an answer before they run a coding agent. The agent produces its own. The skill lays the two side by side, writes down every place they pull apart, flags each gap as either a plain bug or a judgment call, and then it stops. The judging is left to the junior. The review is left to a senior.
Before I shipped it I ran a control. Same model, same inputs, no skill. Two real tasks: a SQL query behind a 90-day revenue dashboard, and an endpoint that lets a support rep refund a customer’s card. For each one I handed over the junior’s guess and the agent’s output and asked for a compare record, once with the skill and once without.
I expected the skill to catch more. It didn’t. The plain model caught everything that mattered. On the refund endpoint it found the missing amount cap and the absent permission check. It also found the one that quietly loses money: no idempotency key, so a timed-out retry refunds the customer twice. The version with the skill found the same three. Neither one missed the dangerous stuff.
The split was somewhere else. The plain model couldn’t stop. It graded the junior “Low” and ranked the fixes in priority order. Then it wrote a section, and I’m not making this up, that it labeled “Teaching Takeaway.” On the SQL task it went further and rewrote the query for them. It did the junior’s thinking, then it did the senior’s, and it handed back a finished paper with a grade on it.
The skill did less, and did it on purpose. Same gaps, flagged, and then two blank sections at the bottom of the page. One for the junior to write down where they went wrong and why. One for the senior to fill in with them, later. It wouldn’t grade. It wouldn’t write the fix. The entire difference between the two records was restraint.
That’s the part I didn’t see coming. Getting a model to catch a double-refund bug is easy now, close to free. Getting it to catch the bug and then say nothing about the answer is the actual work, because the answer is the rep. Hand the junior a graded paper and you’ve automated the one step that was teaching them anything. You’ve built a faster way to learn nothing.
So the instruction that carries the skill is the one that tells it to do less. Not “be thorough.” Surface the gap, then stop. That runs against how most of these tools are being written right now, where the whole contest is which one is more helpful. For a tool that’s supposed to build judgment, helpful is the failure mode.
Two things I’d tell anyone building the same kind of thing. Run the compare in a separate pass from whatever wrote the code, because a model checking its own output grades gently and walks right past its own blind spots. And write the restraint in as a hard rule with the reason attached, not a soft suggestion, because the pull toward helpfulness is strong and the model will do the kid’s homework the moment you leave it room.
It’s a single markdown file, a bit over a hundred lines, and the part worth reading isn’t the checklist of what it catches. It’s the two empty sections at the bottom of every record. That blank space is the product. It’s the red pen, held back, and put in the learner’s hand instead.