# Instructor: structured LLM outputs through Pydantic models

> Instructor turns a Pydantic class into a validated response model for OpenAI, Anthropic, Google, Ollama and Groq clients. It removes manual JSON parsing and retries, but it is an extraction and classification library, not an agent runtime.

**567-labs/instructor** — structured outputs for llms 

- Repository: https://github.com/567-labs/instructor
- Website: https://python.useinstructor.com/
- Stars: 13,911 · Forks: 1,252
- Language: Python
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/567-labs-instructor

## The problem Instructor removes: JSON schemas, parsing and retry loops

Calling an LLM with a function schema is not difficult by itself. The work is in everything around it. You write the JSON schema by hand, you read tool_calls off the response object, you json.loads the arguments string, and then you check whether the fields you asked for actually arrived. When a field is missing or the wrong type, you write the branch that resends the request. The README shows this side by side: a raw OpenAI call with a tools list and a manual json.loads, next to the same call with response_model=User.

Instructor's target reader is a Python developer who already knows what shape the answer should take. You have a database table, an API contract, or a Pydantic model in another service. You want the model to fill it in. The library is for extraction and classification, not for open-ended conversation. The README states this boundary directly: use Instructor for fast extraction, reach for PydanticAI when you need agents. That sentence is the most useful line in the document, because it tells you which half of the problem space the project is claiming.

## How from_provider, response_model and validation retries fit together

The mechanism is a wrapper around a provider client. instructor.from_provider takes a string such as openai/gpt-4o-mini and returns a client whose chat.completions.create accepts a response_model argument. Inside that call, Instructor converts the Pydantic model into the JSON schema the provider expects, sends it, and then validates the returned arguments against the same model.

Validation is where the retry logic lives. If a Pydantic field_validator raises, Instructor sends the error message back to the model and asks again, up to max_retries. That is the loop most teams end up writing by hand, and here it is the default path. The same create call also accepts stream=True with response_model=Partial[User], which yields objects as fields fill in: the README's example prints User(name=None, age=None), then User(name="John", age=None), then the complete object.

Nested models are handled without extra configuration. A User containing List[Address] is converted into the nested schema automatically. The dependency list in pyproject.toml shows what this costs: openai>=2.0.0,<4.0.0, pydantic<3.0.0,>=2.8.0, pydantic-core, jiter, tenacity, jinja2 and typer. Instructor is not a thin shim over httpx. It ships a validation and retry stack, and it pins openai to a major-version range.

## Installing Instructor and running a first extraction

The README gives the install as a single pip command, with uv and poetry as alternatives. Python support in pyproject.toml is >=3.9 and <4.0.

```bash
pip install instructor
```

After that, define a model and point a provider at it. The README's first example uses openai/gpt-4o-mini. The provider string is the part to get right: it selects the backend, and the API key can be passed as an api_key argument instead of an environment variable.

```python
import instructor
from pydantic import BaseModel

class User(BaseModel):
    name: str
    age: int

client = instructor.from_provider("openai/gpt-4o-mini")
user = client.chat.completions.create(
    response_model=User,
    messages=[{"role": "user", "content": "John is 25 years old"}],
)

print(user)  # User(name='John', age=25)
```

What you should see is a User instance, not a dict and not a JSON string. To exercise the retry path, add a validator that rejects negative ages and pass max_retries=3. The README's own example does exactly this with a field_validator on age that raises ValueError('Age must be positive'). If the model returns -5, Instructor resends the request with that error text rather than raising on the first failure.

Swapping providers means changing one string. The README lists anthropic/claude-3-5-sonnet, google/gemini-pro, ollama/llama3.2 and groq/llama-3.1-8b-instant, and notes that api_key can be supplied per client, for example instructor.from_provider("anthropic/claude-3-5-sonnet", api_key="sk-ant-...").

## Where Instructor stops being the right tool

Retries are not free. Each validation failure is another round trip, and a model that consistently misreads a field will burn max_retries calls before raising. There is no documented backoff schedule in the README, and no documented ceiling on how many tokens a retry loop can consume. If your prompt is long and your schema is strict, the cost profile is the model's, not the library's.

The retry loop also assumes the model can act on the error message. Smaller local models reached through ollama/... may not. Nothing in the documented interface compensates for a model that cannot follow a schema, and a validator that rejects a value the model considers reasonable will simply fail repeatedly.

