Pydantic AI: Langkah Natural Berikutnya Setelah Pydantic v2

Kamu sudah pakai Pydantic v2 untuk validasi data. Sekarang pakai model yang sama untuk validasi output LLM — type-safe, testable, tanpa overhead LangChain.

Kamu sudah pakai Pydantic v2 untuk validasi API payloads, config files, dan database records. Model-model, type hints, field constraints: semua itu sudah muscle memory.

Sekarang bayangkan validasi output LLM dengan model yang persis sama. Tidak ada JSON parsing. Tidak ada string matching. Tinggal result.output return Python object yang sudah dikenal IDE-mu.

Itulah Pydantic AI: type-safe agent framework dari tim yang membangun Pydantic. 18.8k stars, 290 releases, dan framework agent Python yang paling cepat bergerak di tahun 2026.

Kenapa Framework Agent Lain?

LangChain punya ekosistem-nya. CrewAI punya marketing-nya. Tapi keduanya treat data sebagai strings dan tool arguments sebagai dictionaries. Kamu tulis tool schemas di YAML, passing context sebagai loose kwargs, dan berharap LLM menghasilkan shape yang benar. Type checkers tidak bisa bantu kamu. Tests butuh full stack.

Pydantic AI mengambil pendekatan yang berbeda: type safety bukan nice-to-have, itu adalah arsitektur. Agents generic atas dependency dan output types. Tools menerima typed RunContext objects. Static type checkers (mypy, pyright) menangkap ketidakcocokan di write-time, bukan runtime.

Bayangkan FastAPI: kamu tidak butuh framework baru untuk handle HTTP, tapi pendekatan type-driven-nya membuat yang lain terasa outdated. Pydantic AI melakukan hal yang sama untuk AI agents.

Dasar-Dasar: Agent + Tool

Agent adalah typed wrapper di atas LLM. Tools adalah fungsi biasa yang di-decorate dengan @agent.tool.

from pydantic_ai import Agent, RunContext

roulette_agent = Agent(
    'openai:gpt-5.2',
    deps_type=int,
    output_type=bool,
    instructions=(
        'Use the `roulette_wheel` function to see if the '
        'customer has won based on the number they provide.'
    ),
)

@roulette_agent.tool
async def roulette_wheel(ctx: RunContext[int], square: int) -> str:
    """check if the square is a winner"""
    return 'winner' if square == ctx.deps else 'loser'

result = roulette_agent.run_sync('Put my money on square eighteen', deps=18)
print(result.output)  # True

Dua hal yang perlu diperhatikan:

  1. deps_type=int: agent tahu type dependencies-nya. ctx.deps di-typed sebagai int. Kalau kamu ganti dependency, type checkers update tool signatures secara otomatis.

  2. output_type=bool: response LLM divalidasi dan di-cast ke bool. Tidak ada JSON parsing, tidak ada string comparison. result.output adalah Python bool.

Structured Output dengan Pydantic Models

Tapi yang lebih berguna: alih-alih bool, gunakan Pydantic model apa saja:

from dataclasses import dataclass
from pydantic import BaseModel, Field
from pydantic_ai import Agent, RunContext

@dataclass
class SupportDeps:
    customer_id: int
    db: DatabaseConn

class SupportOutput(BaseModel):
    support_advice: str = Field(description='Advice returned')
    block_card: bool = Field(description="Block the customer's card?")
    risk: int = Field(description='Risk level', ge=0, le=10)

support_agent = Agent(
    'openai:gpt-5.2',
    deps_type=SupportDeps,
    output_type=SupportOutput,
    instructions='You are a bank support agent.',
)

@support_agent.instructions
async def add_customer_name(ctx: RunContext[SupportDeps]) -> str:
    name = await ctx.deps.db.customer_name(id=ctx.deps.customer_id)
    return f"The customer's name is {name!r}"

@support_agent.tool
async def customer_balance(
    ctx: RunContext[SupportDeps], include_pending: bool
) -> float:
    """Returns the customer's current account balance."""
    return await ctx.deps.db.customer_balance(
        id=ctx.deps.customer_id,
        include_pending=include_pending,
    )

async def main():
    deps = SupportDeps(customer_id=123, db=DatabaseConn())
    result = await support_agent.run('What is my balance?', deps=deps)
    print(result.output)
    # SupportOutput(
    #   support_advice='Hello John, your balance is $123.45',
    #   block_card=False,
    #   risk=1,
    # )

