
Pydantic AI: Produktionsguiden (Bortom Hello World)
Råa LLM-utdata förstör applikationer. Du ber om JSON, du får markdown. Du ber om ett nummer mellan 1 och 10, du får "Visst! Här är ett nummer: sju." Om du har byggt något verkligt med LLM-API:er har du skrivit defensiv parsningskod som får dig att ifrågasätta dina karriärval. Pydantic AI löser detta -- det är det typsäkra agent-ramverket byggt av samma team bakom Pydantic och FastAPI. Tänk på det som "FastAPI för AI-agenter": du definierar vad du vill ha med Python-typdefinitioner, och ramverket hanterar validering, återförsök och verktygsanrop.
Den här Pydantic AI-guiden är för utvecklare som redan gjort sitt första LLM-anrop och vill ha produktionsmönster: strukturerade utdata som inte går sönder, dependency injection för testbara agenter och verkliga verktyg bortom väder-API:er. I slutet har du fungerande agenter med verktyg, DI, streaming och tester.
<!-- IMAGE: Pydantic AI-agentarkitektur -- Agent tar emot prompt, anropar verktyg via RunContext, validerar utdata genom Pydantic-modellen -->Pydantic AI i Korthet
| Attribut | Detaljer |
|---|---|
| Vad det är | Typsäkert AI-agent-ramverk för Python |
| Byggt av | Pydantic-teamet (Samuel Colvin m.fl.) |
| Filosofi | "FastAPI för AI-agenter" -- typdefinitioner driver allt |
| Licens | MIT (öppen källkod) |
| Aktuell Version | v1.74.0 (Mars 2026) |
| Python-version | 3.9+ |
| Stödda Modeller | OpenAI, Anthropic, Google Gemini, Groq, Mistral, Ollama med mera |
| Nyckelfunktioner | Strukturerade utdata, verktygsanrop, dependency injection, streaming, TestModel |
| GitHub-stjärnor | 16 000+ |
| Produktionsklar | Ja -- v1.0 släpptes september 2025 |
| Observerbarhet | Inbyggd Logfire-integration (OpenTelemetry-baserad) |
| Inlärningskurva | Låg om du känner till Pydantic/FastAPI; måttlig annars |
De utmärkande funktionerna är strukturerade utdata (validerade med Pydantic-modeller), dependency injection (som FastAPI:s Depends) och TestModel (mock-LLM för testning utan API-anrop). Om du kommer från LangChain och undrar "finns det något renare?", är detta förmodligen det.
Installation och Första Agent
# Installera med OpenAI-stöd (byt ut openai mot anthropic, google osv.)
pip install "pydantic-ai[openai]"
# Ange din API-nyckel
export OPENAI_API_KEY="sk-..."Din första agent på 5 rader:
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"Det är allt. Agent omsluter modellen, run_sync skickar en prompt och returnerar ett resultat. result.output är en vanlig sträng här, men det kommer att förändras.
Strukturerade Utdata -- Varför Pydantic AI Finns
Det här är kärnfunktionen. Istället för att få en sträng tillbaka från LLM:en och hoppas att den är giltig JSON, definierar du en Pydantic-modell och agenten returnerar ett validerat Python-objekt.
Innan: Rå LLM-utdata
# Det gamla sättet -- hoppas på det bästa
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 är en sträng
# Kanske är det JSON. Kanske har det markdown-kodstaket. Kanske är rating "eight".
# Du är på egen hand.Efter: Strukturerat med Pydantic AI
from pydantic import BaseModel
from pydantic_ai import Agent
class MovieReview(BaseModel):
title: str
rating: int # Garanterat ett int, inte "eight"
summary: str
recommended: bool
agent = Agent("openai:gpt-4o", result_type=MovieReview)
result = agent.run_sync("Review the movie Inception")
review = result.output # Detta är en MovieReview-instans, inte en sträng
print(f"{review.title}: {review.rating}/10")
print(f"Rekommenderas: {review.recommended}")
print(review.summary)Skillnaden är som natt och dag. result.output är ett riktigt MovieReview-objekt. Om LLM:en returnerar rating: "eight" istället för rating: 8 fångar Pydantics validering det. För en djupare titt på hur detta fungerar hos olika leverantörer, se vår guide om strukturerade utdata hos LLM-leverantörer.
Vad Händer När Valideringen Misslyckas
Här är den del som ingen annan handledning visar: vad händer när LLM:en gör fel?
from pydantic import BaseModel, Field
from pydantic_ai import Agent
class StrictReview(BaseModel):
title: str
rating: int = Field(ge=1, le=10) # Måste vara 1-10
pros: list[str] = Field(min_length=2) # Minst 2 fördelar
agent = Agent("openai:gpt-4o", result_type=StrictReview)
# Om LLM:en returnerar rating=15 eller bara 1 fördel:
# 1. Pydantic-validering misslyckas
# 2. Felmeddelandet skickas TILLBAKA till LLM:en
# 3. LLM:en försöker igen med korrigerad utdata
# 4. Detta upprepas upp till återförsöksgränsen
result = agent.run_sync("Review the movie Inception")Den här återförsöksloopen med feedback är Pydantic AI:s killerfunktion. LLM:en lär sig av sina egna valideringsfel. Du skriver ingen återförsökslogik -- ramverket hanterar det.
Verdict: Strukturerade utdata är det enda bästa skälet att använda Pydantic AI över råa API-anrop. Om du parsar LLM-JSON för hand, sluta med det.
Verktyg och Funktionsanrop
Verktyg låter din agent anropa Python-funktioner för att få verkliga data. Istället för att LLM:en hallucinerar fakta kan den fråga din databas, söka i dina dokument eller anropa ett API.
Registrera ett Verktyg
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."""
# Din faktiska söklogik här
results = await doc_search_engine.search(query, limit=5)
return "\n".join(r.title + ": " + r.snippet for r in results)Dekoratorn @agent.tool registrerar funktionen. Pydantic AI läser funktionens typdefinitioner och docstring för att berätta för LLM:en vad verktyget gör, vilka argument det tar och vad det returnerar. Ingen manuell schemaskrivning -- dina typdefinitioner ÄR schemat. För bakgrunden om hur LLM-funktionsanrop fungerar under huven har vi en dedikerad guide.
RunContext: Skicka Data till Verktyg
Här avviker Pydantic AI från andra ramverk. RunContext låter dig skicka körtidsdata (databasanslutningar, användarinfo, API-klienter) till dina verktyg utan globalt tillstånd.
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)ctx.deps ger verktyget tillgång till allt du skickade vid körtid. Verktyget importerar inte en global databasanslutning -- det tar emot en. Det här är dependency injection, och det är vad som gör dina agenter testbara.
Ett Verkligt Verktygsexempel
@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)Verdict: Verktygsanrop i Pydantic AI är renare än något annat ramverk tack vare att typdefinitioner gör det tunga arbetet. Du skriver normala Python-funktioner med typanteckningar. Ramverket räknar ut resten.
Dependency Injection -- Funktionen LangChain Önskar att den Hade
Om du har använt FastAPI:s Depends förstår du redan Pydantic AI:s DI-system. Om du inte har det, här är den korta versionen: istället för att din agent når ut för att ta vad den behöver (globala databasanslutningar, API-klienter, konfiguration), lämnar du över allt vid körtid.
Definiera Beroenden
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."
)Använda Beroenden i Verktyg
@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)
# Kör med riktiga beroenden
result = await agent.run(
"What's my account status?",
deps=AppDeps(db=real_db, search_client=real_search, current_user=user)
)Varför DI Gör Dina Agenter Testbara
Det är den verkliga utdelningen. I LangChain skulle du skicka kontext via chain kwargs eller closures -- det finns inget standardmönster. I Pydantic AI är det trivialt att byta ut riktiga beroenden mot testdubblar:
# I din testfil
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.outputIngen monkey-patching. Ingen mockning av globala importer. Du skickar bara olika deps.
Verdict: Dependency injection är varför erfarna Python-utvecklare föredrar Pydantic AI. Det är FastAPI-inflytandet som visar sig.
Modellleverantörer -- OpenAI, Anthropic, Gemini, Ollama
Pydantic AI är modellagnostiskt. Att byta leverantör är en ändring på en rad:
# OpenAI
agent = Agent("openai:gpt-4o")
# Anthropic
agent = Agent("anthropic:claude-sonnet-4-20250514")
# Google Gemini
agent = Agent("google-gla:gemini-2.0-flash")
# Lokal Ollama
agent = Agent("ollama:llama3.1")Allt annat -- verktyg, strukturerade utdata, DI -- förblir identiskt. Din affärslogik förändras inte när du byter modell.
| Leverantör | Modeller | Gratisnivå | Installationskomplexitet |
|---|---|---|---|
| OpenAI | GPT-4o, GPT-4o mini, o1 | $5 kredit (nya konton) | Låg -- bara API-nyckel |
| Anthropic | Claude Sonnet, Haiku, Opus | Ingen gratisnivå | Låg -- bara API-nyckel |
| Google Gemini | Gemini 2.0 Flash, Pro | Generös gratisnivå | Medium -- projektinstallation |
| Groq | Llama, Mixtral | Gratisnivå tillgänglig | Låg -- bara API-nyckel |
| Ollama (lokal) | Llama, Mistral, Phi osv. | Helt gratis | Medium -- installera Ollama |
Verdict: Modellagnostisk design innebär att du aldrig är låst till en leverantör. Börja med OpenAI för bekvämlighet, benchmarka med Anthropic och använd Ollama för lokal utveckling.
Streaming-svar
För chat-UI:er och realtidsapplikationer är streaming viktigt. Pydantic AI stöder det samtidigt som typssäkerheten bibehålls:
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 är ett delvis validerat AnalysisResult
print(f"Streaming: {partial}")
# Slutresultatet är fullständigt validerat
result = await stream.get_output()
print(f"Slutligt: {result.summary} ({result.confidence:.0%} säkerhet)")Det här fungerar utmärkt med FastAPI:s StreamingResponse -- samma ekosystem, samma mönster. Pydantic AI-agentdokumentationen täcker avancerade streaming-alternativ inklusive textbaserad streaming med stream_text().
Pydantic AI vs LangGraph vs OpenAI Agents SDK
Du är här, så du frågar förmodligen: "ska jag använda Pydantic AI eller LangGraph?" Ärligt svar: de löser olika problem, och du kanske använder båda.
Jämförelsetabell över Funktioner
| Funktion | Pydantic AI | LangGraph | OpenAI Agents SDK |
|---|---|---|---|
| Typsäkerhet | Full (Pydantic-modeller) | Partiell (TypedDict) | Minimal |
| Dependency Injection | Inbyggd (FastAPI-stil) | Ingen | Ingen |
| Strukturerade Utdata | Nativa med återförsök | Via utdataanalysatorer | Via JSON-läge |
| Verktygsanrop | @agent.tool-dekorator | @tool-dekorator | funktionsdefinitioner |
| Multi-Agent | Grundläggande handoffs | Avancerad (tillståndsmaskiner) | Handoffs + skyddsräcken |
| Streaming | Typad streaming | Streaming-händelser | Streaming |
| Modellstöd | 10+ leverantörer | Primärt LangChain-modeller | Bara OpenAI |
| Testning | TestModel inbyggt | Ingen inbyggd testning | Ingen inbyggd testning |
| Inlärningskurva | Låg (om du känner Pydantic) | Hög (grafkoncept) | Låg (enkelt API) |
| Community-storlek | Växande (16K stjärnor) | Stor (LangChain-ekosystem) | Växande (OpenAI-stöd) |
| Bäst för | Rena, testbara agenter | Komplexa tillståndsflöden | Projekt med bara OpenAI |
När du Ska Använda Varje
Välj Pydantic AI när du vill ha ren, typsäker agentkod. Det är idealiskt för enfunktionsuppgifter med verktyg (kundsupportbottar, datautvinning, kodsgranskningsagenter) och situationer där testbarhet spelar roll. Om ditt team redan använder FastAPI och Pydantic är inlärningskurvan nästan plan.
Välj LangGraph när du behöver komplexa flerstegsflöden med villkorlig förgrening, mänskligt godkännande i loopen och sofistikerad tillståndshantering. LangGraph utmärker sig på att orkestrera flera steg, inte individuell agentkvalitet. För en djupdykning, se vår fullständiga LangGraph vs CrewAI vs OpenAI Agents SDK-jämförelse.
Välj OpenAI Agents SDK när du är 100% på OpenAI, vill ha den enklaste möjliga installationen och inte behöver stöd för flera leverantörer eller DI.
Kombinationsmönstret
Här är vad erfarna team faktiskt gör: använder Pydantic AI för enskilda agenter (ren kod, testbar, typade utdata) och LangGraph för orkestrering mellan agenter (routing, tillståndsmaskiner, villkorlig logik). De konkurrerar inte -- de är kompletterande lager.
# Pydantic AI-agent -- ren, testbar, typsäker
support_agent = Agent("openai:gpt-4o", result_type=SupportResponse, deps_type=SupportDeps)
# LangGraph-graf -- orkestrerar när man ska anropa vilken 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)Verdict: Välj Pydantic AI för ren, testbar agentkod. Välj LangGraph för komplexa flerstegsflöden. De utesluter inte varandra.
Testa Dina Agenter med TestModel
Det här är avsnittet som separerar en nybörjarguide från en produktionsguide. Varje riktig kodbas behöver tester, och att testa agenter är notoriskt svårt -- LLM-anrop är långsamma, dyra och icke-deterministiska. Pydantic AI levererar en lösning: 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)
# I tester: byt ut den riktiga modellen mot TestModel
def test_support_agent():
with agent.override(model=TestModel()):
result = agent.run_sync("I need help with billing")
# TestModel returnerar giltiga strukturerade data som matchar din result_type
assert isinstance(result.output, SupportResponse)
assert isinstance(result.output.confidence, float)
assert isinstance(result.output.escalate, bool)TestModel genererar giltiga data som matchar din result_type utan att göra några API-anrop. Noll kostnad, deterministisk, snabb. Pydantic AI-testningsdokumentationen täcker avancerade mönster som FunctionModel för anpassade svar och capture_run_messages för att inspektera verktygsanrop.
Testa Verktyg och DI Tillsammans
def test_order_lookup_tool():
# Mock-beroenden
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)Inga API-anrop. Inga flaky tester. Ingen kostnad. Kör detta i CI/CD vid sidan av resten av din testsvit.
Det här är innehållsgapet nr 1 på hela SERP:en. Ingen annan Pydantic AI-guide täcker testning. Om du bygger agenter för produktion är det här vad du behöver.
Observerbarhet -- Logfire-integration på 5 Minuter
Produktionsagenter behöver AI-observerbarhet. Du vill se varje LLM-anrop, verktygsanrop, latens, tokenantal och kostnad. Pydantic AI integreras nativt med Logfire, Pydantic-teamets observerbarhetsplattform (byggd på OpenTelemetry).
import logfire
from pydantic_ai import Agent
logfire.configure() # Använder LOGFIRE_TOKEN-miljövariabeln
logfire.instrument_pydantic_ai()
agent = Agent("openai:gpt-4o", result_type=MovieReview)
# Varje körning spåras nu automatiskt
result = agent.run_sync("Review Inception")Tre rader. Du får fullständiga spårningar som visar: skickad prompt, modellsvar, verktygsanrop (om några), valideringspass/-missar, återförsök, latens och uppskattad kostnad. Om Logfire inte passar dig är Langfuse ett solitt alternativ med öppen källkod med stöd för kontextengineering för att spåra hur dina prompter utvecklas.
Vanliga Frågor
Vad är Pydantic AI och hur skiljer det sig från LangChain?
Pydantic AI är ett typsäkert agentramverk där Python-typdefinitioner driver validering, verktygsscheman och dependency injection. LangChain är ett större ramverk fokuserat på att kedja LLM-anrop. Den avgörande skillnaden: Pydantic AI validerar utdata på ramverksnivå och tillhandahåller inbyggd dependency injection för testbarhet -- LangChain gör inget av det som standard.
Hur bygger jag en typsäker AI-agent med Pydantic AI?
Definiera en Pydantic BaseModel för dina utdata, skicka den som result_type till Agent och anropa run_sync() eller run(). Agenten returnerar en validerad instans av din modell, inte en rå sträng. Se avsnittet Strukturerade Utdata för fullständiga exempel.
Ska jag använda Pydantic AI eller LangGraph för produktionsagenter?
Använd Pydantic AI för enskilda agenter där typsäkerhet, testbarhet och ren kod spelar roll. Använd LangGraph för att orkestrera komplexa flerstegsflöden med villkorlig routing. Många team använder båda -- Pydantic AI-agenter inuti ett LangGraph-orkestreringslaager.
Hur hanterar Pydantic AI verktygsanrop och dependency injection?
Dekorera en funktion med @agent.tool och Pydantic AI läser dess typdefinitioner för att generera verktygets schema. För DI, sätt deps_type på Agent och acceptera RunContext[YourDeps] i verktyg. Körtidsberoenden (DB-anslutningar, API-klienter) flödar utan globalt tillstånd.
Hur lägger jag till streaming i en Pydantic AI-agent?
Använd agent.run_stream() istället för agent.run(). Det returnerar en asynkron kontexthanterare som producerar partiella resultat via stream_structured() eller stream_text(). Slutresultatet är fortfarande fullt validerat mot din result_type.
Är Pydantic AI produktionsklar 2026?
Ja. Version 1.0 lanserades i september 2025 med ett åtagande om API-stabilitet. Det stöds av Pydantic-teamet (det mest nedladdade Python-biblioteket för datavalidering) och är för närvarande på v1.74.0 med regelbundna uppdateringar.
Kan jag använda Pydantic AI med Ollama och lokala modeller?
Ja. Använd Agent("ollama:llama3.1") och se till att Ollama körs lokalt. Installera ollama-leverantörsextran: pip install "pydantic-ai[ollama]". Strukturerade utdata och verktyg fungerar på samma sätt som med molnleverantörer.
Hur testar jag Pydantic AI-agenter?
Använd TestModel -- en mock-modell som genererar giltiga strukturerade data som matchar din result_type utan API-anrop. Omslut ditt test i agent.override(model=TestModel()) och kör assertions på utdata. Se avsnittet Testning för fullständiga pytest-exempel.
Fungerar Pydantic AI med FastAPI?
Perfekt. De delar samma filosofi om dependency injection och är byggda av samma team. Du kan använda Pydantic AI-agenter inuti FastAPI-endpoints, dela beroendetyper dem emellan och strömma agentsvar via StreamingResponse.
Vad är skillnaden mellan Pydantic AI och OpenAI Agents SDK?
Pydantic AI är modellagnostiskt (fungerar med OpenAI, Anthropic, Gemini, Ollama osv.), har dependency injection, TestModel för testning och Pydantic-validering. OpenAI Agents SDK är enklare men låst till OpenAI-modeller och saknar DI och inbyggd testning. Välj Pydantic AI för flexibilitet; välj OpenAI Agents SDK för den enklaste möjliga konfigurationen med bara OpenAI.
Viktigaste Lärdomar och Nästa Steg
| Koncept | Nyckelinsikt | Nästa Steg |
|---|---|---|
| Strukturerade Utdata | Din result_type valideras och återprovas automatiskt | Definiera Pydantic-modeller för alla agentutdata |
| Verktyg | Typdefinitioner ÄR schemat -- inga manuella definitioner | Bygg verktyg med @agent.tool och RunContext |
| Dependency Injection | Skicka körtidsberoenden explicit för testbarhet | Definiera en deps_type-dataclass för varje agent |
| Testning | TestModel eliminerar API-kostnader i CI/CD | Lägg till agent.override(model=TestModel()) i din testsvit |
| Modellleverantörer | Modellbyte på en rad, inga kodändringar | Börja med OpenAI, benchmarka alternativ senare |
| Observerbarhet | 3-raders Logfire-installation för fullständiga spårningar | Lägg till logfire.instrument_pydantic_ai() i produktion |
Börja med en liten agent som har strukturerade utdata. Lägg till ett verktyg. Lägg till beroenden. Skriv ett test med TestModel. Det är produktionsvägen -- och nu har du allt du behöver för att gå den.
Den officiella Pydantic AI-dokumentationen och GitHub-repositoryt är utmärkta för att gå djupare. Ramverket rör sig snabbt, så bokmärk ändringsloggen.