OpenRouter、プロンプトキャッシュと固定ルーティングを発表
OpenRouter は、エージェントのシステムプロンプトやツール定義を再利用する際のコスト削減のために、プロンプトキャッシングとステッキルーティング(Sticky Routing)の連携による具体的な価格体系と実装戦略を発表した。
キーポイント
キャッシュ読み込みと書き込みの非対称なコスト構造
キャッシュ読み込みは入力トークンの0.1倍〜0.5倍で済むが、書き込み(特にAnthropicの1時間TTL)は2.0倍となり、再利用されない場合のコスト増リスクがある。
ステッキルーティングによるキャッシュヒット率向上
セッションID(session_id)を用いて後続のリクエストを同じプロバイダーに固定し、キャッシュが有効な状態(ウォーム)を維持することで、冷たいエンドポイントへの接続を防ぐ。
キャッシュミスが発生する4つの主要要因
プロンプトが短すぎる場合、キャッシュ期限切れ、オープニングブロックの頻繁な変更、あるいはリクエストが異なるプロバイダーへルーティングされた場合にキャッシュヒットしない。
エージェントセッションにおけるコスト最適化の実践
6ターン以上のセッションにおいて、システムプロンプトやツール定義を毎回再送するのではなく、最初の成功したリクエストからsession_idでルーティングを固定し、キャッシュの恩恵を最大化する。
Sticky Routing と session_id の重要性
キャッシュの書き込みと読み取りを同じプロバイダーエンドポイントに維持するために、明示的な session_id を使用してステッキールーティングを有効化し、会話開始時から安定したキャッシュ状態を実現する必要があります。
キャッシュコストの構造と最適化
キャッシュは「書き込み(初期コスト)」と「読み取り(低価格)」の2段階で構成されており、Anthropic などの一部プロバイダーでは書き込みが通常入力より高くなるため、複数回のターンでの再利用が必須となります。
キャッシュミスの主な原因と対策
プロンプトの最小トークン数不足、TTL による期限切れ、開始部分の内容変更、および異なるプロバイダーへのルーティング漂移がキャッシュミスを引き起こす主要な要因です。
重要な引用
A cache read costs 0.1x to 0.5x of a fresh input token, depending on the provider.
Sticky routing keeps that working across turns by sending a session back to the same provider that holds the warm cache.
The first request pays a cache write... so a single unreused write costs more than not caching at all.
The write happens when the provider stores the reusable part of the prompt. The read happens when a later request reuses that stored content.
For agent builders, the pattern is simple: the first turn may pay to set up the cache, but every turn after that gets much cheaper as long as the same opening block is reused.
The savings grow with the number of turns.
影響分析・編集コメントを表示
影響分析
この発表は、LLM エージェント開発におけるコスト構造の根本的な理解と最適化手法を提供しており、特に高頻度で対話を行うシステムや複雑なツール定義を持つアプリケーションにおいて、運用コストを劇的に削減する可能性を示しています。また、プロバイダー間のキャッシュ状態管理(ステッキルーティング)という技術的アプローチは、マルチプロバイダー環境での実用性を高める重要な標準化の第一歩となるでしょう。
編集コメント
プロンプトキャッシングの価格体系を詳細に解説し、単なる機能紹介ではなく「書き込みコスト」のリスクまで言及している点は非常に実用的です。特にマルチプロバイダー環境でのキャッシュ断絶問題を解決するステッキルーティングの概念は、大規模エージェント開発において即座に適用できる重要な知見と言えます。
エージェントは、各ターンで同じシステムプロンプト、ツール定義、スキーマ、ポリシー指示を送信しています。6 ターンのセッションにおいて、ユーザーの最新メッセージやエージェントの最新ツール結果以外は何も変わっていないにもかかわらず、その最初のブロックに対して 6 回請求される可能性があります。
これを解決するのがプロンプトキャッシングです。プロバイダーは、プロンプトの繰り返し部分をキャッシュから読み取ることで、毎回フル価格で課金する必要がなくなります。スティッキールーティング(Sticky Routing)は、セッションを同じプロバイダーに送り返すことで、この仕組みをターンを超えて維持します。
本記事では、コストに関する側面を取り上げます。キャッシュされたトークンの料金体系、キャッシュ読み取りと書き込みの価格差がなぜ存在するのか、session_id でどのようにして 1 ターン目からエージェントのセッションをウォーム状態に保つのか、そしてキャッシングが実際に機能しているかを確認する方法について解説します。
Tl;dr
- キャッシュ読み取りのコストは、プロバイダーによりますが、新規入力トークンの 0.1 倍〜0.5 倍です。Claude Sonnet 4.6 では、キャッシュ読み取りが 100 万トークンあたり 0.30 ドル($0.30/M)で、新規入力が同額 3.00 ドル($3.00/M)であるため、正確に 0.1 倍となります。
- 最初のリクエストではキャッシュ書き込みのコストが発生します。Anthropic の場合、書き込みコストは入力コストの 1.25 倍(TTL 5 分)または 2.0 倍(TTL 1 時間)です。つまり、一度も再利用されない書き込みを行うと、キャッシングを行わない場合よりも高額になります。
- 次のリクエストが同じプロバイダーのエンドポイントに到達しない限り、ウォームキャッシュは役立ちません。70 社以上のプロバイダーが存在する中で、2 ターン目に冷たい(コールド)エンドポイントに接続されれば、フル価格を支払うことになります。
- 私たちのスティッキールーティングは、フォローアップリクエストをウォームキャッシュを持つプロバイダーに固定します。また、session_id を使用することで、キャッシュヒットが発生する前、つまり最初の成功したリクエストの時点でこの動作を強制します。
- キャッシュミスが発生する原因は主に4つあります。プロンプトが短すぎる場合、キャッシュの有効期限が切れている場合、先頭のブロックが頻繁に書き換わる場合、あるいはリクエストが異なるプロバイダーへ転送された場合です。キャッシュヒットを確認するには、レスポンス内の
cached_tokensをチェックしてください。
プロンプトキャッシングでトークンコストはどれくらい削減できるか?
キャッシュからの読み込みコストは、プロバイダーによって異なりますが、通常の入力価格の0.1倍から0.5倍程度です。この価格差こそが、エージェントループのコストを劇的に下げる要因となります。
繰り返し使用される部分は、往々にして最も高価な部分です。例えば、長いシステムプロンプトやツール定義、JSONスキーマ、ガードレール、取得したドキュメント、あるいはモデルの一貫性を保つための例示などが該当します。キャッシュを使用しない場合、会話の各ターンでこれらすべての要素に対してフル価格が請求されます。一方、キャッシングを活用すれば、最初のリクエストでキャッシュに書き込まれ、その後のリクエストではより安価なレートで読み出される仕組みです。
以下に主要プロバイダーごとの詳細をまとめます:
| プロバイダー | キャッシュ読み込み | キャッシュ書き込み | 有効化方法 |
|---|---|---|---|
| Anthropic Claude (5分 TTL) | 入力価格の0.1倍 | 入力価格の1.25倍 | 自動または明示的 |
| Anthropic Claude (1時間 TTL) | 入力価格の0.1倍 | 入力価格の2.0倍 | 明示的 (ttl: "1h") |
| OpenAI (GPT-5.6以前) | 入力価格の0.25〜0.50倍 | 無料 | 自動 |
| OpenAI (GPT-5.6以降) | 入力価格の0.25〜0.50倍 | 入力価格の1.25倍 | 自動または明示的 |
| Google Gemini (暗黙的) | 入力価格の0.25倍 | 無料 | 自動 |
| Grok (xAI) | 入力価格の0.25倍 | 無料 | 自動 |
| Moonshot AI | 入力価格の0.25倍 | 無料 | 自動 |
| Groq | 入力価格の0.5倍 | 無料 (Kimi K2モデル) | 自動 |
| DeepSeek | 入力価格の0.1倍 | 入力価格の1.0倍 | 自動 |
| Alibaba Qwen | 入力価格の0.1倍 | 入力価格の1.25倍 | 明示的 (cache_control) |
| Z.AI | 入力価格の約0.2倍 | 無料 | 自動 |
詳細な仕組みについては、プロンプトキャッシングのドキュメントをご覧ください。実際の金額はモデルやプロバイダーの経路によって異なりますが、この乗数値を見ることで、そのプロバイダーにおけるキャッシュされた入力と通常入力の価格比較が可能になります。
エージェント開発者にとって、このパターンの本質はシンプルです。最初のやり取りではキャッシュ構築のために費用がかかりますが、同じ冒頭ブロックを再利用する限り、その後のすべてのやり取りで大幅にコストを抑えられます。
コストの内訳:キャッシュへの書き込みと読み出し
プロンプトキャッシングには「書き込み」と「読み出し」の 2 つのコストが発生します。
書き込みは、プロバイダーがプロンプトの再利用可能な部分を保存する際に行われます。一方、読み出しは、後のリクエストでその保存された内容を再利用する際に行われます。同じコンテンツを十分に多く読み出せば、書き込みコストを上回るメリットを得られます。
一部のプロバイダーでは、書き込みコストが通常の入力よりも高くなります。Anthropic の場合、デフォルトの 5 分 TTL では入力コストの 1.25 倍、1 時間の TTL では 2.0 倍になります。一度も再利用されない Anthropic のキャッシュ書き込みは、キャッシングなしで同じプロンプトを送信するよりも高額です。
単発のリクエストであれば、キャッシングが役立つとは限りません。しかし、マルチターン型のエージェントでは反復が前提となります。セッション全体を通じて、エージェントは同じ指示、ツール、スキーマ、ポリシーコンテキストを引き継ぐため、数回のやり取りで書き込みコストを回収できるのです。
短いバーストで次の入力がすぐに続く場合は、キャッシュの有効期限(TTL)を 5 分に設定します。セッションが一時停止してデフォルトのキャッシュが切れる可能性がある一方で、その内容を保持する価値がある場合は、1 時間設定しましょう。
なぜウォームキャッシュが次のリクエストで常に役立つわけではないのか
ウォームキャッシュが有効になるのは、次のリクエストがそのキャッシュを保有しているプロバイダーのエンドポイントに到達した場合に限られます。
複数のプロバイダーへルーティング可能な場合、1 回目の入力でキャッシュが作成されたプロバイダーとは別に、2 回目の入力が別のプロバイダーに割り当てられる可能性があります。すると、2 番目のプロバイダーにはウォームキャッシュが存在しないため、リクエストは成功してもフル価格で課金され、キャッシュされたトークン数は低いままでゼロになることもあります。
そこで、プロンプトキャッシングとスティーキールーティング(固定ルーティング)を組み合わせるのです。キャッシュされたリクエストの後、同じモデルに対する続投リクエストについては、そのプロバイダーのキャッシュ読み取り料金が通常の入力料金より安い場合に限り、同じプロバイダーのエンドポイントへルーティングします。もしその固定プロバイダーが利用不可になった場合は、OpenRouter はリクエストを失敗させるのではなく、次に利用可能なプロバイダーにフォールバックします。
デフォルトでは、OpenRouter は会話の最初のシステムまたは開発者メッセージと、2 番目の非システムメッセージのハッシュ値を基に会話を認識します。これは、これらの冒頭メッセージが一定の場合に機能します。
しかし、エージェントはこの前提を崩すことがあります。状態の要約やツールのコンテキストの再配置、新しい実行メタデータの追加などにより、最初のメッセージを書き換えるケースがあるのです。冒頭のメッセージが変わればハッシュ値も変わり、会話が異なるプロバイダーに割り当てられてしまいます。この問題を解決するには、明示的な session_id を設定する必要があります。

