Claude Media
Claudeのサーバーツール結果は5分TTLで自動キャッシュされる仕組み

Claudeのサーバーツール結果は5分TTLで自動キャッシュされる仕組み

Web Search・Web Fetch・Code Executionの結果は、1時間TTLを設定していても常に5分TTLで自動キャッシュされます。仕組みと料金への影響、usageの読み方を解説します。

サーバーツール結果はなぜ設定を無視して5分でキャッシュされるのか

cache_controlの置き場所を扱った既存記事では、サーバーツールを使うターンに自動でブレークポイントが付くこと自体は触れています。本記事はその先、このブレークポイントのTTLが常に5分固定になる理由と、費用設計・順序制約への影響を掘り下げます。

Claude APIでWeb Search・Web Fetch・Code Executionのようなサーバーツールを使うと、その結果はAPI側が自動でキャッシュ用のブレークポイントを挿入します。このブレークポイントは常に既定の5分TTLで書き込まれ、リクエストに自分で設定したcache_controlのTTLが1時間であっても変わりません。

自動ブレークポイントとは、プロンプトキャッシングが有効なリクエストでサーバーツールが結果を返したとき、APIがエージェントループの次の反復に進む前に、その結果ブロックの末尾へcache_controlを自動で挿入する仕組みです。開発者が明示的にcache_controlを置いたわけではないのに、レスポンスのusageにキャッシュ書き込みが計上されるのはこのためです。Anthropic API上でツール呼び出しループを自前で組んでいる場合、この自動書き込みはループの実装側で意識しなくても勝手に効きます(Tool Runnerでツール呼び出しループを自動化するようなラッパーを使っていても同様です)。

自動ブレークポイントがTTL設定を無視する理由

この自動ブレークポイントが働くには前提条件があります。リクエスト自体にcache_controlが最低1つ含まれていることです。system promptにもtools配列にもcache_controlを一切置いていない、プロンプトキャッシングを使っていないリクエストでは、Web SearchやCode Executionを呼んでもこの自動キャッシュは発生しません。

条件を満たしたうえでサーバーツールが結果を返すと、APIはその結果ブロックにキャッシュブレークポイントを挿入し、後続のループ反復が伸びていくプレフィックスをキャッシュから読めるようにします。ここで肝心なのが、このブレークポイントは自分で設定したcache_controlのTTLとは独立に、常に既定の5分TTLで書き込まれるという点です。tools配列やsystem promptに1時間TTL({"type": "ephemeral", "ttl": "1h"})を設定していても関係ありません。

その結果、usage.cache_creationの内訳を見るとephemeral_1h_input_tokensだけでなくephemeral_5m_input_tokensが混ざって出てきます。すべてのブレークポイントを1時間TTLで統一したつもりでも、サーバーツールを使う限り5分TTLの書き込みが必ず紛れ込む、と理解しておくと事故りません。以下はcache_controlの有無による違いをコード例で示したものです。

// パターン1: cache_controlなし → 自動キャッシュも発生しない
{
  "tools": [{ "type": "web_search_20260318", "name": "Web Search" }],
  "messages": [{ "role": "user", "content": "..." }]
}
 
// パターン2: tools配列の末尾にcache_controlを1つ置く → サーバーツール結果も自動キャッシュされる
{
  "tools": [
    { "type": "web_search_20260318", "name": "Web Search", "cache_control": { "type": "ephemeral" } }
  ],
  "messages": [{ "role": "user", "content": "..." }]
}

パターン1とパターン2の違いはtools配列末尾のcache_control1つだけですが、これがあるかないかで、サーバーツールの結果が自動キャッシュされるかどうかが分かれます。「サーバーツールを使えば自動でお得になる」わけではなく、「プロンプトキャッシングを使っているリクエストの中でサーバーツールを使うと、その結果にもれなくキャッシュが及ぶ」という順序で理解しておく必要があります。

Web Search・Web Fetch・Code Executionでキャッシュ挙動は違うか

3つのサーバーツールは、上記の自動5分TTLブレークポイントという点では共通の挙動を取ります。ただし「何がキャッシュの対象か」「TTL切れとは無関係に残る状態があるか」「usageのどこに計上されるか」は道具ごとに違いがあります。

項目Web SearchWeb FetchCode Execution
キャッシュ対象Web Search検索結果テキストWeb Fetch取得したページ本文Code Execution標準出力・実行結果テキスト
自動ブレークポイントのTTLWeb Search5分固定Web Fetch5分固定Code Execution5分固定
TTLと独立して残る状態Web SearchなしWeb FetchなしCode Executionコンテナのファイル・REPL変数(コンテナ破棄まで残存)
usageの計上先Web Searchcache_creation.ephemeral_5m_input_tokensWeb Fetchcache_creation.ephemeral_5m_input_tokensCode Execution出力テキストは同左、コンテナ状態はusageに計上されない

キャッシュ対象がテキストか状態かという違いはCode Executionだけに存在します。Web SearchとWeb Fetchは結果がプロンプトの一部としてそのままキャッシュされて終わりですが、Code Executionだけは出力テキストの自動キャッシュに加えて、コンテナという別ルートの永続化を持つ点が他の2つと異なります。この違いは後の節で扱います。

usage.cache_creationの内訳をどう読むか

自動キャッシュが実際に働いているかは、レスポンスのusageフィールドで確認できます。

{
  "usage": {
    "input_tokens": 120,
    "cache_creation": {
      "ephemeral_5m_input_tokens": 3400,
      "ephemeral_1h_input_tokens": 8000
    },
    "cache_read_input_tokens": 8000,
    "output_tokens": 210
  }
}

