Claude Media
Claude Agent SDKとPydantic AIの違い — 型で縛るか、ループに任せるか

Claude Agent SDKとPydantic AIの違い — 型で縛るか、ループに任せるか

Pydantic AIは型付きのAgentを任意のモデルで動かし、Claude Agent SDKはClaude Codeのループを組み込みます。構造化出力・依存性注入・ツール定義のコードを並べ、Pythonでの選び方を示します。

違いは「型がエージェントを縛るか、ループが仕事を進めるか」にある

Claude Agent SDKとPydantic AIは、どちらもPythonからエージェントを動かせます。そして、どちらもPydanticの型でデータを検証できます。名前が並ぶと近い道具に見えますが、出発点は別です。

Pydantic AIは、出力の型・依存オブジェクトの型・ツールの引数の型を中心に組む「型付きのAgent」です。モデルは文字列で差し替えます。Claude Agent SDKは、Claude Codeのエージェントループと組み込みツールをライブラリとして渡してくるもので、型は出力の受け口に使う位置づけです。

比べる軸Claude Agent SDKPydantic AI
土台Claude Agent SDKClaude Codeのバイナリが動かすループPydantic AIPythonで書かれた型付きのAgent
モデルClaude Agent SDKClaude(Anthropic・Bedrock・Vertex・Foundry)Pydantic AIOpenAI・Anthropic・Googleなど多数
構造化出力Claude Agent SDKJSON Schemaを渡し、structured_outputを検証して受けるPydantic AIoutput_typeにモデルや関数を渡し、戻り値が型になる
依存性の渡し方Claude Agent SDK専用の仕組みはなく、クロージャーやグローバルで持つPydantic AIdeps_typeとRunContextで型付きで注入
ツールClaude Agent SDK組み込みツール一式に、@toolで足すPydantic AI関数を@agent.toolで登録する(ファイル・シェルはHarnessで足す)
向く仕事Claude Agent SDKファイルとコマンドを触って完結させる作業Pydantic AI型の決まった入出力を持つアプリの中核

比較の左右はPydantic AI側の比較ページの整理とも一致します。同ページはSDKを「Claude Codeのループを受け取る」、Pydantic AIを「ループそのものを持つ」と対比しています。

土台: Claude Codeを動かすか、自前のAgentを動かすか

Agent SDKは、Claude Codeと同じツール・エージェントループ・コンテキスト管理を、PythonとTypeScriptから呼べるようにしたものです。ファイルの読み書き、コマンド実行、Web検索、フック、サブエージェント、権限、セッションが最初から揃っています。動かすのはClaudeで、認証にはAPIキーを使います。

Pydantic AIの紹介ページは、自身を「型付きで拡張できるエージェントループ」と位置づけています。モデルは'anthropic:claude-fable-5-1'のような文字列で指定し、'openai:gpt-6.1-sol'に書き換えれば別の会社のモデルに切り替わります。Claudeを使うことも、使わないこともできます。

ここで次の分かれ道が出ます。

  • Claudeだけで、コード編集のような仕事をそのまま任せたい: Agent SDK
  • モデルを変えうる、または型の決まった業務ロジックの一部としてLLMを呼びたい: Pydantic AI

Pydantic AIにはコーディングエージェントを組むCoderのような部品(Harness)もあります。ただしこれはPydantic AIの上に組み立てる部品であって、Claude Codeの挙動そのものを受け取る仕組みとは別物です。

構造化出力: 同じPydanticモデルでも渡し方が違う

構造化出力は、2つのツールが最も近づく場所です。どちらもPydanticのBaseModelで出力の形を書けます。違いは、そのモデルがどこで検証されるかです。

Agent SDKでは、モデルから作ったJSON Schemaをoutput_formatに渡します。エージェントはツールを使って作業し、最後に検証済みのJSONがResultMessageのstructured_outputに入ります。SDKはスキーマに合うまで再プロンプトし、上限内に通らなければエラー結果になります。

from pydantic import BaseModel
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
 
 
class FeaturePlan(BaseModel):
    feature_name: str
    summary: str
    risks: list[str]
 
 
async def plan():
    async for message in query(
        prompt="Plan how to add dark mode support to a React app.",
        options=ClaudeAgentOptions(
            output_format={
                "type": "json_schema",
                "schema": FeaturePlan.model_json_schema(),
            }
        ),
    ):
        if isinstance(message, ResultMessage) and message.structured_output:
            return FeaturePlan.model_validate(message.structured_output)

最後のmodel_validateで型付きのオブジェクトに戻すのは、呼び出し側の仕事です。スキーマを渡す側と、型に戻す側が分かれています。