最初の一瞬からキャッシュを温めておく:session_id の活用
エージェントのループ処理では、必ず session_id を設定してください。この値を指定すると、OpenRouter は最初のメッセージからキーを導出するのではなく、渡された session_id そのものを「スティッキー・ルーティング」のキーとして直接使用します。
session_id を設定することで、キャッシュがヒットするのを待たずに、最初の成功したリクエストの直後にスティッキー・ルーティングが有効になります。これを設定しない場合、スティッキー化は実際にキャッシュがヒットしてからしか始まりません。複数ターンにわたるエージェント処理において、これは「最初から確実に動作するキャッシュ」か、「時々しか温まっていないキャッシュ」かの決定的な違いとなります。
session_id は、リクエスト本文のトップレベルフィールドとして送るか、x-session-id ヘッダーを通じて渡すことができます。会話やエージェントの実行中は安定した値を維持し、文字数は 256 文字以内に抑えてください。
curl https://openrouter.ai/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-4.6",
"session_id": "my-agent-session-abc123",
"messages": [{"role": "system", "content": "..."}]
}'
from openrouter import OpenRouter
client = OpenRouter()
resp = client.chat.send(
model="anthropic/claude-sonnet-4.6",
session_id="my-agent-session-abc123",
messages=[{"role": "system", "content": "..."}],
)
import { OpenRouter } from '@openrouter/sdk';
const openRouter = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY });
const response = await openRouter.chat.send({
model: 'anthropic/claude-sonnet-4.6',
session_id: 'my-agent-session-abc123',
messages: [{ role: 'system', content: '...' }],
});
セッション ID には、チャットスレッドやチケット、ワークフローの実行、エージェントのタスクなど、「作業単位」に一致する値を設定してください。各ターンごとに新しい session_id を作成すると、リクエストがキャッシュを保持しているプロバイダに届かなくなるため注意が必要です。
Auto Router や Pareto Router といったルーターモデルを利用している場合、セッションの固定機能はプロバイダだけでなく、ルーターが選択したモデル自体も固定します。これにより、セッション中にモデルが切り替わるのを防ぎ、動作の一貫性を保ちつつキャッシュを温存状態に維持できます。
プロンプトキャッシングが実際に機能しているか確認するには?
最も手っ取り早い方法は、利用状況のチェック です。
レスポンス内の usage.prompt_tokens_details.cached_tokens を確認すると、キャッシュから読み込まれたトークン数がわかります。この値がゼロより大きければ、リクエストはキャッシュにヒットしています。また、cache_write_tokens はキャッシュ書き込みリクエスト中に書き込まれたトークン数を示します。
この例では、プロンプトトークンのほとんどがキャッシュから取得されており、今回のリクエストでは新しいキャッシュエントリの作成は行われていません。
キャッシュの動作を確認するには、3 つの場所をチェックできます。Activity ページ の詳細ビュー、/api/v1/generation API、そして API 応答に含まれる usage.prompt_tokens_details オブジェクトです。
cache_discount を使用すると、生成処理でどれほどコストを節約できたかを確認できます。キャッシュ書き込みに課金しているプロバイダーの場合、書き込み時のリクエストではキャッシュ書き込みのコストが通常の入力よりも高くなるため、割引率がマイナスになることがあります。その後のキャッシュ読み取りのリクエストでは、割引率はプラスに転じるはずです。

