The short version: if you want an LLM to hand back JSON your code can actually parse, you have three real options in 2026 — JSON mode, tool/function calling, and constrained decoding. Everything else (regex-parsing model output, hopeful re-prompts, string manipulation on Markdown code blocks) is a workaround people used before schema enforcement went mainstream.

The three techniques look similar from the outside — you send a prompt, you get back a structured object — but they behave differently in failure modes, cost, and how much the schema affects model quality. Choosing the wrong one is one of the most common reasons teams building on top of LLMs in 2026 end up with brittle pipelines that mostly work in demos and quietly fall apart in production.

This guide walks through what each technique actually does under the hood, which provider does which one best, and the practical patterns for making structured output as testable as any other function in your codebase.

Why This Matters More in 2026 Than It Did in 2024

Two years ago, structured output was a nice-to-have. Most LLM applications were chatbots or content generators where the model’s free-text output was the product. Today, LLMs are increasingly buried inside larger systems: extracting fields from documents, choosing next actions inside agent frameworks, populating database rows, triggering downstream workflows.

Every one of those integrations depends on the model returning data that the calling code can actually consume. A single malformed JSON response in a batch of ten thousand documents means a stalled pipeline, a null pointer somewhere three services downstream, and an on-call engineer trying to figure out which record broke. This is why schema enforcement went from “research curiosity” to “table stakes” over a very short window.

The other reason structured output matters more now is that it’s the boundary where LLMs start to look like normal software. Once your model returns typed data with guaranteed field presence, you can write unit tests. You can add contract tests between the model layer and the rest of the system. You can measure regression when you swap providers. Free-text output is fundamentally opaque; structured output is code you can reason about.

The mental model

Think of structured output as a type contract between your LLM and the rest of your program. JSON mode enforces “the response is JSON.” Tool calling enforces “the response is a call to one of these functions with these argument types.” Constrained decoding enforces “the response conforms to this grammar, guaranteed at every token.” The stricter the contract, the fewer failure modes you have to handle downstream.

Technique 1: JSON Mode

JSON mode is the weakest of the three. When you set response_format: { type: "json_object" } on OpenAI, or the equivalent flag on other providers, the model is instructed and constrained (to varying degrees, depending on provider) to emit syntactically valid JSON. That’s it. The keys, the types, the required fields — none of that is enforced.

What you get back is guaranteed to parse with JSON.parse(), but you still have to validate that the JSON has the shape your code expects. If you asked for {"name": string, "age": number} and the model returned {"full_name": "Ada", "years": "36"}, JSON mode is happy. Your code is not.

JSON mode is useful when your schema is genuinely free-form — say, a summarization task where the model needs to produce arbitrary key-value metadata — or when you’re prototyping and don’t want to write out a full schema yet. For production, it’s almost always the wrong choice. You’ll spend more time writing validation and retry logic around JSON mode than you would writing the schema in the first place.

When JSON mode still makes sense

Technique 2: Tool / Function Calling

Tool calling was the industry’s first workable answer to structured output, even though that wasn’t exactly what it was designed for. The technique was introduced so that models could invoke external functions — call a weather API, run a database query, hit a calculator — but developers quickly realized you could use it to enforce output shape by declaring a “fake” tool that represents the response schema.

You define a tool called respond whose input schema matches the object you want back. You tell the model that the only way to complete the task is to call this tool. The model produces a JSON payload matching the tool’s parameter schema, and you extract it from the tool call rather than from a text field.

This works, and works well, across all major providers — OpenAI, Anthropic, Google, Mistral, Cohere. Anthropic in particular treats tool use as the primary structured-output mechanism, and their models are heavily post-trained to produce well-typed tool arguments. The reliability is high enough that most production LangChain and LlamaIndex pipelines lean on tool calling under the hood, even when the “tool” is just a data-shape declaration.

Anthropic (Claude): tool use as the structured-output primitive

Tool use · Pydantic-friendly · Consistent across model tiers

Anthropic’s API doesn’t have a “JSON mode” in the OpenAI sense. Instead, you declare tools, and the model returns a tool_use content block whose input field is validated against the tool’s input_schema. In practice this means you get schema-shaped JSON back for free, and the SDKs make it trivial to bind the response to a Pydantic model or Zod schema.

OpenAI: response_format with json_schema strict mode

Native Pydantic support · Schema-enforced · Strict flag guarantees compliance

OpenAI added strict schema enforcement to its Chat Completions and Responses APIs, backed by grammar-based constrained decoding on the server side. When you pass strict: true alongside a JSON Schema, the returned object is guaranteed to match — not because of retries, but because the token sampler is prevented from producing anything else. The Python SDK integrates directly with Pydantic models via the parse() helper.

Google Gemini: responseSchema and responseMimeType

Constrained decoding · OpenAPI schema subset · Available across Gemini tiers

Gemini exposes a responseSchema field on the generation config that accepts a subset of the OpenAPI 3.0 schema spec. When paired with responseMimeType: application/json, the model’s output is constrained during decoding to satisfy the schema. Field ordering, enums, and nested objects are all respected.

When tool calling is the right pick

