長いシステムプロンプト(RAGコンテキスト、ツールカタログ、エージェントルール、例など)を送る場合、毎回入力料金を全額払っている可能性があります。Anthropicのプロンプトキャッシュを使うと、キャッシュ部分は料金の10%になります。OpenAIも暗黙的に同じことを行います。多くのチームでは、入力費用を確実に60〜90%削減できるため、30分の作業に価値があると考えています。
Kunavoは両方に対応します。独自のcache_controlブレークポイントはMessages APIをそのまま通過します。該当フィールドを送れないChat Completions APIとResponses APIでは、Kunavoが設定し、送信内容に応じて補充します。ただし上限4を超えることはありません。この投稿では両方、キャッシュを静かに無効化する落とし穴、ヒット率の確認方法を説明します。
変更前と変更後
同じ18Kトークンのシステムプロンプトを10回送る単純なループ:
# What most people start with: every call re-pays for the whole prompt.
import anthropic
client = anthropic.Anthropic(
api_key="sk-kn-...",
base_url="https://api.kunavo.com",
)
SYSTEM = open("system-prompt.md").read() # 18,000 tokens of rules + examples
# 10 user questions in a session. Every call sends the 18K-token system block.
for question in questions:
resp = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=600,
system=SYSTEM,
messages=[{"role": "user", "content": question}],
)
# Cost per call (input only): 18,000 × $3 / 1M = $0.054
# 10 calls: $0.54 in input alone.システムブロックをキャッシュ可能にする — フィールドを1つ追加:
# The fix: mark the static prefix as cacheable. After the first call,
# subsequent calls within ~5 minutes pay 10% the input rate on the cached
# portion. Same answer, 89% cheaper.
resp = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=600,
system=[
{
"type": "text",
"text": SYSTEM,
"cache_control": {"type": "ephemeral"}, # mark cacheable
}
],
messages=[{"role": "user", "content": question}],
)
# First call (cache write): 18,000 × $3.75 / 1M = $0.0675 (1.25× input)
# Calls 2–10 (cache hit): 18,000 × $0.30 / 1M = $0.0054 each
# Total: $0.0675 + 9 × $0.0054 = $0.116 (was $0.54 — 78.5% saved)このセッションの入力費用を78.5%節約しました。最初の呼び出しはキャッシュ書き込みのため、単純版より実際にはわずかに高くなります(入力料金の約1.25倍)。2〜10回目は料金の10%です。損益分岐点は2回目で、3回目には得をし、10回目には大差になります。
OpenAI方式:何もする必要なし
OpenAI Chat Completions形式にはcache_controlフィールドがありません。OpenAIが自社サーバーで暗黙的にキャッシュするためです。Claudeはそうではなく、ブレークポイントを付けた部分だけをキャッシュします。そのため/v1/chat/completionsまたは/v1/responses経由でClaudeモデルに到達すると、Kunavoが代わりに設定します。会話にassistantターンが1つ以上あれば最後のメッセージにローリングブレークポイントを1つ、さらにsystemの後とtoolsの後に1つずつ設定します。自分で設定したものは置いた場所から変更せず、Kunavoは空いている位置だけを上限4まで埋めます。設定は不要で、AnthropicルートでもOpenAIルートでも同じモデルの料金は同じです:
# OpenAI Chat Completions style — Kunavo sets the breakpoints for you.
# No flag to set. The "usage" object tells you what was cached.
from openai import OpenAI
client = OpenAI(
api_key="sk-kn-...",
base_url="https://api.kunavo.com/v1",
)
resp = client.chat.completions.create(
model="claude-sonnet-4-6",
messages=[
{"role": "system", "content": LONG_SYSTEM_PROMPT}, # >1024 tokens
{"role": "user", "content": "Latest question…"},
],
)
# In the response:
# resp.usage.prompt_tokens_details.cached_tokens → 17,800
# resp.usage.prompt_tokens → 18,200
# 17.8K/18.2K = 98% of input came from cache. Bill reflects that automatically.どれだけキャッシュから提供されたかはusage.prompt_tokens_details.cached_tokensを読んで確認します。固定プレフィックスが大きいほど節約も大きくなります。目安として、システムプロンプトが可変のユーザー内容より短いならキャッシュ効果は小さいでしょう。静的部分を大きくして先頭に置くようプロンプトを組み直してください。
多層キャッシュ — 最大4ブレークポイント
一部の層が他より速く変わるエージェントループでは、複数のcache_controlブレークポイントを設定します。それぞれはその位置までの全内容のスナップショットです:
# Anthropic supports up to 4 cache breakpoints per request — use them
# to keep the cache hot even as later layers change.
client.messages.create(
model="claude-sonnet-4-6",
max_tokens=600,
system=[
{"type": "text",
"text": ROLE_AND_RULES, # ~3,000 tokens
"cache_control": {"type": "ephemeral"}}, # breakpoint 1
{"type": "text",
"text": LARGE_KNOWLEDGE_BASE, # ~15,000 tokens, rarely changes
"cache_control": {"type": "ephemeral"}}, # breakpoint 2
],
messages=[
{"role": "user",
"content": [
{"type": "text",
"text": CONVERSATION_HISTORY, # grows each turn
"cache_control": {"type": "ephemeral"}}, # breakpoint 3
{"type": "text", "text": new_question},
]},
],
)
# When CONVERSATION_HISTORY changes, breakpoints 1+2 still hit cache.
# Only breakpoint 3 + the new question pay full input rate.キャッシュキーはプレフィックス全体です。位置Nにトークンを追加すると、N以降のすべてのブレークポイントが無効になります。順序が重要です。最も安定した内容を先に置きます。ルール層はめったに変えず、ナレッジベースは毎週更新し、会話はターンごとに増えます。
キャッシュをひそかに壊す一般的な方法
- 現在の日付やrequest_idをプロンプトに入れる。呼び出しごとに新しいプレフィックスになり、ヒット率は0%です。プロンプト入力をハッシュ化して呼び出し間で比較してください。
- 非決定的なシステムプロンプト構築。dictからsystemを組み立てる場合、Pythonの一部バージョンではdictの反復順序が重要です。キーを明示的にソートしてください。
- キャッシュの有効期間は約5分。10分に1回のような疎なトラフィックではヒットしません。呼び出しをまとめるか、損失を受け入れてください。
- 1,024トークンの最小値。1Kトークン未満ではOpenAI方式のキャッシュは有効になりません。小さな静的断片を1つの長いプレフィックスにまとめてください。
- ツール/関数定義はプレフィックスの一部。カタログに新しいツールを追加すると全員のキャッシュが無効になります。ツールカタログを安定させ、バージョン管理してください。
ヒット率の確認
見えないキャッシュはエンジニアリングではなく期待です。毎回の呼び出しでusageをログに記録してください:
# Always read usage. If cached_tokens is 0 when you expected a hit,
# something's wrong — usually a non-deterministic prefix.
resp = client.messages.create(...)
u = resp.usage
print({
"input_uncached": u.input_tokens,
"input_cache_read": u.cache_read_input_tokens,
"input_cache_write": u.cache_creation_input_tokens,
"output": u.output_tokens,
})
# A common gotcha: putting today's date or a request_id in the system prompt
# silently invalidates the cache. Hash your inputs; verify cache_read_input_tokens
# is non-zero on the 2nd identical call.KunavoダッシュボードのUsageページには、モデル別・日別のキャッシュ内訳が表示されます。総入力に占めるcache_read_input_tokensの割合が増えていればキャッシュは機能しています。0のまま、または大きく変動するなら、上記の落とし穴を確認してください。
Kunavoで実際にかかる費用
各モデルのキャッシュ料金は価格ページに掲載されています:
- Anthropicモデル:キャッシュ読み取りは入力料金の10% — 2.5% on Claude Fable 5.1, 5% on Claude Opus 5.5です。書き込みは入力料金の1.25倍です。これはAnthropicの5分倍率で、Kunavoは1時間書き込みも同じ1.25倍で請求します。Anthropicの2倍より低い値です。
- OpenAI/Geminiモデル:キャッシュ読み取りは入力料金の10%です(プロバイダー公開比率)。書き込みはGPT-5.6とGPT-6 Astraでは1.25倍、その他の全モデルでは通常の入力料金です。
- すべてのキャッシュ料金にはKunavoのモデル割引がすでに含まれています(モデルごとの上流表示価格より低い)。そのためKunavoのSonnet 4.6キャッシュ読み取りは
$3 × 0.40 × 0.10 = $0.12 per 1M tokensで、キャッシュなしの上流料金より約25倍安くなります。
キャッシュが答えにならない場合
作業に見合わないケースがいくつかあります:
- 短いプロンプト(合計<1Kトークン)。オーバーヘッドが支配的になるため、気にしないでください。
- ワンショットタスクで繰り返しトラフィックがない場合。初回はわずかに高くなり、キャッシュは2回目以降で初めて回収できます。
- 出力が多く入力が少ないタスク(創作、コード生成)。入力は請求の小さな割合にすぎません。代わりに出力予算の上限に注目してください。
その他すべての場合 — RAGチャットボット、固定ツールカタログを持つエージェント、静的な評価基準で実行する分類器、一貫した少数ショット例を使う構造化抽出パイプライン — では、キャッシュが、午後の数時間で導入できる最も投資対効果の高い最適化です。コスト最適化ガイドにある他の4つの手法と組み合わせれば、出力品質を一切犠牲にせず、70%のコスト削減を現実的に達成できます。
すでにKunavoをご利用ですか?/app/usageを開き、最大のモデルのキャッシュ列を確認してください。ゼロなら、節約できるお金を逃しています。完全ガイド:/docs/caching。