The README's own framing is the clearest limitation. Instructor keeps schema-first flows simple and cheap, and the project directs richer agent runs, built-in observability and shareable traces elsewhere. If you need typed tools, replayable datasets, evals or production dashboards, you are outside what this README claims. The homepage at python.useinstructor.com is the place to check for anything the README leaves out, such as rollback behaviour on a failed extraction or how retries interact with streaming.

## Instructor compared with PydanticAI and hand-rolled function calling

The honest comparison is the one the README makes. PydanticAI is the official agent runtime from the Pydantic team, and the README says it uses the same Pydantic models while adding typed tools, replayable datasets, evals and production dashboards. So the difference is not the model definition. It is the runtime around it. Instructor takes a Pydantic model and returns a validated object from one call. PydanticAI takes the same model and builds an agent loop with tools and observability on top. If your code is a pipeline of extraction steps, Instructor is the smaller dependency. If your code is an agent that decides what to do next, the README points you at PydanticAI instead.

The other alternative is doing it yourself, which the README illustrates with a tools list and a manual json.loads. That approach has no extra dependency beyond the provider SDK, and it gives you full control over the retry prompt. What you give up is the validator-driven retry loop, the Partial streaming wrapper, and the provider abstraction that lets the same create call run against OpenAI, Anthropic, Google, Ollama and Groq. Whether that trade is worth a dependency is a question about how many providers you actually call.

## Maintenance, version pinning and the MIT licence

The repository is not archived, and the last push was on 2026-09-09. Releases are close together: v1.15.4 on 2026-06-28, v1.16.0 on 2026-08-27, and v1.17.0 on 2026-09-09. pyproject.toml lists the package version as 1.17.1, slightly ahead of the newest tagged release. The upgrade cost sits mostly in the openai pin, which is openai>=2.0.0,<4.0.0, and in pydantic<3.0.0,>=2.8.0. A major release of either dependency will require a coordinated upgrade here, and the changelog at CHANGELOG.md is the file to read before you bump.

The licence is MIT, declared in both LICENSE and the pyproject.toml license field. That permits commercial use and modification, but it also means no warranty and no support obligation from the maintainers. Nothing in the repository obliges anyone to fix a provider regression on your schedule. If you depend on Instructor in production, the practical question is whether you can patch around a broken provider adapter yourself. This is a description of the licence terms, not legal advice.

## Conclusion

Adopt Instructor when the job is extraction, classification or any schema-first call where you already have a Pydantic model and want the provider layer to stay thin. Skip it if you need typed tools, replayable datasets, evals and dashboards in one runtime; the README itself points that work at PydanticAI. Before committing, run one of your real prompts through instructor.from_provider with your own model and a field_validator that can fail, and confirm the retry behaviour and error text you get back.

## FAQ

### How to install Instructor?

The README gives pip install instructor as the install command, with uv add instructor and poetry add instructor as alternatives. The package requires Python >=3.9 and <4.0 according to pyproject.toml.

### How to use Instructor in Python?

Define a Pydantic model, call instructor.from_provider with a provider string such as openai/gpt-4o-mini, then pass response_model to client.chat.completions.create. The README's example returns a User instance directly instead of a JSON string.

### Which providers does Instructor support?

The README lists OpenAI, Anthropic, Google, Ollama and Groq through the same from_provider interface, with examples such as anthropic/claude-3-5-sonnet, google/gemini-pro and ollama/llama3.2. API keys can be passed as an api_key argument rather than an environment variable.

### Does Instructor retry when validation fails?

Yes. The README states that failed validations are automatically retried with the error message, and its example passes max_retries=3 alongside a field_validator that rejects negative ages.

### What is the difference between Instructor and PydanticAI?

The README describes Instructor as the choice for fast extraction and keeps schema-first flows simple and cheap, while directing users to PydanticAI when they need richer agent runs, typed tools, replayable datasets, evals and production dashboards. Both use the same Pydantic models.

## Sources

- [567-labs/instructor on GitHub](https://github.com/567-labs/instructor)
- [License: MIT](https://github.com/567-labs/instructor/blob/main/LICENSE)
- [Project website](https://python.useinstructor.com/)
- [README](https://github.com/567-labs/instructor/blob/main/README.md)
- [Releases](https://github.com/567-labs/instructor/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/567-labs-instructor
