この機能は、限定的な技術的保持を伴うZero Data Retention(ZDR)の対象となります。保持される内容とその理由の詳細については、データ保持セクションを参照してください。
プロンプトキャッシングはレイテンシとコストを大幅に削減しますが、それはプロンプトの先頭部分が最近のリクエストとバイト単位で完全に一致している場合に限られます。ツールの順序変更、システムプロンプトに挿入されたタイムスタンプ、または以前のメッセージへの編集は、気づかないうちにキャッシュを無効化する可能性があります。キャッシュ診断がなければ、唯一のシグナルは usage.cache_read_input_tokens がゼロに落ちることだけで、何が変わったのかは示されません。
キャッシュ診断はこのギャップを埋めます。前回のレスポンスの id を渡すと、APIは2つのリクエストを比較し、どこで分岐したか(モデル、システムプロンプト、ツール、またはメッセージ履歴)を教えてくれるため、推測ではなく根本原因を修正できます。
キャッシュ診断はベータ版です。この機能を使用するには、APIリクエストにベータヘッダー cache-diagnosis-2026-04-07 を含めてください。
キャッシュ診断は現在、Claude APIでのみ利用可能です。Amazon BedrockおよびVertex AIではサポートされていません。
ベータヘッダーが存在する場合、APIは各リクエストの軽量なフィンガープリントをレスポンスの id をキーとして保存します。次のリクエストで、その id を diagnostics.previous_message_id として含めます。APIは新しいリクエストのフィンガープリントを再構築し、保存されたものと比較して、最初の分岐点を説明する diagnostics オブジェクトをレスポンスに添付します。
この比較はリクエスト構造に関するものであり、キャッシュが実際にヒットしたかどうかとは独立しています。diagnostics の結果と usage.cache_read_input_tokens を組み合わせる方法については、使用状況と併せて診断結果を読むを参照してください。
フィンガープリントにはハッシュとトークン数の推定値のみが含まれ(生のプロンプト内容は含まれません)、限られた期間のみ保持され、組織とワークスペースにスコープが限定され、他の目的には使用されません。
すべてのターンでベータヘッダーを送信してください。最初のターンでは、比較対象となる前のメッセージがない状態でオプトインするために "previous_message_id": null を渡します。以降のターンでは、前回のレスポンスの id を渡します。
client = anthropic.Anthropic()
SYSTEM = "You are an AI assistant analyzing a large document. <document>...</document>"
# ターン1: previous_message_id=None でオプトイン
r1 = client.beta.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=[{"role": "user", "content": "Summarize section 1."}],
diagnostics={"previous_message_id": None},
betas=["cache-diagnosis-2026-04-07"],
)
# ターン2: 前のレスポンスIDを参照
r2 = client.beta.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=[
{"role": "user", "content": "Summarize section 1."},
{"role": "assistant", "content": r1.content},
{"role": "user", "content": "Now summarize section 2."},
],
diagnostics={"previous_message_id": r1.id},
betas=["cache-diagnosis-2026-04-07"],
)
diagnostics = r2.diagnostics
if diagnostics is None:
print("No divergence detected.")
elif diagnostics.cache_miss_reason is None:
print("Comparison still pending.")
else:
print(f"cache_miss_reason: {diagnostics.cache_miss_reason.type}")ストリーミングレスポンスでは、diagnostics は message_start イベントに表示されます。
# ターン2: 前のレスポンスIDを参照してストリーミング
with client.beta.messages.stream(
model="claude-opus-4-8",
max_tokens=1024,
cache_control={"type": "ephemeral"},
system=SYSTEM,
messages=[
{"role": "user", "content": "Summarize section 1."},
{"role": "assistant", "content": r1.content},
{"role": "user", "content": "Now summarize section 2."},
],
diagnostics={"previous_message_id": r1.id},
betas=["cache-diagnosis-2026-04-07"],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
print()
r2 = stream.get_final_message()
diagnostics = r2.diagnostics
if diagnostics is None:
print("No divergence detected.")
elif diagnostics.cache_miss_reason is None:
print("Comparison still pending.")
else:
print(f"cache_miss_reason: {diagnostics.cache_miss_reason.type}")message_start イベントには完全な diagnostics フィールドが含まれます。取り得る値についてはレスポンス形式を参照してください。
マルチターンの会話では、最新のレスポンスの id を各ターンで previous_message_id として引き継ぎます。最初のイテレーションではオプトインのために null を渡し、以降の各イテレーションでは前回のレスポンスの id を渡します。
レスポンスの Message にある diagnostics フィールドには、4つの状態があります。
| 値 | 意味 |
|---|---|
| フィールドなし | リクエストに diagnostics が含まれていなかったか、ベータヘッダーが欠けていました。 |
null | previous_message_id が null だった(最初のターンで比較対象がない)か、比較が実行されて分岐が見つからなかったかのいずれかです。 |
{"cache_miss_reason": null} | レスポンスがシリアライズされた時点で比較がまだ実行中でした。これはレスポンスが非常に速く開始された場合に発生することがあります。結論が出ていないものとして扱い、次のターンを確認してください。 |
{"cache_miss_reason": {...}} | cache_miss_reason が添付されています。*_changed タイプの場合は最初の分岐点を特定します。previous_message_not_found と unavailable は比較が生成されなかったケースです。 |
cache_miss_reason がnullでない場合、次のような形式になります。
{
"id": "msg_01Xyz...",
"type": "message",
"role": "assistant",
"content": [{ "type": "text", "text": "..." }],
"usage": {
"input_tokens": 42,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 41850,
"output_tokens": 210
},
"diagnostics": {
"cache_miss_reason": {
"type": "system_changed",
"cache_missed_input_tokens": 41850
}
}
}cache_miss_reason は type による判別共用体です。レスポンスは最も早い分岐のみを報告するため、まずそれを修正してください。後続の分岐はその背後に隠れている可能性があります。
| タイプ | 意味 | 変更すべき点 |
|---|---|---|
model_changed | model が前回のリクエストと異なります(例えば、ルーター、A/Bテスト、またはフォールバックが別のモデルを選択した場合)。キャッシュはモデルごとです。 | キャッシュされた会話内ではモデルを一定に保ってください。 |
system_changed | system パラメータが異なります。通常、タイムスタンプ、リクエストID、またはその他のリクエストごとの値がシステムプロンプトに挿入されています。 | システムプロンプトをバイト単位で安定した定数にし、動的データはキャッシュブレークポイントの後の最初の user メッセージに移動してください。 |
tools_changed | tools 配列が異なります。ターン間でツールが追加、削除、または並べ替えられたか、ツールの input_schema JSONが非決定的にシリアライズされました。 | すべてのターンで同じツールリストを固定された順序で送信し、スキーマを決定的にシリアライズしてください(例えば、キーをソートする)。 |
messages_changed | モデル、システム、ツールはすべて一致していますが、messages 内の以前のエントリが追加ではなく変更、並べ替え、または削除されました。通常、会話履歴が切り詰められたか編集されたか、アシスタントのターンと tool_result ブロックが再送信時に異なる形でシリアライズされています。 | 履歴を追加専用として扱い、アシスタントの content とツール結果をそのままエコーバックしてください。 |
previous_message_not_found | 指定された previous_message_id に対する保存されたフィンガープリントが存在しません。これはリクエストが変更されたことの証拠ではありません。通常、前回のリクエストにベータヘッダーが含まれていなかったか、別のワークスペースから送信されたか、送信されてから時間が経ちすぎています。 | すべてのターンでベータヘッダーを送信し、連続するターンを時間的に近づけてください。 |
unavailable | このリクエストに対する診断情報が利用できませんでした。これには、model、system、tools は一致しているが、プロンプトに影響する他のリクエストパラメータ(tool_choice、thinking、context_management、output_config、output_format、またはアクティブな anthropic-beta ヘッダーのセット)が異なるケースや、分岐が比較範囲を超えている非常に長い会話が含まれます。リクエストは正常に処理されました。 | キャッシュされた会話の存続期間中、プロンプトに影響するリクエストパラメータを一定に保ってください。問題が続く場合は、プロンプトキャッシングのページの一般的な問題のトラブルシューティングにある手動チェックを適用してください。 |
4つの *_changed タイプには cache_missed_input_tokens という整数も含まれます。これは分岐点以降に該当する入力トークン数の推定値で、キャッシュ可能なプレフィックスがどれだけ失われたかの目安を示します。トークン化前のバイト長から導出されるため、課金数値ではなく規模の指標として扱ってください。usage.input_tokens と異なる(場合によっては超える)ことがあります。
diagnostics は「リクエストが変更されたか?」に答え、usage.cache_read_input_tokens は「キャッシュがヒットしたか?」に答えます。両者を組み合わせることで、どこを調べるべきかがわかります。
このマトリックスは、実際の previous_message_id を渡したターンに適用されます。最初のターン(previous_message_id: null)では、diagnostics は常に null であり、キャッシュは読み取られるのではなく書き込まれているため cache_read_input_tokens は通常ゼロです。トラブルシューティングは不要です。また、cache_miss_reason が null の場合(比較がまだ保留中。次のターンを確認してください)や、その type が previous_message_not_found または unavailable の場合(比較が生成されなかった)にも、このマトリックスは適用されません。
| 診断結果 | キャッシュ読み取りトークン | 解釈 |
|---|---|---|
null | 高い | 期待どおりに動作しています。プレフィックスは安定しており、キャッシュがヒットしました。 |
null | 低いまたはゼロ | リクエストは一致していますが、キャッシュエントリがもう利用できませんでした。ターン間の間隔を短くするか、1時間のキャッシュTTLの使用を検討してください。 |
cache_miss_reason が *_changed タイプ | 低いまたはゼロ | あなたのバグです。リクエストが変更されました。type が示す原因を修正してください。 |
cache_miss_reason が *_changed タイプ | 高い | まれなケースです。プロンプトの後半で変更が発生しましたが、それより前の cache_control ブレークポイントはヒットしました。修正する価値はありますが、影響は小さいです。 |
previous_message_id 検索用のフィンガープリントは短期間で期限切れになります。診断比較は時間的に近いリクエスト間で実行してください。unavailable が返される場合があります。unavailable を返すか、比較がまだ実行中だった場合は cache_miss_reason: null を返します。キャッシュ診断はZDR適格(条件付き)です。Anthropicはこの機能のためにプロンプトの生テキストやClaudeの出力を保存しません。
各リクエストに対して保存されるフィンガープリントは、暗号学的ハッシュとトークン数の推定値のみで構成され、レスポンスの id をキーとし、組織とワークスペースにスコープが限定されます。フィンガープリントは短期間で期限切れになり、他の目的には使用されません。
すべての機能にわたるZDR適格性については、APIとデータ保持を参照してください。
Was this page helpful?