ツール設計とスケール — 結局どうすればいいか
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-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倍 |
古い 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
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)
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 を備えた安全な実行環境が必要。
第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 設計と同じ問題の別の面である。 どちらも「モデルに何を見せるか」を決めている。