LLM tidak hanya return string yang kamu harap adalah JSON. Pydantic membangun JSON Schema dari SupportOutput, kirim ke model, validasi response, dan return SupportOutput instance yang fully typed. support_advice adalah string. risk antara 0 dan 10. block_card adalah bool. Tidak ada manual parsing.

Dependency Injection yang Benar-Benar Works

LangChain passing dependencies melalui global registries atau loose kwargs. RunContext[T] milik Pydantic AI berbeda: typed, per-run, dan isolated.

Setiap agent.run() call mendapat instance deps sendiri. Tools, dynamic instructions, dan output validators semuanya menerima RunContext[SupportDeps] yang sama. Artinya:

  • Tools bisa akses ctx.deps.db tanpa global state
  • Tests bisa mock SupportDeps dengan mudah
  • Concurrent runs tidak share mutable state

Pattern-nya: instance deps baru per run. Bukan singleton, bukan global; typed value yang kamu passing secara eksplisit.

Testing Tanpa API Key

Killer feature-nya: Agent('test').

Passing string 'test' sebagai model, dan setiap contoh di post ini berjalan tanpa API key. Tidak ada mocking. Tidak ada fixtures. Tidak ada monkey-patching. Agent return responses deterministik dari instruksi, tools, dan output schema-nya.

# Every example in this post works with:
test_agent = Agent('test')
# No API key needed. No network calls.

Framework lain jarang bisa claim ini. LangChain butuh mock LLM di setiap level. CrewAI butuh instance berjalan. Pydantic AI punya zero-config test model yang jalan lewat full agent pipeline: tool calling, structured output validation, dependency injection; tanpa satu pun network call.

Tulis agent-mu, passing 'test', verifikasi logic-nya. Kalau sudah confident, swap ke real model dan deploy.

Capabilities: Perilaku Agent yang Composable

Capabilities bundling tools, instructions, hooks, dan model settings ke reusable units. Ini inovasi v2.x; abstraksi level lebih tinggi daripada registrasi tool individual.

from pydantic_ai import Agent
from pydantic_ai.capabilities import Thinking, WebSearch

agent = Agent(
    'anthropic:claude-sonnet-4-6',
    instructions='Be thorough and cite sources.',
    capabilities=[
        Thinking(effort='high'),
        WebSearch(local='duckduckgo'),
    ],
)

result = agent.run_sync('What was the mass of the largest meteorite found this year?')
print(result.output)

Built-in capabilities termasuk Thinking, WebSearch, WebFetch, ImageGeneration, MCP, dan ToolSearch. Third-party capabilities tersedia via library Pydantic AI Harness.

Lebih bersih dari chain-of-chains milik LangChain. Setiap capability self-contained; punya tools, instructions, dan hooks-nya sendiri. Kamu cukup declare, tidak perlu wiring manual.

Streaming dengan Partial Validation

Streaming structured output dengan partial validation adalah area di mana Pydantic AI memisahkan diri. Panggil run_stream() dan kamu dapat validated partial chunks saat model generate:

from pydantic_ai import Agent
from pydantic import BaseModel

class Article(BaseModel):
    title: str
    summary: str
    word_count: int

agent = Agent('openai:gpt-5.2', output_type=Article)

async with agent.run_stream('Write about LLM observability') as stream:
    async for partial in stream.stream_structured():
        # Every ~100ms, a partially validated Article instance
        # title, summary, word_count appear as the model generates them
        pass

Setiap chunk divalidasi terhadap Pydantic model secara incremental. UI-mu bisa render partial state saat LLM selesai berpikir. Parameter debounce_by mengontrol emission cadence; default ~100ms, atau set debounce_by=None untuk production di mana real-time UX tidak diperlukan.

MCP Support: Agents sebagai Consumers dan Servers

Pydantic AI mendukung Model Context Protocol (MCP) dalam dua mode:

  • Local MCP: menjalankan MCP server di process-mu. Credentials tetap lokal. Cocok untuk database tools, internal APIs, dan apapun yang tidak ingin kamu expose.
  • Native MCP: delegasi ke native MCP support provider jika tersedia.

Agent-mu bisa consume MCP servers (akses database, file system, external tools) dan bertindak sebagai MCP server sendiri; expose kapabilitasnya ke agent lain. Tidak banyak Python agent framework yang bisa serve dua peran ini sekaligus.

Pydantic AI vs LangChain vs CrewAI

