PydanticAI: Agentes de IA com Tipagem Forte
Aprenda a criar agentes de IA type-safe com PydanticAI em Python. Tutorial com saídas estruturadas, tools, dependency injection e streaming de respostas.
O universo de frameworks para agentes de IA em Python está cada vez mais competitivo. Temos o LangGraph, o OpenAI Agents SDK e diversas outras opções. Mas e se você pudesse construir agentes com a mesma segurança de tipos que o Pydantic trouxe para validação de dados?
O PydanticAI é exatamente isso: um framework para agentes de IA criado pelo time do Pydantic, com foco em tipagem forte, saídas estruturadas e uma experiência de desenvolvimento que lembra o FastAPI. Neste artigo, vamos explorar como criar agentes type-safe, definir ferramentas e usar dependency injection para builds robustos.
Por que PydanticAI?
A maioria dos frameworks de agentes trata as respostas de LLMs como strings ou dicionários genéricos. Isso gera problemas que só aparecem em runtime: campos faltando, tipos errados, estruturas inesperadas. O PydanticAI resolve isso com:
- Saídas estruturadas — respostas validadas por modelos Pydantic, com erros claros
- Type safety — type hints em todo o framework, compatível com mypy e pyright
- Model-agnostic — funciona com OpenAI, Anthropic, Google Gemini e Groq
- Dependency injection — inspirado no FastAPI, facilita testes e composição
- Streaming — respostas em tempo real com validação parcial
- Logfire integration — observabilidade nativa para debug e monitoramento
Se você já usa Pydantic para validação de dados e valoriza protocolos e tipagem estrutural, o PydanticAI vai parecer uma extensão natural do seu fluxo.
Instalação
O PydanticAI suporta múltiplos provedores de LLM. Instale com o provedor desejado:
# Instalação básica com OpenAI
uv pip install pydantic-ai[openai]
# Com suporte a Anthropic (Claude)
uv pip install pydantic-ai[anthropic]
# Com todos os provedores
uv pip install pydantic-ai[all]
Configure a chave da API via variável de ambiente:
export OPENAI_API_KEY="sk-..."
# ou
export ANTHROPIC_API_KEY="sk-ant-..."
Criando seu primeiro agente
Um agente PydanticAI é definido com um modelo e, opcionalmente, um tipo de resultado estruturado:
from pydantic_ai import Agent
agente = Agent(
"openai:gpt-4o",
system_prompt="Você é um assistente técnico especializado em Python.",
)
resultado = agente.run_sync("O que são decoradores em Python?")
print(resultado.output)
O run_sync executa o agente de forma síncrona. Para aplicações async, use await agente.run().
Saídas estruturadas com Pydantic
O verdadeiro poder do PydanticAI aparece com saídas tipadas. Em vez de receber texto livre, você define exatamente a estrutura esperada:
from pydantic import BaseModel
from pydantic_ai import Agent
class AnaliseCodigo(BaseModel):
linguagem: str
complexidade: str
problemas: list[str]
sugestoes: list[str]
agente = Agent(
"openai:gpt-4o",
result_type=AnaliseCodigo,
system_prompt="Analise o código fornecido e retorne uma avaliação estruturada.",
)
resultado = agente.run_sync("def f(x): return x if x > 0 else -x")
analise = resultado.output
print(f"Linguagem: {analise.linguagem}")
print(f"Complexidade: {analise.complexidade}")
for problema in analise.problemas:
print(f" - {problema}")
Se o LLM retornar dados que não correspondem ao modelo, o PydanticAI automaticamente pede ao modelo para corrigir a resposta — tudo isso de forma transparente.
Definindo ferramentas com @agent.tool
Agentes realmente úteis precisam interagir com o mundo externo. O PydanticAI permite definir ferramentas que o LLM pode chamar:
from pydantic_ai import Agent, RunContext
agente = Agent(
"openai:gpt-4o",
system_prompt="Você ajuda com cálculos matemáticos. Use as ferramentas disponíveis.",
)
@agente.tool_plain
def calcular_fatorial(n: int) -> int:
"""Calcula o fatorial de um número inteiro positivo."""
if n < 0:
raise ValueError("Número deve ser positivo")
resultado = 1
for i in range(2, n + 1):
resultado *= i
return resultado
@agente.tool_plain
def calcular_fibonacci(n: int) -> list[int]:
"""Retorna os primeiros n números da sequência de Fibonacci."""
if n <= 0:
return []
seq = [0, 1]
for _ in range(2, n):
seq.append(seq[-1] + seq[-2])
return seq[:n]
resultado = agente.run_sync("Qual é o fatorial de 12 e os 10 primeiros Fibonacci?")
print(resultado.output)
O decorator @agente.tool_plain registra a função como ferramenta acessível pelo LLM. O tipo de retorno e a docstring são usados para gerar o schema automaticamente.
Dependency injection
Para cenários mais complexos — acesso a banco de dados, clientes HTTP, configurações — o PydanticAI usa dependency injection inspirado no FastAPI:
from dataclasses import dataclass
import httpx
from pydantic_ai import Agent, RunContext
@dataclass
class Dependencias:
client: httpx.AsyncClient
api_base: str
agente = Agent(
"openai:gpt-4o",
deps_type=Dependencias,
system_prompt="Você consulta dados de repositórios GitHub.",
)
@agente.tool
async def buscar_repo(ctx: RunContext[Dependencias], owner: str, repo: str) -> str:
"""Busca informações de um repositório no GitHub."""
url = f"{ctx.deps.api_base}/repos/{owner}/{repo}"
resp = await ctx.deps.client.get(url)
data = resp.json()
return f"{data['full_name']}: {data['stargazers_count']} stars"
async def main():
async with httpx.AsyncClient() as client:
deps = Dependencias(client=client, api_base="https://api.github.com")
resultado = await agente.run(
"Quantas stars tem o repositório pydantic/pydantic-ai?",
deps=deps,
)
print(resultado.output)
O RunContext[Dependencias] tipa o contexto de forma que editores e type checkers entendam exatamente quais dependências estão disponíveis. Isso facilita muito o tratamento de erros e a escrita de testes.
Streaming de respostas
Para interfaces interativas, o PydanticAI suporta streaming com validação:
from pydantic_ai import Agent
agente = Agent(
"openai:gpt-4o",
system_prompt="Explique conceitos de Python de forma didática.",
)
async def stream_resposta():
async with agente.run_stream("Explique generators em Python") as response:
async for texto in response.stream_text():
print(texto, end="", flush=True)
print()
O streaming funciona também com saídas estruturadas — você recebe validações parciais conforme os dados chegam.
PydanticAI vs LangChain vs OpenAI Agents SDK
| Característica | PydanticAI | LangChain/LangGraph | OpenAI Agents SDK |
|---|---|---|---|
| Tipagem | Forte (Pydantic nativo) | Fraca (dicts) | Moderada |
| Saídas estruturadas | Nativo com validação | Via output parsers | Via response_format |
| Provedores | OpenAI, Anthropic, Gemini, Groq | Amplo | Apenas OpenAI |
| Dependency injection | Sim (estilo FastAPI) | Não | Não |
| Curva de aprendizado | Baixa (se conhece Pydantic) | Alta | Média |
| Streaming tipado | Sim | Parcial | Sim |
| Observabilidade | Logfire nativo | LangSmith | Traces OpenAI |
Se você já trabalha com o ecossistema Pydantic/FastAPI e quer agentes com segurança de tipos, o PydanticAI é a escolha mais natural. Para workflows complexos multi-agente, o LangGraph pode ser mais adequado. Para integração exclusiva com modelos OpenAI, o Agents SDK é mais direto.
Integração com MCP
O PydanticAI também se integra com o Model Context Protocol (MCP), permitindo que agentes acessem servidores MCP como fonte de ferramentas:
from pydantic_ai import Agent
from pydantic_ai.mcp import MCPServerStdio
servidor_mcp = MCPServerStdio("uvx", args=["meu-servidor-mcp"])
agente = Agent(
"openai:gpt-4o",
mcp_servers=[servidor_mcp],
)
Isso conecta o mundo dos agentes tipados com o ecossistema crescente de servidores MCP, combinando o melhor dos dois mundos.
Quando usar PydanticAI
O PydanticAI brilha quando você precisa de:
- Respostas de LLMs com estrutura garantida para alimentar pipelines de dados
- Testes unitários robustos para lógica de agentes (dependency injection facilita mocks)
- Type checking completo em IDEs e CI/CD com mypy
- Integração com APIs e LLMs de múltiplos provedores sem lock-in
O framework ainda é jovem comparado ao LangChain, mas a qualidade do código e a filosofia de design — herdadas diretamente do Pydantic — fazem dele uma aposta sólida para produção.
Desenvolvedores que trabalham com tipagem forte em outras linguagens podem comparar a abordagem do PydanticAI com os generics de Go no golang.com.br e o sistema de tipos algébricos do Rust no rustlang.com.br. Para quem desenvolve no ecossistema JVM, o Kotlin no kotlin.dev.br oferece uma experiência de null safety que complementa bem a filosofia do Pydantic.
Perguntas frequentes
O que é PydanticAI?
PydanticAI é um framework Python para construir agentes de IA com tipagem forte. Criado pelo time do Pydantic, ele usa modelos Pydantic para garantir que respostas de LLMs tenham a estrutura esperada, com validação automática e correção de erros.
O PydanticAI funciona com Claude e GPT?
Sim. O PydanticAI é model-agnostic e suporta OpenAI (GPT-4o, GPT-4), Anthropic (Claude), Google Gemini e Groq. Trocar de provedor exige apenas mudar a string do modelo na configuração do agente.
Qual a diferença entre PydanticAI e LangChain?
O PydanticAI foca em tipagem forte e saídas estruturadas com validação nativa. O LangChain é mais amplo, com centenas de integrações, mas usa tipos genéricos (dicts). Para agentes que precisam de respostas com estrutura garantida, o PydanticAI é mais robusto.
O PydanticAI é pronto para produção?
O PydanticAI está em desenvolvimento ativo e já é usado em projetos reais. A base sólida do Pydantic (usado por FastAPI, Django Ninja e milhares de projetos) garante qualidade. Para produção, recomenda-se fixar a versão e acompanhar o changelog do projeto.
Equipe python.dev.br
Contribuidor do Python Brasil — Aprenda Python em Português