blog / we-took-the-json-out-of-our-ai-deck-pipeline

We took the JSON out of our AI deck pipeline

Our deck-making agent used to pass work between stages in six JSON files. brief.json from the interview, outline.json from the outline, then design-direction.json, slide-plan.json, input-evidence.json, input-inventory.json. Around 26KB of schema documentation existed to describe them.

All six are gone. What replaced them is one markdown document. This is what we learned, because most of it generalises past decks.

A schema in the middle of an interview turns it into a form

Our interview step had one job: get the story straight before any slide exists, and push back when the positioning is weak. It wrote its output to brief.json, with fields for audience, outcome, ask, problem, proof, differentiation, objections.

That schema was quietly doing damage.

When the output is a set of slots, the interview optimises for filling slots. It gets to differentiation, collects an answer, and moves on — because the field is now populated and populated fields look like progress. Which is precisely the failure the interview existed to prevent: politely transcribing a weak pitch into a clean brief.

Worse, the next stage worked from the fields. The outline stage read brief.json rather than the conversation that produced it — so it built from a lossy summary of something that had been in context five minutes earlier. The founder's exact words, the hesitation before the real answer, the thing they said third that turned out to be the actual ask: all compressed away before the step that needed them most.

The artifact a human touches has to be in their words

The same problem showed up twice more in the same afternoon, and the third time we noticed the pattern.

The per-slide design packet. Our design stage emitted slide-plan.json with {archetype, density, focal_point, hierarchy, avoid} per slide. Precise, machine-readable, and impossible for a founder to check. Compare:

{"archetype": "big-stat", "density": "low", "focal_point": "center"}

against

one big number, the $40k, nothing else on it

A founder validates the second in two seconds and will tell you immediately if it's wrong. The first they scroll past. So the founder's line became the artifact and the packet became its derived expansion — which is the right way round, because the human decision is the one that needs checking.

The vocabulary. We have nineteen named layout archetypes — Statement, Big stat, Split feature, Data panel, Image story. Good vocabulary, genuinely useful, and we caught ourselves about to ask founders to pick from it. Nobody outside the building knows what "split feature" means. They say "picture on the left, the points on the right."

So the agent proposes the plain sentence, the founder edits the sentence, and the mapping to Split feature happens later, where only a machine reads it.

Three separate decisions, one rule underneath:

Every artifact a human touches is in the human's words. The schema is derived from it, never the reverse.

What we kept, and why it isn't a contradiction

Two JSON files survived: the brand kit and the QC scan.

They compare hex values, contrast ratios and type scales numerically, and a script does the comparing. Nobody hand-edits either one. That's the actual test — not "is this data structured?" but "does a human make decisions in this file?" If yes, it's prose. If it's only ever written and read by code, a schema is fine and a table of numbers is better than a paragraph about numbers.

Where a document needs both, the machine-readable part rides in frontmatter inside the same markdown file. Which is how the slides themselves have always worked, so the pipeline now uses one format end to end instead of two.

An instruction is not a gate

Our workshop deck has a slide that says "AI can add a lot of value — but it's often in a rush to build."

While designing this, mid-discussion, with that slide freshly in context, the agent announced "writing it" and started building. The person it was talking to had not finished the sentence proposing the design.

That's the useful data point. A prose reminder does not work, even when the reminder is verbatim in the context window and the topic under discussion is that exact failure. So the fix isn't better wording — it's structure. Stage advancement now requires an explicit recorded sign-off in the document's frontmatter, and "critique this" is a mode the agent is held in rather than an instruction it is trusted to remember. Findings only, no edits, until released.

If you're building agent pipelines, this is worth internalising: anything you're tempted to enforce with emphasis in a prompt should probably be enforced with a state machine.

Where the document lives, and why not on disk

Obvious answer: markdown files in the working directory. That's what we built first.

It's wrong, and the reason is one line from the same workshop deck: "do it on your phone. Talk, don't type."

A phone has no filesystem. On-disk markdown means the feature only exists for people running a coding agent on a laptop — which is the smallest and least representative slice of the people making pitch decks. So the document lives on the deck itself, server-side, reachable by every client: web, mobile, desktop, IDE. Pick it up next week in a different app and it's there, at the stage you left it.

That decision had a consequence we liked: the deck gets created at the very first step, so there's never a moment where the work exists but has nowhere to live.

What it costs to be wrong about this

Deleting six artifacts took an afternoon. Missing a stale reference took ten minutes more — the build stage was still opening with cat ./deck-brief/outline.json, a file nothing wrote any more, which meant the pipeline read an empty string and built from nothing. Green tests, clean typecheck, broken product. Worth saying because it's the normal outcome of a format migration: the format changes in one place and the readers keep reading.

The check that caught it was mechanical — grep every artifact name across every stage and see who still mentions one. If you do this kind of migration, do that grep before you claim it works.

Frequently asked questions

Why is markdown better than JSON for an AI pipeline?

It isn't, in general. It's better specifically where a human reviews or edits the artifact, because prose in their own words is checkable at a glance and a schema isn't. For data only code reads, JSON is fine and often clearer.

Doesn't structured output make LLM pipelines more reliable?

For extraction and function calls, yes. The trap is using it as a handoff between two reasoning steps: the second step then works from the fields rather than the material, and you've inserted a lossy compression exactly where nuance mattered. Keep structure at the edges, keep prose in the middle.

How do you validate a markdown artifact?

Frontmatter for anything a script must compare, plus deterministic lints over the prose. Ours checks one point per slide, a number budget counted in the prose but not in charts, and that every slide has a stated visual form. Cheap, no model tokens, and it runs on every write.

What replaced the six files?

One markdown document per deck with six named sections — what we're making, the story, what it should look like, the slides, the art direction, and the agent's read. Four hold the founder's words; two are the agent's. Writes go one section at a time, and each one snapshots the previous version, so an agent can't overwrite a founder's paragraph by accident.

See it work

/deck is the skill this came out of. It interviews you, argues with the weak parts, decides what each slide looks like in words you can check, then builds — or point it at a deck you already have and it diagnoses that instead. It's open source.

Install the skillsRead the source