AI エージェントのツール設計とスケール — 結局どうすればいいか
14本を統合する。「1本をどう書くか」と「増えたときどうするか」は別の問題なので、分けて扱う。
第1部: 1本のツールをどう書くか
1. 既存 API の薄いラッパーにしない
最も繰り返される主張。
エージェント向けのツールは既存 API の薄いラッパーであってはならない。実際のワークフロー単位に統合され、返り値が高信号で、エラーが指示的であるべき —
writing-tools-for-agents
なぜか: API は「機械が呼ぶ」前提で分割されている。エージェントはタスク単位で考えるので、API の粒度で並べると、1つの目的に多数の呼び出しが要る。
具体的な処方:
| ❌ | ✅ |
|---|---|
create_pr / review_pr / merge_pr を別ツールに | action パラメータを持つ1つのツールに統合 |
| 内部 ID を返す | 意味のある安定した識別子(slug、UUID)を返す |
| API のレスポンス全体を返す | 次のステップの推論に必要なフィールドだけ返す |
Fewer, more capable tools reduce selection ambiguity and make your tool surface easier for Claude to navigate. —
define-tools数が少なく高機能なツールは選択の曖昧さを減らし、Claude がツール群を辿りやすくする。
2. description が最重要。3〜4文以上
Provide extremely detailed descriptions. This is by far the most important factor in tool performance. —
define-tools極めて詳細な説明を書け。これがツールの性能を左右する、群を抜いて最も重要な要因である。
書くべき4点:
- 何をするか
- いつ使うべきか、そしていつ使うべきでないか
- 各パラメータの意味と、挙動への影響
- 重要な制限。特に「このツールが返さない情報」
良い例と悪い例の差は「返さないもの」を書いているか:
✅ ...The tool will return the latest trade price in USD. It should be used when the user
asks about the current or most recent price of a specific stock.
It will not provide any other information about the stock or company.
❌ Gets the stock price for a ticker.3. スキーマで表せないことは input_examples で
JSON Schema はパラメータ間の相関や慣習を表現できない。 ネストしたオブジェクト、任意パラメータ、形式に敏感な入力があるときに効く。
効果は明確: 複雑なパラメータ処理の精度が 72% → 90%(advanced-tool-use)。
巧い書き方は「フル装備 → 中間 → 最小」の3段階を見せること。任意パラメータをいつ含めるべきかが伝わる。
"input_examples": [
{"location": "San Francisco, CA", "unit": "fahrenheit"},
{"location": "Tokyo, Japan", "unit": "celsius"},
{"location": "New York, NY"}, # 'unit' is optional
]コスト: 単純な例で 20〜50 トークン、複雑なもので 100〜200 トークン。server tool(web search、code execution など)と client toolset(computer use・browser use)では使えない。
4. エラー耐性のある設計にする
swe-bench-sonnet の “error-proof our tools” が最も具体的。現在の Claude Code の組み込みツールの原型。
| 工夫 | 効果 |
|---|---|
| 絶対パスを必須にする | 相対パスの誤りを構造的に防ぐ |
str_replace は完全一致を要求し、0件でも2件以上でも失敗させる | 曖昧な置換を成立させない |
old_str の一意性要件を description に明記 | 失敗の原因が Claude に伝わる |
一般則: 「間違えられない形」にする。 曖昧な入力を受理して曖昧に動くより、明示的に失敗して理由を返すほうがエージェントには扱いやすい。
5. 自分でツールを設計させる
We found that the Claude 4 models can be excellent prompt engineers. —
multi-agent-research-systemClaude 4 系のモデルは優れた prompt engineer になりうると分かった。
ツールの説明文を改善させる「ツールテストエージェント」を作った結果、以降のエージェントのタスク完了時間が 40% 短縮した。
writing-tools-for-agents のタイトル自体が “with agents” である。ツール設計は eval を回して初めて良し悪しが分かるので、その反復をエージェントにやらせる。
第2部: ツールが増えたときどうするか
6. 問題は2つある。context と精度
context だけの話ではないというのが重要。
| 問題 | 実測 |
|---|---|
| context 肥大 | 複数 MCP サーバ構成で会話開始前に 55K〜134K トークン |
| 選択精度の劣化 | 利用可能なツールが 30〜50個を超えると、正しいツールを選ぶ能力が落ちる |
→ 「context に余裕があるから放置してよい」わけではない。
7. 4つの発生源に4つの対処
まず自分のトークンがどこへ消えているかを特定する。
| 発生源 | 対処 | しきい値 | 効果 |
|---|---|---|---|
| ツール定義の先読み | tool search | 10個以上 / 定義 10kトークン超 / MCP 複数集約 | 85%減(72K → 8.7K) |
tool_result の往復 | programmatic tool calling | fan-out 型のみ | 37%減。逐次型は +8% |
| 同じ定義への繰り返しの支払い | prompt caching | 初日から | 読み取りが 0.1倍(Opus 5.5 は 0.05倍、Fable 5.1 / Mythos 5.1 は 0.025倍) |
古い tool_result の蓄積 | context editing | 会話が長引いたら | 選択的に落とす |
導入順が推奨されている(manage-tool-context):
- prompt caching —— 初日から。cache write は 25% 割増だが 2回目のヒットで元が取れる
- tool search —— ツールが 20個を超えたら
- context editing —— 初期の
tool_resultが無関係になったら - programmatic tool calling —— 小さなツール呼び出しの連鎖が繰り返し現れたら
8. tool search を使うときの実務
defer_loading は「送るもの」ではなく「context に入るもの」を制御する。
You still send every tool’s full definition in the
toolsarray on every request, including the deferred ones.それでも毎リクエストで、
tools配列にはすべてのツールの完全な定義を送っている。遅延ロード対象のものも含めてである。
設計上のコツ:
- 最頻出の 3〜5 個は非 deferred のままにする(検索せずに呼べる)
- ツール名に一貫した namespace を使う(
github_、slack_)→ 1回の検索でグループ全体がマッチする tool_searchツール自身にdefer_loadingを付けない(全 deferred は 400 エラー)defer_loading: trueにcache_controlは付けられない(400)- computer use / browser use の toolset は、
defer_loadingをエントリではなくconfigsのメンバーごとに書く(エントリに書くと拒否される。有効なメンバー全部で同じ値にし、見つかると全メンバーが一度に読まれる) - 1回の検索が返すのは既定で5件、Claude が
limitで 1〜10,000 に変えられる - Amazon Bedrock では、サーバ側の tool search は InvokeModel API でだけ使える(Converse API では使えない)
prompt caching は壊れない。 API は deferred なツールを system prompt の prefix から除外し、発見時に会話内へ tool_reference を追記する設計になっている。
9. programmatic tool calling は向き不向きが激しい
最も誤用されやすい。 実測が明快に分かれている。
| ワークロード | 結果 |
|---|---|
| 75ツールのプロジェクト管理エージェント | 課金入力トークン 38%減、精度は変化なし |
| τ²-bench(1ターンに1〜2回の逐次呼び出し) | スコア変化なし、コスト 8% 増 |
| 本番トラフィック(ツール定義 10〜49個) | 20〜40% 削減 |
If you are unsure, measure billed input tokens with and without
allowed_callerson a representative sample of your traffic before enabling it broadly.判断がつかないなら、広く有効にする前に、代表的なトラフィックのサンプルで
allowed_callersの有無それぞれで課金対象の入力トークンを測れ。
向く: 多数項目への fan-out / 大きな結果をフィルタできる / agentic な検索と取得 向かない: 厳密に逐次 / 少数かつ小さい応答 / 呼び出し間にユーザーのフィードバックが要る
ツール設計側の要求も変わる:
Because Claude deserializes tool results in code, document the format (JSON structure and field types).
Claude はツールの結果をコード内でデシリアライズするため、その形式(JSON の構造とフィールドの型)を文書化せよ。
→ プログラム的に呼ばれるツールは、返り値のスキーマを description に書く。
10. MCP をコードの API として出す
code-execution-with-mcp は最も削減幅が大きい(150,000 → 2,000 トークン、98.7%減)。
仕組み: MCP サーバをファイルツリーとして提示し、各ツールを import 可能な関数にする。ツールを直接呼ばせる代わりにコードを書かせる。
5つの利点(context 以外も大きい):
| 利点 | 中身 |
|---|---|
| progressive disclosure | 必要なツールだけ読ませる。削減の主因 |
| context 効率の良い結果 | 1万行を実行環境でフィルタし、先頭5件だけログ出力 |
| 強力な制御フロー | ループ・条件分岐・待機をラウンドトリップなしで |
| プライバシー | PII を context に一度も載せずにシステム間移送できる |
| 状態の永続化と skill 化 | 繰り返す処理を関数として保存し再利用 |
前提: 適切な sandboxing を備えた安全な実行環境が必要。
返り値を絞るのはツール側だけの仕事ではない
ツール1本の返り値設計(第1部)と、本数への対処(第2部)の他に、呼び出し結果をモデル自身に絞らせるという第3の軸がある。improved-web-search-with-dynamic-filtering はそれを web 検索に適用した実測。
Instead of reasoning over full HTML files, Claude can dynamically filter the search results before loading them into context, keeping only what’s relevant and discarding the rest. —
improved-web-search-with-dynamic-filtering完全な HTML ファイルの上で推論する代わりに、Claude は検索結果を context に読み込む前に動的に絞り込み、関連するものだけを保持して残りを捨てられる。
BrowseComp で Opus 4.6 が 45.3% → 61.6%、Sonnet 4.6 が 33.3% → 46.6%。2ベンチ平均で精度 +11%・入力トークン -24%。
ただし原典は「常に安くなる」とは書いていない。
Price-weighted tokens decreased for Sonnet 4.6 on both benchmarks but increased for Opus 4.6. —
improved-web-search-with-dynamic-filtering価格加重トークンは Sonnet 4.6 では両ベンチで減ったが、Opus 4.6 では増えた。
絞り込むためのコードを書く分のトークンがかかるので、入力トークンの削減と支払額の削減は別物。原典自身が「本番で遭遇しそうな代表的クエリで測れ」と指示している。
ツールを1つ渡しただけで、実行環境が増えることがある
第1〜3の軸はどれも「モデルに何を見せるか」だった。4つ目の軸は「そのツールを誰が実行するか」で、 Anthropic 定義のツールはここが2つに割れている。
| 実行するのは | 例 | |
|---|---|---|
| サーバツール | Anthropic 側。同じリクエストの中で結果まで返る | code-execution-tool |
| クライアントツールセット | 自分の環境。tool_use を受けて自分で動かす | computer-use-tool |
The API runs every command server-side and returns the results to Claude within the same request, so you never execute code or send back
tool_resultblocks yourself. —code-execution-toolAPI はすべてのコマンドをサーバ側で実行し、同じリクエストの中で Claude に結果を返す。だから自分でコードを実行したり
tool_resultブロックを返したりすることは無い。
厄介なのは、この2つが同居したときに Claude が区別を失うこと。
Claude can sometimes confuse these environments, attempting to use the wrong tool or assuming state is shared between them. —
code-execution-toolClaude はこの2つの環境を取り違えることがある。誤ったツールを使おうとしたり、状態が共有されていると思い込んだりする。
そして意図せず2つ目が生えることがある。web search / web fetch は結果を絞るために code execution を自動で有効にするので、 自前の bash ツールを既に持たせているなら、その時点で実行環境が2つある。 原典の対処は system プロンプトで区別を明示することで、文面がそのまま載っている(code-execution-tool の「そのまま使える具体例」)。
クライアント側のツールセットでは、境界の定義そのものが自分の責任になる。 computer use の座標がその典型で、
Every
coordinate,start_coordinate, andregionvalue, and the position thatcursor_positionreports, is in the pixel space of the full-display screenshots you return, with the origin at the top left. —computer-use-tool
coordinate/start_coordinate/regionの値も、cursor_positionが報告する位置も、すべて自分が返した全画面スクリーンショットの画素空間(原点は左上)。
ツールセットはディスプレイの寸法を受け取らないので、縮小と座標の逆変換はアプリ側にしか置き場所が無い。 「クリックが一方向に一定してずれる」はここの実装漏れとして原典の診断表に載っている。
第3部: 設計判断の早見表
ツールを1本書くとき
- 既存 API の粒度ではなく、ワークフローの粒度になっているか
descriptionは 3〜4文以上あり、「いつ使わないか」と「返さないもの」を書いたか- 返り値は高信号か(次のステップに要らないフィールドを削ったか)
- 識別子は意味のある安定したものか
- 間違えられない形になっているか(絶対パス必須、曖昧一致で失敗)
- 複雑な入力なら
input_examplesを 3段階で付けたか - プログラム的に呼ばれるなら、返り値のスキーマを書いたか
ツールが増えてきたとき
まず現状を測る(/context、/mcp、usage の内訳)。そのうえで上から順に当てはめる。
| 当てはまる状況 | 打つ手 |
|---|---|
| ツール定義が context を食っている | tool search。最頻出 3〜5個は非 deferred。namespace を揃える |
| fan-out がある | programmatic tool calling。ただし逐次型なら入れない(8%高くつく) |
| MCP サーバを複数集約している | code execution with MCP を検討(98.7%減の実測) |
| 定義が安定している | prompt caching(初日から) |
そもそもツールを減らせないか
- 関連する操作を
actionパラメータで1本に統合できないか - MCP ではなく CLI(
gh/aws/gcloud)で足りないか- CLI は「ツール一覧に載らない」ぶん context 効率が良い
- hook で前処理して、ツールの返り値を絞れないか
- 1万行のログを grep して該当行だけ返す
4. 通底する一つの考え
ツール設計の良し悪しは、すべて「エージェントが次に何をすべきかを判断できるか」で決まる。
- description を詳しく書くのは、いつ呼ぶかを判断させるため
- 返り値を高信号にするのは、次の一手を判断させるため
- エラーを指示的にするのは、どう直すかを判断させるため
- ツールを統合するのは、選択の曖昧さを減らすため
- tool search を使うのは、30〜50個を超えると選択できなくなるから
つまりツール設計は、context 設計と同じ問題の別の面である。 どちらも「モデルに何を見せるか」を決めている。