The LLM should write the model, not the code

I. The work, not the rhetoric — again

The last essay turned the lens onto the prompt — the artifact the AI reads — and argued it's code, so it deserves the same architecture the rest of your code finally got: a typed payload, a deterministic render, drift caught at build time. This essay turns the lens onto a bigger question that's been sitting underneath the whole series, and that the entire AI-builder industry is now sprinting at from two different directions: what should the AI write?

Not "should AI write software" — that argument is over; it does, every day, in my stack and yours. The question is what artifact the AI should produce. Because the artifact you let the model author is the artifact you have to live with. And right now the industry has split into two camps, neither of which is the one I'd bet a decade on.

II. Camp A: the LLM writes the code

This is the loud camp. Lovable, v0, Bolt, Replit's agent — you describe an app, the model writes the code, you get a running thing in minutes. It is genuinely impressive, and it is the most expressive possible target: code is Turing-complete, so there is nothing the model can't, in principle, produce. Want a weird animation, a bespoke pricing rule, a one-off integration? The model just writes it.

The expressiveness is exactly the problem. What you get back is an opaque pile of code. It runs — until it doesn't — and when it doesn't, you are debugging a system no human designed, with no source of truth above the code that tells you what it was supposed to be. There's nothing to diff against. There's nothing to validate before it runs. Change one thing and the model happily rewrites three files in locally-coherent, globally-divergent ways — the exact AI drift I started this series on, now industrialized into a product category. The artifact is the code, and the code is ungovernable. You can read it, but you can't reason about the system from it, because the system is only ever implied by a hundred-thousand tokens of generated detail.

I've built on this substrate enough to know its ceiling. It's fantastic for a demo, a prototype, the first weekend of an idea. It is a liability the moment the thing has to survive a second engineer, a refactor, a compliance review, or a year.

III. Camp B: the LLM writes the config

The quieter camp saw Camp A's governance problem and over-corrected. Here the model doesn't write code at all — it writes configuration, or flows, in a constrained vocabulary the platform fully controls. Dify, Langflow, n8n: the AI assembles a graph of pre-defined nodes. Google's recent generative-UI work, A2UI, has the model emit a UI described in a fixed component vocabulary the client knows how to render. The model fills in a structure; it never authors the structure.

This is safe and inspectable in exactly the ways Camp A isn't. A flow is a small declarative artifact you can read, diff, and reason about. A generative UI made of known components can't render a security hole the renderer doesn't already permit. The blast radius is bounded because the vocabulary is bounded.

And that bound is the whole problem. You are locked to the platform's node set, the platform's component library, the platform's idea of what an application is. The moment your real requirement falls outside the vocabulary — the custom rule, the integration nobody built a node for, the behavior the component library can't express — you are stuck. There's no escape hatch into general-purpose code, because the entire safety story depended on there not being one. Camp B traded expressiveness for governance and discovered, predictably, that you need both.

IV. The seam nobody is selling: the LLM writes the model

Camp A: maximally expressive, ungovernable. Camp B: governable, boxed in. Stated that way, the seam between them is obvious — and it's the one I've spent twenty-five years building the substrate for without realizing it was the answer to this specific question.

Have the AI author the model. Not the code. Not a flow in someone's fixed vocabulary. The typed metadata — the durable spine — that the application is generated from.

Walk the loop:

  1. The LLM writes typed metadata. An entity, its fields, its relationships, its sources, a projection, a prompt's payload, an API surface. Declarative, typed, far smaller than the code it implies. This is the artifact the model authors — and it's an artifact a model is good at authoring, because it's structured and bounded in shape while still describing real software.

  2. verify gates it before it runs. This is the move neither camp has. The metadata is validated — every reference resolves, every type is real, every required slot is filled, the relationships are coherent — before a line of code is generated or executed. Camp A validates by running and seeing what breaks. Camp B validates by refusing to let you express anything risky. The model-authoring approach validates the declaration: you catch the hallucinated field, the dangling reference, the impossible relationship at author time, on a small artifact, with a precise error — not at runtime in a pile of code, and not by being forbidden from expressing it.

  3. Deterministic codegen produces the disposable per-language code. Once the model is valid, idiomatic code falls out of it — Drizzle/Zod/Fastify for TypeScript, EF Core for .NET, Spring for Java, Pydantic/FastAPI for Python, Exposed for Kotlin — the same generators I've written about, byte-checked against each other by a conformance harness. The model didn't hand-write any of it. The code is output, and output is regenerable.

  4. Turing-complete escape hatches cover the rest. The ~20% the model genuinely can't express — the custom SQL view, the regex from outside the metadata, the real business logic — is hand-written code that lives in seams the generated code leaves open. Camp B has no answer here; this approach has the full power of the language exactly where you need it, and a governed spine everywhere you don't.

That's the unification: Camp A's expressiveness (real code, escape hatches) with Camp B's governance (a small, validatable, inspectable declaration) — and neither camp's fatal compromise. The metadata is the asset; the code is regenerable; the LLM is the author of the model, not of an opaque pile of code.

V. Why metadata is the right thing to author

The deeper reason this works isn't ergonomic — it's that metadata is a fundamentally better asset than generated code, on every property that matters once a system has to live past its first week:

  • It's validatable. A typed declaration can be checked against rules before it runs. A pile of code can only be checked by running it. (verify, above.)
  • It's walkable. Metadata is a graph — entities reference entities, payloads reference fields, APIs reference projections. You can traverse it, query it, reason over the whole estate. Generated code is a graph too, but an implicit one you have to reconstruct by parsing; the metadata graph is explicit by construction.
  • It's portable. The same model generates idiomatic code in five languages. The code is, by definition, language-specific and non-portable — that's what makes it idiomatic. The portable thing is the spine above it.
  • It's multi-tenant-able. You can overlay tenant-specific or variant-specific metadata on a base model and regenerate, without forking the code — the pattern a pharmaceutical regulatory platform I worked on used twenty years ago to customize per customer without code changes. You cannot meaningfully overlay one pile of generated code on another.
  • It's diffable. A change to the model is a small, reviewable diff in a pull request — this field's type changed, this relationship was added. The same change expressed as a code regeneration is a large diff across many files where the signal drowns in the noise. The metadata diff is the semantic change; the code diff is its shadow.

