guias·Fabricio Telles

PydanticAI: Guia Definitivo — Agentes Type-Safe em Python

Guia completo sobre PydanticAI: o framework da equipe Pydantic para criar agentes IA type-safe com dependency injection, durable execution e validação...

TL;DR

PydanticAI é o framework de agentes IA criado pela mesma equipe por trás do Pydantic — a biblioteca de validação usada internamente pela OpenAI, Google e Anthropic. A proposta é trazer a experiência “FastAPI” para o mundo dos agentes: type hints definem o contrato, o framework cuida da validação, e você foca na lógica de negócio. Com v2 lançada em junho de 2026, o framework agora inclui capabilities (bundles composáveis de tools + hooks + instruções), Harness (baterias para produção), suporte nativo a streaming, multi-agent via pydantic-graph, e integrações com Temporal/DBOS para durable execution. Se você é dev Python e quer agentes que respeitem tipos, sejam testáveis e rodem em produção sem gambiarras — PydanticAI é a resposta.

┌─────────────────────────────────────────────────┐
│          SPIDER CHART — PydanticAI v2           │
├─────────────────────────────────────────────────┤
│                                                 │
│            Type Safety ★★★★★                    │
│                  ╱╲                             │
│    DX/Ergon. ★★★★★  ╲  Observabilidade ★★★★☆   │
│              ╱        ╲                         │
│   Streaming ★★★★☆     Multi-Agent ★★★☆☆        │
│              ╲        ╱                         │
│   Ecosystem ★★★☆☆  ╱  Durable Exec ★★★★☆      │
│                  ╲╱                             │
│          Produção-Ready ★★★★☆                   │
│                                                 │
│  Escala: ★ = básico → ★★★★★ = referência       │
└─────────────────────────────────────────────────┘

8 Eixos avaliados:

EixoScoreJustificativa
Type Safety5/5Validação Pydantic nativa, output_type, deps_type tipados
Developer Experience5/55 linhas para um agente funcional; DX score 8/10 no benchmark Nextbuild
Streaming4/5Streaming nativo com validação parcial de schema; AG-UI e Vercel protocol
Multi-Agent3/5Via pydantic-graph e agent-as-tool; sem delegação autônoma tipo CrewAI
Ecosistema3/5~15x menor que LangChain; crescendo com Harness e comunidade
Durable Execution4/5Temporal, DBOS, Kitaru integrados; capability layer em progresso
Observabilidade4/5OpenTelemetry nativo via Logfire; sem vendor lock-in
Production-Ready4/5MIT, model-agnostic (20+ providers), UsageLimits, 100% test coverage

Overview — O Que É PydanticAI

Pense no PydanticAI como o FastAPI dos agentes de IA. Se FastAPI pegou type hints do Python e transformou em documentação automática + validação + DX incrível para APIs web, PydanticAI faz a mesma coisa para interações com LLMs.

O framework foi criado por Samuel Colvin e a equipe da Pydantic — sim, a mesma biblioteca que a OpenAI, Anthropic e Google usam internamente para validação de dados nos seus SDKs. Isso não é coincidência. O insight fundamental é: se LLMs produzem dados estruturados, esses dados precisam de validação. E ninguém faz validação em Python melhor que o Pydantic.

Pilares Fundamentais

1. Type Safety em Tudo Não é um detalhe de implementação — é a filosofia central. Seu IDE te dá autocomplete, type checkers pegam bugs antes do runtime, e o framework garante que outputs do LLM estejam no formato que você definiu.

2. Dependency Injection de Verdade Tools sem acesso a dependências são inúteis. O PydanticAI tem um sistema completo de DI via RunContext[T] que mantém seus agentes testáveis e desacoplados.

3. Model-Agnostic Suporte a 20+ providers: OpenAI, Anthropic, Google Gemini, Groq, Mistral, AWS Bedrock, Ollama (modelos locais), e mais. Troque o modelo sem mudar uma linha de lógica.

4. Observabilidade Aberta Emissão de dados via OpenTelemetry — funciona com Logfire (da própria Pydantic), mas também com qualquer stack OTel. Sem vendor lock-in.

