Claude Media
ツール定義のcache_controlはどこに置くか

ツール定義のcache_controlはどこに置くか

Anthropic APIでツール定義をプロンプトキャッシュに乗せるcache_controlの配置ルールをまとめます。MCPツールセットやcomputer use/browser useでの特殊な挙動も扱います。

基本ルール:配列末尾のツール1つに付ける

結論から言うと、tools 配列の最後のツール1つに cache_control: {"type": "ephemeral"} を置きます。これで配列の先頭からそのツールまでの、ツール定義プレフィックス全体がキャッシュされます。ツールを1つずつ個別にキャッシュする仕組みではありません。

プロンプトキャッシュとは、Anthropic APIがリクエストの先頭側の共通部分(システムプロンプト、ツール定義、会話履歴の一部)を再利用する仕組みです。2回目以降の呼び出しで、コストとレイテンシを削減できます。まずはAnthropic APIのPrompt Cachingを理解するで全体像を押さえておくと、この記事のツール定義側のルールも位置づけがつかみやすくなります。

キャッシュは tools → system → messages というプレフィックス階層に沿って効きます。tools の途中に変更が入ると、そこから後ろの system と messages のキャッシュもまとめて無効になります。ツール定義は毎回同じ順序・同じ内容で送り、その末尾に cache_control を置くのが出発点です。

ファイル操作・検索・実行系のツールを何十個も並べるエージェントでは、ツール定義がリクエストの入力トークンの多くを占めることがあります。プレフィックス階層の一番手前にある tools を安定させることが、後段のシステムプロンプトや会話履歴のキャッシュ効率に響きます。キャッシュ読み込みがレート制限のITPMにどう影響するかはClaude APIのITPM制限にキャッシュ読み込みがカウントされない仕組みにまとめています。

{
  "tools": [
    { "name": "get_weather", "description": "..." },
    {
      "name": "get_time",
      "description": "...",
      "cache_control": { "type": "ephemeral" }
    }
  ]
}

この例では get_weather と get_time の両方を含むツール定義プレフィックス全体がキャッシュされます。get_weather の定義文を書き換えるだけでも、そこから後ろの get_time を含む全体が無効になります。ツール定義の変更頻度が高い構成では、この巻き込み範囲が設計の中心になります。

末尾以外のツールに付けたらどうなるか

マーカーは「ここまでを1つの塊としてキャッシュする」という区切りです。公式ドキュメントによると、cache_control を付けたブロックでは、そのブロックまでのプレフィックスのハッシュが1件だけ書き込まれます。それより前の位置には書き込まれません。

したがって、途中のツールに付けても動作は壊れません。キャッシュされるのはそのツールまでです。ツールのマーカーがこれだけなら、後ろのツール定義は通常の入力として扱われます。一方で、1リクエストあたりのマーカーは4箇所までなので、無駄な区切りは枠を消費するだけです。

3つ目のツールを get_time の後ろに足す場合も同じ考え方です。get_weather から get_time までのプレフィックスは変わらないので、その部分はキャッシュから読まれます。ただし system と messages は、新しいツールを含む形でプレフィックスが変わるため、キャッシュを作り直すことになります。

枠は4つしかない:先に配分を決める

マーカーの上限は4箇所です。最上位の cache_control でリクエスト全体に自動キャッシュを指定した場合、自動分も1枠を使います。明示マーカーがすでに4つあるところへ自動キャッシュを足すと、400エラーが返ります。

配分は変更頻度の低い部分から決めます。たとえば、ツール定義に1枠、システムプロンプトに1枠、会話履歴に残りを割り当てます。会話履歴側に複数の枠を残す理由は、ブレークポイントから遡れる範囲に限りがあるためです。遡れるのは20位置までで、連続する tool_use や tool_result の連なりは1位置と数えます。この範囲を超えて履歴が伸びると、直前の書き込みを見つけられません。

くらべる

ツール定義のマーカー位置

自分で順序を決められる

通常のツール配列

配列の最後のツールに cache_control を置きます。先頭からそのツールまでが1つのキャッシュ範囲になります。

展開後の順序を選べない

mcp_toolset など

ツールセットのエントリ自体に cache_control を置きます。APIが展開後の最後のツールにブレークポイントを適用します。