キャッシュミスが発生する理由と対策
キャッシュが機能していないように見える場合、通常は以下の 4 つのいずれかが原因です。プロンプトが短すぎる、キャッシュの有効期限が切れている、先頭の内容が変更されている、あるいはリクエストが異なるプロバイダーへ振り向けられたケースです。
プロンプトがプロバイダーの最小サイズを下回っている
各プロバイダーにはキャッシュ化に必要な最小のプロンプトサイズが設定されており、それ未満では何もキャッシュされません。Anthropic の場合、Claude Opus 4.5〜4.8 および Claude Haiku 4.5 は 4,096 トークンが必要です。Claude Haiku 3.5 は 2,048 トークン、Claude Sonnet 4/4.5/4.6(および Opus 4/4.1)は 1,024 トークンが最低限必要です。OpenAI も 1,024 トークンを要求します。Gemini 2.5 Pro は 4,096 トークン、Gemini 2.5 Flash は 1,024 トークンが必要です。
再利用可能なコンテンツの量が閾値に満たない場合、キャッシュは機能しません。無理やりテキストを埋め込んで強引に利用しようとするのは避けてください。ツール、スキーマ、取得したドキュメント、例示データ、ポリシー文書など、すでに再利用可能な要素が豊富な場面でキャッシュを活用しましょう。
会話の合間にキャッシュが期限切れになる
キャッシュは長く持ちません。Anthropic のデフォルト設定では 5 分ですが、長時間セッション用の 1 時間オプションも用意されています。Gemini のインプリシット(暗黙的)なキャッシュは約 3〜5 分で有効期限が切れますし、参照してもリセットされません。一度期限が切れると、次のリクエストでは新しいキャッシュの作成が必要になります。
ユーザーが会話の間隔を空けることが多い場合は、サポートされている環境ではより長い TTL(Time To Live)を設定するか、アイドル期間後に新しい書き込みを受け付けるエージェントを設計してください。
プロンプトの先頭部分が常に変わる
自動キャッシュやインプリシットキャッシュは、プロンプトの先頭部分が一定である場合に最も効果を発揮します。安定した要素を先に配置しましょう。具体的には、システム指示、ツール定義、スキーマ、固定された参照資料などです。一方、変化する要素は後方に回します。ユーザーからの質問、タイムスタンプ、一時的な状態情報、ツールの出力結果、短命なメタデータなどが該当します。
細かい違いも重要です。最初のシステムメッセージにタイムスタンプが含まれていると、会話のたびにプロンプトが新規作成されたように見なされてしまいます。キャッシュ対象に含まれる必要がない場合は、それを後続のユーザーメッセージやツールメッセージへ移動させましょう。
リクエスト先のプロバイダが変わってしまった
キャッシュは、書き込まれた場所にのみ存在します。もしその後のリクエストが異なるプロバイダのエンドポイントにルーティングされた場合、そのエンドポイントは以前のキャッシュを読み取ることはできません。
エージェントワークフローでは、session_id を設定してステイキー・ルーティングによりセッションを「温かい」プロバイダーに維持しましょう。ただし注意点として、自分で provider.order を指定すると、その順序がステイキー・ルーティングよりも優先されます。特定の注文順が必要な場合は、provider routing controls を利用してください。
エージェントループにおけるキャッシュとステイキー・ルーティングの併用
エージェントが各ターンで同じコンテンツを送信する場合、以下のチェックリストを確認しましょう。
- 安定したコンテンツを先頭に配置する:システムプロンプト、ツール定義、スキーマ、ポリシー、長期にわたる文脈など。
- 変化するコンテンツは後方に配置する:ユーザーメッセージ、ツールの結果、タイムスタンプ、実行固有の状態など。
- 明示的な cache_control を必要とするプロバイダーに対してプロンプトキャッシュを有効にする。
- 会話またはワークフローの実行に対して安定した session_id を設定する。
- cached_tokens と cache_discount を確認し、実際にキャッシュ読み取りが行われているか検証する。
大まかなイメージとして、10,000 トークンの同じコンテンツを 6 ターンにわたって繰り返すエージェントを考えてみましょう。
| シナリオ | Turn 1 | Turns 2-6 | 総コスト(キャッシュなしの 1 ターンとの比較) |
|---|---|---|---|
| キャッシュなし | 入力全体を毎回読み込み | 入力全体を毎回読み込み | 6.0 倍 |
| Anthropic の 5 分キャッシュ+ステイキー・ルーティング | 書き込み 1.25x | 読み取り 0.1x | 1.75 倍 |
| フリーライティングプロバイダー+読み取り 0.25x | 入力/書き込み 1.0x | 読み取り 0.25x | 2.25 倍 |
| フリーライティングプロバイダー+読み取り 0.5x | 入力/書き込み 1.0x | 読み取り 0.5x | 3.5 倍 |
この例は繰り返されるコンテンツのみを対象としており、小さな変化のあるメッセージやモデルの出力トークンは考慮していません。ターン数が増えるほど、コスト削減効果は大きくなります。