この例では、system promptなど自分で1時間TTLを指定した部分がephemeral_1h_input_tokensに、Web Searchの結果を自動キャッシュした分がephemeral_5m_input_tokensに、それぞれ別枠で計上されています。読み違えやすいのは、この2つの数値は同じリクエスト内で同時に発生しうることです。「1時間TTLだけを使っているはずなのに5分TTLの書き込みコストが計上されている」ように見えたら、まずサーバーツールの利用有無を疑うと切り分けが早く進みます。

料金面では、5分TTLの書き込みは通常の入力トークン単価の1.25倍、1時間TTLの書き込みは2倍という価格構造になっています。サーバーツール結果が5分TTL固定になるのは、この意味ではむしろ単価の低い側に倒れているとも言えます。ただし単価そのものより、「設定していないのに書き込みが発生する」という予期しない挙動として費用監視の設計を崩しやすい点が実務上の注意点です。

1時間TTLと自動5分TTLを混在させるときの順序制約

プロンプトキャッシングには「TTLが長いブレークポイントほど手前に置く」という順序制約があります。1時間TTLのブレークポイントは、同じリクエスト内の5分TTLのブレークポイントより必ず前に置かなければなりません。

サーバーツールの自動ブレークポイントは常に5分TTLなので、この制約は多くの場合自然に満たされます。1時間TTLをsystem promptやtools配列の先頭側に自分で設定しておけば、あとから追加されるサーバーツール結果への自動5分ブレークポイントはその後ろに来るため、順序は崩れません。

注意が必要なのは逆方向です。サーバーツールの結果より後ろに、自分で新しい1時間TTLのブレークポイントを追加しようとすると、すでに手前に5分TTLのブレークポイント(自動挿入分)が存在する状態になり、順序制約に反します。エージェントループの後半でmessages側に1時間TTLを追加する設計をしている場合、サーバーツールを併用するときはこの順序が崩れていないかを確認する必要があります。

3つのサーバーツールで挙動は同じか

自動キャッシュはWeb Search・Web Fetchの結果テキストと、Code Executionの出力の両方に等しく適用されます。ただしCode Executionには、この自動キャッシュとは別にコンテナの状態(作成したファイルやREPLの変数)を維持する仕組みがあり、こちらはプロンプトキャッシュとは独立して動きます。つまりCode Executionを使うと、①出力テキストはプロンプトの一部として自動キャッシュされる、②サンドボックスのファイルやREPL状態はコンテナIDを介して別ルートで永続化される、という2つの独立した仕組みが同時に走ります。前者はキャッシュのTTLで消え、後者はコンテナを明示的に破棄するまで残ります。この2つを同じ「キャッシュ」という言葉で混同すると、コンテナの中身がキャッシュのTTL切れと同時に消えると誤解しやすいので注意してください。

Tool Search Tool経由で発見されるツールの結果は対象が異なります。発見されたツール定義自体はtool_referenceとして会話に展開されますが、これはツール定義側の話であり、本記事が扱うサーバーツールの実行結果の自動キャッシュとは別の仕組みです。ツール定義をdefer_loadingで遅延させてもキャッシュが壊れない理由はdefer_loadingでプロンプトキャッシュを壊さずツールを追加する仕組みで扱っています。

サーバーツール自動キャッシュはループのコストをどう変えるか

この仕組みが効くのは、1回のリクエストの中でサーバー側のエージェントループが複数回反復する場面に限られます。Claudeが複数回Web Searchを呼び直したり、Code Executionの出力を踏まえて追加のコードを実行したりするとき、各反復のたびに直前までの結果を毎回丸ごと再処理していては、反復が増えるほど入力トークンが線形に膨らみます。自動キャッシュはこの再処理を「読み込み」に置き換え、反復回数が伸びるループのコストカーブを寝かせる方向に働きます。

裏を返すと、別々のトップレベルリクエストをまたいだキャッシュ延命には寄与しません。5分TTLの自動書き込みは、そのリクエストが終わって5分以内に次のリクエストが来なければ普通に失効します。長時間セッションを想定して1時間TTLのcache_controlを自分で設計している開発者ほど、「サーバーツールの結果も1時間もつ」と思い込みやすい箇所です。サーバーツールを使うワークロードでコストを見積もるなら、①エージェントループ内の反復コストは自動キャッシュが吸収する、②リクエストをまたぐ延命は自分で置いたcache_controlのTTLに依存する、の2つを分けて考える必要があります。

すべてのサーバーツールはBatch APIにも対応しており、バッチ内でも同じサーバー側エージェントループが動きます。バッチリクエストは同期リクエストより1ターンあたりの反復上限が高く設定されているため、反復回数が伸びやすい分だけ、自動キャッシュが吸収する再処理コストの絶対量も同期リクエストより大きくなりがちです。バッチでサーバーツールを多用する構成ほど、この自動キャッシュの有無がコスト差として効いてきます。

まとめ

サーバーツールの結果は、プロンプトキャッシングが有効なリクエストである限り自動でキャッシュされ、そのTTLは常に5分固定です。この挙動はWeb Search・Web Fetch・Code Executionの3つで共通しており、生のMessages APIを直接叩く実装にも、SDK経由でツール呼び出しループを組んでいる実装にも等しく及びます。自分で1時間TTLを指定していても上書きされず、usage.cache_creation.ephemeral_5m_input_tokensとして別枠で計上されます。Web Search・Web Fetchの結果テキストとCode Executionの出力はこの対象ですが、Code Executionのコンテナ状態はまったく別のキャッシュとは無関係な仕組みで永続化される点も切り分けておくと、費用の内訳を読み違えずに済みます。プロンプトキャッシングの基本設計はPrompt Cachingの仕組みと適用判断で扱っているので、TTLの選び方から見直したい場合はあわせて確認してください。

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