13 KiB
リファレンス: Claude Code の deferred tools 機構
調査日: 2026-04-30。Claude Code(このセッションのハーネス)が採用しているツール提示・遅延ロード方式について、自身の system prompt と system-reminder の内容から観察できた事実と、そこから合理的に推測される実装方針をまとめる。Pod / insomnia でハーネス側のツール抽象を設計する際の参考資料。
ハーネス内部の実装は確認していないため、観察事実と推測を分けて記載する。
1. 観察事実
1.1 ツール定義の表現
system prompt 冒頭に、ツール定義が以下の形式の テキストブロック として埋め込まれている:
<functions>
<function>{"description": "...", "name": "Read", "parameters": {...JSONSchema...}}</function>
<function>{"description": "...", "name": "Edit", "parameters": {...}}</function>
...
</functions>
各 <function> は JSONSchema を含む単行 JSON。Anthropic API の tools パラメータに渡る構造化データではなく、プロンプトの一部としてレンダリングされたテキストである。
1.2 ツール呼び出しの表現
モデル側の出力も XML タグ列で行う(function_calls / invoke / parameter などのタグ)。ネイティブの tool_use content block ではない。ハーネスがこのテキストをパースし、対応するツールを実行する。
1.3 deferred tools の宣言
特定のツール群は最初の <functions> ブロックに含まれず、代わりに system-reminder で 名前リストだけ が提示される:
The following deferred tools are now available via ToolSearch.
Their schemas are NOT loaded — calling them directly will fail with InputValidationError.
Use ToolSearch with query "select:<name>" to load tool schemas before calling them:
AskUserQuestion
CronCreate
...
このリストには名前のみで schema は無い。
1.4 ToolSearch によるロード
ToolSearch 自体は最初から完全なスキーマで利用可能(通常のツールとして system prompt 冒頭の <functions> に含まれる)。select:<name> クエリを投げると、tool_result の本文として:
<functions>
<function>{"description": "...", "name": "AskUserQuestion", "parameters": {...}}</function>
</functions>
が返ってくる。「上のツール定義と同じエンコーディング」と明示されており、以降そのツールは通常通り呼べるようになる。
2. パラダイムの推測: prompted tool use
観察事実から、Claude Code は Anthropic API の structured tool use ではなく prompted tool use を採用している(あるいはハイブリッド)と判断できる。
| 項目 | structured | prompted |
|---|---|---|
| ツール定義 | API リクエストの tools 配列 |
system prompt 内のテキスト |
| ツール呼び出し | tool_use content block |
テキスト中の特定タグ |
| 検証 | API レイヤ(schema 強制) | ハーネスレイヤ(自前パース&検証) |
| 拡張性 | API の制約に縛られる | 自由(XML/JSON/独自形式) |
Claude Code の振る舞いはすべて prompted 側に寄っている。API は単に「テキストを生成するモデル」として使われ、ツール抽象は完全にハーネスのレイヤにある。
3. deferred tools が成立する仕組み(推測)
prompted tool use 前提で考えると、deferred tools は素直に説明できる:
- ハーネスは 全ツールのレジストリ を内部に持つ
- リクエスト時、初期
<functions>ブロックには「コアツール + ToolSearch」だけを描画。残りは system-reminder で名前のみ列挙 - モデルが
ToolSearchを呼ぶと、ハーネスはレジストリから該当 schema を引き、tool_result の テキスト として<function>...</function>を返す - モデルはそのテキストを参照しつつ、対応する tool 呼び出しタグを生成
- ハーネスはタグをパースし、レジストリで再度バリデーションして実行
検証の真実は レジストリ であり、context にスキーマテキストが現れたかどうかではない。スキーマテキストは「モデルが正しい引数を生成するためのプロンプト材料」として機能する。
4. 設計上のメリット
4.1 prompt cache のプレフィックス安定化
Anthropic の prompt caching はプレフィックスマッチで効く。tools パラメータや system プロンプト前半が変わると、それ以降の cache が一括無効化される。
deferred tools 方式では:
- API リクエストの
toolsパラメータは終始固定(あるいは空) - 初期 system prompt の
<functions>ブロックも固定 - ToolSearch の結果は 会話末尾の tool_result に積まれるだけ → 前方プレフィックスは揺らがない
→ ツール群が大量にあってもプレフィックスキャッシュが安定する。
4.2 context 圧縮
全ツールの schema をいきなり system prompt に展開すると、肥大化して入力トークンを浪費する。MCP サーバが大量のツールを expose する世界では現実的でない。deferred 方式なら そのセッションで実際に使うツールの schema だけ が context に乗る。
4.3 ツール数のスケーラビリティ
レジストリに登録するだけなら理論上数百〜数千ツールでも扱える。モデルには「使えるツール名リスト」だけ見せ、必要に応じて schema を取り寄せる構造。
5. トレードオフ
- 1ターンの遅延: ツールを呼ぶ前に ToolSearch が必要。初回だけだが UX 上のレイテンシは増える
- モデルの認知負荷: 「使う前にロードする」を学習・指示する必要がある(system-reminder で明示している)
- ハルシネーション余地: 名前を知っているが schema を知らない状態で呼ぼうとして InputValidationError を起こすケースが発生しうる
- ハーネス側の責務増: パース・検証・レジストリ管理がすべてハーネス側に乗る。バグると安全性に直結
6. Pod / insomnia への示唆
Pod でローカル LLM をエージェントとして動かす場合、同様の課題が発生する:
- 提供したいツールが増えると context が肥大化
- ローカルモデルは structured tool use の精度が API モデルに劣ることが多い → prompted 方式の方が安定する場合がある
- KV cache の効きを最大化したい(ローカルだと特に prefill コストが重い)
deferred tools 方式は prompted tool use を前提とする限り、これらの課題への自然な解になる。具体的には:
- ハーネス内にツールレジストリを持ち、
toolsメタデータと実装を分離 - system prompt には固定の core tools だけ展開、それ以外は名前で示唆
tool_search相当のツールで schema を引ける動線を用意- パース・検証はハーネス側で完結、モデルへの API 呼び出しは text-in/text-out に統一
特に「prompt cache のプレフィックス安定化」は、ローカル推論でも KV cache 再利用に直接効く。
7. 未確認事項
- Anthropic API の
toolsパラメータが実際に空なのか、core tools だけ入っているのか、ハイブリッドなのかは確認できていない - ToolSearch の結果テキストが context に残り続けるのか、後続の compaction で削られるのか
- レジストリのスコープ(セッション固定 / プラグインで動的追加 / MCP 経由など)の境界
- system-reminder で名前リストが提示されるタイミングが固定なのか動的なのか
これらを確認するには Claude Code のソース(公開部分)か、API リクエストのキャプチャが必要。
8. Codex による Web 検証
検証日: 2026-04-30。Codex で Web 上の公開情報を確認した範囲では、本ドキュメントの「deferred tools の目的・メリット・トレードオフ」は概ね妥当。ただし、「Claude Code が structured tool use ではなく prompted tool use を採用している」という断定は、公開情報だけでは裏取りできない。
8.1 公式情報で確認できたこと
- Claude Code / Claude Agent SDK には
ToolSearch/ tool search が存在する。公式ドキュメントでは、すべての tool definition を upfront に context window へ入れる代わりに、必要な tool を動的に発見・ロードする仕組みとして説明されている。 - tool search は大量ツール環境向けの context 効率化として説明されている。Claude Code docs では、50 tools で 10-20K tokens を消費しうること、30-50 tools を超えると tool selection accuracy が落ちることが述べられている。
- Claude Code docs では、tool search はデフォルト有効で、
ENABLE_TOOL_SEARCHによりtrue/auto/auto:N/falseを設定できるとされている。 - tool search は MCP server 由来の tool や custom SDK MCP server 由来の tool にも適用される。
- 初回 discovery には search step の追加 round-trip が発生する。ツール数が 10 未満程度なら、全 tool を upfront に読む方が速い場合がある。
- Claude API docs には、tool definition property として
defer_loadingが記載されている。defer_loading: trueは「初期 system prompt から tool を除外し、tool search がtool_referenceを返した時に on demand でロードする」ものとして説明されている。 - prompt caching との関係も公式に説明されている。
defer_loading: trueの tools は rendered tools section から除外され、cache key 計算前の prefix に現れない。発見後の full definition は conversation body 側に展開されるため、prompt cache を保ちやすい。 - Anthropic の engineering blog でも Tool Search Tool は紹介されている。そこでは「Tool Search Tool だけを upfront にロードし、3-5 個程度の relevant tools を on demand に発見する」設計として説明され、token 使用量削減と tool selection accuracy 改善が述べられている。
8.2 本ドキュメントの推測と食い違う可能性がある点
- 公開されている Claude API の説明では、tool search は
tools配列、defer_loading: true、tool_reference、tool_useblock を使う structured tool use の仕組みとして説明されている。そのため、「API は単に text-in/text-out で、ツール抽象は完全にハーネスのレイヤにある」と断定するのは強すぎる。 - 公式情報上は、deferred tool も API request の
toolsparameter に定義として渡し、その tool definition にdefer_loading: trueを付ける設計である。したがって「API リクエストのtoolsパラメータは終始固定(あるいは空)」という推測は、少なくとも公開 API の設計とは一致しない。 ToolSearchがselect:<name>で schema text を返す、という観察は、このセッションのハーネス上の事実としては扱えるが、公式 API docs の表現とは異なる。公式 API では search tool がtool_referenceを返し、それが conversation body 内で full tool definition に展開されると説明されている。<functions><function>...やfunction_calls/invoke/parameterの XML タグ列は、観察対象のハーネスで見えている表現として記録できる。ただし Claude Code 内部 system prompt は公式に公開されていないため、Web 上の公式情報だけで Claude Code 全体の内部実装形式として確認することはできない。
8.3 現時点での整理
公開情報と観察事実を両立させるなら、次の程度に弱めて理解するのが安全:
Claude Code の観察上は、ツール定義や呼び出しが prompt 内テキストとして見えている。ただし、公開されている Anthropic API の tool search は
tools配列、defer_loading、tool_reference、tool_useを使う structured tool use として説明されている。したがって、Claude Code 内部が完全な prompted tool use なのか、API の structured tool use を CLI / ハーネス側で別表現にレンダリングしているのか、あるいはそのハイブリッドなのかは未確認。
Pod / insomnia への示唆としては、deferred tools の設計目的である context 圧縮、tool selection accuracy の維持、prefix cache の安定化は公式情報でも裏付けられる。一方で、Anthropic API の現在の公開設計を参考にするなら、tool_search 相当の実装は「単なる schema text の注入」だけでなく、内部 registry 上の tool reference、ロード済み tool の状態管理、検証レイヤを明確に分けて設計する方がよい。