使い分けの目安:
- 会話が進むにつれて再利用されるコンテンツが増える多回対話には、自動キャッシュを活用してください。
- 取得したドキュメントや長い参照ファイル、キャラクター設定、CSV データ、ポリシーテキストなど、どの大きなブロックをキャッシュすべきかを明確に把握している場合は、明示的なキャッシュブレイクポイントを設定しましょう。
- エージェントセッション、サポートチケット、チャットスレッド、ワークフロー実行、あるいは開始メッセージが対話ごとに変わるあらゆる会話には、session_id を使用してください。
- デフォルトの 5 分では対話中に期限切れになる可能性がある、より長い Anthropic セッションには 1 時間のキャッシュを利用します。短く密度の高い往復応答にはデフォルト設定で十分です。
エージェントが同じ高コストなコンテンツを繰り返し送信する場合でも、キャッシュされた読み込みとスティッキールーティング(定常ルーティング)によって、それがループ内で最も高額な部分になるのを防げます。
よくある質問
OpenRouter はプロンプトキャッシングに対応していますか?
はい。OpenRouter は対応するプロバイダーおよびモデル全体でプロンプトキャッシングをサポートしています。ほとんどのプロバイダーは自動的にこれを有効にしていますが、Anthropic とアリババの Qwen では明示的なキャッシュ制御のために cache_control を使用します。
キャッシュされた読み込みのコストは、プロバイダーによって通常の入力価格の 0.1 倍から 0.5 倍です。つまり、最初のリクエスト以降、再利用されるプレフィックスは大幅に安価になります。
OpenRouter でキャッシュされたトークンはいくらですか?
キャッシュ読み込みのコストは、プロバイダーによって異なりますが、通常の入力価格の 0.1 倍から 0.5 倍程度です。Anthropic、DeepSeek、Alibaba Qwen は 0.1 倍で読み込めます。OpenAI は 0.25 倍から 0.50 倍、Gemini、Grok、Moonshot は 0.25 倍、Groq は 0.5 倍となっています。
なぜ OpenRouter ではプロンプトキャッシュが機能しないのか
主な原因は、プロンプトがプロバイダーの最小トークン数に満たない場合、キャッシュの有効期限が切れている場合、プロンプトの先頭部分が不安定な場合、あるいは会話のやり取り間でプロバイダー側の挙動に変化が生じている場合です。エージェントワークフローでは、まず安定した session_id を設定することから始めましょう。その後、レスポンス内の cached_tokens を確認します。この値がゼロより大きければ、キャッシュヒットが成功したことを意味します。
エージェントのやり取り全体でキャッシュを温めておくにはどうすればよいですか?
会話、チケット、あるいはワークフローの実行に対して安定した session_id を渡してください。OpenRouter はこれを「スティッキールーティング」のキーとして使用するため、フォローアップのリクエストは、すでにキャッシュが温められている同じプロバイダーエンドポイントへルーティングされます。session_id が設定されていれば、キャッシュヒットが観測される前であっても、最初の成功したリクエスト以降にスティッキネス(固定性)が発動します。
キャッシュによってコスト削減が実現できたかどうを確認するには?
レスポンス内の usage.prompt_tokens_details.cached_tokens を確認して読み込み回数を調べ、cache_write_tokens で書き込み回数を調べます。cached_tokens の値がゼロより大きければキャッシュヒットしています。また、レスポンスの cache_discount を見れば、生成ごとのコスト効果を確認できます。あるいは、Activity ページの詳細ビューを開くか、/api/v1/generation API を利用して詳細情報を取得することも可能です。
キャッシュは Auto Router と併用できますか?
はい、session_id を設定すれば、Auto Router や Pareto Router といったルーターモデルは、会話中に解決されたモデルとプロバイダーを固定します。これにより、続報のやり取りでも同じキャッシュ(ウォーム状態)にアクセスし続けることができます。
原文を表示
Your agent sends the same system prompt, tool definitions, schemas, and policy instructions on every turn. In a 6-turn session, you can get billed for that same opening block 6 times, even though the only thing that changed is the user’s latest message or the agent’s latest tool result.
Prompt caching fixes that. The provider reads the repeated part of your prompt from cache instead of charging you full price for it every time. Sticky routing keeps that working across turns by sending a session back to the same provider that holds the warm cache.
This post covers the money side: what cached tokens cost, why cache reads and writes are priced differently, how session_id keeps an agent’s session warm from turn one, and how to check that caching is actually working.
Tl;dr
- A cache read costs 0.1x to 0.5x of a fresh input token, depending on the provider. On Claude Sonnet 4.6, a cache read runs at $0.30/M against $3.00/M input, exactly 0.1x.
- The first request pays a cache write. Anthropic writes cost 1.25x (5-minute TTL) or 2.0x (1-hour TTL) of input, so a single unreused write costs more than not caching at all.
- A warm cache only helps if your next request lands on the same provider endpoint. Across 70+ providers, turn two can hit a cold endpoint, and you pay full price.
- Our sticky routing pins follow-up requests to the provider holding the warm cache, and session_id forces that from the first successful request, before any cache hit has happened.
- Cache misses come from 4 causes: a prompt that’s too short, an expired cache, an opening block that keeps changing, or a request that moved to a different provider. Check cached_tokens in the usage response to confirm a hit.
How much does prompt caching cut your token cost?
A cache read costs 0.1x to 0.5x of normal input pricing, depending on the provider. That range is why caching can make agent loops much cheaper.
The repeated part is usually the expensive part: a long system prompt, tool definitions, JSON schemas, guardrails, retrieved documents, or examples that keep the model consistent. Without caching, each turn pays full price for all of it again. With caching, the first request writes it to the cache, and later requests read it back at the cheaper rate.
Here’s the provider-level view:
ProviderCache readCache writeHow to enable
Anthropic Claude (5-min TTL)0.1x input1.25x inputAutomatic or explicit
Anthropic Claude (1-hour TTL)0.1x input2.0x inputExplicit (ttl: "1h")
OpenAI (before GPT-5.6)0.25x-0.50x inputFreeAutomatic
OpenAI (GPT-5.6 and later)0.25x-0.50x input1.25x inputAutomatic or explicit
Google Gemini (implicit)0.25x inputFreeAutomatic
Grok (xAI)0.25x inputFreeAutomatic
Moonshot AI0.25x inputFreeAutomatic
Groq0.5x inputFreeAutomatic (Kimi K2 models)
DeepSeek0.1x input1.0x inputAutomatic
Alibaba Qwen0.1x input1.25x inputExplicit (cache_control)
Z.AI~0.2x inputFreeAutomatic
The prompt caching docs have the full breakdown. The exact dollar amount still depends on the model and provider route; the multiplier tells you how cached input compares with normal input for that provider.
For agent builders, the pattern is simple: the first turn may pay to set up the cache, but every turn after that gets much cheaper as long as the same opening block is reused.
Where does the cost go: cache writes versus cache reads?
Prompt caching has two costs: the write and the read.
The write happens when the provider stores the reusable part of the prompt. The read happens when a later request reuses that stored content. You come out ahead once the same content gets read enough times to cover the write.
On some providers, the write costs more than normal input. Anthropic cache writes cost 1.25x input for the default 5-minute TTL and 2.0x input for the 1-hour TTL. A single Anthropic cache write that’s never reused costs more than sending the same prompt without caching.
For a one-off request, caching may not help. For a multi-turn agent, repetition is the default: the agent carries the same instructions, tools, schemas, and policy context across the whole session. So the write pays for itself over a few turns.
Use the 5-minute cache lifetime (TTL) for short bursts where the next turn arrives quickly. Use the 1-hour one when a session may pause long enough for the default cache to expire, but the content is still worth keeping around.
Why doesn’t a warm cache always help on the next request?
A warm cache only helps if the next request lands on the provider endpoint that holds it.
When requests can route to many providers, turn one can write a cache on one provider while turn two lands somewhere else. The second provider has no warm cache to read from. The request still works, but you pay full price and cached_tokens stays low or zero.
That’s why we pair sticky routing with prompt caching. After a cached request, we route follow-up requests for the same model back to the same provider endpoint when that provider’s cache-read pricing is cheaper than normal input. If that sticky provider becomes unavailable, OpenRouter falls back to the next available provider instead of failing the request.
By default, OpenRouter recognizes a conversation by hashing its first system or developer message and its first non-system message. That works when those opening messages stay the same.
Agents often break that. Some rewrite their first messages as they summarize state, reorder tool context, or add new run metadata. When the opening messages change, the hash changes, and the conversation can land on a different provider. The fix is an explicit session_id.

