【翻訳】Claude Code の構築から得た教訓:プロンプトキャッシュが全てだった!

この記事はAnthropicのClaude Code開発者であるThariq氏が投稿した内容の翻訳になります。

この記事の要約
  • このX投稿は、AnthropicのClaude Code開発者であるThariq氏が、プロンプトキャッシングを活用したコンテキスト最適化の記事を共有したもので、AIセッションのコスト削減と効率化を強調している。
  • 記事の核心は、プロンプトの静的要素(システムプロンプトやツール定義)を先頭に配置し、更新をシステムメッセージで扱うことでキャッシュヒット率を高め、長期エージェントタスクを低コストで実現する方法を詳述。
  • 投稿直後、OpenAIも類似のプロンプトキャッシング事例を公開し、業界全体でコンテキスト管理技術の進化が注目を集めている。

用語の説明(翻訳時追加)

  1. プロンプトキャッシュ – リクエストの先頭部分をキャッシュし、同じプレフィックスが再利用される仕組み。
  2. Claude Code – Inception が提供するコード支援エージェント。
  3. API – アプリケーション・プログラミング・インターフェース。外部から機能を呼び出す手段。
  4. cache_control ブレークポイント – キャッシュの区切り位置を指示するパラメータ。
  5. system prompt – エージェントに与える指示や設定のテキスト。
  6. tools – エージェントが呼び出せる外部機能やユーティリティ。
  7. subagents – メインエージェントから別のモデルにタスクを委譲する仕組み。
  8. MCP ツール – Claude Code がサポートする多数のツールの総称。
  9. ToolSearch – 必要なツールを検索・取得するための特別なツール。
  10. コンパクション – コンテキストウィンドウが足りなくなったときに会話を要約し、ウィンドウを再確保する処理。
  11. キャッシュセーフ – キャッシュが無効にならないように設計された手法。
  12. SEV – Service‑Level Event(サービス障害)の略。

「Cache Rules Everything Around Me(キャッシュがすべてを支配する)」という言葉はエンジニアリングでよく言われますが、エージェントにも同じルールが当てはまります。
長時間稼働するエージェント製品(Claude Code など)は プロンプトキャッシュ によって実現可能です。これにより、前回のやり取りの計算結果を再利用でき、レイテンシとコストを大幅に削減できます。

プロンプトキャッシュとは何か、どのように機能するか、そして技術的にどう実装するか?
詳細は @RLanceMartin のプロンプトキャッシュに関する記事と、当社の新しい自動キャッシュ機能のリリースをご覧ください。

Claude Code では、システム全体をプロンプトキャッシュを中心に設計しています。高いキャッシュヒット率はコスト削減につながり、サブスクリプションプランのレートリミットを緩やかに設定できるため、キャッシュヒット率を監視し、低すぎる場合は障害(SEV)として扱います。

以下は、スケールでプロンプトキャッシュを最適化する過程で得た(しばしば直感に反する)教訓です。


1. キャッシュ用にプロンプトを配置する

プロンプトキャッシュは プレフィックスマッチ(接頭辞一致)で動作します。API はリクエストの先頭から各 cache_control ブレークポイントまでをキャッシュします。したがって、要素の順序は非常に重要で、できるだけ多くのリクエストが同じプレフィックスを共有できるようにしたいのです。

最適な配置例(Claude Code)

  1. Static system prompt & Tools(全体でキャッシュ)
  2. Claude.MD(プロジェクト単位でキャッシュ)
  3. Session context(セッション単位でキャッシュ)
  4. Conversation messages

この順序にすると、セッション間でキャッシュヒットが最大化されます。

注意:この順序は意外に壊れやすいです。例として、静的システムプロンプトに詳細なタイムスタンプを入れたり、ツールの順序を非決定的に並べ替えたり、ツールのパラメータ(例:AgentTool が呼び出せるエージェント)を更新したりすると、キャッシュが無効になります。


2. 更新はメッセージで行う

プロンプトに入れた情報が古くなることがあります(例:時間が変わった、ユーザーがファイルを変更した)。プロンプト自体を更新したくなるかもしれませんが、そうするとキャッシュミスが発生し、ユーザーにとって高コストになります。

代わりに、次のターンで メッセージ に情報を渡すことを検討してください。Claude Code では、更新された情報(例:今日は水曜日です)を <system‑reminder> タグで次のユーザーメッセージやツール結果に付加し、モデルに伝えます。これによりキャッシュが保持されます。


3. セッション中にモデルを変更しない

プロンプトキャッシュはモデルごとに固有です。そのため、キャッシュの動作は直感に反しがちです。

例:Opus で 100 k トークンまで会話が進んでいるときに、比較的簡単な質問をしたい場合、Haiku に切り替えるよりも Opus のままで回答させた方が安く済みます。なぜなら Haiku 用のキャッシュを再構築しなければならないからです。

モデルを切り替える必要がある場合は サブエージェント を使うのがベストです。Opus が「ハンドオフ」メッセージを生成し、別のモデルにタスクを委譲します。Claude Code の Explore エージェントは Haiku を使ってこの手法を頻繁に利用しています。


4. セッション中にツールを追加・削除しない

会話の途中でツールセットを変更すると、キャッシュが壊れる最も一般的な原因の一つです。直感的には「今必要なツールだけをモデルに渡すべき」ように思えますが、ツールはキャッシュプレフィックスの一部なので、追加・削除は会話全体のキャッシュを無効にします。


