Getting a language model to return clean, predictable JSON is one of the most frustrating parts of shipping an AI feature. One call returns perfect data; the next wraps it in markdown, adds a chatty preamble, or drops a required field. LLM structured outputs fix this by forcing a model’s response to match a schema you define, so your code receives validated objects instead of free-form text you have to parse and pray over.
In 2026, three libraries dominate this space: Instructor, Outlines, and BAML. They solve the same problem from very different angles. This guide breaks down how each one works, where it shines, and which to reach for in your stack.
Why LLM Structured Outputs Matter
Reliable LLM structured outputs turn a probabilistic text generator into a dependable component you can build on. Without them, you write brittle regex, retry loops, and JSON repair hacks that break the moment a provider updates a model. With them, your function-calling pipelines, data-extraction jobs, and agent workflows get type-safe data every time.
The payoff shows up most in production. Structured data extraction, classification, and tool-calling all depend on outputs that conform to a contract. The three libraries below approach that contract differently: one validates after generation, one constrains generation token by token, and one compiles a schema into cross-language clients.

Instructor: Pydantic Validation and Auto-Retries
Instructor is the most popular option, with more than 3 million monthly downloads and 11k+ GitHub stars. Built on top of Pydantic, it wraps your existing LLM client, intercepts the response, validates it against a model you define, and automatically retries with the validation error if the data fails.
- Pydantic-native: Define a schema as a normal Python class and get runtime validation for free.
- Automatic retries: On a validation failure, it re-prompts the model with the error so it can self-correct.
- Broad provider support: Works with OpenAI, Anthropic, Google, Mistral, Cohere, Ollama, DeepSeek, and 15+ providers.
- Streaming: Supports partial responses and lists for real-time use cases.
The trade-off: validation happens after the model generates. Errors surface at runtime, and each retry costs another API call. For most Python teams calling hosted APIs, that is a fair price for how little code Instructor requires.
Outlines: Guaranteed Schemas via Constrained Decoding
Outlines takes a fundamentally different route. Instead of validating after the fact, it constrains generation itself. As the model produces token logits, an Outlines logits processor sets the probability of any token that would violate your schema to zero, so only legal tokens can be sampled.
Schemas compile once into a finite-state machine, and an index of state transitions is reused at runtime so there is no per-token recomputation. The result is output that matches your structure with zero retries — the model literally cannot generate invalid JSON. Within the set of valid tokens, normal sampling still applies, so temperature and other parameters work as expected.
Because it operates on raw logits, Outlines is best when you run local or open models (via vLLM, Transformers, or similar) and need hard guarantees. It is less of a fit when you only call closed APIs that do not expose token-level control.
BAML: Contract-First, Cross-Language Outputs
BAML (Boundary Markup Language) brings a contract-first, code-generation approach. You define your schemas and prompts in .baml files, and BAML generates type-safe client code for Python, TypeScript, Ruby, and more from a single definition.
Its standout feature is a forgiving parser built for the real world. BAML handles messy model output — markdown fences wrapped around JSON, chain-of-thought reasoning mixed with data, and trailing commentary — that would break a strict JSON parser. That makes it resilient across providers without per-model tuning.
BAML shines when multiple services in different languages consume the same LLM contracts, or when you need strong guarantees about data shapes across language boundaries. The cost is a new file format and build step to learn, which is overkill for a single quick Python script.
Instructor vs Outlines vs BAML: Quick Comparison
| Library | Approach | Best For | Guarantee |
|---|---|---|---|
| Instructor | Post-generation Pydantic validation + retries | Python teams on hosted APIs | Validated after generation |
| Outlines | Constrained decoding (logit masking) | Local/open models needing zero retries | Schema enforced during generation |
| BAML | Contract-first codegen + robust parser | Multi-language, multi-service stacks | Resilient parsing across providers |
How to Choose the Right Library
A simple rule of thumb works for most teams. Start with Instructor if you are in Python and calling hosted APIs — it is the fastest path to reliable data with the least code. Reach for Outlines when you self-host models and need a hard guarantee with no wasted retries. Move to BAML when several services or languages must share the same LLM contracts.
These tools also pair naturally with the rest of a modern LLM stack. Structured outputs feed cleanly into agent frameworks like LangGraph and CrewAI, and they make evaluating LLM outputs far easier because every response already conforms to a known shape. They also complement LLM guardrails for safer production pipelines.

Frequently Asked Questions
What are LLM structured outputs?
LLM structured outputs are model responses forced to match a predefined schema, such as a JSON object or typed data class, so applications receive validated, predictable data instead of free-form text.
Is Instructor or Outlines better?
Instructor is better for Python teams calling hosted APIs because it validates with Pydantic and retries automatically. Outlines is better for self-hosted models because it constrains decoding and guarantees a valid schema with no retries.
What makes BAML different?
BAML uses a contract-first .baml file to generate type-safe clients across Python, TypeScript, and Ruby, and ships a robust parser that handles messy LLM output like embedded markdown and reasoning text.
Do structured outputs replace function calling?
No. They complement it. Function calling decides which action to take, while structured outputs guarantee the arguments and results conform to a schema your code can trust.
Conclusion
Choosing among Instructor, Outlines, and BAML comes down to where your models run and how many languages touch them. All three deliver reliable LLM structured outputs — the difference is whether you validate after generation, constrain it directly, or compile a shared contract. Pick the one that matches your stack, and you will spend far less time fighting malformed JSON.
Ready to build more reliable AI features? Explore our other 2026 guides on agents, evals, and guardrails, and subscribe to NewsifyAll for hands-on LLM engineering tutorials every week.