Force a warm cache from turn one with session_id
For agent loops, set session_id. When you pass it, OpenRouter uses it directly as the sticky routing key instead of deriving a key from the opening messages.
With session_id, sticky routing kicks in after the first successful request, before any cache hit has happened. Without it, stickiness only starts after a cache hit is detected. For multi-turn agents, that’s the difference between a cache that’s reliable from turn one and one that’s only sometimes warm.
You can send session_id as a top-level request body field or through the x-session-id header. Keep it stable for the conversation or agent run, and keep it under 256 characters.
curl https://openrouter.ai/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-4.6",
"session_id": "my-agent-session-abc123",
"messages": [{"role": "system", "content": "..."}]
}'from openrouter import OpenRouter
client = OpenRouter()
resp = client.chat.send(
model="anthropic/claude-sonnet-4.6",
session_id="my-agent-session-abc123",
messages=[{"role": "system", "content": "..."}],
)import { OpenRouter } from '@openrouter/sdk';
const openRouter = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY });
const response = await openRouter.chat.send({
model: 'anthropic/claude-sonnet-4.6',
session_id: 'my-agent-session-abc123',
messages: [{ role: 'system', content: '...' }],
});Use a value that matches the unit of work: a chat thread, ticket, workflow run, or agent task. Don’t create a new session_id for every turn, or requests stop landing on the provider that holds the cache.
If you use router models such as Auto Router or Pareto Router, session stickiness also pins the model the router picked, not just the provider. That keeps the conversation from switching models mid-session, so behavior stays consistent and the cache stays warm.
How do I confirm prompt caching is even working?
The fastest way to check is to inspect usage.
In the response, usage.prompt_tokens_details.cached_tokens shows how many tokens were read from cache. If it’s greater than zero, the request hit the cache. cache_write_tokens shows how many tokens were written during a cache-write request.
{
"usage": {
"prompt_tokens": 10339,
"completion_tokens": 60,
"total_tokens": 10399,
"prompt_tokens_details": {
"cached_tokens": 10318,
"cache_write_tokens": 0
}
}
}In this example, most of the prompt tokens came from cache, and this turn didn’t write a new cache entry.
You can inspect cache behavior in three places: the detail view on the Activity page, the /api/v1/generation API, and the usage.prompt_tokens_details object returned with API responses.
Use cache_discount to see what a generation saved. On providers with paid writes, you may see a negative discount on the write turn because the cache write costs more than normal input. On later cache-read turns, the discount should turn positive.

