Agents Eat, Update and Create Documentation.

You Have No Excuse for Undocumented Code. Every engineer knows the three excuses, because every engineer has used them.

  1. Documentation is too expensive. Writing it well takes hours that could go into features, and it is never the thing that ships.
  2. Nobody reads it anyway. You spend a day on a beautiful design doc, and it goes to the wiki to die. Nobody opens it again. Ever.
  3. Documentation rots. You write it, the code moves, and within two quarters, the docs are lying to people. A wrong document is worse than no document.

Here is the uncomfortable part: all three were true. This was not laziness but a rational response to a real cost-benefit problem. The math did not work.

The math has flipped because of LLMs. Documentation stopped being a message from engineers to engineers and became the substrate that the machines building your software run on. LLMs are voracious consumers of documentation — and, it turns out, tireless producers of it.

All three excuses are now dead, and here is the short version of why.

"Too expensive" is dead, because LLMs write it. The thing that reads documentation can also produce it — not as a chore bolted onto the work, but as the natural byproduct of the work itself. The human role moved from author to editor, and that is a completely different cost.

"Nobody reads it" is dead, because something now reads everything. Every agent, on every task, pulls in whatever context it can find, and does measurably better work when what it finds is true. Documentation stopped being a message in a bottle to a hypothetical future colleague and became a live input to the system, building your product this week.

"It rots" is dead, because rot was never a law of nature. It was the predictable consequence of documentation updates being manual, expensive, and easy to skip. Make the update cheap — the agent does it — and make the omission visible at review time, and the doc gets fixed in the same commit as the code that broke it. That last part needs a little machinery, which is most of what the rest of this post is about.


LLMs thrive on documentation

Point an agent at an undocumented codebase, and it does something worse than fail — it guesses. It infers intent from structure and confidently re-derives a decision you already made and already paid for. It picks the approach you tried and rejected eight months ago, because nothing in the source records that you rejected. Code is an excellent description of what, a poor description of why, and completely silent on what we considered and threw away.

That missing context is exactly what documentation holds. And now something reads it. An agent that finds the spec explaining why the registries were split from the resolver will not spend your tokens relitigating the split. One that finds a reference doc describing an invariant will not violate it. Documentation has become the institutional memory that a fresh context window does not have and cannot reconstruct from source alone.

That inverts the economics. Documentation used to be a tax paid for a hypothetical future colleague who probably would not read it. It is now a performance input to the machine doing your work today. Anyone who has watched an agent flail through a poorly documented repo and then sail through a good one has felt the difference.

LLMs maintain the documentation

Agents produce documentation as a natural byproduct of the work itself, in two flavors that most teams have not noticed are different.

They write design-time documents as they think. An agentic workflow does not begin with code. It begins with a brainstorm that produces a spec — what we are building, why, and what we rejected. The spec produces a plan — the order of work, and how we will know it worked. The plan produces a review of what we actually found. These are not overhead bolted onto the process; they are the process. The agent needs them to reason well, and you get them whether you asked or not.

And they keep working them. A design document is not written once; it is argued with. The spec gets amended as the design shifts, the plan gets re-cut when a task turns out to be two tasks, and the agent redrafts both as you push back. Design docs are live while the decision is in flight — and then they stop. Once the work ships, the spec's job changes from guiding the decision to recording it, and from that moment it is history and should be left alone. Keep that transition in mind; the back half of this post turns on it.

They write and maintain as-built documents, too. When a provider is renamed, the agent can find every reference doc that names it and update it in the same change. Point one at a legacy codebase with no documentation, and it will backfill a reference layer in an afternoon — a job nobody ever volunteered for.

The human role changed from author to editor. That is a very different cost.


Rot was never a law of nature

Which leaves the last and best excuse, and the one people will throw at generated documentation hardest. The agent wrote a thousand pages. In six months, it will be a thousand pages of lies.

It would be, if you did nothing. But look at what rot actually is. Documentation goes stale because keeping it current is manual, tedious, and trivially skippable — a chore that lands on a human at the exact moment they are trying to finish something else. Nobody decides to let the docs lie. They just decline, over and over, to spend forty minutes updating a reference page after a rename, and two quarters later, the page is fiction.

Both halves of that are now fixable. The update is no longer expensive — the agent that renamed the symbol can find every document naming it and fix them in the same breath. And the omission no longer has to be invisible: a review-time check can ask, on every change, whether the docs still tell the truth about the code that just moved.

