Instructor
Get validated, typed JSON from any LLM using plain Pydantic models, with automatic retries.
- Source repo
- 567-labs/instructor
- Stars
- ★ 14k
- Last updated
- 1d ago
- License
- MIT
- Primary language
- Python
- FA score
- 55/100 · Major gaps
At a glance
- How it runs
- Works with
- Universal · cross-platformOpenAI API · Claude API
- Cost
- Free software; you pay for model usage
- Setup effort
- Low · running in minutes
- You'll need
- Typical use
- A Python backend engineer extracting names, ages and addresses from support tickets or emails into a database.
- Not a fit if
- Teams expecting a full agent runtime with tools and observability built in
- Non-Python stacks that cannot adopt Pydantic-based models
- Source review
- 55/100 · Major gaps
What does this agent do, and when should you use it?
Instructor is a Python library that turns free-form LLM responses into Pydantic-validated structured objects. Developers define a BaseModel, create a patched client with instructor.from_provider (covering OpenAI, Anthropic, Google, Ollama and more), and call client.chat.completions.create(response_model=User, messages=[...]) to get a typed instance back. Validation failures are retried automatically with the error message via max_retries, Partial[Model] with stream=True yields progressively filled objects, and nested models are handled recursively. It is MIT-licensed and installed through pip, uv or poetry as a dependency inside your own Python application, not as a standalone server or hosted endpoint.
Instructor reads a caller-defined Pydantic BaseModel and uses it to constrain LLM output. A client is created with instructor.from_provider("openai/gpt-4o-mini"), then client.chat.completions.create(response_model=User, messages=[...]) generates or injects the corresponding schema or function-calling parameters, sends the request, parses the response and constructs the Pydantic instance. When field validators or types fail, it re-requests the model with the error message up to max_retries times. Passing response_model=Partial[User] with stream=True yields objects whose fields fill in incrementally. Nested models such as List[Address] are handled recursively without hand-written JSON Schema.
- A Python backend engineer extracting names, ages and addresses from support tickets or emails into a database.
- A data team turning unstructured documents into structured records such as product name, price and stock status.
- An application developer who wants one extraction code path while switching between OpenAI, Anthropic and Ollama.
- A product team streaming partially generated structured objects to a frontend for progressive display.
- A quality engineer enforcing Pydantic field rules, such as positive ages, on model output.
- A privacy-sensitive project running local models through Ollama so data stays on the internal network.
How do you install or deploy this agent?
You need a Python environment and credentials for the model provider you call. Install with a package manager:
pip install instructorOr with uv / poetry:
uv add instructor
poetry add instructorAfter installation, provide an API key for the chosen provider (for example OPENAI_API_KEY) or run a local model service such as Ollama.
How do you use this agent?
Define a Pydantic model, point from_provider at a provider/model, and pass response_model:
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)You can pass an API key directly or switch providers:
client = instructor.from_provider("anthropic/claude-3-5-sonnet", api_key="sk-ant-...")
client = instructor.from_provider("ollama/llama3.2")Enable automatic retries and streaming:
user = client.chat.completions.create(
response_model=User,
messages=[{"role": "user", "content": "..."}],
max_retries=3,
)
from instructor import Partial
for partial_user in client.chat.completions.create(
response_model=Partial[User],
messages=[{"role": "user", "content": "..."}],
stream=True,
):
print(partial_user)What are this agent's strengths and limitations?
- Pydantic-first design gives type hints, IDE completion and field-level validation for free.
- Failed validations are retried automatically with the error message, removing hand-written parsing and error handling.
- The from_provider interface covers OpenAI, Anthropic, Google, Ollama and Groq with the same call shape, making provider switches cheap.
- Partial[Model] with stream=True yields progressively filled objects for real-time display.
- Nested models are handled recursively, so complex JSON Schema is not written by hand.
- MIT-licensed and installable via pip, uv or poetry directly into existing Python projects.
- It is a Python library first; ports for TypeScript, Ruby, Go, Rust and Elixir are separate implementations whose parity must be checked.
- Real usage depends on an external LLM provider, so you need network access, an API key and per-token spend.
- The README documents no built-in observability, tool orchestration or eval tooling; richer agent workflows need PydanticAI or custom code.
- Provider SDK and model-name changes remain the adopter's responsibility to track and adapt.
How does this agent compare with similar options?
The README explicitly contrasts Instructor with three alternatives: raw JSON mode, which lacks automatic validation, retries, streaming and nested-object support; LangChain/LlamaIndex, which Instructor positions as broader and heavier than its focused extraction role; and custom in-house solutions, where it cites battle-testing across many developers and edge cases. It also recommends PydanticAI when you need richer agent runs, built-in observability or shareable traces.
Key facts side by side with the most closely related agents.
| Agent | Source review | Form / cost | Stars | Updated | Language | Full support on |
|---|---|---|---|---|---|---|
| Instructor This agent | 55 · Major gaps | Library / SDKFree + model costs | ★ 14k | 1d ago | Python | OpenAI API · Claude API |
| Adaline Gateway | 69 · Some gaps | Library / SDKFree + model costs | ★ 607 | 2mo ago | TypeScript | OpenAI API · Claude API |
| Pydantic AI | 65 · Some gaps | Library / SDKFree + model costs | ★ 21k | today | Python | OpenAI API · Claude API |
| Mirascope | 55 · Major gaps | Library / SDKFree + model costs | ★ 1.5k | today | Python | Claude API |
How does FollowAgents rate this agent?
Why each dimension lost points
Trust: data-flow transparency is moderate — usage.md documents cumulative token accounting, cache hits, and provider billing differences, and cli/usage.md warns about legacy estimates; dependencies are bounded in pyproject.toml. But least_privilege scores 1: the library patches clients and auto-retries by default, README passes api_key in plaintext without key-management guidance. user_confirmation scores 1: auto-retry and cache hits have no explicit confirmation. sensitive_data_handling scores 1: no PII/log redaction guidance. external_effects scores 1: real provider calls incur cost with no cost guardrails. rollback scores 1: no rollback/undo mechanism described. source_attribution scores 2: LICENSE and author/contributor links are clear.
Reliability: self_consistency scores 2 — docs and code structure broadly align, but README and getting-started mix client.create and client.chat.completions.create styles, a minor inconsistency. dependency_availability scores 2 — bounded versions in pyproject.toml and a locked requirements.txt, but no stated vulnerability mitigation. failure_messages scores 2 — docs show IncompleteOutputException and validation-retry feedback, adequate for ordinary use.
Adaptability: audience_and_scenarios scores 2 — covers multiple providers, multi-language implementations, FastAPI/async. capability_boundaries scores 2 — README explicitly recommends PydanticAI for richer agent runs, a clear boundary. trigger_precision scores 1 — as a library rather than an agent, triggering depends on the caller and docs do not systematically explain when to use which mode. environment_fit scores 2 — declares Python 3.9+ and per-provider extras.
Convention: information_architecture scores 2 — clear docs tree. install_notes scores 2 — install and extras well documented. naming_stability scores 1 — README and getting-started mix from_provider with legacy patch/from_openai, and repo URLs differ between 567-labs and jxnl. examples_and_faq scores 2 — rich FAQ and examples. known_limitations scores 2 — usage.md and cli/usage.md explicitly list billing and accumulation limits. license scores 3 — full MIT text. versioning_changelog scores 1 — version in pyproject but no CHANGELOG. maintenance_responsibility scores 1 — maintainer emails listed but publisher identity unverified and update path unclear.
Effectiveness: output_usability scores 3 — returns typed Pydantic objects directly. marginal_value scores 2 — clear gain over manual JSON parsing, but competitive space. cost_benefit scores 2 — docs mention token optimization and caching, but auto-retry can amplify cost with no guardrails.
Verifiability: claim_traceability scores 1 — README claims 3M+ monthly downloads, 10K+ stars, 1000+ contributors, and usage by OpenAI/Google etc., none backed by in-repo evidence. cross_source_corroboration scores 1 — tests exist but were not executed in this static review, so no cross-confirmation. fact_inference_separation scores 1 — marketing claims and factual statements are mixed without clear separation.
- README claims about downloads, stars, contributor counts, and big-company usage lack in-repo evidence and are marketing statements, not reliability signals.
- The library auto-retries and patches clients by default, which can amplify API cost; README examples pass api_key in plaintext, so key management and least privilege are the caller's responsibility.
- Repository URLs differ between 567-labs and jxnl, publisher identity is unverified, and the update/maintenance path is unclear.
- Docs mix from_provider with legacy patch/from_openai styles; watch naming stability when migrating.
- This is a static review; no tests were executed, so test quality and determinism are unverified.