Pydantic AIでは、モデルをそのままoutput_typeに渡します。

from pydantic import BaseModel
from pydantic_ai import Agent
 
 
class FeaturePlan(BaseModel):
    feature_name: str
    summary: str
    risks: list[str]
 
 
agent = Agent("anthropic:claude-fable-5-1", output_type=FeaturePlan)
result = agent.run_sync("Plan how to add dark mode support to a React app.")
plan = result.output  # FeaturePlan として型が付く

AgentがAgent[依存の型, 出力の型]というジェネリクスなので、result.outputは型チェッカーにもFeaturePlanとして見えます。既定の出力モードでは、スキーマが特別な出力ツールの引数としてモデルに渡されます。ほかに、ネイティブの構造化出力を使うNativeOutputと、スキーマをプロンプトに差し込むPromptedOutputも選べます。

失敗時の動きも異なります。

失敗したときClaude Agent SDKPydantic AI
検証に通らないClaude Agent SDKSDKが再プロンプトし、上限超過でerror_max_structured_output_retriesPydantic AIモデルに差し戻して再試行し、出力ツールごとに再試行の枠を持つ
自分で再試行を促すClaude Agent SDK再プロンプトはSDKが担うPydantic AI出力関数の中でModelRetryを送出して差し戻せる
成功に見えて空Claude Agent SDKsubtypeがsuccessでもstructured_outputが無い場合があるPydantic AI戻り値は検証済みの型

SDKの側では、successだけを見て終わらせない書き方が要ります。subtypeがsuccessでもstructured_outputが空のまま返る場合があるためです。SDKの構造化出力は内部ではStructuredOutputという名前のツール呼び出しとして現れるので、ツール呼び出しをUIに出すアプリでは、これを「エージェントが選んだ手順」として表示しない処理も必要になります。

SDKの構造化出力の細部はAgent SDKの構造化出力入門にまとめています。

依存性注入: 型で注入するか、ツールの外で持つか

依存性注入は、2つの設計思想がもっとも分かりやすく出る場所です。

Pydantic AIは、DB接続やHTTPクライアントをdataclassにまとめ、deps_typeで型を宣言し、実行時にdeps=で渡します。ツールや動的な指示文はRunContext[依存の型]を第1引数に受け取り、ctx.depsから取り出します。型を間違えれば型チェッカーが指摘します。

from dataclasses import dataclass
 
from pydantic_ai import Agent, RunContext
 
from bank_database import DatabaseConn  # 公式の例が使う架空のDB接続
 
 
@dataclass
class SupportDeps:
    customer_id: int
    db: DatabaseConn
 
 
support_agent = Agent(
    "anthropic:claude-fable-5-1",
    deps_type=SupportDeps,
    instructions="You are a support agent in our bank.",
)
 
 
@support_agent.tool
async def customer_balance(ctx: RunContext[SupportDeps]) -> float:
    """Returns the customer's current account balance."""
    return await ctx.deps.db.customer_balance(id=ctx.deps.customer_id)

テストでは、agent.override(deps=...)で依存を差し替えられます。本物のDBを渡さずに、同じAgentを単体テストへ載せられるのが利点です。トップページには、オフラインで動く組み込みの'test'モデルを使う手も紹介されています。

Agent SDKのドキュメントには、これに相当する型付きの注入口の節がありません。@toolの関数はアプリのプロセス内で動くので、DB接続などはクロージャーやモジュールの変数で持つことになります。差し替えたいなら、ツールを作る関数に接続を引数で渡す形に自分で組みます。

def make_balance_tool(db):
    @tool("customer_balance", "Get the balance", {"customer_id": int})
    async def customer_balance(args):
        balance = await db.customer_balance(id=args["customer_id"])
        return {"content": [{"type": "text", "text": str(balance)}]}
 
    return customer_balance

上の形はSDKの@toolの書式に沿った例で、ドキュメントに載る型付き注入の機能ではありません。テストで差し替えたい依存が多いアプリほど、Pydantic AIのdepsが効きます。

ツール定義: 関数の型から作るか、スキーマとハンドラーを書くか

Pydantic AIのツールは、型注釈付きの関数に@agent.tool(RunContextを使わないなら@agent.tool_plain)を付けるだけです。関数のシグネチャがツールのスキーマになり、docstringがモデルに渡る説明になります。引数はPydanticで検証され、失敗はモデルに返されて再試行されます。

Agent SDKのツールは、名前・説明・入力スキーマ・ハンドラーの4つで定義します。Pythonでは@toolに型の辞書({"latitude": float}など)を渡し、Annotatedで項目の説明を足せます。ハンドラーはcontentの配列を返す形で、create_sdk_mcp_serverでアプリ内のMCPサーバーにまとめてmcp_serversに渡します。