5. Durable Execution Integração documentada com Temporal, DBOS e Kitaru para agentes que sobrevivem a crashes, fazem retry inteligente e mantêm estado entre execuções.

Evolução: v1 → v2

A v1 (setembro 2025) trouxe estabilidade de API, human-in-the-loop tool approval e durable execution com Temporal. Foram 100+ releases sem breaking changes.

A v2 (junho 2026) introduziu o conceito de capabilities — o primitivo fundamental que unifica tools, hooks, instruções e settings em um bundle composável. Pense em capabilities como plugins inteligentes que podem ler e reescrever o que o modelo vê a cada step do loop.


Tutorial Prático — Seu Primeiro Agente

Vamos do zero ao agente funcional em poucos minutos. Se você já trabalhou com FastAPI ou Pydantic, vai se sentir em casa.

Instalação

# Com uv (recomendado)
uv add pydantic-ai

# Ou com pip
pip install pydantic-ai

Para instalação mínima com um provider específico:

pip install "pydantic-ai-slim[google]"

Configuração do Provider

# Google Gemini (free tier disponível)
export GOOGLE_API_KEY="sua-chave"

# OpenAI
export OPENAI_API_KEY="sua-chave"

# Anthropic
export ANTHROPIC_API_KEY="sua-chave"

Agente Básico — 5 Linhas

from pydantic_ai import Agent

agent = Agent(
    "google:gemini-2.5-flash",
    instructions="Você é um especialista em Python. Responda em uma frase.",
)

result = agent.run_sync("O que é PydanticAI?")
print(result.output)

O formato do modelo é "provider:modelo". O instructions define o system prompt para este agente. O .run_sync() executa de forma síncrona — para produção, use await agent.run() com async/await.

Agente com Output Estruturado

Aqui o PydanticAI brilha de verdade. Em vez de parsear strings, você define um schema e o framework garante que o LLM retorne dados naquele formato:

from pydantic import BaseModel
from pydantic_ai import Agent

class AnaliseRepositorio(BaseModel):
    nome: str
    linguagem_principal: str
    stars: int
    pontos_fortes: list[str]
    pontos_fracos: list[str]

agent = Agent(
    "anthropic:claude-sonnet-4-20250514",
    output_type=AnaliseRepositorio,
    instructions="Analise repositórios open-source com base nas informações fornecidas."
)

result = agent.run_sync("Analise o repositório FastAPI")
repo = result.output  # AnaliseRepositorio tipado!

print(f"{repo.nome} ({repo.linguagem_principal})")
print(f"Stars: {repo.stars:,}")
for ponto in repo.pontos_fortes:
    print(f"  ✓ {ponto}")

O que acontece por baixo: PydanticAI converte AnaliseRepositorio em um JSON Schema, envia ao LLM, valida a resposta com Pydantic, e retorna um objeto tipado. Se a validação falhar, faz retry automático (configurável via output_retries).


Deep Dive — Conceitos Fundamentais

Agent: O Coração do Framework

O Agent é a interface principal. Ele encapsula modelo, instruções, tools, dependencies e output type:

from pydantic_ai import Agent

agent = Agent(
    "openai:gpt-4o",
    instructions="Assistente de análise de dados financeiros.",
    output_type=RelatorioFinanceiro,
    deps_type=DatabaseConnection,
    retries=3,
    output_retries=2,
)

Parâmetros-chave:

  • instructions — System prompt isolado para este agente (não herda de agentes anteriores)
  • system_prompt — System prompt que persiste no histórico entre agentes
  • output_type — Schema Pydantic para validação do output
  • deps_type — Tipo das dependências injetadas
  • retries — Retries globais para o agente
  • output_retries — Retries específicos para validação de output

Modos de execução:

# Síncrono (scripts, testes)
result = agent.run_sync("prompt")

# Assíncrono (produção)
result = await agent.run("prompt")

# Streaming (UIs em tempo real)
async with agent.run_stream("prompt") as stream:
    async for chunk in stream:
        print(chunk, end="")

Tools: Function Calling com Type Safety

