Structured Output is not "please return JSON only" in a prompt. It is an API capability: you hand over a Schema, the model is constrained while generating, and the whole reply is a validatable object. This piece is dated 2026-09-07 and does not guess the next format. Below: first the definition, then why all three made it a first-class citizen at the same time, then one sample that is enough to generate a Schema. Why the contract picks JSON: see the previous piece Why AI likes JSON; how to grow a Schema from a sample: Generate Structured Output from a sample.
In 2024 you could still stuff a model into curly braces with a prompt. In 2026, GPT-5.6, Claude Fable 5.1, and Gemini 3.8 Flash all write Structured Output as a formal API. The product lines differ โ see 2026 AI model war โ but the hop they hand to a program is the same: a parseable object, plus a Schema. This is not one more switch in the docs. It is the model going from "can talk" to "can be caught by the next hop."
What it actually is
Structured Output is an API capability from the model vendors: you attach a JSON Schema (or an equivalent type description) at call time, and the model's entire reply must be a JSON object that matches that Schema. Missing fields, type drift, enums that fly off, extra unknown keys โ blocked at generation time, not after your JSON.parse blows up.
Three things have to hold at once for it to count as Structured Output:
- The output is an object, not a paragraph. An explanation for people is optional. What the program gets is an object.
- The shape is specified by a Schema. type, enum,
required,additionalPropertieslive in the contract, not in the prompt. - The constraint happens at decode time. Illegal tokens are excluded at sample time. That is constrained decoding, not a retry after the fact.
The shape can be right and the values still wrong. The Schema guarantees keys and types, not "unit price ร qty = total." Google's own docs say this plainly. It applies to all three: the Schema passed; business rules still need another check.
How it differs from "please return JSON"
A prompt is a request. An API is a contract. Write "return JSON only, no markdown" into the system prompt and the model will usually play along, but the failure mode is soft: an extra layer of explanation, a number written as a string, a required field dropped, a key your parser does not know. All you can do is retry, regex, and a human fallback.
Structured Output moves the contract from natural language into the decoder. The model no longer "tries to look like JSON"; it "can only emit legal tokens." Failure becomes an API error or an SDK parse failure, not a paragraph that looks a lot like JSON.
| Prompt constraint | Structured Output | |
|---|---|---|
| What it guarantees | Looks like JSON most of the time | Generated against a Schema |
| How failure shows up | Looks right, won't parse | Generation is blocked, or the SDK rejects it |
| Where the field contract lives | A verbal agreement in the prompt | required / enum / types |
| Where it belongs | Demos, drafts | Billing, writes, agent loops |
Boundaries with JSON Mode and Function Calling
The same product often has three words that get mixed. Mix them, and it feels like "the model sometimes listens, sometimes doesn't."
| Capability | Guarantees | Does not guarantee |
|---|---|---|
| JSON Mode | The braces parse | Fields are there, types are right, enums are closed |
| Structured Output | The whole reply matches the Schema | The business numbers add up |
| Function Calling / tools | The chosen tool's parameters match the Schema | The model picks the right tool |
JSON Mode is a weak form of Structured Output; it can stay in demos. Function Calling is a different contract: the model says "I need to call this tool," and the parameters must validate. Claude writes both as the same shape; OpenAI and Gemini split them into response_format / responseSchema and tools. Fields can be shared; don't copy the wrapper wrong. For the agent-side tool loop, see DevDay 2026 Agent.
Why all three shipped it: production, not taste
A chat window can talk. A production system cannot. From 2024 to 2026, all three made the same capability a first-class citizen because the downstream changed.
- Agents need a loop, not a paragraph. Tool parameters, intermediate state, and routing results all have to parse. A fluent paragraph does not enter the next hop. For the agent path after DevDay, see How agent development will change.
- Writes and billing cannot rely on lucky retries. An invoice, a ticket, an eval trace โ miss one field and you have dirty data. A 95% prompt success rate looks good in a demo; it is not enough to write to the database.
- Constrained decoding can already ship in flagships. "Generate strictly against a Schema" used to be too slow or too brittle. After OpenAI pushed the Schema into the decoder in 2024, the path was proven sellable; Claude and Gemini have no reason to leave developers on prompts.
- Cross-model routing needs the same object. Swapping
model_idshould not swap field names. The contract lives in the Schema; the wrappers can each write their own.
So "all started supporting it" is not the three vendors agreeing they like curly braces. Whoever lets developers hook the model into a program first gets into production. Why JSON was chosen โ it parses, it validates, training data is full of it โ the previous piece already covered.
Where each vendor wrote the capability
What they like is the same object, not the same request body. Write the wrapper into the docs; leave the fields in a shared file.
1. GPT / OpenAI: the Schema goes into the decoder
In Chat Completions, Structured Outputs hang off response_format, type json_schema; production should turn on strict: true. The Responses API puts the same object on text.format. Paste fields from an old guide onto the new API and you often don't get a nice error โ it just stops constraining the way you expected. The SDK's .parse() takes another pass with Pydantic / Zod.
JSON Mode (parse-only) can stay in demos; don't leave it on billing or write paths. The tool side is a second contract: a function's parameters are also JSON Schema.
2. Gemini: mime type plus Schema
Gemini folds JSON Mode and Structured Output into one path: response_mime_type: application/json, then hang responseSchema / response_json_schema. It looks the most "Schema-native," and the subset is the narrowest: basic types, enum, format, bounds, and required are available; deep polymorphism, recursive $ref, and trees that are too large or too deep โ the docs say they may be rejected outright.
High-volume Structured Output still often picks Gemini 3.8 Flash; see Pick a model by task. Output cap 64K; chunk long documents first. Gemini 4 has no release date; keep writing the production path as 3.x. Details: When will Gemini 4 be released.
3. Claude: the same shape for output and tools
Anthropic writes "give me an object" and "go call a tool" as the same shape. To ask for JSON directly, use the Messages API's output_config.format (the old name output_format is deprecated). The agent path adds input_schema to the tool and turns on strict: true on the tool definition โ not on tool_choice.
The Schema likewise wants additionalProperties: false and a complete required list. What you get: for the tool the model picked, parameters are constrained at generation time. The SDK's client.messages.parse() checks for you and does not hand a raw string to the business layer.
Why they showed up together
On the surface it is a product race. Underneath it is the same technical path and the same developer demand.
- The technical path converges. Constrained decoding compiles a Schema into a set of legal tokens. Whoever ships a stable API first turns "please return JSON" into debt.
- The ecosystem is already built on JSON. SDKs, browsers, databases, OpenAPI, Zod, MCP's JSON-RPC โ the next hop all eats objects. No vendor has a motive to invent a format that only works in its own chat window.
- Evals and compliance need to be diffable. A paragraph cannot be compared automatically; a JSON document can show whether a field drifted or a type drifted. This site's JSON Diff is built for that hop.
- MCP writes the tool contract as objects too. Tool names, parameters, and return values are all JSON. This site's MCP Tool page is writing that contract, not a prompt.
So the three docs use different words, and the developer experience is converging: lock the fields first, then pick a wrapper, then swap model_id.
What it means for developers
Once the capability is first-class, the workflow has to change. It is not one more prompt line.
- Write the sample first, then the Schema. Infer types and required from real business JSON; don't draw a tree from thin air. The tutorial: Generate a Schema from a sample.
- One field list, three wrappers. OpenAI / Claude / Gemini request bodies are generated from the same Schema. Hand-copy three field lists and they will drift next week.
- Strict mode on by default.
strict: true,additionalProperties: false, a completerequired. Miss a listing and you allow a missing field. - A second set of real output must be checked again. The first sample is always a bit too clean. The Schema passed; the total can still be wrong.
- Swap the model, not the contract. Lock field names and types. What you swap is the wrapper and
model_id.
Gemini's Schema language is an OpenAPI subset. Start with the intersection: objects, arrays, string / number / integer / boolean, enum, required. Leave oneOf, recursive refs, and extra-deep nesting until you confirm that platform can swallow them.
A minimal sample
Below is business JSON for "classify a ticket." It is not a request wrapper; it is the object all three models should emit. Enums as strings, confidence as number, needs-a-human as boolean.
{
"ticket_id": "TCK-20260907-042",
"intent": "billing",
"priority": "high",
"language": "zh-CN",
"summary": "ๅ็ฅจ้้ขไธ่ฎขๅไธไธ่ด",
"needs_human": true,
"confidence": 0.81,
"entities": [
{
"type": "invoice_id",
"value": "INV-20260905-018"
}
]
}
With this site's inference rules, that sample yields:
| Field | Infer types | What to do after generate |
|---|---|---|
intent / priority |
string | Collapse to an enum; don't leave free text |
confidence |
number | Writing "0.81" drifts to string; add 0โ1 bounds |
needs_human |
boolean | Samples must be true / false, not "yes" |
entities |
array of object | Every item needs type and value |
summary |
string | This is one of the few fields that should stay free text |
Once the sample is ready, open Structured Output to generate the OpenAI / Claude / Gemini wrappers, then review required and additionalProperties by hand. The same object can also become a tool via Function Calling: the model is not "talking about this ticket"; it is submitting a document that must validate.
How to accept it in JSON Toolbox
- Paste the sample above into JSON Format and confirm it parses.
- Generate a first draft with Structured Output or JSON โ Schema.
- Take a second set of real model output to Schema validation. The first sample is always a bit too clean.
- When you switch from GPT to Claude or Gemini, use JSON Diff to see whether a field dropped or a type drifted.
- Convert to Zod when the frontend needs checks, and to OpenAPI 3.1 when you need API docs.
Everything stays in the browser and is never uploaded.
FAQ
What is the difference between Structured Output and "please return JSON"?
A prompt is only a request. Structured Output hands the Schema to the decoder. Production uses the latter.
Why have GPT, Gemini, and Claude all started supporting it?
Agents, billing, and writes cannot rely on a paragraph. All three need to hook the model into a program; constrained decoding is the same path.
Can JSON Mode replace Structured Output?
Not as a production contract. JSON Mode only guarantees it parses, not fields and types.
Are Structured Output and Function Calling the same thing?
No. One constrains the whole reply; the other constrains tool parameters. Fields can be shared; don't copy the wrapper wrong.
Does a valid Schema mean the business is correct?
No. The shape can be right and the total still wrong. A second set of real output must be checked again.
Summary
AI Structured Output is an API, not a prompt trick. You hand over a Schema, the decoder guarantees the shape, and the program catches an object. GPT, Gemini, and Claude all support it because production systems โ agents, writes, evals, routing โ cannot rely on a well-written paragraph. The three wrappers differ: response_format / text.format, responseSchema, output_config / input_schema. What they share is fields, types, required, and "no extra keys." JSON Mode stays in demos. Grow the contract from one sample; validation, Zod, and OpenAPI all follow it.