Technique 3: Constrained Decoding

Constrained decoding is the most powerful of the three. Instead of asking the model to produce JSON and hoping for the best, or wrapping the request in a tool call, the sampler itself is modified so that at every token the model can only emit tokens that keep the output on a path toward a valid grammar completion.

Under the hood, this means constructing a finite-state machine (or, more generally, a pushdown automaton) from your schema, and at each generation step masking out any tokens that would violate the grammar. If the next character has to be a comma, the sampler physically cannot pick any other token. The output isn’t validated after the fact — it’s prevented from ever being wrong.

This is what OpenAI’s strict mode does server-side. It’s also what open-source runtimes like vLLM, TGI, Outlines, XGrammar, and llama.cpp’s grammar backend give you when you run your own inference. If you’re self-hosting models, constrained decoding is the reason you can get schema-enforced output from an open-weights model that has no native “tool calling” behavior at all.

Outlines

Python · Finite-state grammar compilation · Works with Transformers, vLLM, llama.cpp

Outlines compiles a Pydantic model or JSON Schema into a finite-state machine over the tokenizer’s vocabulary, then plugs into the decoding loop to mask invalid tokens. Because the compilation is amortized across many generations, the per-token overhead is small in steady state. Outlines is the reference implementation most other libraries measure themselves against.

Instructor

Python · Provider-agnostic · Pydantic-first, retry-based

Instructor takes a different approach. Instead of modifying the decoder, it wraps the LLM client to enforce a Pydantic schema through validation-and-retry loops. The model produces JSON, the JSON is parsed against your schema, and if it fails, Instructor re-prompts with the validation error inline. This works across every provider that returns text — OpenAI, Anthropic, Ollama, Groq — and it composes with tool calling or JSON mode as a “belt and suspenders” layer.

XGrammar & llama.cpp grammars

C++ · Zero-cost decoding overhead · GBNF and JSON Schema support

XGrammar is a high-performance grammar-constrained decoding library that’s been adopted by vLLM, MLC-LLM, and SGLang. llama.cpp exposes a similar mechanism via GBNF grammars. Both give you sub-millisecond overhead per token relative to unconstrained decoding, which is why they’ve become the default choice for self-hosted inference of any real scale.

The one catch: schema strictness can hurt quality

Constrained decoding gives you a guarantee that’s almost too strong. Because the sampler is forced to commit to your schema starting from the very first token, the model has no room to think in prose before it starts producing structured data. On reasoning-heavy tasks, this can hurt accuracy noticeably — the model produces syntactically perfect JSON with semantically wrong contents.

The fix is one of two patterns:

  1. Add a reasoning field to the schema. Include a reasoning or notes string property at the top of your object. Because JSON emits fields in declaration order, the model gets to write out its chain-of-thought before it commits to the actual answer. This trick is well-known in the community and is the reason most Anthropic tool schemas start with a thought property.
  2. Two-step generation. First call: unconstrained, produces free-text reasoning. Second call: constrained, converts the reasoning into the structured payload. More expensive, but for the highest-stakes extractions it’s worth the extra tokens.
3
Techniques that matter
100%
Schema guarantee with constrained decoding
1st
Field should be reasoning, not answer

Choosing Between the Three

A simple decision tree covers most cases:

Are you self-hosting a model? Use constrained decoding via vLLM, Outlines, XGrammar, or llama.cpp grammars. You paid for the GPU; you get the schema guarantee for free.

Are you on Anthropic? Use tool calling with a Pydantic model or Zod schema mapped to a tool’s input_schema. Claude’s post-training is heavily optimized for this pattern.

Are you on OpenAI or Gemini? Use their native strict-mode schema enforcement (response_format.json_schema with strict: true on OpenAI, responseSchema on Gemini). This is server-side constrained decoding without you having to run the sampler.

Do you need to switch providers frequently? Use Instructor or a similar validation-wrapper library on top of whichever provider you’re currently pointing at. You lose the “impossible to fail” guarantee of true constrained decoding, but the abstraction layer pays for itself the first time you migrate.

Are you doing pure exploratory prototyping? Use JSON mode. Iterate. Once you know the schema, upgrade to one of the enforced techniques before you ship.

The Testing Payoff

The reason to care about all this isn’t just uptime — it’s that structured output turns your LLM into something you can write real tests against. Once the response is a typed object, you can:

This is the thing that gets missed in most tutorials. Structured output’s biggest win isn’t that the JSON parses — that’s a solved problem. The win is that your LLM starts to behave like any other function in your codebase, and you can apply thirty years of software engineering practice to it.

Common Pitfalls

Over-nesting the schema. Deep nested objects with lots of optional fields make constrained decoding slower and give the model more room to hallucinate structure. Flatten where you can.

Missing the reasoning field. If your schema starts with the answer, you’re asking the model to guess before it thinks. Always put a reasoning or notes field before the answer field.

Trusting the schema to mean “correct.” Schema enforcement guarantees shape, not truth. A model can happily return a well-typed but wrong answer. You still need evals.

Enums vs open strings. If a field can only take three values, use an enum in the schema. The model will be constrained to those three at decode time, and you’ll never have to handle a fourth in downstream code.