Tools são funções Python que o LLM pode invocar. O PydanticAI usa decorators para registrá-las:

import httpx
from pydantic_ai import Agent, RunContext

agent = Agent(
    "google:gemini-2.5-flash",
    instructions="Ajude com informações sobre o clima.",
)

@agent.tool_plain
def buscar_clima(cidade: str) -> dict:
    """Busca a previsão do tempo para uma cidade."""
    response = httpx.get(
        f"https://api.weatherapi.com/v1/current.json",
        params={"key": "API_KEY", "q": cidade}
    )
    return response.json()

Dois decorators disponíveis:

  • @agent.tool_plain — Tool sem acesso ao contexto de execução
  • @agent.tool — Tool com acesso ao RunContext (dependências, retry info, etc.)

A docstring é crucial: o LLM lê para decidir quando e como chamar a tool. Type hints nos parâmetros ajudam o modelo a passar os tipos corretos.

Passando tools no construtor:

agent = Agent(
    "openai:gpt-4o",
    tools=[buscar_clima, converter_moeda, calcular_juros]
)

Dependencies: Injeção de Dependência Elegante

O padrão de DI do PydanticAI é inspirado no FastAPI e resolve um problema real: como dar acesso a banco de dados, APIs e config para suas tools sem usar globals ou hardcoding?

from dataclasses import dataclass
from pydantic_ai import Agent, RunContext

@dataclass
class AppDeps:
    db_connection: AsyncSession
    redis_client: Redis
    api_key: str

agent = Agent(
    "anthropic:claude-sonnet-4-20250514",
    deps_type=AppDeps,
    instructions="Consulte o banco de dados para responder perguntas dos clientes.",
)

@agent.tool
async def buscar_pedido(ctx: RunContext[AppDeps], pedido_id: int) -> str:
    """Busca detalhes de um pedido no banco de dados."""
    async with ctx.deps.db_connection as session:
        pedido = await session.get(Pedido, pedido_id)
        return pedido.to_json() if pedido else "Pedido não encontrado"

# Em produção
deps = AppDeps(
    db_connection=async_session,
    redis_client=redis,
    api_key=os.environ["API_KEY"]
)
result = await agent.run("Qual o status do pedido #4521?", deps=deps)

# Em testes — swap de dependências trivial
with agent.override(deps=MockAppDeps()):
    result = await agent.run("Qual o status do pedido #4521?")

O RunContext[AppDeps] dá type safety completo. Seu IDE sabe exatamente o que ctx.deps contém. E trocar dependências para testes é uma linha.

Result Types: Validação Automática

O PydanticAI suporta múltiplos tipos de output:

# String simples (padrão)
agent = Agent("openai:gpt-4o")

# Modelo Pydantic
agent = Agent("openai:gpt-4o", output_type=MeuModelo)

# Union de tipos (o LLM escolhe qual retornar)
agent = Agent("openai:gpt-4o", output_type=MeuModelo | OutroModelo | str)

# Tipos primitivos
agent = Agent("openai:gpt-4o", output_type=bool)
agent = Agent("openai:gpt-4o", output_type=int)
agent = Agent("openai:gpt-4o", output_type=list[str])

Quando a validação falha, o PydanticAI envia o erro de volta ao LLM com o contexto do que deu errado, dando chance para corrigir. Isso funciona surpreendentemente bem na prática — mas cada retry é uma chamada de API adicional (custo + latência).

Streaming: Respostas em Tempo Real

Streaming é suportado nativamente com validação parcial de schema:

from pydantic_ai import Agent

agent = Agent("openai:gpt-4o", output_type=Artigo)

async with agent.run_stream("Escreva sobre observabilidade") as stream:
    # Stream de texto bruto
    async for text in stream.stream_text():
        print(text, end="", flush=True)

    # Ou stream com validação parcial
    async for partial in stream.stream_structured():
        # partial é um objeto parcialmente preenchido
        if partial.titulo:
            render_titulo(partial.titulo)

O PydanticAI também suporta protocolos de UI stream:

  • AG-UI Protocol (CopilotKit) — para frontends com shared state
  • Vercel AI Data Stream Protocol — para integração com Next.js

