CLAUDE LABEN
FORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられていますFORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられています
記事一覧/API & SDK
API & SDK/2026-04-28中級

Claude API のプロンプトキャッシュがヒットしない時の診断手順

Claude API のプロンプトキャッシュが効いていない時、まず確認すべきは usage フィールドです。cache_read_input_tokens がゼロのまま増えない原因を、5つの典型パターンに沿って切り分けます。

claude-api81prompt-caching12troubleshooting61cost-optimization25anthropic12

cache_control を設定したのに、月末の請求書がぜんぜん安くなっていない」— Claude API のプロンプトキャッシュを導入した方から、この相談を一番よく受けます。私自身も最初にキャッシュを入れた時、3日間まったくヒットしていないことに気づかず、「やっぱり効果ないのかな」と諦めかけました。

実は、プロンプトキャッシュが効かない原因は意外と限られています。そして、診断の出発点はリクエストごとに必ず返ってくる usage フィールドにあります。ここでは私が個人運営しているアプリで何度もぶつかった「キャッシュミス」の典型パターンを、診断順に整理します。

まず usage フィールドを読む

Claude API のレスポンスには、必ず usage というオブジェクトが含まれています。プロンプトキャッシュを使っている時は、ここに2つの追加フィールドが現れます。

import anthropic
 
client = anthropic.Anthropic()
 
response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": "あなたは経験豊富な技術ライターです。" * 200,  # 約2,000トークン
            "cache_control": {"type": "ephemeral"},
        }
    ],
    messages=[{"role": "user", "content": "こんにちは"}],
)
 
print(response.usage)
# Usage(
#   input_tokens=10,
#   cache_creation_input_tokens=2103,
#   cache_read_input_tokens=0,
#   output_tokens=42
# )

注目するのは次の3つの値です。

  • input_tokens: キャッシュの対象外で、毎回読み込まれる入力トークン数
  • cache_creation_input_tokens: 今回のリクエストでキャッシュに「書き込まれた」トークン数(5分TTLなら標準単価の1.25倍、1時間TTLなら2倍が課金されます)
  • cache_read_input_tokens: キャッシュから「読み込まれた」トークン数(標準単価の0.1倍)

ヒットしている状態とは、2回目以降のリクエストで cache_read_input_tokens がゼロより大きく、cache_creation_input_tokens がゼロに近づいている状態を指します。これが何度リクエストしても変わらないなら、何かが間違っています。

原因①: 最小トークン数を満たしていない

Claude のプロンプトキャッシュには、キャッシュ対象として認められる「最小トークン数」が設定されています。2026年4月時点での目安は次のとおりです。

  • Claude Sonnet 4.6 / Claude Opus 4.6: 1,024 トークン
  • Claude Haiku 4.5 系: 2,048 トークン

この閾値を下回るプレフィックスに cache_control を付けても、サーバー側でキャッシュは作られず、cache_creation_input_tokens は常にゼロのまま、input_tokens だけが膨らみ続けます。

短いシステムプロンプト(数百トークン程度)に cache_control を付けて「効かない!」と悩むケースは本当に多いです。私が最初にハマったのもこれでした。診断としては、システムプロンプト全体のトークン数を tokenizer で先に数えてみてください。1,024未満なら、キャッシュよりも先に「プロンプト自体を圧縮しない」方向で設計を見直す方が現実的です。

原因②: cache_control の位置が間違っている

プロンプトキャッシュは「cache_control が付いたブロックの末尾までを1つのキャッシュキーとして登録する」仕組みです。つまり、キャッシュしたい静的部分の 最後cache_control を置く必要があります。

# ❌ 間違い: 動的部分の後に cache_control を置いている
system=[
    {"type": "text", "text": SYSTEM_INSTRUCTION},
    {"type": "text", "text": f"今日は{today}です"},  # 動的
    {"type": "text", "text": "出力フォーマットは以下のとおり: ...",
     "cache_control": {"type": "ephemeral"}},
]

上のコードでは、今日は{today}です が日付ごとに変わるため、キャッシュキー全体が毎日変わってしまい、ヒットしません。動的な値はキャッシュ対象の 後ろ に置くのが鉄則です。

