ツール設計とスケール — 結局どうすればいいか

11本を統合する。「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 では使えない。

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-system Claude 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 search10個以上 / 定義 10kトークン超 / MCP 複数集約85%減(72K → 8.7K)
tool_result の往復programmatic tool callingfan-out 型のみ37%減。逐次型は +8%
同じ定義への繰り返しの支払いprompt caching初日から読み取りが 0.1倍
古い tool_result の蓄積context editing会話が長引いたら選択的に落とす

導入順が推奨されているmanage-tool-context):

1. prompt caching        初日から。cache write は 25% 割増だが 2回目のヒットで元が取れる
2. tool search           ツールが 20個を超えたら
3. context editing       初期の tool_result が無関係になったら
4. programmatic tool calling  小さなツール呼び出しの連鎖が繰り返し現れたら

8. tool search を使うときの実務

defer_loading は「送るもの」ではなく「context に入るもの」を制御する。

You still send every tool’s full definition in the tools array on every request, including the deferred ones. それでも毎リクエストで、tools 配列にはすべてのツールの完全な定義を送っている。遅延ロード対象のものも含めてである。

設計上のコツ:

  • 最頻出の 3〜5 個は非 deferred のままにする(検索せずに呼べる)
  • ツール名に一貫した namespace を使うgithub_slack_)→ 1回の検索でグループ全体がマッチする
  • tool_search ツール自身に defer_loading を付けない(全 deferred は 400 エラー)
  • defer_loading: truecache_control は付けられない(400)

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_callers on 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 を備えた安全な実行環境が必要。


第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 設計と同じ問題の別の面である。 どちらも「モデルに何を見せるか」を決めている。