Why does your cache miss, and how do you stop it?
When caching looks broken, it usually comes down to one of 4 things: the prompt is too short, the cache expired, the opening content changed, or the request moved to a different provider.
The prompt is below the provider’s minimum
Every provider has a minimum prompt size, and below it nothing gets cached. On Anthropic, Claude Opus 4.5 through 4.8 and Claude Haiku 4.5 need 4,096 tokens; Claude Haiku 3.5 needs 2,048; Claude Sonnet 4, 4.5, and 4.6 (and Opus 4 / 4.1) need 1,024. OpenAI needs 1,024. Gemini 2.5 Pro needs 4,096; Gemini 2.5 Flash needs 1,024.
If your reusable content sits below that minimum, caching won’t start. Don’t pad the request with filler text just to force it. Use caching where you already have a lot of reusable content: tools, schemas, retrieved documents, examples, or policy text.
The cache expired between turns
Caches don’t live long. Anthropic’s default is 5 minutes, with a 1-hour option for longer sessions. Gemini’s implicit cache lasts about 3-5 minutes and doesn’t reset when you read from it. Once a cache expires, the next request has to write a new one.
If your users often pause between turns, use a longer TTL where supported, or build the agent to accept a new write after idle periods.
The start of the prompt keeps changing
Automatic and implicit caching work best when the start of the prompt stays the same. Put the stable stuff first: system instructions, tools, schemas, and fixed reference material. Put the changing stuff later: user questions, timestamps, temporary state, tool outputs, and short-lived metadata.
Small details count here. A timestamp in the first system message makes the prompt look new on every turn. Move it into a later user or tool message if it doesn’t need to be part of the cached content.
The request drifted to a different provider
A cache lives where it was written. If a later request routes to a different provider endpoint, that endpoint can’t read the earlier cache.
For agent workflows, set session_id and let sticky routing keep the session on the warm provider. One catch: if you set provider.order yourself, your order wins over sticky routing. Use provider routing controls if you need a specific provider order.
Putting caching and sticky routing together for an agent loop
If your agent sends the same content every turn, here’s the checklist:
- Put stable content first: system prompt, tool definitions, schemas, policies, and long-lived context.
- Put changing content later: user messages, tool results, timestamps, and run-specific state.
- Enable prompt caching for providers that need explicit cache_control.
- Set a stable session_id for the conversation or workflow run.
- Inspect cached_tokens and cache_discount to confirm that reads are happening.
For a rough picture, imagine an agent that repeats the same 10,000 tokens over 6 turns.
ScenarioTurn 1Turns 2-6Total cost (vs. 1 uncached turn)
No cachingFull inputFull input each turn6.0x
Anthropic 5-minute cache + sticky routing1.25x write0.1x reads1.75x
Free-write provider + 0.25x reads1.0x input/write0.25x reads2.25x
Free-write provider + 0.5x reads1.0x input/write0.5x reads3.5x
This example covers only the repeated content. It ignores the smaller changing messages and the model’s output tokens. The savings grow with the number of turns.