Generated code has none of these properties and was never supposed to. It's the disposable artifact. The whole argument of this series is that the durable layer has to live above the code, and the AI-builder question is just that argument pointed at authorship: make the AI write the durable layer, not the disposable one.

VI. One mechanism, three render targets

Here's the part that convinced me the seam is real and not just a nice story — and it ties straight back to the prompt essay.

A data model, a prompt, and a UI are the same shape.

Each one is a declarative template that renders a typed payload to a target, where every reference in the template must resolve against the payload's type:

  • A data model renders a typed entity to a persistence and API target — tables, DTOs, routes. Every field reference must resolve to a real field.
  • A prompt renders a typed payload to a text target — the string the model reads. Every `` must resolve to a real field on the payload. (This is exactly the fourth pillar I built into 7.0.0: payload-as-projection, external text, deterministic render, drift caught at build time.)
  • A UI renders a typed payload to a visual target — a form, a grid, a view. Every bound field must resolve to a real field. This is where Camp B's generative-UI instinct is right — a UI should be a declarative artifact over a known shape — except the shape shouldn't be a fixed component vocabulary you can't extend. It should be your typed model, with the same escape hatches everywhere else has.

One mechanism — typed payload + declarative template + reference-resolution + deterministic render — pointed at three different render targets. The same verify that proves a prompt's variables resolve proves a UI's bindings resolve and a data model's references resolve. The same drift gate covers all three. I didn't design it this way on purpose; I built the projection-and-render machinery for entities and database views, and discovered the prompt payload was the identical shape. The UI binding is the third instance of the same pattern. When an abstraction pays for itself three times in domains you didn't design it for, it's not a coincidence — it's the seam.

To be clear about where this stands: the data-model and prompt render targets ship today. The UI-binding render target — having the LLM author a typed view declaration the same way it authors an entity or a payload — is where I see this heading, not something I'm claiming as done. But the architecture already implies it. The mechanism is built; the third target is a matter of pointing it.

VII. The industry is arriving at the same place in its own words

This isn't a lonely position. The people thinking hardest about this are circling the same conclusion from different vocabularies.

The Model-Driven Engineering research community — the academic descendants of the OMG's Model-Driven Architecture I first brushed up against in 2001 — has spent the last two years arguing, in paper after paper, that the way to use LLMs in serious software is to let them operate on models with deterministic safeguards around them, rather than letting them free-write code. The framing is almost word-for-word the seam I'm describing: the LLM proposes; a deterministic, model-based pipeline validates and generates. Recent surveys of LLMs in MDE land squarely on "integrate LLMs with deterministic safeguards" as the durable pattern (the 2025 MDE-and-LLM survey literature on arXiv is thick with this exact argument). They're describing the loop in Section IV from the modeling-language side; I'm describing it from the working-codegen-implementation side. Same shape.

And Andrej Karpathy's autonomy-slider framing from his 2025 "Software 3.0" talk gets at the other half of it. His point: don't build the fully-autonomous agent that writes the whole thing unsupervised (Camp A's fantasy), and don't build the rigid tool that does nothing on its own (Camp B's cage) — build the system with a slider, where the human dials how much the AI does and keeps a tight verification loop around it. Authoring the model is what makes that slider real for software. The model is small enough for a human to actually review at high autonomy, structured enough for a machine to validate, and the generated code below it is regenerable so the cost of turning the slider back down is near zero. You can't run a meaningful autonomy slider over an opaque pile of code — there's nothing to review at the high end and nothing to safely regenerate at the low end. You can run it over a typed model.

Two camps, two research traditions, one builder's decade of dogfooding — all converging on the seam between "AI writes the code" and "AI writes the config." The seam is: AI writes the model.

VIII. Where this is heading

I've been building toward this answer the whole time without naming it. Essay one said the metadata is the spine that keeps AI-generated code coherent. Essay two placed that spine against the rest of the AI stack. Essay three showed the prompt is the same spine pointed at a text target. This essay is the through-line made explicit: if the metadata is the durable asset, then the highest-leverage thing the AI can do is author the metadata — and a validate-then-generate loop around a typed model gives you Camp A's power without its chaos and Camp B's safety without its cage.

Today, MetaObjects has the pieces that make this concrete: typed metadata generating idiomatic code across five languages, runtime metadata, drift verify, and the prompt pillar — typed payload, declarative template, deterministic render, build-time verification. The model-authoring loop is the natural composition of those pieces with an LLM in the author's seat and verify in the gate. The UI render target and the full estate-graph exposure are where I see it going next, not where I'm claiming it's parked. But the architecture is built to want them, and that's usually the part that's hard.

The artifact you let the AI author is the artifact you're stuck with. I'd rather be stuck with a typed model I can validate, diff, port, and regenerate from than with a pile of code I can only run and pray over. After twenty-five years and a few production systems' worth of evidence, that's the bet.

This is the fourth essay in a series. The first was the drift problem and the origin story; the second placed the metadata layer against the rest of the AI stack; the third turned the lens onto prompts. This one asks what the AI should write at all. The next will keep following the thread — more of the work, less of the rhetoric.

My writing lives at dougmealing.com/writing, and I'm always up for a conversation about any of this — drop me a note.