Cheap updates plus visible omissions equals no rot — except for one prerequisite that turns out to be the hard part. Before you can ask "do the docs still tell the truth?", you have to know which documents are supposed to describe the code as it stands today — and which are history that should never be touched.

That sounds trivial. It is not, because the agents are also busy burying you.


What I had to change to make my docs legible to a machine

The documentation in Flutter-AdaptiveCards, an open-source Flutter monorepo, was written partly by me and partly by the agents working alongside me. I had never counted it. When I did: twenty-seven documents describing the library, and seventy-four recording decisions — specs, plans, reviews, and a heap of superseded designs in an archive. Nearly three to one, in a repository whose entire reason to exist is the published library.

Each of the seventy-four had a purpose — a spec, a plan, a review — and each was honest about being a point-in-time record. But as a collection they still have no organized scheme: nothing marks which are binding and which are superseded, and facts about the system that were still true sat buried in dated design arguments where no reader, human or agent, would look for them. Anything still current had to be pulled up out of specs/, plans/, and reviews/ into the top-level documentation — where it gained something no prose ever had before: a source of truth sitting right next to it. (Is machine-written documentation slop? Some is. But an as-built page matches the code or it does not, and that is checkable.) The records themselves stayed behind, untouched, as history.

The heavier rebuilding was in the twenty-seven — the actual documentation, not the decision records. Almost every page served two or three purposes at once: a table of properties that slid into a walkthrough of wiring a form, then stopped to explain why the design worked that way. Making those pages legible to an agent meant taking each one apart and rebuilding it around a single purpose — the walkthrough extracted into its own guide, the rationale moved to an explanation page, the tables left behind as reference. An hour of classification also exposed what two years of writing had hidden: zero tutorials.

Seventy-four records that still need an organizing scheme, and twenty-seven pages that had to be pulled apart before any scheme would fit. Two problems — and one of them is already solved.


Recognizing design-time and run-time documents

Diátaxis already solved half of this, and solved it well. Its four types — tutorials, how-to guides, reference, explanation — give you a stable taxonomy for documenting a product that exists, along with real guidance on what belongs in each and how to write it. That is not a small thing, and nothing here replaces it.

But notice what it is a taxonomy of. Diátaxis's own foundations describes the four types as "a complete enumeration of the types of documentation that serve practitioners in a craft." The qualifier is the important part. A practitioner is someone using the thing, and against that need the four types genuinely are complete — I have never found a fifth.

A design spec serves someone else. Try to file one: it is not a tutorial, because nobody learns the library from it; not a how-to, because it directs no task; not reference, because it is not even true of the system — half of it describes approaches we rejected. Explanation is the closest fit and still wrong, because it explains a decision rather than the product, and filing it there parks a dated, half-wrong artifact beside the documents readers trust to be current. The spec serves the maker, and answers a question no user ever asks: why is it like this, and what did we rule out?

Diátaxis has mapped its area thoroughly, and that area does not include this. Everything else needs its own scheme — and "everything else" is no longer a rounding error. It is 74 documents to 27.

As-built docs — the run-time half — describe what exists and how to use it. The term is borrowed from construction, where the as-built drawing reflects what actually got built rather than what was proposed. These are Diátaxis's four types, and they must be true today.

Intent docs — the design-time half — record what we decided and why: specs, plans, reviews, superseded designs. They are live while the decision is in flight and frozen once it is made — true when written, and some are now wrong on purpose.

If that sounds like an Architecture Decision Record, it should. ADRs have covered one corner of this territory for a decade, and they got the hard part right: a decision, its context, and its consequences, written down and never edited afterward. What ADRs never had to solve is the part that is new — an ADR was a human practice for a handful of decisions, and nobody needed a taxonomy for a dozen files that nothing read. Agents produce this material continuously, in several distinct forms, and then come back and read it. The category where ADRs once sat alone now holds seventy-odd documents and has an automated reader — which is what turns a filing convention into an architecture problem.

Intent docs As-built docs (Diátaxis)
Sorts by Decision state × authority User need
Tense What we decided, then What is true, now
Truth condition Was true when written; may be superseded Must be true today, or it is a defect
When it's wrong Archive it — the record retains value Fix it — a stale reference doc is a bug
Forms Spec, plan, review, archive Tutorial, how-to, reference, explanation
Cardinality Append-only; grows without bound Bounded; one doc per thing that exists

The last row is the load-bearing one. Intent docs are append-only history. As-built docs are a bounded set that has to keep up with the code. A stale reference doc is a bug — you fix it. A stale spec is the point — you archive it, and the record of the road not taken keeps its value precisely because it is no longer true. One collection grows forever and is never corrected; the other stays roughly the size of your product and must be corrected constantly.