Multi-Agent: Coordenação entre Agentes

PydanticAI oferece três padrões para multi-agent:

1. Agent como Tool (delegação simples):

pesquisador = Agent("openai:gpt-4o", instructions="Pesquise informações na web.")
redator = Agent(
    "anthropic:claude-sonnet-4-20250514",
    instructions="Escreva artigos baseados em pesquisas.",
)

@redator.tool_plain
async def pesquisar(query: str) -> str:
    """Pesquisa informações sobre um tópico."""
    result = await pesquisador.run(query)
    return result.output

2. pydantic-graph (workflows complexos):

from pydantic_graph import Graph, Node, Edge

class PesquisaNode(Node):
    async def run(self, state):
        # Executa pesquisa
        ...

class AnaliseNode(Node):
    async def run(self, state):
        # Analisa resultados
        ...

graph = Graph(nodes=[PesquisaNode, AnaliseNode])

3. Capabilities v2 (composição avançada):

from pydantic_ai import Agent
from pydantic_ai.capabilities import Capability, ToolSearch, WebSearch

agent = Agent(
    "anthropic:claude-opus-4-7",
    capabilities=[
        WebSearch(),
        ToolSearch(),  # Descobre tools on-demand
        Capability(
            id="analytics",
            description="Consulta métricas de analytics.",
            toolset=MCPToolset("https://mcp.exemplo.com/analytics"),
            defer_loading=True,  # Carrega só quando necessário
        ),
    ],
)

Capabilities v2 — O Novo Primitivo

O lançamento do PydanticAI v2 em junho de 2026 introduziu capabilities como o conceito central de extensibilidade. Uma capability é um bundle composável que pode incluir:

  • Instructions específicas
  • Tools e toolsets
  • Lifecycle hooks (lêem e reescrevem o que o modelo vê)
  • Model settings

Isso significa que uma extensão inteira — um sistema de memória, um guardrail, um toolkit de coding — alcança todas as camadas do agente através de um único conceito.

from pydantic_ai import Agent
from pydantic_ai.capabilities import Thinking, WebSearch, CodeMode
from pydantic_ai_harness import Memory, Guardrails

agent = Agent(
    "anthropic:claude-opus-4-7",
    capabilities=[
        Thinking(effort="high"),      # Extended thinking unificado entre providers
        CodeMode(),                   # Execução de código sandboxed via Monty
        WebSearch(),                  # Nativo onde o provider suporta, fallback local
        Memory(backend="postgres"),   # Do Harness — memória persistente
        Guardrails(block_pii=True),   # Do Harness — proteção automática
    ],
)

O Harness é o pacote first-party de “baterias” — capabilities prontas para produção como memória, guardrails, context management, file system access e code mode. O split é deliberado: core permanece pequeno e estável; Harness move rápido.


PydanticAI vs. Outros Frameworks

Como o PydanticAI se posiciona no ecossistema de 2026? Aqui vai um comparativo honesto baseado em benchmarks reais:

CritérioPydanticAILangGraphCrewAIMastra
LinguagemPythonPythonPythonTypeScript
DX Score (Nextbuild)8/106/107/108/10
Type SafetyNativoTypedDictLimitadoZod
Multi-AgentVia tools/graphNativo (grafos)Nativo (crews)Agent Networks
Durable ExecutionTemporal/DBOSCheckpointingNenhumInngest
StreamingNativo + AG-UINativoLimitadoNativo
MemóriaManual (UsageLimits)State + checkpointUnified MemoryObservational Memory
Custo Infraestrutura~$390/90dias~$670/90dias~$1,088/90diasN/A
LicençaMITMITMITApache 2.0
ObservabilidadeOTel nativoLangSmithLimitadoCustom

Dado importante do benchmark Nextbuild: O type system do PydanticAI capturou 23 bugs durante desenvolvimento que teriam chegado em produção no LangChain. Isso é o tipo de vantagem que compound ao longo do tempo em projetos reais.


Prós e Contras

