ian.schuepbach.work

Spec-driven, model-tiered AI development

How I get reliable output from unreliable components: treat the spec as the durable artifact, put cheap models in charge of process and expensive models in charge of judgment, and never let a builder grade its own work.

01The spec is the durable artifact

In agentic development, code is cheap to regenerate and conversations evaporate. What survives -- what is worth an expensive model's time to write and a human's time to review -- is the spec. I write specs the way a PM writes requirements: the problem, the constraints, the acceptance criteria, and the tunable surface (anything a human might want to change later lives in config from version one, never as a retrofit).

A good spec makes the implementing model interchangeable. When a build goes sideways, I do not patch the conversation; I fix the spec and regenerate. Big refactors get a fresh spec rather than a maintained pile of amendments -- superseding beats archaeology.

02Cheap models host, expensive models think

Most of an agentic workflow is not thinking. It is dispatching: watch for a trigger, launch a worker, collect a result, post a status. I run that layer on small, cheap models with mechanical instructions -- string triggers and fixed verbs, no judgment calls. Judgment is concentrated at checkpoints, where a frontier model reviews a spec, audits a diff, or makes a taste call.

  • Host tier -- small models run loops, route messages, and follow checklists. If a step needs discretion, the design is wrong.
  • Build tier -- mid-size models implement against the spec. They are fast, cheap, and honest about being replaceable.
  • Judgment tier -- the expensive model writes the spec, reviews the result, and owns the hard calls. It shows up briefly and leaves artifacts behind.

This is a budgeting discipline as much as an engineering one: frontier-model tokens go where they change the outcome, not where a while-loop would do.

03Cold verification gates

A model that just built something is the least trustworthy judge of it. So verification runs cold: a fresh context, a different model or tool, no access to the builder's rationalizations. Clone the repo and build it. Curl the endpoint. Run the evals. The gate either passes on observable behavior or it fails -- prose explanations are not evidence.

The same principle covers humans: anything destructive, outward-facing, or money-spending stops at a human-in-the-loop approval gate, by architecture rather than by convention. Guardrails you have to remember are not guardrails.

04A working public example

underthink, a Claude Code plugin, is the small public end of this methodology -- built spec-first, with the model-tiering philosophy applied to the tooling itself. The larger private example is the six-machine home agentic network, where the same tiers and gates govern a fleet that non-technical people rely on daily.

05On-demand frontends

My mom runs her budget through a rendered page an agent built for her. Underneath it is a plain markdown file with her numbers in it, the page parses that file, draws the wheel, and writes her changes back into the same file through a narrow read/write protocol. She doesn't open the markdown. She doesn't need to. But if the page vanished tomorrow, nothing would be lost -- the file is the asset, and another page could be rendered over it by dinner.

That's the whole idea. Durable substance lives in plain text that people and agents can both read, and interfaces are views rendered on top of it, cheap enough to produce that they're cheap to throw away. The same trick covers her dashboard, a worksheet, a page a relative opens from a link on her phone, and so forth -- different faces, same files underneath.

This sounds like the "generative UI" demos going around, and the rendering half is the same trick. The difference is where the data lives. Generic generative UI generates the data model along with the pixels, so when you throw the interface away you throw the substance away with it, and now you can't throw anything away, and you're right back to an app holding your data. In my setup the rendered layer owns nothing. A 43-question interactive worksheet I shipped my mom exists to materialize its answers as a markdown file, once the file is full, the worksheet gets put away. The UI was scaffolding. The demos also tend to be screenshots. This is a household in production -- my mom's daily tools have run this way since August, and she only ever touches the rendered faces.

The part that took actual engineering isn't either end. Markdown is easy and web pages are easy, the plumbing between them is the part that fought back. A rendered view you rely on can't be a baked export, because a stale dashboard teaches you to stop trusting it, and if you have to worry about whether it's current you won't use it, which defeats the whole point. So the pages read LIVE through one versioned protocol -- read, write with an expected hash so a page never silently overwrites what it didn't read, append, list -- and the same unmodified page runs inside a note-taking app, on a phone, and on the public web, because the protocol has many answerers. The rules are written down: no polling loops (there's a checker script, because I don't trust myself on that one), snapshots allowed only as a paint-fast boot trick, honest timestamps on anything materialized.

Two smaller things fall out of this that I haven't seen elsewhere, as far as I know. A link can live in a button label or a card footer and it indexes exactly like a link in prose, so generated UI gets backlinks. And the cost of generating an interface is an engineering variable like any other -- splitting the plumbing agents never write from the content they do takes the tokens spent per page from around 1750 to around 400.

When rendering a purpose-built view costs minutes of agent time instead of a sprint, "app" stops being the unit you maintain, the file and the protocol underneath it are. I think interfaces are headed that way generally. We'll see.

06What this looks like in practice

PhaseWho does itArtifact
Frame the problemHuman + frontier modelSpec with acceptance criteria
ImplementMid-tier models, in parallel lanesCode, config surface, tests
VerifyCold context: fresh model, real commandsPass/fail evidence, not prose
ApproveHuman, at the gateThe decision, logged

The pattern scales down to a one-file utility and up to a multi-machine agentic system. The constant is that every layer produces something inspectable -- a spec, a diff, a gate result -- so trust accumulates in artifacts instead of vibes.