5. Plan Mode(計画モード)— キャッシュを意識した設計

Plan Mode はキャッシュ制約に合わせて設計された機能の好例です。直感的なやり方は、ユーザーが計画モードに入ったときにツールセットを「読み取り専用」だけに入れ替えることですが、これだとキャッシュが壊れます。

代わりに、すべてのツールを常にリクエストに含めEnterPlanModeExitPlanMode をツール自体として扱います。ユーザーが計画モードをオンにすると、エージェントはシステムメッセージで「計画モードに入ります」ことをや示します(例:コードベースを探索し、ファイルは編集しない、計画が完了したら ExitPlanMode を呼び出す)。ツール定義は決して変わりません。

この設計の副産物として、EnterPlanMode がツールなので、モデルが自ら「難しい問題」を検知したときに自律的に計画モードに入ることができ、キャッシュが壊れません。


6. Tool Search(ツール検索)— 削除ではなく遅延

同じ原則がツール検索機能にも当てはまります。Claude Code では数十種類の MCP ツールをロードできますが、すべてをリクエストに含めるとコストが増大します。一方で会話中にツールを削除するとキャッシュが壊れます。

解決策:defer_loading
ツールを削除する代わりに、軽量のスタブ(ツール名だけ)を defer_loading: true として送ります。モデルは必要に応じて ToolSearch ツールでそのスタブを「発見」し、選択されたときに初めて完全なツールスキーマをロードします。これにより、キャッシュプレフィックスは常に同じ順序で安定します。

API でも tool search ツールを利用すれば、同様の処理が簡単になります。


7. フォークコンテキスト — コンパクション

コンパクションは、コンテキストウィンドウが足りなくなったときに行う処理です。会話を要約し、要約結果で新しいセッションを開始します。

コンパクションにはキャッシュに関する多くのエッジケースがあります。特に、要約を生成するために「全会話」を別の API コールで送ると、システムプロンプトやツールが異なるため、メイン会話のキャッシュプレフィックスと全く合致せず、入力トークン全てにフルプライスがかかります。

解決策:キャッシュセーフなフォーク

コンパクションを実行するときは、親会話と全く同じ システムプロンプト、ユーザーコンテキスト、システムコンテキスト、ツール定義を使用します。まず親会話のメッセージを前置し、最後にコンパクション用のプロンプトを新しいユーザーメッセージとして追加します。

API から見ると、リクエストは親会話の最終リクエストとほぼ同一です(同じプレフィックス、同じツール、同じ履歴)。したがってキャッシュプレフィックスが再利用され、追加されるトークンはコンパクションプロンプトだけです。

この方法では「コンパクションバッファ」を確保し、要約結果と新しいメッセージがコンテキストウィンドウに収まるようにします。

コンパクションは複雑ですが、Claude Code の学びを基に API に直接コンパクション機能 を組み込んでいるので、開発者は自分のアプリケーションで同じパターンをすぐに利用できます。


8. 学んだ教訓

  1. プロンプトキャッシュはプレフィックスマッチ:プレフィックスのどこかが変わると、以降のすべてが無効になります。システム全体をこの制約に合わせて設計し、順序を正しく設定すれば、ほとんどのキャッシュは無料で機能します。
  2. システムプロンプトの変更よりメッセージで対応:計画モードへの切り替えや日付の更新などは、システムプロンプトを編集するのではなく、会話中のメッセージに挿入してください。
  3. 会話中にツールやモデルを変更しない:ツールはモデルの状態遷移(例:計画モード)に利用し、ツールセット自体は変更しません。ツールのロードは遅延させ、削除は避けます。
  4. キャッシュヒット率を稼働率と同様に監視:キャッシュブレークが発生したらインシデントとして扱い、アラートを設定します。数%のキャッシュミス率の上昇でもコストとレイテンシに大きな影響があります。
  5. フォーク操作は親のプレフィックスを共有:サイド計算(コンパクション、要約、スキル実行)を行う場合は、親会話と同一のキャッシュセーフなパラメータを使用し、プレフィックスのヒットを確保します。

Claude Code は最初からプロンプトキャッシュを前提に構築されており、エージェントを作るなら同様のアプローチを取るべきです。

コメント欄の紹介

この投稿には86件以上のリプライがつき、AIエージェント開発者たちが熱い議論を交わしています。主なものを翻訳して紹介します。

@somi_ai(AI SaaS開発者)
「tool swappingの洞察が一番刺さった。私たちも『タスクごとにツール定義を動的にロードすれば効率的だ』と思っていたけど、毎回キャッシュが吹き飛んでいた。
静的ツールセット+内部ルーティングに変えた瞬間、ヒット率が40%→90%に跳ね上がった。まさに目から鱗。」

@rileytomasek(dexa.ai創業者)
「これって主にAnthropic特有の問題じゃない?」
Thariq氏回答:「いや、どのプロバイダでもツール定義が変わるとキャッシュミスは確定。設計次第で回避できる話。」

@ejae_dev(Agentic Coding専門)
「キャッシュ最優先設計のリスクもある。
エージェントの制御フローが『キャッシュしやすさ』に引っ張られて、本当の最適行動を避けてしまう可能性が出てくる。」Thariq氏本人は「この記事、近いうちにブログにも正式公開するよ!」と返信。
今後さらに詳細版が読めるのが楽しみです。

感想

これは簡単な質問だから軽量モデルに切り替えて質問!・・・って、これ駄目なんですね。
頻繁に切り替えてました( ;∀;)