✅ Prós

  1. Type safety genuíno — Não é cosmético. IDE, linter e runtime trabalham juntos para prevenir bugs.

  2. DX excepcional — Agente funcional em 5 linhas. Curva de aprendizado mínima se você conhece Python.

  3. Dependency injection de verdade — Testes limpos, desacoplamento real, swap de mocks trivial.

  4. Model-agnostic — 20+ providers, troque sem reescrever lógica. MCP nativo.

  5. Observabilidade open-source — OTel/Logfire sem vendor lock-in.

  6. Custo-eficiente — UsageLimits nativo (cap de tokens, requests, tool calls). Benchmarkado a $390/90 dias vs $1,088 do CrewAI.

  7. 100% test coverage — Exemplos da docs são unit-testados. Raridade no ecossistema.

  8. Validation retries inteligentes — Envia erro de validação de volta ao LLM para autocorreção.

❌ Contras

  1. Ecossistema menor — ~15x menos integrações que LangChain. Você vai encontrar edges não documentados.

  2. Multi-agent não é first-class — Sem roles, goals, delegação autônoma. Precisa wiring manual.

  3. Sem memória built-in — Estado é manual. Sem compressão automática como Mastra.

  4. Sem managed hosting — Roda como lib Python pura. Deploy é por sua conta.

  5. Retries custam dinheiro — Cada retry de validação é uma chamada de API adicional.

  6. Nem todo provider suporta structured outputs igualmente — Gemini, OpenAI e Anthropic são os melhores; outros variam.

  7. pydantic-graph é avançado — Usa generics pesados, não é beginner-friendly.


Quando Usar PydanticAI

Use PydanticAI quando:

  • Você quer outputs validados do LLM — O caso de uso #1. Definir schemas e obter objetos tipados é incomparável.

  • Já usa Pydantic ou FastAPI — A experiência é idêntica. Você literalmente já sabe usar.

  • Type safety importa — Para produção, para coding agents que trabalham no seu código, para times que valorizam correctness.

  • Precisa de testabilidade — DI nativo + agent.override() tornam testes de agentes triviais.

  • Budget é preocupação — UsageLimits controlam custos; benchmark mostrou menor custo de infra.

  • Quer observabilidade sem lock-in — OTel funciona com qualquer stack de monitoring.

Não use PydanticAI quando:

  • Precisa de multi-agent robusto com delegação autônoma — Use CrewAI.

  • Precisa de workflows cíclicos complexos com checkpointing — Use LangGraph.

  • Precisa de centenas de integrações prontas — Use LangChain (breadth) ou n8n (visual).

  • Seu time é TypeScript — Use Mastra ou Vercel AI SDK.

  • Precisa de hosting gerenciado — Use LangGraph Platform ou CrewAI AMP.


Próximos Passos

Se este guia te convenceu a experimentar PydanticAI, aqui está um caminho estruturado:

  1. Instale e rode o exemplo básicouv add pydantic-ai → agente de 5 linhas
  2. Adicione output_type — Defina um BaseModel e veja a mágica da validação
  3. Implemente uma tool — Conecte a uma API real com @agent.tool_plain
  4. Injete dependências — Use deps_type e RunContext para desacoplar
  5. Explore capabilities (v2)Thinking, WebSearch, ToolSearch
  6. Configure Logfire — Observabilidade em 2 linhas de código
  7. Integre durable execution — Temporal ou DBOS para produção

Leitura Complementar

Se você está explorando o ecossistema de agentes IA, esses recursos complementam este guia:


Conclusão

PydanticAI é para quem leva Python a sério. Não é o framework com mais integrações, nem o mais visual, nem o que abstrai multi-agent em roles bonitos. É o que trata agentes IA como engenharia de software — com tipos, testes, injeção de dependência e validação.

A aposta da equipe Pydantic é clara: o caos atual dos agentes vai convergir para padrões de engenharia. E quando convergir, quem já está rodando type-safe, observável e testável vai estar muito à frente.

Se isso ressoa com o jeito que você pensa sobre software — vale cada minuto investido.


Quer se manter atualizado sobre frameworks de agentes, arquitetura e AI engineering em Português? Acompanhe o ft.ia.br para conteúdo técnico sem enrolação.