← All writing

What Should the Agents Write?

AI Lowered the Cost of Writing Code, Not of Owning It

TL;DR: “Just have the AI build the whole app” is half right, and the half that’s right is genuinely new: agents produce running full-stack applications, and the familiarity tax that made teams cling to incumbent frameworks has collapsed. But AI lowered the cost of producing code without lowering the cost of owning it. Ownership is review, security, audit, and change, forever. Agent errors concentrate precisely where running the app and clicking around cannot reach: authorization, state transitions, validation edges. The answer isn’t reviewing faster. It’s shrinking what has to be verified: let the agent write a few hundred lines of declaration, and let a runtime that was tested once supply the semantics. We hold this position because we’ve paid for it: we recently falsified one of our own published claims against our own source code, fixed the runtime to match the doctrine, and then caught two more holes in the fix before it shipped. That story is in here, because it’s the whole argument in miniature.


The steelman, at full strength

Start where the enthusiasts are correct, because they’re correct about a lot.

An agent with a decent harness will, today, take “build me a ticketing system with users, comments, and email notifications” and produce a running application: schema, API, frontend, deploy scripts. Not a sketch; a thing that works when you click it. The stale objections mostly don’t survive contact: the code is reasonably idiomatic, the agent fixes its own build errors, and iteration is conversational. If your mental model of AI codegen is 2023, it’s wrong now.

And a quieter collapse matters more than the demos. For decades, platform choices were governed by the human familiarity tax: you built on Rails or Django or Express because people knew them, and knowing them was the expensive part. Agents don’t pay that tax. An agent is exactly as fluent in an obscure framework as a famous one, provided the spec is in context. “Nobody knows this stack” stopped being an argument the moment nobody had to.

So when someone says just use AI and be done with it (for a prototype, a weekend tool, an app whose blast radius is small), they’re right, full stop. This essay is not about that case.

What didn’t get cheaper

Here is the asymmetry the demos skip: AI lowered the cost of producing code and left the cost of owning it untouched. Every generated line still has to be reviewed by someone accountable, scanned, patched, upgraded, audited, and understood by whoever inherits it. Code was always a liability dressed as an asset; agents made the liability dramatically cheaper to acquire. A team that used to write two thousand lines a week now owns twenty thousand it didn’t write — and the bottleneck moves, precisely and predictably, from writing to reading.

Worse, the errors that matter cluster where reading is least effective. An agent’s application runs — that’s the seduction. But “it runs and the demo works” exercises the happy path, and the failures that end up in incident reports live off it: the endpoint that forgot one role check, the state field a crafted PATCH can teleport, the validation that checks each field but not the relationship between them. Confident, running, and subtly wrong at the security edges: the exact places clicking around cannot reach and reviewers under volume skim past. This isn’t a claim that agents are careless; it’s a claim about where their wrongness concentrates, and it concentrates in the parts of a backend that were always the hard parts.

An earlier essay here (Give the AI Less to Be Wrong About) made the case that the fix is not reviewing faster. It’s shrinking the surface that needs review at all. This essay is about what that means concretely, and what it cost us to mean it.

Divide the labor where the risk lives

Ask the title’s question literally: in an agent-authored world, what should the agents write?

Not the authorization middleware. Not the state-transition guards. Not the validation chains or the audit trail. Not because agents can’t produce plausible versions of those (they can, endlessly), but because those are exactly the components where plausible-but-subtly-wrong is most expensive, and where every regeneration re-rolls the dice. Semantics that must be correct should be implemented once, tested like infrastructure, and never re-authored per application.

That’s the division of labor ADL encodes. The agent writes the declaration: a few hundred lines of YAML naming the resources, the fields, who may do what, which states exist and how they move, what must be true before a write lands. The runtime supplies the semantics: the permission enforcement, the transition guards, the validation engine, the history: the same tested machinery under every domain, no more regenerated per app than SQLite regenerates B-trees per schema. And the human reviews intent, not implementation: the declaration is the part a domain expert can actually read, in an afternoon, and say “no, reviewers may not approve their own tickets” about.

Run the failure modes through that split. The forgotten role check can’t hide in middleware the agent wrote, because the agent didn’t write middleware: the permission line is either in the declaration where a reader sees it, or the operation is denied. The teleportable status field doesn’t exist, because a write to a state-machine field executes a legal transition’s guards or is rejected. The agent can still be wrong (it can declare the wrong rule), but its wrongness is now legible, sitting in the one artifact whose whole design goal is to be reviewable. You haven’t eliminated review; you’ve moved it to where it works.

What this doctrine cost us last week

A claim like “the declared surface is sovereign — nothing routes around the pipeline” obligates you to something uncomfortable: it has to be true of your own runtime, the code that executes, and documentation cannot stand in for that. So we audit ours, source against claims. Recently, that audit found a violation in the worst possible place.

Our Lua scripting layer (the deliberate escape hatch for logic the declaration can’t express) exposed a store binding that could execute raw SQL writes. Not in the docs, which said reads only. Not in the essays, one of which argued the hatch “cannot be sovereign.” In the shipped binding: execute, begin, commit, rollback, reachable from any hook, bypassing validation, permissions, rules, audit, and history. Our published claims were falsifiable against our source, and falsified.

There were two available responses. Soften the documentation to match the runtime, quietly true, quietly weaker. Or fix the runtime to match the doctrine. We fixed the runtime: the write surface is gone from the default binding entirely, reads pass a conservative SQL classifier, and raw SQL survives only as an explicit configuration opt-in that defaults off, warns at startup, and reports in health.

Then the better part of the story: the fix itself was audited, and the audit caught the fix being wrong. The first patch’s classifier allowed any statement beginning with WITH, which admits writable common table expressions, so WITH t AS (SELECT 1) DELETE FROM t would have sailed through a “read-only” boundary. It also matched EXPLAIN ANALYZE literally, missing the parenthesized form that executes the statement. Confident, running, subtly wrong at the security edge: the precise failure mode this essay attributes to agent-written code, reproduced by our own first attempt at a security patch. Both holes are now closed, with tests that prove the hostile statements never reach the database and counter-tests that prove legitimate queries still do.

We tell this story in public because it demonstrates the thesis twice. Once: security edges are where wrongness hides, whoever writes the code — which is why the surface anyone authors, human or agent, must be small enough to actually audit. And twice: a declared contract is only worth what its enforcement survives, so the enforcement has to be falsifiable against source and the runtime has to move when it loses. That is expensive. It is also the entire difference between a spec that runs and a spec that reassures.

The honest concessions

Outside its domain, “just use AI” wins. ADL declares regulated, record-keeping, workflow-shaped backends. If you’re building a game server, a collaborative editor, a streaming pipeline (the shapes our own boundary essay marks as wrong for ADL), then agents plus a conventional framework are the correct tool, and this essay’s argument does not apply. The claim is about where the blast radius lives, not about everything.

The agent can still write wrong ADL. A declaration is smaller and legible, not infallible. An agent can misdeclare a permission as readily as it can miswrite middleware. The difference is that the mistake now sits in three reviewable lines instead of a diff nobody reads. Review shrinks; it does not vanish. Anyone who tells you otherwise is selling something.

The frontend is still the agent’s, conventionally. Kalos renders nothing. Your UI is still code (agent-written or not) against the runtime’s APIs and schema. The shrunken-surface claim covers the backend, which is where the audit obligations live, and stops there.

Closer

Let the agents write endlessly — just arrange the system so the part that must be right is the part short enough to read; everything we publish, and everything we just fixed in public, is the cost of holding that line.