Back to AI App Dev Series

PydanticAI SDK Track Part 1: Platform Setup & First Agent

May 24, 2026 Wasil Zafar 35 min read

Install PydanticAI, configure the Gateway proxy, create your first type-safe agent with structured output, understand the agent run lifecycle, and explore debugging with Logfire.

Table of Contents

  1. Installation & Environment Setup
  2. Your First PydanticAI Agent
  3. PydanticAI Gateway
  4. Agent Run Lifecycle
  5. Troubleshooting & Getting Help
What You’ll Learn: PydanticAI brings the type safety and validation power of Pydantic to AI agent development. This article gets you from installation to your first working agent — with type-checked inputs and outputs, model-agnostic design, and the patterns that make PydanticAI unique among agent frameworks. Think of it as FastAPI for AI agents: declarative, typed, and developer-friendly.

1. Installation & Environment Setup

PydanticAI is a Python agent framework built by the creators of Pydantic. It provides type-safe, model-agnostic AI agent development with first-class support for structured outputs, dependency injection, and streaming. Requires Python 3.9+.

Python Version: PydanticAI requires Python 3.9 or higher. It leverages modern typing features extensively. Ensure your environment meets this requirement before installing.

Install the full package with all optional provider dependencies:

# Install PydanticAI with all optional dependencies
pip install pydantic-ai

# Or install with specific provider support only
pip install 'pydantic-ai[openai]'
pip install 'pydantic-ai[anthropic]'
pip install 'pydantic-ai[google]'

# Install multiple providers
pip install 'pydantic-ai[openai,anthropic,google]'

1.1 Verifying Installation

Confirm PydanticAI is installed correctly and check the version:

import pydantic_ai
print(f"PydanticAI version: {pydantic_ai.__version__}")

from pydantic_ai import Agent
print("Agent class imported successfully")

# Check Pydantic is available (core dependency)
import pydantic
print(f"Pydantic version: {pydantic.__version__}")
Dependency Note: PydanticAI installs Pydantic v2 as a core dependency. If you have existing code using Pydantic v1, you may need to migrate. The pydantic-ai package also installs httpx for async HTTP and logfire-api for optional observability integration.

2. Your First PydanticAI Agent

2.1 Basic Agent Creation

An Agent in PydanticAI is the core building block. It wraps a model, system prompt, tools, and output type into a reusable, type-safe unit:

from pydantic_ai import Agent

# Create a simple agent with a system prompt
agent = Agent(
    "openai:gpt-4o",
    system_prompt="You are a helpful assistant that provides concise answers."
)

# Run the agent synchronously
result = agent.run_sync("What is the capital of France?")
print(result.data)
# Output: The capital of France is Paris.

2.2 Structured Output Agent

The real power of PydanticAI is type-safe structured output. Define a Pydantic model and the agent will return validated, typed data:

from pydantic_ai import Agent
from pydantic import BaseModel

# Define a structured output type
class WeatherReport(BaseModel):
    city: str
    temperature_celsius: float
    condition: str
    humidity_percent: int
    wind_speed_kmh: float

# Create an agent with structured output
weather_agent = Agent(
    "openai:gpt-4o",
    result_type=WeatherReport,
    system_prompt="You are a weather reporting assistant. Return structured weather data."
)

# Run and get typed result
result = weather_agent.run_sync("What's the weather like in Tokyo today?")
report = result.data

# Full type safety — IDE autocomplete works here
print(f"City: {report.city}")
print(f"Temperature: {report.temperature_celsius}°C")
print(f"Condition: {report.condition}")
print(f"Humidity: {report.humidity_percent}%")
print(f"Wind: {report.wind_speed_kmh} km/h")
Type Safety Guarantee: When you specify result_type=WeatherReport, PydanticAI instructs the model to return JSON matching the schema, then validates the response through Pydantic. If validation fails, it automatically retries with the error feedback. Your code never receives invalid data.

3. PydanticAI Gateway

3.1 Gateway Configuration

The PydanticAI Gateway acts as a unified proxy for all model providers. It simplifies API key management, adds request logging, and provides rate limiting across providers:

import os
from pydantic_ai import Agent

# Configure the Gateway URL (typically set as environment variable)
os.environ["PYDANTIC_AI_GATEWAY_URL"] = "http://localhost:8000"

# When Gateway is configured, agents route through it automatically
agent = Agent(
    "openai:gpt-4o",
    system_prompt="You are a helpful assistant."
)

# This request goes through the Gateway proxy
result = agent.run_sync("Explain dependency injection in 2 sentences.")
print(result.data)

3.2 Gateway Benefits

The Gateway provides several operational advantages for production deployments:

# Start the PydanticAI Gateway server
pip install pydantic-ai-gateway
pydantic-ai-gateway serve --port 8000