Feature Pydantic AI LangChain CrewAI
Type safety Full (generic agents, typed deps) Partial (typed tools, loose deps) Minimal
Dependency injection RunContext[T], per-run isolation Global registry / kwargs Config-based
Structured output Pydantic models, JSON Schema, 4 modes Pydantic output parsers Pydantic models
Streaming run_stream(), partial validation astream_events() Limited
MCP support Native (local + native modes) Via community integrations Not native
Ecosystem size Growing fast (18.8k stars, 290 releases) Massive (50+ loaders, 200+ integrations) Medium
Test model Agent('test') — zero config Requires LLM mock Requires LLM mock
Durable execution Temporal, DBOS, Prefect Not built-in Not built-in
Observability Pydantic Logfire (OTel) LangSmith / LangFuse Not built-in
Learning curve Low (FastAPI-like) High (many abstractions) Medium

Trade-offs yang Jujur

Pilih Pydantic AI saat:

  • Kamu sudah pakai Pydantic v2 dan mau ergonomi yang sama untuk agents
  • Type safety dan testability lebih penting daripada pre-built integrations
  • Kamu mau Agent('test') untuk development lokal yang cepat
  • MCP support adalah requirement
  • Kamu butuh durable execution (agent survive API failures)

Tetap dengan LangChain saat:

  • Kamu butuh 50+ pre-built document loaders, vector store integrations, dan RAG pipelines out of the box
  • Tim-mu sudah tahu LangChain dan biaya migrasi tidak worth it
  • Kamu membangun prototype di mana speed-to-deploy mengalahkan type safety

Realitasnya: Ekosistem Pydantic AI lebih kecil. Ada lebih sedikit third-party tools, lebih sedikit tutorials, lebih sedikit StackOverflow answers. V2.x line dirilis Juni 2026; usianya kurang dari dua bulan. Kalau kamu temui edge case, kamu akan baca source code, bukan blog posts.

Tapi tim Pydantic bergerak cepat. 290 releases dalam hitungan bulan, update hampir setiap hari. Framework yang kamu pakai bulan September tidak akan terlihat sama dengan yang kamu install hari ini. Dan fondasi type-safe-nya berarti kamu membangun di atas sesuatu yang scalable, bukan prototype yang break saat traffic naik.

Observability Tanpa Kebisingan

Production agents butuh visibilitas. Satu baris mengaktifkan tracing Pydantic Logfire:

import logfire

logfire.instrument_pydantic_ai()
# Now every agent run, tool call, and LLM request is traced
# Costs, latency, tool arguments, model outputs — all visible
# OpenTelemetry-compatible, works with your existing stack

Tidak ada SDK changes. Tidak ada decorator wrapping. Tinggal import dan instrument. Traces mencakup tool call durations, token usage per call, dan full agent reasoning chain. Kritis untuk debugging kenapa agent memanggil tool yang sama 15 kali atau kenapa latency lonjakan jam 3 pagi.

Catatan Singkat tentang Versi

Post ini mencakup Pydantic AI v2.x (dirilis Juni 2026). Kalau kamu pernah membaca tutorial lama, mereka merujuk ke v1.x yang punya API berbeda:

  • result.dataresult.output (v2)
  • Agent wrappers untuk durability → Capabilities system (v2)
  • RunContext.deps sebagai sole argument → Full RunContext[T] typing (v2)

Contoh kode dari sebelum Juni 2026 tidak akan bekerja dengan pydantic-ai versi sekarang. Cek versi sebelum copy-paste.

Memulai

pip install pydantic-ai
# or
uv add pydantic-ai

Python 3.10+. MIT license. Ekstensi opsional untuk fitur spesifik provider (pydantic-ai[openai], pydantic-ai[anthropic], dll).

Kesimpulan

Pydantic AI tidak mencoba menggantikan ekosistem LangChain. Ia memecahkan masalah yang berbeda: apa yang terjadi saat kamu mengambil pengembangan agent dengan serius: type safety, testability, observability, dan production reliability.

Kalau kamu sudah baca Post 3 tentang Pydantic v2 production patterns, ini adalah bab selanjutnya. Model yang sama yang memvalidasi API requests-mu kini memvalidasi LLM output-mu. Type hints yang sama yang menangkap bugs di database layer-mu kini menangkap bugs di agent pipeline-mu.

Dan kalau kamu membaca Post 4 tentang DSPy, catat bahwa Pydantic AI dan DSPy saling melengkapi: DSPy mengoptimasi prompts dan programs-mu, Pydantic AI mengeksekusinya dengan type safety. Layer yang berbeda dari stack yang sama.

Coba mulai dari Agent('test'), jalankan contoh-contohnya, dan rasakan sendiri apakah type safety-nya worth it untuk stack yang kamu build.

Pydantic AI v2.16.0 | MIT License | Python ≥3.10 | ai.pydantic.dev