# Pydantic AI

Pydantic AI is a Python agent framework from the Pydantic team, built around type safety, validated structured outputs, dependency injection and model-agnostic design.

## Overview

Pydantic AI is an open-source Python framework for building agents and other applications on language models. It comes from the team behind Pydantic, the widely used Python library for data validation. Its aim is to make building with models feel like ordinary, well-typed Python: you declare what goes in, what comes out and which tools are available, and the framework checks the types and validates the data at every step.

Three ideas define it. First, outputs are validated: you tell the agent which data shape to return, and if the model's answer does not fit, the error goes back to the model so it can try again. Second, dependencies are injected: tools receive a typed context holding things like a database connection or the current user, so tools are easy to test. Third, it is model-agnostic: the same agent code can run on models from many providers.

An everyday comparison is a well-designed tax form. Each box says exactly what goes in it: a date, an amount, a yes or no. If you write a word where a number belongs, the clerk hands the form back and asks you to fix it. Pydantic AI treats model output the same way. The model must fill in the boxes correctly before the result is accepted.

## What it is

Pydantic AI is a library you install with pip. It is MIT-licensed and builds on Pydantic models for schemas and validation.

| Part | What it does |
|---|---|
| Agent | The main object: a model, instructions, tools, an output type and a dependency type |
| Output type | The data shape the final answer must match, often a Pydantic model |
| Dependencies | A typed object passed to tools and instructions at run time |
| Run context | The object tools receive, giving access to dependencies and run details |
| Tools | Python functions the model can call, with schemas built from type hints and docstrings |
| Toolsets | Groups of tools, including tools from MCP servers |
| Models and providers | Adapters for many model vendors and for local or self-hosted models |
| Message history | The record of a conversation, which can be passed to the next run |
| Graphs | A typed state-machine library for complex control flow |
| Evals | A companion library for testing agents against datasets |
| Durable execution | Integrations that let long-running agents survive failures and restarts |

## Where it came from

Pydantic was created by Samuel Colvin and became a core part of many Python projects, including the validation layer of several model provider SDKs. In late 2024 the Pydantic team released Pydantic AI, arguing that many agent frameworks did not give Python developers the type safety and plain-code feel they were used to.

On 4 September 2025 the team released version 1.0, after about nine months of public use and feedback, with a promise of API stability. That release highlighted durable execution through Temporal, human approval for tool calls, and observability through OpenTelemetry and Pydantic Logfire, the team's monitoring product. On 23 June 2026 Pydantic AI 2.0 shipped and became the current major version. The project also grew companion libraries: `pydantic-graph` for state machines and `pydantic-evals` for testing.

## How it works

### Step 1: Create an agent

You create an agent with a model name, instructions, an output type and a dependency type. The output type can be a simple type, such as a string or a list of integers, or a Pydantic model with several fields. The dependency type describes what tools will need at run time.

### Step 2: Register tools

You decorate functions as tools. Pydantic AI reads the function's parameters and docstring to build the schema the model sees. A tool that needs dependencies takes a run context as its first argument. For example, a `lookup_order` tool can read the database client from the context instead of from a global variable.

### Step 3: Run the agent

You call the agent with a prompt and the actual dependencies. Runs can be synchronous, asynchronous or streamed. The framework sends the prompt and tool schemas to the model and enters the tool loop: the model asks for a tool, the framework validates the arguments, runs the tool and returns the result.

### Step 4: Validate the output

When the model produces a final answer, Pydantic validates it against the output type. Depending on the model, the output is requested through a tool call, through the provider's native [structured outputs](/tools/structured-outputs) feature, or through prompting. If validation fails, the validation error is sent back to the model with a request to correct it, up to a retry limit. You can add your own output validators for checks that the schema cannot express, such as "the end date must be after the start date".

### Step 5: Observe and test

Pydantic AI emits OpenTelemetry traces, so you can follow every model call and tool call in Logfire or any compatible backend; see [OpenTelemetry](/tools/opentelemetry). For testing, you can replace the real model with a test model or a function model that returns fixed answers. This makes unit tests fast, cheap and repeatable. The evals library runs agents over datasets with scoring.

### Step 6: Scale up

For complex flows, the graph library defines nodes and edges with typed state. For long tasks, durable execution integrations save progress so a crash does not lose the work. Tools can be marked as needing approval, so a person must confirm before the call runs.

## Key concepts and terms

| Term | Meaning |
|---|---|
| Agent | The object that holds model, instructions, tools and types |
| Output type | The schema the final answer must satisfy |
| Dependency injection | Passing resources to tools at run time instead of using globals |
| `RunContext` | The object a tool receives with dependencies and run information |
| Tool | A function the model can call |
| Toolset | A group of tools, possibly from an MCP server |
| Output validator | Extra custom checks on the final output |
| Retry | Sending a validation error back so the model can fix its answer |
| Test model | A fake model used for fast, deterministic tests |
| Logfire | Pydantic's observability product, built on OpenTelemetry |
| Durable execution | Running agents so they survive failures and resume |

## A worked example

This scenario is illustrative. A property management company wants to turn tenant emails into maintenance tickets.

1. The team defines a `Ticket` model with fields: `unit` (string), `category` (one of plumbing, electrical, heating, other), `urgency` (low, medium, high) and `summary` (string, at most 200 characters).
2. They create an agent with `Ticket` as its output type and a dependency type that holds a database client.
3. A tool `get_unit_history(unit)` reads previous tickets for that unit through the run context.
4. An output validator rejects any ticket marked "high" urgency unless the summary mentions water, gas, power loss or no heating, and asks the model to reconsider.
5. In tests, they swap in a test model and check that the code path from email to database insert works without calling a real model.
6. On 400 historical emails, they compare the agent's category with the human-assigned category. The agent agrees on 372, or 93 per cent. Most disagreements are between "heating" and "plumbing" for radiator leaks, so they add one sentence to the instructions.

Because every ticket is validated, the database never receives a missing field or an unknown category.

## Strengths and limitations

**Strengths:**

- Strong typing and validated outputs reduce a whole class of runtime errors.
- Dependency injection makes tools clean and easy to unit test.
- Works with many model providers through one interface.
- Test models make fast, deterministic tests possible.
- OpenTelemetry tracing and optional Logfire integration.
- Durable execution, tool approval, graphs and evals for production needs.

**Limitations:**

- Python only.
- Less opinionated about multi-agent structure than role-based frameworks.
- Strict validation can cause extra retries, and so extra cost, with weaker models.
- A major version change in 2026 means older examples may need updating.
- Getting the full benefit requires comfort with type hints and Pydantic models.

## How it compares with alternatives

| Option | Strength | Trade-off |
|---|---|---|
| Pydantic AI | Type safety, validated outputs, dependency injection | Python only, fewer multi-agent conventions |
| [LangGraph](/tools/langgraph) | Mature graphs with checkpoints | More concepts, looser typing |
| [CrewAI](/tools/crewai) | Role-based crews and flows | Less type-focused |
| [OpenAI Agents SDK](/tools/openai-agents-sdk) | Minimal primitives, handoffs | Best with OpenAI models |
| [DSPy](/tools/dspy) | Optimises prompts against a metric | Different goal: tuning, not app structure |

## Practical guidance and best practices

1. Define an output model for every agent whose result feeds code.
2. Keep output models small and clear; use enums for fixed choices.
3. Pass resources through dependencies, never through global variables.
4. Write unit tests with a test model before calling real models.
5. Add output validators for business rules the schema cannot express.
6. Set a sensible retry limit and monitor how often retries happen.
7. Require approval for tools with side effects; see [human-in-the-loop](/tools/human-in-the-loop).
8. Turn on tracing early and review failed runs regularly.

## Common mistakes

- Using a free-text string output and then parsing it with regular expressions.
- Designing huge, deeply nested output models that models fill unreliably.
- Hiding database connections in globals, which makes tools hard to test.
- Ignoring retry counts, so validation failures quietly double the cost.
- Copying examples written for an older major version without checking the current API.

## Frequently asked questions

### What is Pydantic AI?

Pydantic AI is an open-source Python framework from the Pydantic team for building agents and model-powered applications with type safety, validated outputs, dependency injection and support for many model providers.

### Is Pydantic AI the same as Pydantic?

No. Pydantic is the data validation library. Pydantic AI is a separate agent framework that uses Pydantic for schemas and validation.

### Which models does it support?

It supports models from many providers through a common interface, including major commercial APIs and local or self-hosted models. Some features, such as native structured output, depend on what the provider offers.

### What happens if the model returns invalid output?

Pydantic AI validates the output against your type. If it fails, the error is sent back to the model with a request to fix it, up to a retry limit, after which an error is raised.

### Can it build multi-agent systems?

Yes. One agent can call another from inside a tool, agents can hand control to each other in your code, and the graph library handles complex flows. See [multi-agent systems](/tools/multi-agent-systems).

### How do I test a Pydantic AI agent?

Replace the real model with a test model or function model for unit tests, then use the evals library or your own datasets to measure quality with real models. See [evals](/tools/evals).

## Glossary

- Agent: the core object combining model, tools and types.
- Output type: the schema for the final answer.
- Dependency: a resource passed to tools at run time.
- Run context: the object tools receive.
- Validator: a function that checks data.
- Retry: asking the model to correct an invalid answer.
- Toolset: a collection of tools.
- Logfire: Pydantic's observability platform.
- Durable execution: resumable, failure-tolerant runs.

## Summary

Pydantic AI brings the habits of well-typed Python to agent development. You declare the output shape, the dependencies and the tools, and the framework validates everything, sending errors back to the model when its answer does not fit. It reached 1.0 in September 2025 and 2.0 in June 2026, adding durable execution, tool approval, tracing and evals. Use small, clear output models, inject dependencies, test with fake models first and watch retry rates.
