PydanticAI ビジュアルガイド

Lesson CH07-L01

Toolset

複数ツールをクラスにまとめ、Agentに付け替え可能にする。

読了目安
10 min
Colab目安
15 min
合計
25 min
前提
YouTube URL 直接入力

関連: 公式ドキュメント

一行サマリ

FunctionToolset で関連ツールをひとまとめにし、Agent(toolsets=[...])Agent に「束」として付け替え可能 にする。prefixed() filtered() renamed() CombinedToolset再利用 / 名前衝突回避 / 動的差し替え ができ、Ch3 の @agent.tool 単発登録より大規模設計に強い。

ヒーロー: ツールを「束」にする

Ch3 では @agent.tool で関数を 1 個ずつ Agent に直結させていました。Toolset はそれを 「Agent から切り離して束として取り回す」 ための仕組み。検索系・天気系・社内 DB 系のように 目的別に固まった束 を、複数 Agent で再利用したり、実行時に差し替えたりできます。

図を読み込み中…
図1. @agent.tool 直結 vs Toolset 束

概念: 4 つの基本形と合成

型 / 操作役割
FunctionToolset関数のリストを束にする基本クラス
CombinedToolset複数 Toolset を 1 つに統合
.prefixed('weather')ツール名にプレフィックスを付けて衝突回避
.filtered(predicate)条件に合うツールだけ通す
.renamed({old: new})ツール名を任意にリネーム

すべて メソッドチェーン可能 で、toolset.prefixed('api').filtered(lambda c, t: not t.name.startswith('_')) のように合成できます。

コード: 3 つのパターン

パターン 1: FunctionToolset を作って Agent に渡す

from pydantic_ai import Agent, FunctionToolset, RunContext
from pydantic_ai.models.google import GoogleModel
 
# 関数を 2 通りの方法で登録
weather = FunctionToolset()
 
@weather.tool_plain
def temperature(city: str) -> float:
    """指定都市の現在気温 (摂氏) を返す。"""
    table = {'Tokyo': 22.5, 'Osaka': 24.1, 'Sapporo': 12.0}
    return table.get(city, 20.0)
 
@weather.tool
def conditions(ctx: RunContext, city: str) -> str:
    """指定都市の現在の天気を文字列で返す。"""
    return f'{city}: 晴れ'
 
agent = Agent(
    GoogleModel('gemini-3-flash-preview'),
    toolsets=[weather],
    instructions='天気の質問には toolset を使って答えてください。',
)
 
print(agent.run_sync('東京の気温と天気は?').output)

ポイント:

  • FunctionToolset() を作って @toolset.tool / @toolset.tool_plain で登録
  • Agent には toolsets=[weather]リスト渡し
  • 同じ weather を別 Agent でも Agent(..., toolsets=[weather]) で再利用可能

パターン 2: 複数 Toolset を CombinedToolset で統合

from pydantic_ai import Agent, CombinedToolset, FunctionToolset
from pydantic_ai.models.google import GoogleModel
 
calc = FunctionToolset()
 
@calc.tool_plain
def add(a: float, b: float) -> float:
    """2 数の和。"""
    return a + b
 
@calc.tool_plain
def multiply(a: float, b: float) -> float:
    """2 数の積。"""
    return a * b
 
# weather (上のセル) と統合
all_tools = CombinedToolset([weather, calc])
 
agent = Agent(
    GoogleModel('gemini-3-flash-preview'),
    toolsets=[all_tools],
    instructions='必要に応じて天気と計算のツールを使ってください。',
)
 
print(agent.run_sync('大阪と札幌の気温の差は?').output)

CombinedToolset複数の束を 1 束に見せる だけのシンプルなラッパ。Agent 側は 1 個の Toolset を見ているのと同じ感覚で使えます。

パターン 3: prefixed で名前衝突回避

天気系 Toolset と株価系 Toolset の両方に current() がある場合、そのままでは衝突します。

stocks = FunctionToolset()
 
@stocks.tool_plain
def current(symbol: str) -> float:
    """指定銘柄の現在株価。"""
    return 150.5
 
# 同名ツールが weather にあるとして、prefix で衝突回避
combined = CombinedToolset([
    weather.prefixed('weather'),   # weather_temperature, weather_conditions
    stocks.prefixed('stock'),       # stock_current
])
 
agent = Agent(GoogleModel('gemini-3-flash-preview'), toolsets=[combined])

renamed({'old': 'new'}) で個別リネーム、filtered(lambda ctx, t: ...)特定の Agent からだけ一部ツールを隠す といった応用が効きます。

図を読み込み中…
図2. Toolset 操作の合成例

観察: 動的差し替え (agent.override)

Ch3-L04 で扱った agent.override(deps=...) と同じ感覚で、Toolset も override(toolsets=[...]) で実行時に差し替えられます。テスト時にモック束を当てる、ユーザー権限で切り替える、といった用途に最適。

mock_tools = FunctionToolset()
 
@mock_tools.tool_plain
def temperature(city: str) -> float:
    return 99.9  # テスト用固定値
 
with agent.override(toolsets=[mock_tools]):
    print(agent.run_sync('東京の気温').output)

まとめ

  • FunctionToolset で関連ツールを束にし、Agent(toolsets=[...]) で複数 Agent に使い回せる
  • CombinedToolset / prefixed / filtered / renamedメソッドチェーン で合成
  • agent.override(toolsets=[...]) で実行時差し替え (テスト・権限切り替え)
  • @agent.tool 直結 (Ch3) より 大規模 / 再利用 / テスト に強い設計

次レッスンでは MCP クライアント — 外部 MCP サーバーのツールをそのまま Agent に統合する仕組みを扱います (Toolset の延長で Agent(toolsets=[mcp_server]) で繋がる)。

Colab で実際に動かす

本レッスンの内容を Google Colab 上で実行できるノートブックを用意しています。下のボタンから自分のColab環境に開けます (要 Google アカウント / GOOGLE_API_KEY)。

Open in Colab

notebooks/ch07/01-toolset.ipynb