Skip to content

9 min read

Compilers and suites are verifiers nobody on your team built

On this page

There are two proposals on the whiteboard and budget for one of them. The first is a coding agent that picks up small tickets, edits the repository, and opens a pull request. The second is a release-notes agent that reads the week's merged pull requests and drafts the customer-facing announcement, a job that currently costs a staff engineer about three hours every Thursday and that he visibly resents. The second proposal has a named owner, a defensible weekly time saving, and no argument about production access. The engineer pushing the coding agent says it should go first anyway, and the product manager wants to know why, given that the release notes are the thing actually burning hours.

The reason is not that coding is harder, or more valuable, or more fun to build. It is that for the coding agent, every individual output can be graded in seconds by machinery the team already has, the grade is the same every time you ask, and nobody on the team had to build the grader. For the release-notes agent, every individual output is graded by a person reading it and forming an opinion, and there is no way to get that opinion in eight seconds, forty times in a row, at three in the morning. Both agents will produce plausible-looking work at roughly the same rate. Only one of them produces work whose wrongness becomes an observable event rather than a discussion.

Both halves of that answer rest on machinery worth naming plainly before the argument leans on it any harder. A verifier is a program that takes one candidate output and returns a verdict on it, pass or fail, with no person in the loop. Four of them are already installed in the repository the coding agent would be editing, put there to reject malformed programs at the moment a fix is still cheap. The compiler refuses to produce a runnable artifact when the program is not legal in the language. A type checker — mypy on a Python service, tsc on a TypeScript one — reads the code without running it and reports where the shapes passed between functions disagree. A linter such as ruff or ESLint matches the source against a catalogue of patterns known to be dangerous. The test suite runs the code against assertions somebody wrote down about what it ought to produce. Engineers meet all four as the pipeline that turns a pull request red before a human has read a line of it, and a coding agent can invoke the same four itself, in a subprocess, on its own half-finished work, dozens of times before anyone else sees it. The release-notes agent has no equivalent: a draft announcement is legal English whatever it says, so there is nothing for a subprocess to reject.

Verifier-first design gave you the principle that you build the check before you build the generator. What makes code unusual is that for a large class of its failure modes, the check has already been built, by somebody else, and is sitting in the repository being maintained for reasons that have nothing to do with you.

What the property actually says

The claim is narrower than "code is verifiable", which is false in the strong sense and useless in the weak one. The property that makes code attractive has four parts, and dropping any one of them breaks the argument.

The check applies to an individual output. Not to the agent's average quality over a week, not to a sample of ten patches reviewed at the end of a sprint, but to this patch, right now, before it goes anywhere. That is what allows the agent to consult it during generation instead of after, which is the difference between a feedback loop and a report card.

The check is deterministic. The same tree checked twice gives the same verdict twice. This sounds like a small thing until you try to build a retry loop on top of a signal that flickers, because then a passing attempt tells you nothing about whether the next attempt on the same tree will pass, and you cannot distinguish "the agent fixed it" from "the check felt different this time".

The check is cheap enough to run repeatedly. A verdict that costs eight seconds can sit inside the loop. A verdict that costs a reviewer's attention costs somewhere between twenty minutes and a day of latency, and it costs it in a currency you have a fixed and small supply of.

The check already exists and somebody else maintains it. This is the part that gets skipped, and it is where most of the economics live. You did not write tsc. You did not write pytest, or the Go compiler's escape analysis, or the borrow checker, or the thousand rules in ruff. Decades of language and tooling work went into producing machinery whose entire purpose is to reject malformed programs, and it is available to your agent for the cost of a subprocess call.

Put together, the interface between an agent and a verifier of this kind is startlingly thin:

bash
$ python -m pytest tests/ -q
........................F.......                                   [100%]
FAILED tests/test_invoices.py::test_proration_on_midcycle_upgrade
  assert 1147 == 1150
1 failed, 31 passed in 4.83s
$ echo $?
1

An integer, and a byte stream that names a file, a test, and two numbers that disagree. No rubric, no reviewer, no calendar, no meeting. A program can read that, and a program can decide what to do next on the strength of it.

The domains ranked by whether the property holds

The four parts give you a test you can apply to any candidate first agent, rather than arguing about which task feels more automatable.

