Designing a parser contract for AI output (not just a prompt)

2026年8月10日1 次浏览来源:Dev.to阅读原文

Most posts about getting structured data out of an LLM stop at the prompt: ask for JSON, maybe hand it a schema, done.

That's necessary but not sufficient — the harder problem shows up on the other end, in the code that has to trust what came back.

I hit this building the import pipeline for a CRM (Anguardia) that reads AI-generated prospect research, and the parser ended up teaching me more than the prompt did.

The format isn't the hard part The prompt asks for a fixed markdown shape — headings, a table, checkbox tasks: That's the easy 80%.

Any capable model follows a structure like this reliably.

The interesting decisions all live in the parser that reads it back.

Decision 1: the parser never throws parseDossier has no failure mode — it always returns a dossier object and a warnings array, even for input that doesn't look like a dossier at all.

A model's output is not a contract you control, so treating a malformed dossier as an error case just means building a second, worse UI for "sorry, try again." Best-effort parsing plus visible warnings does the same job without the dead end.

Decision 2: unknown fields are dropped, not guessed A model will occasionally add a field nobody asked for, or misspell one.

Silently coercing it into the nearest known field is how you end up with a company's Slack handle stored as its website.

The parser drops anything it doesn't recognize and says so — a warning the user can see, not a guess they can't.

Same logic on malformed data that did land in the right field: A due date that isn't YYYY-MM-DD doesn't get parsed loosely — it gets dropped, with a warning.

The alternative (a fuzzy date parser trying to make sense of whatever the model wrote) fails in a way nobody notices until a task has the wrong due date silently.

Decision 3: "never invent" is a prompt instruction and a parser rule The prompt tells the model not to guess contact details: That's necessary but it's a request, not a guarantee — nothing stops a model from ignoring it.

So the parser is built the same way independently: a blank table cell stays null, not an empty string coerced into something that looks like data.

Two independent layers agreeing "blank beats plausible" is worth more than either one alone.

Decision 4: version the format with a marker, not a schema migration The product's name changed after the format shipped.

Rather than migrate every dossier anyone had already generated, the parser just accepts both markers indefinitely.

A one-line HTML comment on the first line is a cheap, durable version tag — cheaper than a schema registry, and it survives a rebrand without anyone having to regenerate old research.

The pattern, generalized If you're parsing anything an LLM produces and acting on it automatically: Never throw on malformed input — return a result plus diagnostics, always Reject and report unknown data, don't coerce it — a warning is recoverable, a wrong guess isn't Match your prompt's honesty constraints in the parser — don't rely on the model alone to keep a promise Version the format at the boundary (a marker, a header), not by trying to migrate every past output None of this is specific to CRMs or prospect research — it's the same shape for any pipeline where a model's output becomes a record something else acts on.

The prompt gets the output roughly right most of the time.

The parser is what makes "most of the time" safe to automate.

If you want to see the actual prompt this parses: the free Dossier v1 prompt — paste it into Claude, ChatGPT, or any model with a company name, no signup required.

分享
Baike.dev

baike.dev helps you discover great languages, frameworks, databases, DevOps and cloud-native tools.

Quick links

About

Contribute

Found a great developer tool? Share it with the community.

Submit a tool
© 2026 baike.dev Developer EncyclopediaUpdated daily · Discover great developer tools