項目Claude Agent SDKPydantic AI
定義の起点Claude Agent SDK名前・説明・スキーマ・ハンドラーの4点Pydantic AI型注釈付きの関数とdocstring
スキーマの出どころClaude Agent SDK型の辞書またはJSON SchemaPydantic AI関数のシグネチャ
戻り値Claude Agent SDKcontentブロックの配列Pydantic AI関数が返す型
エラーClaude Agent SDKisError相当で内容を組み立てて返せるPydantic AIModelRetryで差し戻せる
登録Claude Agent SDKアプリ内MCPサーバー経由Pydantic AIAgentへ直接

SDKでは、ハンドラーが例外を投げてもエージェントのループは止まりません。SDKのMCPサーバーが例外を拾い、生のメッセージをエラー結果としてClaudeに渡します。意図した文面を読ませたいときは、自分でエラーを組み立てて返します。

Agent SDKの強みは、組み込みツールがすでにあることです。ファイル編集やコマンド実行を自作する必要はなく、allowed_toolsで許可を絞るだけで済みます。Pydantic AIでは、同等のものをCoderなどのHarnessから足す形になります。

止め方と観測: 権限・予算か、型・テスト・トレースか

「勝手に走りすぎない」ための道具の置き場も違います。

Agent SDKは、権限の評価順(フック、拒否ルール、確認ルール、権限モード、許可ルール)と、max_turns・max_budget_usdといった上限で止めます。対象はファイルとコマンドで、ツール呼び出しの手前で拒否できます。無人の実行で何を許すかを決めるときの設計は、Agent SDKのHooksとpermission_deniedの扱いが参考になります。

Pydantic AIは、型で受けられないデータを実行時の検証で弾き、'test'モデルや依存の差し替えで挙動を検証し、OpenTelemetryのスパンで中身を追います。紹介ページによれば、計装は標準のOpenTelemetryで、logfire.instrument_pydantic_ai()の1行でPydantic Logfireに送れますし、OTLPに対応する別のバックエンドでも使えます。長時間の実行を再開できる耐久実行(Temporal・DBOS・Prefectなど)も、Pydantic AI側の特長として挙げられています。

なお、Pydantic AIの比較ページは、Pydantic側が書いた対比表です。SDKに耐久実行・評価・画像生成などが「ない」とする行も、同じページの整理であることを前提に読む必要があります。

選ぶ基準: 何を型にしたいかで決める

2つは排他ではなく、解く問題が違います。選ぶ観点を3つに絞ります。

判断軸

選び分けの3つの観点

  • 仕事の中身

    リポジトリを読み、コマンドを走らせて直す仕事ならAgent SDKです。既存のデータを受け取って分類・抽出・判断するアプリの一部なら、Pydantic AIが素直です。

  • モデルの前提

    Claudeに固定してよいならSDKの組み込みツールが効きます。将来のモデル変更やコスト比較を残したいなら、文字列で切り替えられるPydantic AIです。

  • テストの置き方

    依存を差し替えた単体テストを書きたい設計ならPydantic AIです。SDKは、権限と上限で動作範囲を絞る方向で安全を作ります。

すでにAgent SDKで組んでいて、型付きの依存とテストが欲しくなった場合は、Pydantic AIが用意した移行用のスキルで、動作を保ったまま1経路ずつ移す方法が紹介されています。逆にSDKへ寄せる場合の移行手段はドキュメントに記載がなく、@toolへの書き直しを見込むことになります。

LangGraphなど、ほかのフレームワークとの位置づけはClaude Agent SDKとLangGraphの違い、ロール分担型のCrewAIとの違いはClaude Agent SDKとCrewAIの違いで扱っています。ループ側の動きを先につかむならAgent SDKのエージェントループが入口です。

導入コマンドの違い

どちらもpipで入ります。

pip install claude-agent-sdk
pip install pydantic-ai

Agent SDKはAPIキー(ANTHROPIC_API_KEY)の設定が前提で、Claude Codeのバイナリを呼びます。Pydantic AIはモデルごとのAPIキーを環境に置くだけで動き、キーなしで試すならAgent('test')が使えます。

まとめ

型を中心に据えてLLMをアプリの部品として呼ぶならPydantic AI、Claude Codeの仕事ぶりをそのまま自分のアプリに載せるならAgent SDKです。構造化出力は両方で書けるので、決め手になるのは出力ではなく、依存の注入とツールの前提でした。

この記事を共有:XはてブLinkedIn