# ✅ 正しい: 静的部分の末尾に cache_control、動的部分はその後
system=[
    {"type": "text", "text": SYSTEM_INSTRUCTION},
    {"type": "text", "text": "出力フォーマットは以下のとおり: ...",
     "cache_control": {"type": "ephemeral"}},
    {"type": "text", "text": f"今日は{today}です"},  # キャッシュ後の動的ブロック
]

ツール定義についても同様です。tools 配列の最後の要素に cache_control を付けると、その時点までのツール定義群がまとめてキャッシュされます。

原因③: TTL(有効期限)切れ

デフォルトの TTL(Time To Live)は 5分 です。最後にヒットしてから5分以上アクセスが空くと、キャッシュは破棄されます。低頻度のバックグラウンドジョブや、ユーザーの操作間隔が長いチャットボットでは、毎回キャッシュ書き込みが発生してしまい、コスト削減効果がほぼ消えます。

このパターンは、平日昼間だけ使われる業務ツールでよく観測しました。

対策として、2026年に正式提供された 1時間 TTL が有効です。書き込み時のコストは2倍に上がりますが、アクセス頻度の低いワークロードでは全体としては安くなります。

system=[
    {
        "type": "text",
        "text": LARGE_SYSTEM_PROMPT,
        "cache_control": {"type": "ephemeral", "ttl": "1h"},
    }
]

導入前後で、cache_read_input_tokens の比率が一日を通してどう変化したかをログに残し、効果を必ず検証してください。

原因④: 動的な値がキャッシュ対象に紛れ込んでいる

これは私が一番頻繁にやらかすミスです。「全リクエストで同じ」と思い込んでいた静的部分に、実は微妙に変動する値が混ざっている、というパターンです。

よくある例:

  • システムプロンプトの先頭に 現在時刻: 2026-04-28T09:00:34Z のようなタイムスタンプを入れている
  • ユーザーIDをシステムプロンプトに埋め込んでいる
  • セッションごとのランダムなトラッキング用UUIDが含まれている
  • 改行コード(\n\r\n)が環境によって混在している

ハッシュ値で検証するのが確実です。

import hashlib
 
def cache_key_hash(text: str) -> str:
    return hashlib.sha256(text.encode("utf-8")).hexdigest()[:16]
 
# リクエスト前に、キャッシュ対象部分のハッシュをログ出力
prefix = "".join(b["text"] for b in system_blocks_until_cache_control)
print(f"cache prefix hash: {cache_key_hash(prefix)}")

このハッシュが毎回変わっていたら、何かが動的になっています。差分を取って原因を特定してください。私はこれで「サーバーのリクエスト時刻をうっかり混ぜていた」ことに気づき、半日以上の遠回りを避けられました。

原因⑤: ツール定義のリクエスト順が一定でない

ツール(tools 配列)をキャッシュしているのに効かない時は、配列の順序が原因のことがあります。Claude のキャッシュキーは「内容のバイト列」として比較されるため、ツールの並び順が変わると別のキャッシュとして扱われます。

Python の dict から動的にツール一覧を生成している場合、辞書の挿入順が条件によって入れ替わると、毎回別のキャッシュが作られます。生成ロジックを次のように固定するのが安全です。

TOOL_ORDER = ["search_docs", "execute_sql", "send_email"]
 
def build_tools(enabled: set[str]) -> list[dict]:
    # 必ず固定順で並べる
    return [TOOL_DEFINITIONS[name] for name in TOOL_ORDER if name in enabled]

「ユーザーごとに使えるツール集合が違う」設計の場合は、そもそもキャッシュヒット率が出にくくなります。共通ツール群と差分ツールを別ブロックに分け、共通部分だけキャッシュ対象にする設計が現実的です。

診断スクリプト:3リクエスト連続で usage を観察する

原因を切り分ける時に私が使っている、シンプルな診断スクリプトを置いておきます。同じプロンプトを3回連続で投げ、usage の推移を見るだけのものです。

import anthropic
from anthropic.types import TextBlockParam
 
client = anthropic.Anthropic()
 
SYSTEM_PROMPT = open("system_prompt.txt").read()  # 1,024 トークン以上を想定
 