Two collections with opposite lifecycles cannot live in one folder under one set of rules. That is not tidiness talking — it is the reason your docs/ directory stopped making sense the moment the agents started filling it.

One sentence sorts every hard case:

An artifact that records a decision made at a point in time is intent. An artifact a reader consults to use or understand the thing today is as-built.

Run the edge cases. Changelog: as-built — it describes what shipped. Architecture decision record: intent. Troubleshooting guide: as-built. Post-mortem: intent. It holds.


Not every doc has to be true

Rename a class, grep the docs for the old name, and you get eleven hits. Six are in reference and how-to docs, which describe the library as it stands and are now lying to your users. Five are in a shipped design spec and an archived proposal, which argued about that name last spring and are supposed to still contain it. Those five are the minutes of a meeting that already happened — rewriting them to match today's code would be forging the record, and the next agent to read them would learn a history that never occurred.

Six must change, five must not, and the grep cannot tell them apart. Neither can a reviewer skimming a diff, and neither can an agent. That is the whole problem, and the split is what solves it: put intent docs in their own tree and the directory alone answers does this file have to match the code? Everything under specs/, plans/, reviews/, and archive/ is frozen history. Everything at the top level of docs/ has to keep up.

That is the only distinction the gate needs. The doc_type: tag does a different job — it says which of Diátaxis's four an as-built doc is, so the agent knows the rules for writing it and can spot a reference doc drifting into how-to:

---
doc_type: reference   # reference | how-to | explanation | tutorial
---

So: the directory decides whether a document must be true; the tag decides what kind of true document it is. With the first of those in place the rule writes itself, and a reviewer or an agent can run it. Call it the gate:

When a change adds, removes, or renames a provider, a config section, or a public contract, grep the as-built docs for the affected symbols and update them in the same change. A stale reference is a blocker, not a nice-to-have.

Run that against an unsorted pile and it fails — not because the tooling is weak, but because nothing in the pile says which files are supposed to describe the present.


Write the strategy where the agent will read it

If agents consume documentation in order to work, then the documentation strategy is itself a document the agent should consume. A taxonomy living in a wiki page or the head of whoever set it up will drift the moment the team grows or the model changes. Write it as an agent skill instead: a loadable, versioned instruction file checked in beside the code. Mine holds the boundary rule, so the agent knows whether a new document is intent or as-built before it writes it; the classification compass, so it can tag an as-built doc and defend the choice with evidence rather than guesswork; the violation patterns worth flagging; and one essential guardrail — the skill is advisory on restructuring. It proposes splits; it never silently moves or rewrites files. Turn an agent loose to reorganize your docs and it will cheerfully shatter every inbound link you have.

Then wire it into the code-review gate. That is the step that matters. A skill the agent loads only when someone remembers to ask for it is a style guide, and style guides are advisory. A skill invoked from the review checklist on every change is a control. Grade the severity or the gate gets tuned out: a doc naming a deleted class is a defect; a doc that mildly mixes purposes is a comment.

Notice what just happened. The strategy for governing documents that agents read and write is itself a document that agents read and act on.

Mine is on GitHub if you want a working example to steal from. It is about a hundred lines: the scope of what it governs, the four-way classification compass, the anti-patterns to flag, the doc_type: tag, the hook into the review gate, and an explicit list of things it must never do.


The excuses are gone

Too expensive, nobody reads it, it rots. Every one of those was a defensible answer to a real problem, right up until the machines arrived — and now the cost has fallen through the floor, something reads everything, and the rot is caught in the commit that caused it.

What you have to build in return is small. 

  •   Two document trees: as-built docs at the top level of docs/, intent docs in specs/, plans/, reviews/, and archive/ — the directory alone tells you which documents owe the code the truth. 
  • A border: the boundary rule, so a human knows which tree a new file belongs in, and a doc_type: tag so an agent knows what kind of document it is writing. 
  • A gate: a review-time check that blocks on staleness and merely comments on style. A split without a border is a folder structure nobody follows, and a border without a gate is a convention that decays — but none of the three is much work.

The agents will happily write you a swamp. Give them the split, the border, and the gate, and they will write you a library instead.




Part of the "Stuff we push off" series




Revision History

Created 2026/07

Comments

Popular posts from this blog

Installing the RNDIS driver on Windows 11 to use USB Raspberry Pi as network attached

Home FIOS Network - Exploring the 4 boxes and their connections

GitHub "Clone to Desktop" with Windows GitHub.