MCPツールセットとcomputer use・browser use

mcp_toolset では、ツールセット内のツール順序をクライアント側から制御できません。上の比較のとおりエントリ自体に置く理由は、この点にあります。

computer use・browser useのツールセットエントリも同じです。cache_control はエントリ自体に置き、ブレークポイントはそのツールセットの定義が終わった直後に着地します。メンバーツールの configs エントリの内側には置けません。ツールセットのメンバーは1つの定義としてまとめてロードされるためです。

バッチアクション内のcache_controlは1つのブレークポイントにまとまる

computer useのバッチアクションでは、そのターンのメンバーである tool_use や tool_result ブロックのどれかに cache_control を付けると、バッチの終端で効果を発揮します。同じバッチに複数のマーカーがあっても、1つのブレークポイントとして扱われます。

それでも各マーカーは、リクエスト全体の4箇所という上限にそれぞれ数えられます。1バッチにつき1つで足ります。

defer_loadingでツール検索を使ってもキャッシュが壊れない理由

Tool Searchは、数百〜数千のツールをオンデマンドで読み込む仕組みです。defer_loading を付けたツールは、システムプロンプトのプレフィックスに含まれません。Claudeがツール検索でそのツールを見つけた時点で、会話履歴の中に tool_reference ブロックとして追加されます。プレフィックスは変わらないので、ツールを動的に増やしてもキャッシュは保たれます。

常時ロードする少数のツール(キャッシュ対象)と、検索で見つける大量のツールを分けて運用できる、というのがこの設計の意味です。defer_loading はstrict modeの文法構築とも独立しています。文法は、遅延ロード中かどうかにかかわらず全ツールセットから構築されます。そのため、プロンプトキャッシュと文法キャッシュの両方が保たれます。

何がキャッシュを無効化するか

変更の種類によって、無効になる範囲が階層ごとに異なります。

変更無効になる範囲
ツール定義の変更無効になる範囲tools / system / messagesすべて
Web検索・引用機能のオン/オフ切り替え無効になる範囲system / messages
通常速度とspeed: "fast"の切り替え無効になる範囲system / messages
tool_choice の変更無効になる範囲messages
disable_parallel_tool_use の変更無効になる範囲messages
画像の有無の切り替え無効になる範囲messages
thinkingパラメータの変更無効になる範囲messages(モデルによってはtools / systemも)
output_config.effort の変更無効になる範囲thinkingパラメータと同じ(既定値の明示指定は省略と等価)

tool_choice を会話の途中で切り替える設計では、無効になるのは messages だけです。変更点より前にも cache_control を置いておくと、そこまでの部分を読み続けられます。disable_parallel_tool_use や画像の有無の切り替えも同じです。

ツールごとの事情は次のとおりです。

ツールキャッシュとの関係
computer use / browser useキャッシュとの関係スクリーンショットの有無がmessagesキャッシュに影響する。cache_controlはツールセットのエントリに置く
text editor / bash / memoryキャッシュとの関係標準的なクライアントツールで、キャッシュとの特別な相互作用はない
web検索・web fetchキャッシュとの関係有効/無効の切り替えがsystemとmessagesの両方を無効化する
ツール検索で発見したツールキャッシュとの関係tool_referenceブロックとして履歴に積まれるだけで、プレフィックスキャッシュは崩れない
コード実行のコンテナ状態キャッシュとの関係プロンプトキャッシュとは独立に管理される

ツールを会話の途中で足したいとき

tools を書き換えるとキャッシュ全体が無効になるため、会話の途中でツールを増やす設計では、ツール検索(defer_loading)か、参照によるツールの追加で対応します。対応モデルでは、ベータ機能の「会話の途中でのツール変更」が別の選択肢になります。

リクエストに anthropic-beta: inline-tools-2026-09-15 ヘッダーを付け、role: "system" のメッセージに tool_addition ブロックを入れます。ブロックにはツールの完全な定義を載せられます。キャッシュは当たり続け、追加したメッセージ分だけが新しい入力として処理されます。

くらべる

途中でツールを足す2つの方法

全階層が無効

tools配列を書き換える

