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.

7 min de leitura Equipe python.dev.br

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 safetytype 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ísticaPydanticAILangChain/LangGraphOpenAI Agents SDK
TipagemForte (Pydantic nativo)Fraca (dicts)Moderada
Saídas estruturadasNativo com validaçãoVia output parsersVia response_format
ProvedoresOpenAI, Anthropic, Gemini, GroqAmploApenas OpenAI
Dependency injectionSim (estilo FastAPI)NãoNão
Curva de aprendizadoBaixa (se conhece Pydantic)AltaMédia
Streaming tipadoSimParcialSim
ObservabilidadeLogfire nativoLangSmithTraces 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.

E

Equipe python.dev.br

Contribuidor do Python Brasil — Aprenda Python em Português