# The Gateway provides:
# - Single API key management (one key for all providers)
# - Request/response logging for debugging
# - Rate limiting and retry logic
# - Cost tracking across providers
# - Model fallback chains
Development Tip: During local development, you can skip the Gateway entirely. Agents will call provider APIs directly using the appropriate environment variables (OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.). The Gateway is most valuable in team and production environments.
Real-World Application

Type-Safe Data Pipeline

A data engineering team replaced their ad-hoc LLM scripts with PydanticAI agents. Every agent has validated inputs and outputs, catching data quality issues at the boundary. Result: pipeline failures from malformed LLM output dropped from 12% to 0.3%.

Data EngineeringType Safety

4. Agent Run Lifecycle

4.1 Run Methods

PydanticAI provides three ways to run an agent, each suited to different contexts:

import asyncio
from pydantic_ai import Agent

agent = Agent(
    "openai:gpt-4o",
    system_prompt="You are a concise assistant."
)

# Method 1: run_sync() — blocking, for scripts and simple apps
result_sync = agent.run_sync("What is 2 + 2?")
print(f"Sync result: {result_sync.data}")

# Method 2: run() — async, for web servers and async apps
async def async_example():
    result = await agent.run("What is the meaning of life?")
    print(f"Async result: {result.data}")
    return result

asyncio.run(async_example())

# Method 3: run_stream() — streaming, for real-time output
async def stream_example():
    async with agent.run_stream("Write a haiku about Python.") as response:
        async for text in response.stream_text():
            print(text, end="", flush=True)
    print()  # Final newline

asyncio.run(stream_example())

4.2 RunResult Attributes

Every agent run returns a RunResult object with rich metadata about the interaction:

from pydantic_ai import Agent

agent = Agent(
    "openai:gpt-4o",
    system_prompt="You are a helpful assistant."
)

result = agent.run_sync("Explain the Liskov Substitution Principle.")

# Access the response data
print(f"Response: {result.data[:100]}...")

# Access conversation messages (full history)
messages = result.all_messages()
print(f"\nMessage count: {len(messages)}")
for msg in messages:
    print(f"  - {msg.kind}: {str(msg)[:80]}...")

# Access token usage statistics
usage = result.usage()
print(f"\nToken usage:")
print(f"  Request tokens: {usage.request_tokens}")
print(f"  Response tokens: {usage.response_tokens}")
print(f"  Total tokens: {usage.total_tokens}")
Lifecycle Summary: Agent creation (define model, prompt, tools, output type) → run() / run_sync() / run_stream() → Model generates response → Output validated against result_type → If validation fails, retry with error context → Return typed RunResult.

5. Troubleshooting & Getting Help

PydanticAI integrates with Pydantic Logfire for comprehensive debugging and observability:

import logfire
from pydantic_ai import Agent

# Configure Logfire for debugging (sends traces to Logfire dashboard)
logfire.configure()

agent = Agent(
    "openai:gpt-4o",
    system_prompt="You are a helpful assistant."
)

# All agent runs are now traced in Logfire
result = agent.run_sync("What causes a KeyError in Python?")
print(result.data)

# Logfire captures:
# - Full request/response payloads
# - Token usage and latency
# - Tool calls and their results
# - Retry attempts on validation failures
# - Streaming chunk timing

Common issues and their solutions:

# Issue 1: ModelNotFoundError
# Solution: Ensure the model string is correct
# Valid formats: "openai:gpt-4o", "anthropic:claude-sonnet-4-20250514", "google:gemini-2.0-flash"

# Issue 2: API key not found
# Solution: Set the appropriate environment variable
import os
os.environ["OPENAI_API_KEY"] = "sk-..."  # For OpenAI models
os.environ["ANTHROPIC_API_KEY"] = "sk-ant-..."  # For Anthropic models
os.environ["GOOGLE_API_KEY"] = "AI..."  # For Google models

# Issue 3: ValidationError on result
# Solution: Check your result_type model matches what the LLM can produce
# Use Optional fields for data the model might not always provide
from pydantic import BaseModel
from typing import Optional

class FlexibleOutput(BaseModel):
    answer: str
    confidence: Optional[float] = None  # Model may not always provide this
    sources: list[str] = []  # Default empty list if not provided
Community Resources: PydanticAI documentation at ai.pydantic.dev, GitHub issues for bug reports, and the Pydantic Discord server for community support. Logfire provides a free tier for development debugging.
Try It Yourself: Build a ‘movie recommender’ agent that takes a genre and mood as typed inputs (using a Pydantic model) and returns a structured recommendation with title, year, director, and why_recommended fields. Test with 5 different genre/mood combinations and verify the output validates against your Pydantic model every time.

Next in the PydanticAI SDK Track

In Part 2: Agents, Dependencies & Output, we’ll deep dive into agent architecture — typed dependency injection for runtime context, structured output types with Pydantic models, capabilities configuration, and result validation patterns.