Candidate taskPer-output check?Deterministic?Cost per verdictWho built and maintains the check
Fix a failing test in a Python serviceYes — the suiteYes, modulo flakes5 s – 11 minThe Python community, plus your team's tests
Add a typed endpoint to a TS serviceYes — tsc --noEmitYes~8 sThe TypeScript team
Draft the weekly release announcementNo—20 min of a staff engineerNobody; you would be inventing it
Rewrite user-facing error stringsPartial — length and placeholder lintYes, for the partial bitSeconds for the lint, days for the rubricYour team, for the thin part only
Author API reference pagesPartial — samples compile, links resolveYes, for the partial bit~90 s site buildYour docs toolchain, for the thin part only
Change production network TerraformWeak — plan and policy checksMostly40 s, and the real verdict is productionHashiCorp, plus whatever policy you wrote

The rows where the property holds fully are the rows where an agent's mistakes turn into events. The rows where it holds partially are worth returning to, because the partial coverage is real and the temptation is to treat it as full coverage. The release-notes row is the honest one: there is no check, and if you want the loop, you have to become the check yourself, every time, for every draft.

Three weaker claims that get mistaken for this one

"Code is structured, and models do well with structure." Structure helps generation — a model producing Python has a grammar to conform to and a great deal of prior art to imitate. Structure does not help grading. A Salesforce opportunity record is highly structured, and there is still no program that will tell you the sales stage is wrong. JSON is structured, and a schema validator will tell you the shape is legal without telling you the value is right. The property under discussion is about the existence of a grader, and grading and generation are separate concerns.

"Engineers adopt developer tooling quickly, so the coding agent will actually get used." Adoption is real and it does matter for a pilot, but it is a claim about diffusion rather than about correctness, and it cuts both ways: engineers would happily adopt a release-notes agent too, since it removes a chore they dislike. An adopted agent whose errors are invisible is worse than an unadopted one.

"There is more code than prose in the training data, so models are simply better at code." Public code is abundant and models are indeed strong at it, and this is a real advantage. It is an advantage in generation quality, which without grading buys you fluent wrongness at higher throughput. The reason to start with code is that when the model is wrong, you find out cheaply, which means you can afford to let it be wrong often.

The benchmark that made this concrete is SWE-bench, where each task instance ships with two lists of tests from the repository itself — the ones that must go from failing to passing, and the ones that must keep passing. The grader is the project's own suite, which nobody wrote for the benchmark. That the field could build a serious evaluation this way, and then iterate on it for years, is downstream of the same property: the check was already there.

Where the property thins out

The property belongs to the ecosystem, and it arrives in your repository only to the extent that your repository has taken delivery of it. A Python service with 12% line coverage, no type annotations, and no CI lint has almost none of it, even though Python nominally offers all three. The four checks are not a fact about the language; they are a fact about what has been installed, configured, and kept green. A common and expensive misreading of "start with code" is to point an agent at the least-tested service in the company, because that is where the pain is, and then to be surprised that the loop behaves like the release-notes loop.

The property is also not a claim that the checks establish correctness. A patch that compiles, type-checks, lints clean and turns the suite green has satisfied every mechanical grader in the repository and may still do the wrong thing entirely, and treating green as a synonym for correct is how teams end up merging confident nonsense at speed. That gap is real enough to spend two chapters on.

There are also corners of software where the property is much weaker than the reputation of "code" suggests. A Terraform change to production networking has a plan that tells you what will be created and destroyed, and no mechanical way to tell you that destroying it is a bad idea. A CSS change has no verifier short of a screenshot diff that a human still has to look at. A migration against a 400-million-row table type-checks in milliseconds and takes out the database at 40 minutes. When people say code is the good domain for agents, they mean the parts of code where a compiler, a type checker, a linter, and a suite have jurisdiction, and those parts have edges.

The next chapter takes the word "check" apart, because so far it has been doing the work of four different things. The claim that a cheap deterministic verdict exists is only useful once you know what each verdict is a verdict about, and the four available graders turn out to disagree in ways that make the difference between a caught defect and a two-day-old production incident.

Why code is the highest-leverage agent domain — read the current version at https://daviddominguez.dev/learn/en/why-code-is-the-highest-leverage-agent-domain/compilers-and-suites-are-verifiers-nobody-on-your-team-built

Back to top