def diagnose():
    for i in range(3):
        resp = client.messages.create(
            model="claude-sonnet-4-6",
            max_tokens=64,
            system=[
                TextBlockParam(
                    type="text",
                    text=SYSTEM_PROMPT,
                    cache_control={"type": "ephemeral"},
                )
            ],
            messages=[{"role": "user", "content": f"テスト {i}"}],
        )
        u = resp.usage
        print(
            f"req {i}: input={u.input_tokens} "
            f"create={u.cache_creation_input_tokens} "
            f"read={u.cache_read_input_tokens}"
        )
 
diagnose()

期待される出力:

req 0: input=10 create=2103 read=0
req 1: input=10 create=0    read=2103
req 2: input=10 create=0    read=2103

req 1 以降で read がプラスに転じれば、キャッシュは正しく機能しています。req 1 でも read=0 のままなら、上記の原因①〜⑤を順に潰してください。

より深いコスト最適化の設計パターンについては、Claude API のプロンプトキャッシュで月額コストを半分にした実装メモ と Claude API のプロンプトキャッシュと Token-Efficient Tool Use — コスト最大90%削減の本番最適化ガイド を併せてご覧ください。レート制限と組み合わせた本番設計は API レート制限のベストプラクティス も参考になります。

書籍で体系的に

キャッシュが効いている時にダッシュボードで見える兆候

正しく動き始めると、運用ダッシュボードには3つの変化が現れます。

ひとつ目は、キャッシュ対象プレフィックスの 1リクエストあたり入力トークンコスト がおよそ10分の1に落ちることです。TTLが切れるタイミングで一時的に書き込みコストが乗りますが、グラフ全体の形は「ずっと一定の高さ」から「平らで、たまに小さな山が立つ」形に変わります。

ふたつ目は、cache_read_input_tokenscache_creation_input_tokens の比率です。10:1 以上なら定常状態として健全です。3:1 を下回るようなら、書き込みコストが節約分を食い潰している状態で、原因③(TTL)か原因④(プレフィックスに動的値が混入)を疑います。

みっつ目は、レイテンシの改善です。キャッシュヒットしたプレフィックスでは、Time to First Token が体感で30〜50%短くなります。これはあまり語られない副次効果ですが、ユーザーが応答を待つ画面を持つプロダクトでは、コスト指標と同じくらい重要なUX指標になります。

この3つを既存のエラー率・レート制限ヘッドルームと同じダッシュボードに並べておくと、デグレが起きた週のうちに気づけるようになります。請求書が来てから慌てずに済むのは、本当に大きな違いです。

次の一歩

まずは手元で動かしているプロダクトに上の診断スクリプトを2分で組み込み、cache_read_input_tokens が増えるかどうかを目視で確認してみてください。増えていなければ、原因①「最小トークン数」から順に潰すのが最短ルートです。

キャッシュは「設定すれば効く」機能ではなく、「効いていることを usage で観測しながら設計を直す」機能です。診断ループを一度回せるようになると、本番の請求書は確実に小さくなります。

シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

API & SDK2026-04-26
Claude API のプロンプトキャッシュで月額コストを半分にした実装メモ
Claude API のプロンプトキャッシュを正しく設計すると、長文プロンプトを使う本番ワークロードは月額コストが体感で半分以下になります。実例ベースで設計のコツとつまずきどころをまとめました。
API & SDK2026-06-29
Claude API の Context Editing を入れたらエージェントが同じ調査を繰り返したとき — クリア境界とキャッシュ無効化を計測する運用メモ
Context Editing でツール結果を自動クリアしたら、エージェントが直前に読んだ内容を忘れて同じツールを呼び直し、キャッシュも毎回壊れてコストが上がった。沈黙する劣化を計測ログで切り分け、trigger・keep・clear_at_least を実測で決める運用メモです。
API & SDK2026-06-24
ツール定義を一行直しただけで、キャッシュが丸ごと作り直しになりました — cache_control ブレークポイントの置き場所
ヒット率が突然ゼロに張り付いた原因は、揮発するブロックを安定したブロックより上流に置いていたことでした。prefix キャッシュのカスケード失効の仕組みと、安定→揮発でブロックを並べ替え、4つしかない cache_control ブレークポイントをどこに置くかを実装と判断表で整理します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →