
Pydantic AI: O Guia de Produção (Além do Hello World)
As saídas brutas dos LLM quebram aplicações. Pede JSON e recebe markdown. Pede um número entre 1 e 10 e obtém "Claro! Aqui está um número: sete." Se já construiu algo real com APIs de LLM, escreveu código de análise defensiva que o fez questionar as suas escolhas de carreira. A Pydantic AI resolve isto; é a framework de agentes com tipagem segura criada pela mesma equipa por detrás do Pydantic e do FastAPI. Pense nela como o "FastAPI para agentes de IA": define o que pretende com dicas de tipo Python (type hints) e a framework trata da validação, repetições e chamada de ferramentas.
Este guia da Pydantic AI destina-se a programadores que já executaram a sua primeira chamada a um LLM e procuram padrões de produção: saídas estruturadas que não falham, injeção de dependências para agentes testáveis e ferramentas do mundo real para além das APIs meteorológicas. No final, terá agentes funcionais com ferramentas, DI, streaming e testes.
<!-- IMAGE: Arquitetura do agente Pydantic AI, o Agente recebe o prompt, chama ferramentas via RunContext, valida a saída através do modelo Pydantic -->Pydantic AI num Relance
| Atributo | Detalhes |
|---|---|
| O que é | Framework de agentes de IA com tipagem segura para Python |
| Criado por | Equipa Pydantic (Samuel Colvin et al.) |
| Filosofia | "FastAPI para agentes de IA", as dicas de tipo conduzem tudo |
| Licença | MIT (código aberto) |
| Versão Atual | v1.74.0 (março de 2026) |
| Versão Python | 3.9+ |
| Modelos Suportados | OpenAI, Anthropic, Google Gemini, Groq, Mistral, Ollama e mais |
| Funcionalidades Principais | Saídas estruturadas, chamada de ferramentas, injeção de dependências, streaming, TestModel |
| Estrelas no GitHub | 16.000+ |
| Pronto para Produção | Sim, v1.0 lançada em setembro de 2025 |
| Observabilidade | Integração nativa com Logfire (baseada em OpenTelemetry) |
| Curva de Aprendizagem | Baixa se conhecer Pydantic/FastAPI; moderada caso contrário |
As funcionalidades de destaque são as saídas estruturadas (validadas com modelos Pydantic), a injeção de dependências (como o Depends do FastAPI) e o TestModel (LLM simulado para testes sem chamadas à API). Se vem do LangChain e se pergunta "haverá algo mais limpo?", provavelmente é isto.
Instalação e Primeiro Agente
# Install with OpenAI support (swap openai for anthropic, google, etc.)
pip install "pydantic-ai[openai]"
# Set your API key
export OPENAI_API_KEY="sk-..."O seu primeiro agente em 5 linhas:
from pydantic_ai import Agent
agent = Agent("openai:gpt-4o", system_prompt="You are a helpful assistant.")
result = agent.run_sync("What's the capital of France?")
print(result.output) # "Paris"É tudo. O Agent envolve o modelo, o run_sync envia um prompt e devolve um resultado. O result.output é aqui uma cadeia de texto simples, mas isso está prestes a mudar.
Saídas Estruturadas, Porquê a Existência da Pydantic AI
Esta é a funcionalidade central. Em vez de receber uma cadeia de texto do LLM e esperar que seja JSON válido, define um modelo Pydantic e o agente devolve um objeto Python validado.
Antes: Saída Bruta do LLM
# The old way -- hope for the best
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Review the movie Inception. Return JSON with title, rating (1-10), summary."}]
)
# response.choices[0].message.content is a string
# Maybe it's JSON. Maybe it has markdown code fences. Maybe rating is "eight".
# You're on your own.Depois: Estruturado com Pydantic AI
from pydantic import BaseModel
from pydantic_ai import Agent
class MovieReview(BaseModel):
title: str
rating: int # Guaranteed to be an int, not "eight"
summary: str
recommended: bool
agent = Agent("openai:gpt-4o", result_type=MovieReview)
result = agent.run_sync("Review the movie Inception")
review = result.output # This is a MovieReview instance, not a string
print(f"{review.title}: {review.rating}/10")
print(f"Recommended: {review.recommended}")
print(review.summary)A diferença é abismal. O result.output é um objeto MovieReview real. Se o LLM devolver rating: "eight" em vez de rating: 8, a validação do Pydantic deteta-o. Para uma análise mais aprofundada de como isto funciona em diferentes fornecedores, consulte o nosso guia sobre saídas estruturadas em fornecedores de LLM.
O Que Acontece Quando a Validação Falha
Eis a parte que nenhum outro tutorial mostra: o que acontece quando o LLM falha?
from pydantic import BaseModel, Field
from pydantic_ai import Agent
class StrictReview(BaseModel):
title: str
rating: int = Field(ge=1, le=10) # Must be 1-10
pros: list[str] = Field(min_length=2) # At least 2 pros
agent = Agent("openai:gpt-4o", result_type=StrictReview)
# If the LLM returns rating=15 or only 1 pro:
# 1. Pydantic validation fails
# 2. The error message is sent BACK to the LLM
# 3. The LLM tries again with the corrected output
# 4. This repeats up to the retry limit
result = agent.run_sync("Review the movie Inception")Este ciclo de repetição com feedback é a funcionalidade killer da Pydantic AI. O LLM aprende com os seus próprios erros de validação. Não escreve lógica de repetição, a framework trata disso.
Veredicto: As saídas estruturadas são a melhor razão individual para usar a Pydantic AI em vez de chamadas brutas à API. Se estiver a analisar JSON de LLM manualmente, pare.
Ferramentas e Chamada de Funções
As ferramentas permitem que o seu agente chame funções Python para obter dados reais. Em vez de o LLM inventar factos, pode consultar a sua base de dados, pesquisar na sua documentação ou chamar uma API.
Registar uma Ferramenta
from pydantic_ai import Agent
agent = Agent("openai:gpt-4o")
@agent.tool
async def search_docs(query: str) -> str:
"""Search the documentation for relevant articles."""
# Your actual search logic here
results = await doc_search_engine.search(query, limit=5)
return "\n".join(r.title + ": " + r.snippet for r in results)O decorador @agent.tool regista a função. A Pydantic AI lê as dicas de tipo e a docstring da função para informar o LLM sobre o que a ferramenta faz, que argumentos aceita e o que devolve. Sem escrita manual de esquemas, as suas dicas de tipo SÃO o esquema. Para antecedentes sobre como funciona a chamada de funções de LLM nos bastidores, temos um guia dedicado.
RunContext: Passar Dados às Ferramentas
É aqui que a Pydantic AI diverge de outras frameworks. O RunContext permite passar dados de runtime (ligações à base de dados, informações do utilizador, clientes API) às suas ferramentas sem estado global.
from dataclasses import dataclass
from pydantic_ai import Agent, RunContext
@dataclass
class SupportDeps:
customer_id: str
db_connection: DatabaseConnection
agent = Agent("openai:gpt-4o", deps_type=SupportDeps)
@agent.tool
async def get_order_history(ctx: RunContext[SupportDeps], limit: int = 5) -> str:
"""Fetch recent orders for the current customer."""
orders = await ctx.deps.db_connection.query(
"SELECT * FROM orders WHERE customer_id = $1 ORDER BY date DESC LIMIT $2",
ctx.deps.customer_id, limit
)
return format_orders(orders)O ctx.deps dá à ferramenta acesso ao que quer que tenha passado em runtime. A ferramenta não importa uma ligação global à base de dados, recebe uma. Isto é injeção de dependências e é o que torna os seus agentes testáveis.
Um Exemplo de Ferramenta do Mundo Real
@agent.tool
async def run_sql_query(ctx: RunContext[SupportDeps], sql: str) -> str:
"""Run a read-only SQL query against the analytics database.
Only SELECT queries are allowed."""
if not sql.strip().upper().startswith("SELECT"):
return "Error: only SELECT queries are allowed"
results = await ctx.deps.db_connection.fetch(sql)
return json.dumps(results, default=str)Veredicto: A chamada de ferramentas na Pydantic AI é mais limpa do que em qualquer outra framework graças às dicas de tipo a fazerem o trabalho pesado. Escreve funções Python normais com anotações de tipo. A framework descobre o resto.
Injeção de Dependências, A Funcionalidade Que o LangGraph Gostaria de Ter
Se já usou o Depends do FastAPI, já compreende o sistema de DI da Pydantic AI. Se não usou, eis a versão curta: em vez de o seu agente se estender para agarrar o que precisa (ligações globais à base de dados, clientes API, configuração), entrega-lhe tudo em runtime.
Definir Dependências
from dataclasses import dataclass
from pydantic_ai import Agent
@dataclass
class AppDeps:
db: AsyncDatabasePool
search_client: SearchAPIClient
current_user: User
agent = Agent(
"openai:gpt-4o",
deps_type=AppDeps,
system_prompt="You are a customer support agent."
)Usar Dependências nas Ferramentas
@agent.tool
async def lookup_account(ctx: RunContext[AppDeps]) -> str:
"""Look up the current user's account details."""
account = await ctx.deps.db.fetchrow(
"SELECT * FROM accounts WHERE user_id = $1",
ctx.deps.current_user.id
)
return json.dumps(account, default=str)
# Run with real dependencies
result = await agent.run(
"What's my account status?",
deps=AppDeps(db=real_db, search_client=real_search, current_user=user)
)Porquê a DI Torna os Seus Agentes Testáveis
Esta é a verdadeira vantagem. No LangChain, passaria o contexto através de kwargs da cadeia ou closures, não há um padrão definido. Na Pydantic AI, trocar dependências reais por duplos de teste é trivial:
# In your test file
from pydantic_ai import Agent
from your_app import agent, AppDeps
async def test_account_lookup():
mock_deps = AppDeps(
db=MockDatabase({"user_123": {"status": "active", "plan": "pro"}}),
search_client=MockSearch(),
current_user=User(id="user_123")
)
result = await agent.run("What's my account status?", deps=mock_deps)
assert "active" in result.output
assert "pro" in result.outputSem monkey-patching. Sem simular importações globais. Apenas passa dependências diferentes.
Veredicto: A injeção de dependências é a razão pela qual os programadores Python experientes preferem a Pydantic AI. É a influência do FastAPI a mostrar-se.
Fornecedores de Modelos, OpenAI, Anthropic, Gemini, Ollama
A Pydantic AI é agnóstica quanto ao modelo. Mudar de fornecedor é uma alteração de uma linha:
# OpenAI
agent = Agent("openai:gpt-4o")
# Anthropic
agent = Agent("anthropic:claude-sonnet-4-20250514")
# Google Gemini
agent = Agent("google-gla:gemini-2.0-flash")
# Local Ollama
agent = Agent("ollama:llama3.1")Todo o resto, ferramentas, saídas estruturadas, DI, permanece idêntico. A sua lógica de negócio não muda quando muda de modelos.
| Fornecedor | Modelos | Nível Gratuito | Complexidade de Configuração |
|---|---|---|---|
| OpenAI | GPT-4o, GPT-4o mini, o1 | Crédito de $5 (novas contas) | Baixa, apenas chave API |
| Anthropic | Claude Sonnet, Haiku, Opus | Sem nível gratuito | Baixa, apenas chave API |
| Google Gemini | Gemini 2.0 Flash, Pro | Nível gratuito generoso | Média, configuração do projeto |
| Groq | Llama, Mixtral | Nível gratuito disponível | Baixa, apenas chave API |
| Ollama (local) | Llama, Mistral, Phi, etc. | Completamente gratuito | Média, instalar Ollama |
Veredicto: O design agnóstico quanto ao modelo significa que nunca fica preso a um único fornecedor. Comece com a OpenAI por conveniência, faça benchmarking com a Anthropic e use o Ollama para desenvolvimento local.
Streaming de Respostas
Para interfaces de chat e aplicações em tempo real, o streaming é essencial. A Pydantic AI suporta-o mantendo a segurança de tipos:
from pydantic_ai import Agent
from pydantic import BaseModel
class AnalysisResult(BaseModel):
summary: str
sentiment: str
confidence: float
agent = Agent("openai:gpt-4o", result_type=AnalysisResult)
async def stream_analysis(text: str):
async with agent.run_stream(f"Analyze this text: {text}") as stream:
async for partial in stream.stream_structured():
# partial is a partially-validated AnalysisResult
print(f"Streaming: {partial}")
# Final result is fully validated
result = await stream.get_output()
print(f"Final: {result.summary} ({result.confidence:.0%} confident)")Isto funciona lindamente com o StreamingResponse do FastAPI, mesmo ecossistema, mesmos padrões. A documentação dos agentes Pydantic AI cobre opções avançadas de streaming, incluindo streaming apenas de texto com stream_text().
Pydantic AI vs LangGraph vs OpenAI Agents SDK
Está aqui, por isso provavelmente pergunta-se: "devo usar a Pydantic AI ou o LangGraph?" Resposta honesta: resolvem problemas diferentes e pode usar ambos.
Tabela de Comparação de Funcionalidades
| Funcionalidade | Pydantic AI | LangGraph | OpenAI Agents SDK |
|---|---|---|---|
| Segurança de Tipos | Total (modelos Pydantic) | Parcial (TypedDict) | Mínima |
| Injeção de Dependências | Integrada (estilo FastAPI) | Nenhuma | Nenhuma |
| Saídas Estruturadas | Nativo com repetição | Via analisadores de saída | Via modo JSON |
| Chamada de Ferramentas | Decorador @agent.tool | Decorador @tool | Definições de função |
| Multi-Agente | Transferências básicas | Avançado (máquinas de estado) | Transferências + guardrails |
| Streaming | Streaming tipado | Eventos de streaming | Streaming |
| Suporte de Modelos | 10+ fornecedores | Principalmente modelos LangChain | Apenas OpenAI |
| Testes | TestModel integrado | Sem testes integrados | Sem testes integrados |
| Curva de Aprendizagem | Baixa (se conhecer Pydantic) | Alta (conceitos de grafos) | Baixa (API simples) |
| Tamanho da Comunidade | Em crescimento (16K estrelas) | Grande (ecossistema LangChain) | Em crescimento (apoio OpenAI) |
| Ideal Para | Agentes limpos e testáveis | Fluxos de trabalho complexos | Projetos apenas OpenAI |
Quando Usar Cada Um
Escolha a Pydantic AI quando quiser código de agente limpo e com tipagem segura. É ideal para tarefas de agente único com ferramentas (bots de apoio ao cliente, extração de dados, agentes de revisão de código) e situações onde a testabilidade importa. Se a sua equipa já usa FastAPI e Pydantic, a curva de aprendizagem é quase plana.
Escolha o LangGraph quando precisar de fluxos de trabalho complexos em várias etapas com ramificação condicional, aprovação humana no loop e gestão de estado sofisticada. O LangGraph destaca-se na orquestração de múltiplos passos, não na qualidade individual do agente. Para uma análise aprofundada, veja a nossa comparação completa LangGraph vs CrewAI vs OpenAI Agents SDK.
Escolha o OpenAI Agents SDK quando estiver 100% na OpenAI, quiser a configuração mais simples possível e não precisar de suporte multi-fornecedor ou DI.
O Padrão de Combinação
Eis o que as equipas experientes fazem realmente: usam a Pydantic AI para agentes individuais (código limpo, testável, saídas tipadas) e o LangGraph para orquestração entre agentes (encaminhamento, máquinas de estado, lógica condicional). Não competem, são camadas complementares.
# Pydantic AI agent -- clean, testable, type-safe
support_agent = Agent("openai:gpt-4o", result_type=SupportResponse, deps_type=SupportDeps)
# LangGraph graph -- orchestrates when to call which agent
graph = StateGraph(SupportState)
graph.add_node("classify", classify_intent)
graph.add_node("support", lambda state: support_agent.run_sync(state["query"]))
graph.add_node("escalate", escalate_to_human)Veredicto: Escolha a Pydantic AI para código de agente limpo e testável. Escolha o LangGraph para fluxos de trabalho complexos em várias etapas. Não são mutuamente exclusivos.
Testar os Seus Agentes com TestModel
Esta é a secção que separa um guia para iniciantes de um guia de produção. Todas as bases de código reais precisam de testes e testar agentes é notoriamente difícil; as chamadas LLM são lentas, caras e não determinísticas. A Pydantic AI oferece uma solução: o TestModel.
from pydantic_ai import Agent
from pydantic_ai.models.test import TestModel
from pydantic import BaseModel
class SupportResponse(BaseModel):
answer: str
confidence: float
escalate: bool
agent = Agent("openai:gpt-4o", result_type=SupportResponse)
# In tests: swap the real model for TestModel
def test_support_agent():
with agent.override(model=TestModel()):
result = agent.run_sync("I need help with billing")
# TestModel returns valid structured data matching your result_type
assert isinstance(result.output, SupportResponse)
assert isinstance(result.output.confidence, float)
assert isinstance(result.output.escalate, bool)O TestModel gera dados válidos que correspondem ao seu result_type sem fazer quaisquer chamadas à API. Custo zero, determinístico, rápido. A documentação de testes da Pydantic AI cobre padrões avançados como o FunctionModel para respostas personalizadas e o capture_run_messages para inspecionar chamadas de ferramentas.
Testar Ferramentas e DI em Conjunto
def test_order_lookup_tool():
# Mock dependencies
mock_deps = SupportDeps(
customer_id="test-123",
db_connection=MockDB(orders=[{"id": "ord-1", "status": "shipped"}])
)
with agent.override(model=TestModel()):
result = agent.run_sync(
"Where is my order?",
deps=mock_deps
)
assert isinstance(result.output, SupportResponse)Sem chamadas à API. Sem testes instáveis. Sem custos. Execute isto em CI/CD juntamente com o resto da sua suite de testes.
Esta é a maior lacuna de conteúdo em toda a SERP. Nenhum outro guia da Pydantic AI aborda os testes. Se está a construir agentes para produção, é disto que precisa.
Observabilidade, Integração Logfire em 5 Minutos
Os agentes de produção precisam de observabilidade de IA. Quer ver cada chamada LLM, invocação de ferramenta, latência, contagem de tokens e custo. A Pydantic AI integra-se nativamente com o Logfire, a plataforma de observabilidade da equipa Pydantic (construída sobre OpenTelemetry).
import logfire
from pydantic_ai import Agent
logfire.configure() # Uses LOGFIRE_TOKEN env var
logfire.instrument_pydantic_ai()
agent = Agent("openai:gpt-4o", result_type=MovieReview)
# Every run is now traced automatically
result = agent.run_sync("Review Inception")Três linhas. Obtém rastreios completos que mostram: prompt enviado, resposta do modelo, chamadas de ferramentas (se houver), sucessos/falhas de validação, repetições, latência e custo estimado. Se o Logfire não for a sua escolha, o Langfuse é uma alternativa sólida de código aberto com suporte de engenharia de contexto para rastrear a evolução dos seus prompts.
FAQ
O que é a Pydantic AI e como difere do LangChain?
A Pydantic AI é uma framework de agentes com tipagem segura onde as dicas de tipo Python conduzem a validação, os esquemas de ferramentas e a injeção de dependências. O LangChain é uma framework maior focada em encadear chamadas LLM. A diferença chave: a Pydantic AI valida saídas ao nível da framework e fornece injeção de dependências integrada para testabilidade, o LangChain não faz nenhum dos dois por defeito.
Como construo um agente de IA com tipagem segura com a Pydantic AI?
Defina um BaseModel Pydantic para a sua saída, passe-o como result_type para o Agent e chame run_sync() ou run(). O agente devolve uma instância validada do seu modelo, não uma cadeia de texto bruta. Consulte a secção Saídas Estruturadas para exemplos completos.
Devo usar a Pydantic AI ou o LangGraph para agentes de produção?
Use a Pydantic AI para agentes individuais onde a segurança de tipos, testabilidade e código limpo importam. Use o LangGraph para orquestrar fluxos de trabalho complexos em várias etapas com encaminhamento condicional. Muitas equipas usam ambos, agentes Pydantic AI dentro de uma camada de orquestração LangGraph.
Como lida a Pydantic AI com a chamada de ferramentas e injeção de dependências?
Decore uma função com @agent.tool e a Pydantic AI lê as suas dicas de tipo para gerar o esquema da ferramenta. Para DI, defina deps_type no Agent e aceite RunContext[YourDeps] nas ferramentas. As dependências de runtime (ligações BD, clientes API) fluem sem estado global.
Como adiciono streaming a um agente Pydantic AI?
Use agent.run_stream() em vez de agent.run(). Devolve um gestor de contexto assíncrono que produz resultados parciais via stream_structured() ou stream_text(). O resultado final continua totalmente validado contra o seu result_type.
A Pydantic AI está pronta para produção em 2026?
Sim. A Versão 1.0 foi lançada em setembro de 2025 com um compromisso de estabilidade da API. É apoiada pela equipa Pydantic (a biblioteca Python mais descarregada para validação de dados) e encontra-se atualmente na v1.74.0 com atualizações regulares.
Posso usar a Pydantic AI com Ollama e modelos locais?
Sim. Use Agent("ollama:llama3.1") e certifique-se de que o Ollama está a correr localmente. Instale o extra do fornecedor ollama: pip install "pydantic-ai[ollama]". As saídas estruturadas e ferramentas funcionam da mesma forma que com fornecedores na nuvem.
Como testo agentes Pydantic AI?
Use o TestModel, um modelo simulado que gera dados estruturados válidos correspondentes ao seu result_type sem chamadas à API. Envolva o seu teste em agent.override(model=TestModel()) e execute asserções na saída. Consulte a secção Testes para exemplos completos de pytest.
A Pydantic AI funciona com FastAPI?
Perfeitamente. Partilham a mesma filosofia de injeção de dependências e são construídos pela mesma equipa. Pode usar agentes Pydantic AI dentro de endpoints FastAPI, partilhar tipos de dependência entre eles e transmitir respostas do agente através de StreamingResponse.
Qual é a diferença entre a Pydantic AI e o OpenAI Agents SDK?
A Pydantic AI é agnóstica quanto ao modelo (funciona com OpenAI, Anthropic, Gemini, Ollama, etc.), tem injeção de dependências, TestModel para testes e validação Pydantic. O OpenAI Agents SDK é mais simples, mas está bloqueado aos modelos OpenAI e carece de DI e testes integrados. Escolha a Pydantic AI para flexibilidade; escolha o OpenAI Agents SDK para a configuração mais simples possível apenas para OpenAI.
Pontos-Chave e Próximos Passos
| Conceito | Insight Chave | Próximo Passo |
|---|---|---|
| Saídas Estruturadas | O seu result_type é validado e repetido automaticamente | Defina modelos Pydantic para todas as saídas do agente |
| Ferramentas | As dicas de tipo SÃO o esquema, sem definições manuais | Construa ferramentas com @agent.tool e RunContext |
| Injeção de Dependências | Passe deps de runtime explicitamente para testabilidade | Defina uma dataclass deps_type para cada agente |
| Testes | O TestModel elimina custos de API em CI/CD | Adicione agent.override(model=TestModel()) à sua suite de testes |
| Fornecedores de Modelos | Mudança de modelo numa linha, sem alterações de código | Comece com OpenAI, avalie alternativas mais tarde |
| Observabilidade | Configuração Logfire de 3 linhas para rastreios completos | Adicione logfire.instrument_pydantic_ai() à produção |
Comece com um pequeno agente que tenha saídas estruturadas. Adicione uma ferramenta. Adicione dependências. Escreva um teste com TestModel. Esse é o caminho para a produção e agora tem tudo o que precisa para o percorrer.
A documentação oficial da Pydantic AI e o repositório GitHub são excelentes para se aprofundar. A framework evolui rapidamente, por isso marque o registo de alterações.