HTML as a Native Data Format for LLMs | AST-as-HTML A document platform built by an AI assistant uses HTML as a native data format for LLMs instead of JSON, encoding templates as HTML and employing a 'rewrite the whole thing' editing strategy. The approach claims lower token costs, faster responses, and better data integrity compared to granular tool APIs, though a July 2026 correction notes that accuracy gains are neutral for whole-tree editing and that id-anchored patches are more reliable above 300 nodes. Note July 2026 : After publishing this piece we put its claims to a pre-registered benchmark, then found and corrected a defect in the benchmark itself, then ran three follow-up studies. Not every claim survived. The original argument stands below as written, with inline annotations where specific claims changed, and the full chronology in the update log near the end of the article. Where it nets out: the HTML dialect is accuracy-neutral for whole-tree editing its measured wins are token cost and human legibility, with a small fluency edge reappearing in focused views ; no editing interface dominates below about 200 nodes; above about 300, id-anchored patches are the reliable and cheap path; and the case for whole-tree rewrite now rests on structural immunity to tool-history loss, on token economy, and on the codec's guarantees, not on model fluency. Companion posts: the benchmark, the correction story, the crossover, and focused views. We built a document platform where an AI assistant designs marketing documents flyers, brochures, one-pagers inside brand-approved rails, and humans finish them by clicking into the rendered page and typing. Getting the agent to author templates , the structural layouts those documents are built from, turned out to hinge on a single unfashionable decision: We encode our templates as HTML, not JSON. And the agent's main editing tool is "rewrite the whole thing." That inverts most of the current advice about building agents on structured data. It also turned out to be the cheaper, sturdier choice: fewer tokens burned, faster responses, and better data integrity on every edit. This post is about why. The Problem A document template in our system is a tree: a document contains pages, pages contain blocks, blocks contain text atoms, image atoms, styled containers, and slots that reference reusable widgets. Every node carries attributes: CSS classes, length budgets for copy, type-scale choices, slot constraints. Themes paint the tree through CSS variables, so a template never hardcodes a color; it says bg-primary and the active brand theme decides what that means. We wanted an assistant that could build and restructure these trees conversationally: "Design a full-width widget with a rounded content box on the left and a stat panel on the right." And we wanted its output to land in the same editor, with the same undo semantics and the same validation, as a human's edits. The Obvious Design, and Why We Didn't Ship It The textbook approach is to store the tree as JSON and give the model a granular tool API: insertNode parentId, type, index setAttribute nodeId, key, value moveNode nodeId, newParentId, index removeNode nodeId We've built agents like this. They work, but they under-perform in three predictable ways: You're teaching a bespoke schema from scratch. Every node type, every attribute, every containment rule has to be spelled out in the prompt, and the model's only fluency is whatever your prompt bought. It has seen your JSON schema zero times in training. Granular tools invite granular failure. Building a twelve-node layout takes a dozen round trips. Each call can reference a stale id, a wrong parent, an index that shifted two calls ago. The tree passes through eleven intermediate states, each a chance to strand the agent somewhere invalid, and each a state your renderer might have to survive. Correction, July 2026: an earlier update here reported a measured +33-point gap for rewrite on multi-turn reference edits; that gap was our own benchmark harness hiding the model's tool calls from the conversation history. With correct history, rewrite vs tools on multi-turn reference edits is 88.1% vs 91.3%, no significant difference, and no arm ever produced a stale-reference failure. The model can't "see" its work. With mutation-by-tool-call, the model's picture of the current tree is a mental reconstruction from its own call history. Drift is inevitable. The Inversion Our templates serialize to plain HTML with a small attribute grammar: