Building Your First AI Agent with Pydantic AI: A Step-by-Step Tutorial
Build your first AI agent with Pydantic AI in 4 easy steps. Learn agents, structured output, tools, and streaming with practical code examples.
Introduction
Pydantic AI makes building AI agents surprisingly simple. In this tutorial, you will create a functional agent that can search the web, answer questions, and provide structured output — all in under 50 lines of Python. If you have used FastAPI, the patterns will feel immediately familiar.
Prerequisites
Before starting, make sure you have Python 3.9+ installed. The only external dependency you need is Pydantic AI itself:
pip install pydantic-ai
Optionally, set up an API key for your preferred LLM provider (OpenAI, Anthropic, Gemini, etc.). Pydantic AI is model-agnostic, so the same code works with any provider.
Step 1: Your First Agent
Create a file called agent.py and add the following:
from pydantic_ai import Agent
# Define a simple agent
agent = Agent(
"openai:gpt-4o",
system_prompt="You are a helpful assistant that provides concise answers."
)
# Run the agent
result = agent.run_sync("What is Pydantic AI?")
print(result.data)
Run it with python agent.py. That is all it takes to get started — Pydantic AI handles model selection, prompt formatting, and response parsing automatically.
Step 2: Adding Structured Output
One of Pydantic AI's superpowers is type-safe structured output. Define a Pydantic model for your response:
from pydantic import BaseModel
from pydantic_ai import Agent
class WeatherResponse(BaseModel):
location: str
temperature: float
conditions: str
humidity: int | None = None
weather_agent = Agent(
"openai:gpt-4o",
result_type=WeatherResponse,
system_prompt="Extract weather information from the user's query."
)
result = weather_agent.run_sync("What is the weather in Tokyo?")
print(f"Location: {result.data.location}")
print(f"Temperature: {result.data.temperature}°C")
The agent automatically returns validated, typed data. If the model produces invalid output, Pydantic AI retries with validation error feedback — no manual parsing required.
Step 3: Adding Tools
Agents become powerful when they can call tools. Here is an agent with a custom tool:
from pydantic_ai import Agent, RunContext
agent = Agent("openai:gpt-4o")
@agent.tool
def get_stock_price(ctx: RunContext, symbol: str) -> str:
"""Get the current stock price for a given symbol."""
# In production, call a real API here
return f"${symbol}: $245.30"
result = agent.run_sync("What is the stock price of AAPL?")
print(result.data)
Pydantic AI automatically generates JSON schema from your function signatures, handles tool call routing, and validates arguments on the fly. You can also flag tools for human approval using deferred tool patterns.
Step 4: Streaming and Observability
For real-time applications, you can stream structured output:
async with agent.run_stream("Explain quantum computing") as result:
async for message in result.stream():
print(message, end="", flush=True)
For observability, pass a Logfire instance:
from pydantic_ai import Agent
from pydantic_ai.logfire import configure_logfire
configure_logfire() # Enables tracing, evals, and cost tracking
Conclusion
You have just built your first AI agent with Pydantic AI — complete with tools, structured output, and streaming. The framework's type-safe design means your IDE provides autocomplete for everything, and many errors are caught before your code ever runs. To learn more, visit the official documentation at ai.pydantic.dev.