名前や説明を変える、ツールを追加するといった編集は、tools / system / messages すべてのキャッシュを作り直します。

プレフィックスは維持

tool_additionで足す

tools は最初に送った形のまま、必要になった時点のシステムメッセージでツール定義を渡します。

制約も公式ページにあります。tools に遅延ロードでないツールが1つもない場合、この方法で最初に定義したツールは、そのリクエストで1回だけ完全なキャッシュミスになります。ベータ期間中は、computer useのように、メッセージ内で定義できず400エラーになるツールもあります。その場合は tools に宣言したうえで、参照で追加します。

ツール定義側のTTLと事前書き込み

ツール定義は変更頻度が最も低いため、1時間TTL("ttl": "1h")の候補になります。1つのリクエストで1時間と5分のマーカーを併用するときは、長いTTLのエントリを短いTTLより前に置く必要があります。tools は階層の先頭なので、ツールに1時間、会話履歴に5分という割り当てはこの条件を満たします。

最初のリクエストでキャッシュを温めておく方法もあります。max_tokens: 0 を指定すると、出力を生成せずにキャッシュだけを書き込んで返ります。このときブレークポイントは、後続リクエストと共通の最後のブロック(システムプロンプトやツール定義)に置きます。最上位の自動キャッシュは最後のブロックに付くため、この用途では明示マーカーが必要です。stream: true、thinking.type: "enabled"、output_config.format、tool_choice の tool / any、Message Batchesと組み合わせると invalid_request_error で拒否されます。

キャッシュにはモデルごとの最小長もあります。Claude APIの公式ドキュメントでは、Claude Sonnet 5.5とOpus 5.5が512トークン、Opus 4.7が2,048トークンです。Opus 4.8とSonnet 4.6は1,024トークン、Haiku 4.5とOpus 4.6・4.5は4,096トークンです。ツール定義が短くてこの長さに届かない場合は、マーカーを付けてもエラーなしでキャッシュされません。

Web検索やコード実行を使ったターンのキャッシュは自動で付く

プロンプトキャッシュを有効にしたリクエストで、Claudeがweb検索・web fetch・コード実行のようなサーバーツールを使うと、APIはそのサーバーツールの結果に自動でキャッシュブレークポイントを置きます。エージェントループの次の反復に備えた動きです。この自動ブレークポイントは常に5分のデフォルトTTLで、自分で設定した cache_control のTTLとは独立です。

レスポンスの usage を見ると、1時間TTLのマーカーだけを使っているつもりでも cache_creation.ephemeral_5m_input_tokens に書き込みが記録されることがあります。原因はこの自動付与です。リクエストに既に1つ以上の cache_control マーカーがある場合にだけ働きます。

配置ミスの切り分け

キャッシュが期待どおりに読まれないとき、usage の数字と配置を次の順で突き合わせます。

手順

ツール定義のキャッシュが効かないとき

  1. 1

    書き込みも読み取りも0か

    cache_creation_input_tokens と cache_read_input_tokens がどちらも0なら、モデルごとの最小長に届いていないか、マーカー自体が付いていません。

  2. 2

    書き込みだけが毎回出るか

    読み取りが出ず書き込みだけが続くときは、マーカーより前のどこかが毎回変わっています。ツール定義の順序、説明文の差し込み値、system の日時などを見ます。tool_use ブロックのキーの順序も候補です。SwiftやGoのように、JSON変換でキーの順序が毎回変わる言語ではキャッシュが壊れます。

  3. 3

    マーカーの位置は意図どおりか

    ツールを足したときに、マーカーを末尾へ動かし忘れるのが典型です。

ツール数が少ないうちは配置ミスの影響も小さく済みます。Advanced Tool Useで紹介されているように、5つのMCPサーバー・58ツールで約55Kトークン、社内の別の構成では134Kトークンがツール定義だけで埋まる例があります。この規模では、キャッシュの効き方1つでリクエストごとのコストが大きく変わります。

まとめ

4枠の配分と、会話の途中でツールを足すかどうかを先に決めておくと、キャッシュを壊す変更を避けやすくなります。ツールを足すなら、tools を書き換えない defer_loading か tool_addition が候補です。

この記事を共有:XはてブLinkedIn