0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pydantic AI v2、エージェントの拡張を「capability」1個に畳んだ設計

0
Posted at

エージェントに「Web検索」と「コード実行サンドボックス」と「セッションをまたぐ記憶」を足したい。よくあるフレームワークだと、この作業は一箇所では終わらない。ツールを登録する場所、システムプロンプトを書き足す場所、実行中にモデルへ渡す文脈を差し替えるフック、モデル設定のノブ、それぞれが別のレイヤーに散らばっていて、機能を1つ増やすたびに4〜5箇所を触ることになる。

Pydantic AI v2 が出した答えは、その散らばりを1個のオブジェクトに畳むことだった。7回のベータを経て、v2.0.0 が2026年6月23日に安定版になっている。

capability は、4つの層を束ねた1個の部品

v2 の中心概念が capability(ケイパビリティ)だ。これは「命令文(instructions)・ツール・ライフサイクルフック・モデル設定」という、エージェントを構成する4つの層を1つにまとめた合成可能な単位を指す。つまり機能追加とは「capability を1個 Agent に渡すこと」に統一される。ミドルウェアをアプリに use() するのに近い感覚だと思えばいい。

たとえばコード実行・Hacker News の MCP サーバー・Web検索を積んだエージェントは、公式リポジトリの例だとこう書ける。

from pydantic_ai import Agent
from pydantic_ai.capabilities import MCP, WebSearch
from pydantic_ai_harness import CodeMode

agent = Agent(
    'anthropic:claude-opus-4-7',
    capabilities=[
        CodeMode(),
        MCP('https://hn.caseyjhand.com/mcp', native=False),
        WebSearch(native=False),
    ],
)

capabilities=[...] に並べたものが、それぞれ内部でツールもプロンプトもフックも登録していく。呼び出し側はリストに一行足すだけで、その機能が要求する全レイヤーの配線が済む。WebSearch(native=False)native は、プロバイダがネイティブ検索を持つならそれを使い、無ければローカル実装にフォールバックする指定だ。CodeMode() は Monty というサンドボックスで動き、本来 N 回に分かれるツール呼び出しを1回の run_code にまとめる。Thinking(effort='high') のように、プロバイダごとにバラバラだった拡張思考を横断で揃える capability もある。

本当のレバレッジは、実行中にモデルへの入力を書き換えるフック

capability が強いのは、ツールを足すだけでなくエージェントの実行ループそのものに割り込めるからだ。v2 のフックは層ごとに整然と分かれていて、命名も規則的になっている。

フックの層 何に割り込むか
Run エージェントの実行全体
Node 実行グラフの各ノード
Model Request モデルへのリクエスト送信
Tool Validate / Execute ツール引数の検証・実行
Output 出力の検証・後処理

各層に before_* / after_* / wrap_* / on_*_error の4種が揃う。wrap_* は前後を包むミドルウェア型、on_*_error は失敗時だけ走る。たとえばモデルへ送る直前に文脈を差し替えるならこうだ。

@hooks.on.before_model_request
async def log_request(ctx: RunContext, request_context: ModelRequestContext) -> ModelRequestContext:
    print(f'Sending {len(request_context.messages)} messages to the model')
    return request_context

request_context を受け取り、加工して返す。ここでメッセージ列を削れば文脈圧縮になり、機密情報を伏せればマスキングになる。「モデルが実際に見る内容を実行中に書き換える」処理を、外付けの capability として配れるようになったのが v2 の勘所だ。プロンプト圧縮やガードレールが、フレームワーク本体をフォークせずに一個の pip パッケージとして流通する。

core は小さく保ち、電池は Harness に外出しした

v2 でもう一つ効いているのが、ライブラリを2つに割った判断だ。

インストール 中身
core(pydantic-ai) uv add pydantic-ai 実行ループ、各プロバイダ、capability と hooks の API、深いプロバイダ連携が要る基幹 capability
Harness(pydantic-ai-harness) uv add pydantic-ai-harness メモリ、ガードレール、文脈管理、ファイルシステム、コード実行などの「電池」

CodeMode の Monty サンドボックスなどは追加依存が要るので、uv add "pydantic-ai-harness[codemode]" のように extras で入れる。Harness 側が抱える capability は幅広い。ファイル操作の FileSystem(パストラバーサル防止つき)、コマンド実行の Shell(許可・拒否リストとタイムアウト)、スライディングウィンドウや LLM による文脈圧縮、セッションをまたぐキーバリューの永続メモリ、コスト/トークン予算・ツールのアクセス制御・秘密情報のマスキング・承認フローといったガードレール群が並ぶ。

割った狙いははっきりしている。core は後方互換を厳格に守って安定させ、動きの速い機能は Harness で速く回す。そして広く必須だと分かった capability は core へ「昇格」させる。React が安定 API と実験 API を分けているのと同じ、成熟度でレイヤーを切る発想だ。

実務で触るときの注意

移行する場合、いきなり v2 に飛ばずまず v1 の最新まで上げて deprecation 警告を全部消すのが公式の勧めで、破壊的変更の多くはそこで顕在化する。OpenAI 系のモデル名は Responses API 準拠に変わっている点、capability を遅延ロードする defer_loading=True がある点も移行時に効いてくる。

設計として気になるのは、capability が「命令・ツール・フック・設定」を全部飲み込む万能部品ゆえに、複数の capability が同じ before_model_request でプロンプトを触り合ったとき、最終的にモデルへ何が渡ったかを追いにくくなりうることだ。リストに並べた順序が挙動を左右する以上、フックの実行順とデバッグ手段はチーム内で早めに握っておいたほうがいい。

とはいえ、エージェント拡張を「配れる1個の部品」に落とし込んだ抽象は素直に良い。自分のエージェントに機能を足すたびに設定ファイルを5箇所いじっていた人ほど、この設計の身軽さは効いてくるはずだ。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?