AppliedAIPrep logoAppliedAI/Prep
Courses/Applied AI Engineering/Prompting as an engineering discipline14 min read

Getting output your program can actually rely on

The step that turns a chat toy into a component you can build on. Three levels of guarantee, why asking politely is the weakest of them, and the validation layer you need even when the format is guaranteed.

TL;DR: There are three ways to get structured output, and they are not equivalent: ask for it, constrain the generation so only valid tokens are possible, or use the provider's schema feature. Even with a guarantee you still validate, because valid JSON with a hallucinated value is the failure that reaches production. Structure is what makes a model a component instead of a demo.

Where you are. You know a prompt has an output contract. Enforcing it is what comes next. This is the most immediately practical lesson in the module: nearly every feature in the first of the four shapes, turning messy input into structured data, lives or dies on what you learn here.

Why this is the pivotal step

A model that returns prose is something a person reads. A model that returns {"status": "refund_requested", "amount": 4200} is something a program can branch on, store, and act upon.

That single difference is what lets you put a model inside a system rather than in front of a user. Everything in modules 5 and 7 assumes it.

Three levels of guarantee

They are usually presented as alternatives. They are a ladder, and you should know which rung you are on.

Level 1: ask for it. Put the shape in the prompt, give an example, and hope.

This mostly works, and "mostly" is the problem. You get a stray sentence before the JSON, a trailing comma, a code fence around it, or a helpful explanation you did not ask for. At one failure in fifty, a person testing by hand will not see it and production will.

Level 2: constrain the generation. Rather than asking, restrict what the model is allowed to emit. At each step, tokens that would make the output invalid are masked out, so a malformed result is not merely unlikely but impossible. If the schema says the next thing must be " then no other token can be chosen.

This is a genuine guarantee about form, and it is the meaningful jump.

Level 3: the provider's schema feature. Most model APIs now accept a schema and enforce it for you, which is level 2 with the work done for you. Use it when it exists.

rendering diagram…

The guarantee you do not get

Here is the part that catches people, and it is the reason this lesson is not simply "use the schema feature."

Constraining the form guarantees nothing about the content.

{"account_id": "AC-99812", "amount": 4200} is perfectly valid JSON. It parses. Every field is present with the right type. The account may not exist and the amount may appear nowhere in the source document.

Structure moved you from "might crash" to "will not crash." It did not move you from "might be wrong" to "is right." Those are different problems and only one of them is solved.

So the validation layer stays, and it checks things a schema cannot:

  • Is every value real? Identifiers, product codes, and statuses should be checked against your own data, not trusted from text.
  • Is every claim in the source? If you asked for extraction, each extracted value should appear in the document you supplied. Cheap to check, catches a lot.
  • Are numbers sane? Ranges, signs, totals that should add up.
  • Is empty represented properly? Which brings us to the mistake that deserves its own section.

Design the empty case first

The most common structured-output bug is not malformed JSON. It is a model with no good answer inventing a plausible one, because your schema left it nowhere else to go.

If a field is required and the document does not contain it, the model must produce something, so it produces something reasonable-looking. You built the trap.

Two fixes, and use both. Make fields nullable and say explicitly in the prompt what to do when the information is absent. And give the response an escape hatch: a found: false flag, a confidence field, or a permitted "unknown" value.

A schema that cannot express "I did not find it" will get lies instead. Design that path before the happy one.

Do this before moving on

Take a document type you have on hand and write a schema for four or five fields you would want extracted. Include at least one field that is genuinely absent from some of your documents.

Run it two ways: asking for JSON in the prompt, and using your provider's schema feature. Compare parse failures across a dozen documents. Then, separately, check what each returns for the field that is sometimes missing. The second comparison usually matters more than the first, and it is the one most people never run.

Go deeper

Key takeaways

  • Three levels: ask, constrain the generation, or use the provider's schema. Only the last two are guarantees.
  • A guarantee about form is not a guarantee about content. Valid JSON with an invented value is the failure that reaches production.
  • Validate values against your own data, and check extracted claims appear in the source.
  • Design the missing-data path first. A schema with no way to say "not found" will be answered with something plausible instead.
LEARNING LAB1 of 4

Check yourself before an interviewer does. Answer from memory first.

You switch to a provider schema feature and parse failures drop to zero. What class of bug is unaffected?

Sign in to track where you are in this course.