When to use what:
- Use automatic caching for multi-turn conversations where the reused content grows with the conversation.
- Use explicit cache breakpoints when you know exactly which large blocks should be cached: retrieved documents, long reference files, character cards, CSV data, or policy text.
- Use session_id for agent sessions, support tickets, chat threads, workflow runs, and any conversation where the opening messages may change between turns.
- Use the 1-hour cache for longer Anthropic sessions where the default 5-minute one may expire between turns. Use the default for short, dense back-and-forths.
When your agent sends the same expensive content again and again, cached reads and sticky routing keep it from becoming the most expensive part of the loop.
FAQ
Does OpenRouter support prompt caching?
Yes. OpenRouter supports prompt caching across supported providers and models. Most providers enable it automatically, while Anthropic and Alibaba Qwen use cache_control for explicit caching. Cache reads cost 0.1x to 0.5x of normal input pricing depending on the provider, so a reused prefix gets much cheaper after the first request.
How much do cached tokens cost on OpenRouter?
Cache reads cost 0.1x to 0.5x of normal input pricing, depending on the provider. Anthropic, DeepSeek, and Alibaba Qwen can read at 0.1x. OpenAI reads at 0.25x to 0.50x. Gemini, Grok, and Moonshot read at 0.25x. Groq reads at 0.5x.
Why is prompt caching not working through OpenRouter?
The common causes are a prompt below the provider’s token minimum, an expired cache, an unstable prompt prefix, or provider drift between turns. For agent workflows, start by setting a stable session_id, then check cached_tokens in the usage response, where any value above zero confirms a cache hit.
How do I keep a cache warm across an agent’s turns?
Pass a stable session_id for the conversation, ticket, or workflow run. OpenRouter uses it as the sticky routing key, so follow-up requests route back to the same provider endpoint that holds the warm cache. With session_id set, stickiness activates after the first successful request, before any cache hit is observed.
How do I check whether caching saved money?
Inspect usage.prompt_tokens_details.cached_tokens for cache reads and cache_write_tokens for cache writes; a cached_tokens value above zero confirms a hit. You can also read cache_discount in the response to see the per-generation cost effect, or open the detail view on the Activity page or the /api/v1/generation API.
Does caching work with the Auto Router?
Yes. With a session_id set, router models such as Auto Router and Pareto Router pin both the resolved model and the provider for the conversation, so follow-up turns keep hitting the same warm cache.
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み