Assuming providers implement schemas the same way. OpenAI’s JSON Schema support isn’t identical to Gemini’s OpenAPI subset, and Anthropic’s tool input_schema has its own quirks. If you’re multi-provider, keep the schema conservative — stick to basic types, avoid recursive references, and don’t assume format validators (email, URI, date-time) are enforced.

Where the Frontier Is Heading

Three trends are worth watching in the second half of 2026.

Grammar-aware decoding for reasoning models. Reasoning-style models (OpenAI’s o-series, Anthropic’s extended-thinking Claude, DeepSeek R-line) produce long internal chains of thought before their final answer. New research and library work is figuring out how to keep the thinking phase unconstrained while snapping the final answer to a schema — getting the best of both worlds without the two-call latency penalty.

Schema-aware fine-tuning. Rather than adding constraints at decode time, some teams are fine-tuning models directly on schema-annotated data so that the base model produces schema-compliant output without any decoder modifications. This is faster at inference and often produces higher-quality outputs, at the cost of a training cycle per schema family.

MCP as a structured-output substrate. The Model Context Protocol standardizes how models declare tools, arguments, and typed responses across providers. As MCP adoption spreads, the “structured output” conversation shifts from “how do I get JSON” to “how do I declare this contract once and use it everywhere.”

Structured Output as a Career Skill

Fluency with structured output is a load-bearing skill for anyone shipping LLM features in production. It shows up in interview loops for LLM engineers, applied ML engineers, and AI-native platform teams. Companies like Anthropic, OpenAI, LangChain, and Databricks all treat schema-enforced generation and validation as a core competency — not a niche.

If you’re moving into an AI engineering role, being able to explain why constrained decoding is different from tool calling, and knowing when each is worth its tradeoffs, is a real differentiator. It’s also one of the few LLM-adjacent skills that transfers cleanly across providers, because the underlying grammar-and-schema ideas outlast any specific API.

Explore AI & ML Roles

Live openings at companies shipping LLM-powered products — the teams that ship structured-output pipelines every day.

Browse AI/ML Jobs → AI Skills Hub →

Quick-Reference Checklist

Print this. Pin it above your desk. Come back to it every time you’re about to write a new prompt that expects a typed response.

  1. Never rely on plain JSON mode in production. If your provider supports schema enforcement, use it.
  2. Prefer the provider’s native structured output over library wrappers when you’re on a single provider — less abstraction, fewer surprises.
  3. Put reasoning fields first in the schema so the model can think before it commits.
  4. Use enums for fields with fixed sets of values. Never accept an open string when you actually mean one-of-three.
  5. Validate anyway, even with constrained decoding. Provider bugs happen; models get swapped; schemas drift.
  6. Write unit tests on the parsed object. Not on the raw text. That’s the entire point.
  7. Log the raw response. When something goes wrong at 2 AM, you’ll want the untouched bytes.

Frequently Asked Questions

What is the difference between JSON mode and structured output? +
JSON mode only guarantees that the model returns syntactically valid JSON — the shape of the object is not enforced. Structured output (also called schema-enforced output) guarantees that the response matches a specific JSON Schema or Pydantic model, so field names, types, and required properties are all validated. Structured output is a superset of JSON mode.
Should I use tool calling or structured output for data extraction? +
For pure data extraction — pulling fields out of a document, classifying content, generating a report — use structured output. It is simpler, cheaper, and does not require you to model the operation as a fake function call. Reserve tool calling for cases where the model genuinely needs to trigger an action or choose between several tools.
How reliable is structured output in production? +
Very reliable when it is backed by constrained decoding. OpenAI, Google, and open-source runtimes like vLLM and llama.cpp implement grammar-based decoding that guarantees schema compliance at the token level. Anthropic delivers similar reliability through tool use. Free-text JSON parsing without schema enforcement fails several percent of the time, which is unacceptable for most production workloads.
What are Instructor and Outlines? +
Instructor is a Python library that wraps LLM APIs to enforce Pydantic schemas through re-prompting and validation retry loops — it works across providers. Outlines is a library that implements token-level constrained decoding using finite-state machines, guaranteeing grammar compliance directly during generation. Instructor is provider-agnostic and easier to adopt. Outlines requires model weights or a compatible inference runtime, but is more efficient and cannot fail.
Does structured output make the model less accurate? +
It can, if used carelessly. Constrained decoding forces the model to commit to a schema before it has finished reasoning — which is why chain-of-thought is often stripped from structured output modes. The fix is to give the schema a dedicated 'reasoning' or 'notes' field where the model can think in prose before emitting the structured payload, or to use a two-step pattern where reasoning happens in a first unconstrained call and structuring happens in a second.
What roles hire for LLM structured output skills? +
LLM engineers, AI product engineers, applied ML engineers, and platform engineers building LLM gateways all work with structured output daily. Companies like Anthropic, OpenAI, LangChain, LlamaIndex, Databricks, and most AI-native startups now consider this a core competency. Browse open AI/ML roles on our platform to find teams that ship structured-output pipelines in production.