← 記事一覧
Guide

Claude prompt cachingをcache_controlで使う:5分キャッシュと1時間キャッシュのコスト差

A cream-background cover showing a developer terminal connected to a Claude prompt cache layer, with two labeled cache w

Claude prompt cachingには、ひとつの美しい数字と、ひとつの踏み抜きやすい罠がある。キャッシュ読み取りは通常入力の0.1倍で済む一方、キャッシュ書き込みは通常入力より高い。Anthropicの現行ドキュメントでは、5分キャッシュの書き込みは入力価格の1.25倍、1時間書き込みは2倍、キャッシュヒットは稼働中のClaudeモデル全体で0.1倍とされている(Anthropic prompt caching docs)。

つまりキャッシュはレイテンシ機能であるだけでなく、価格設計の機能でもある。アプリが長いシステムプロンプト、ツールスキーマ、サンプル集、ポリシー束、取得済みドキュメント、複数ターンの状態を繰り返すなら、出力トークンを測るのと同じように、キャッシュの書き込みと読み取りも測るべきだ。

今日、2026年6月14日時点でひとつ注意点がある。Anthropicは6月9日にClaude Fable 5を発表したが、その後6月12日の更新で、Fable 5とMythos 5へのアクセスは復旧作業中のため一時停止中だと告知した(Anthropic)。OneHopもanthropic/claude-fable-5を掲載しており、prompt cache対応と書いているが、モデルページでは現在一時的に利用不可と表示している(OneHop)。統合は今のうちに作っておき、モデルIDは設定可能にして、アクセスが戻ったら切り替えればいい。

アプリのリクエストがprompt cacheレイヤーに流れ込み、その先でOneHop経由のClaude Fable 5へ渡される、カバー風のアーキテクチャ図

開発者が本当に必要なキャッシュ計算

Anthropicのprompt cacheはプロンプトのプレフィックスを保存する。再利用される部分は完全に同一でなければならない。ツール、システム内容、メッセージの順に考慮され、cache_controlが付いたブロックまでがキャッシュ対象になる(Anthropic prompt caching docs)。

役に立つ価格モデルはシンプルだ。再利用するプレフィックスが100,000入力トークンだとする。

Cache modeWrite cost multiplierRead cost multiplierBreak-even intuition
キャッシュなし毎リクエスト1.0倍なし毎回入力を満額で払う
5分キャッシュ初回のみ1.25倍ヒットごとに0.1倍最初の再利用で元が取れる
1時間キャッシュ初回のみ2.0倍ヒットごとに0.1倍さらに再利用するか、長いアイドル時間をまたぐ必要がある

Claude Fable 5について、Anthropicは発表記事で入力100万トークンあたり10ドル、出力100万トークンあたり50ドルと記載している。またprompt caching docsでは、Fable 5のキャッシュ価格として、5分書き込みが12.50ドル/M、1時間書き込みが20ドル/M、キャッシュヒットが1ドル/Mとされている(Anthropicprompt caching docs)。

Anthropicの定価で見ると、その100kトークンのプレフィックスにかかる費用はこうなる。

  • 通常入力: $1.00
  • 5分書き込み: $1.25
  • 1時間書き込み: $2.00
  • キャッシュ読み取り: $0.10

つまり同じ100kトークンのプレフィックスをTTL内に2回使うなら、5分キャッシュは$1.25 + $0.10 = $1.35で済む。キャッシュなしなら$2.00だ。1時間キャッシュは2回利用で$2.10なので2呼び出しでは負けるが、3回目があるか、長めの停止後にコールド再書き込みを避けられるなら勝つ。

本番で私が使っているルールはこうだ。ホットループはデフォルトで5分。人間が途中で止まる、エージェントがツール待ちをする、ワークフローが数分後に再開するなら1時間を使う。

キャッシュを有効にする2つの方法

Anthropicはいま2つの方法を案内している。最短ルートは自動キャッシュだ。トップレベルにcache_controlフィールドを追加すると、会話が伸びるにつれてClaudeがブレークポイントを前へ進める。より制御したいなら明示的なブレークポイントを使う。安定したプレフィックスの最後のコンテンツブロックにcache_controlを置く(Anthropic prompt caching docs)。

自動キャッシュはチャット履歴やエージェント状態に向いている。

import os
from anthropic import Anthropic

client = Anthropic(
    api_key=os.environ["ONEHOP_API_KEY"],
    base_url=os.getenv("ANTHROPIC_BASE_URL", "https://api.onehop.ai/v1"),
)

message = client.messages.create(
    model=os.getenv("CLAUDE_MODEL", "anthropic/claude-fable-5"),
    max_tokens=700,
    cache_control={"type": "ephemeral"},
    system="You are a senior backend engineer. Be concise and specific.",
    messages=[
        {"role": "user", "content": "My app uses FastAPI, Postgres, and Redis."},
        {"role": "assistant", "content": "Got it. What do you want to change?"},
        {"role": "user", "content": "Design a cache key strategy for user dashboards."},
    ],
)

print(message.content[0].text)
print(message.usage.model_dump())

これがOneHopへの変換ルートだ。Anthropic形式のリクエストはそのままにして、base URLを設定可能にし、https://api.onehop.ai/v1へ向ける。OneHopのモデルページでもanthropic/claude-fable-5がモデルIDとして示されており、新規ユーザーはカード不要で10ドル分の無料クレジットを受け取れると書かれている(OneHop)。短い道で行くなら、OneHopのClaude Fable 5を開いて、10ドル無料で始めるといい。

明示的キャッシュは、プレフィックスが安定していて、ユーザーメッセージが毎リクエスト変わる場合に向いている。変化する部分の手前にブレークポイントを置く。

from anthropic import Anthropic
import os

client = Anthropic(
    api_key=os.environ["ONEHOP_API_KEY"],
    base_url="https://api.onehop.ai/v1",
)

response = client.messages.create(
    model="anthropic/claude-fable-5",
    max_tokens=500,
    system=[
        {
            "type": "text",
            "text": open("system_prompt.md").read(),
            "cache_control": {"type": "ephemeral"},
        }
    ],
    messages=[
        {"role": "user", "content": "Review this migration plan for race conditions."}
    ],
)

print(response.usage.model_dump())

変化するタイムスタンプやユーザーメッセージの後に悪いキャッシュブレークポイントを置いた例と、良いブレークポイントを置いた例を比べるビフォーアフター図

1時間TTLを使うTypeScript版

高価な静的コンテキストがあり、現実的にアイドル時間が発生するアプリでは1時間キャッシュを使う。たとえば、CI待ちのコードレビューエージェント、人間が途中で止まるカスタマーサポート副操縦士、法務リサーチのセッション、ツール処理に数分かかる複数ステップのデータ分析などだ。

Anthropicのドキュメントでは、1時間TTLは{"type":"ephemeral","ttl":"1h"}として示されており、自動キャッシュはデフォルトで5分を使うと書かれている(Anthropic prompt caching docs)。

import Anthropic from "@anthropic-ai/sdk";
import fs from "node:fs";

const client = new Anthropic({
  apiKey: process.env.ONEHOP_API_KEY!,
  baseURL: process.env.ANTHROPIC_BASE_URL ?? "https://api.onehop.ai/v1",
});

const policyPack = fs.readFileSync("policy-pack.md", "utf8");

const msg = await client.messages.create({
  model: process.env.CLAUDE_MODEL ?? "anthropic/claude-fable-5",
  max_tokens: 800,
  system: [
    {
      type: "text",
      text: policyPack,
      cache_control: { type: "ephemeral", ttl: "1h" },
    },
  ],
  messages: [
    {
      role: "user",
      content: "Apply the policy pack to this refund request: customer used 3 of 10 seats.",
    },
  ],
});

console.log(msg.content);
console.log(msg.usage);

大事なのは退屈な部分だ。モデルとbase URLをコードの奥深くに隠さない。どちらも環境変数に置く。現時点でFable 5の可用性は動いている。ビジネスロジックを書き換えずに、別の稼働中Claudeモデルへフォールバックできる統合にしておくべきだ。

usageで監視すべきもの

Prompt cachingはusageフィールドを見ない限り見えない。Anthropicは、キャッシュを検証するにはcache_creation_input_tokenscache_read_input_tokensなどのフィールドを確認せよとしている。両方がゼロなら、プロンプトはキャッシュされていない。よくある原因は、そのモデルのキャッシュ可能な最小長に届いていないことだ(Anthropic prompt caching docs)。

リクエストごとにこれをログに出す。

const usage = msg.usage;

console.log({
  input: usage.input_tokens,
  output: usage.output_tokens,
  cacheCreate: usage.cache_creation_input_tokens,
  cacheRead: usage.cache_read_input_tokens,
});

新しいusageオブジェクトでは、Anthropicのドキュメント上、キャッシュ作成がephemeral_5m_input_tokensephemeral_1h_input_tokensのようなTTL別バケットに分かれている例もある。最初はusageオブジェクト全体を保存する。どのゲートウェイとSDKバージョンで動いているかが正確に分かってから正規化すればいい。

良いダッシュボードは4つの問いに答える。

  1. 何トークンがキャッシュへ書き込まれているか?
  2. 何トークンがキャッシュから読み取られているか?
  3. ルート別のキャッシュ読み取り/書き込み比率はどうか?
  4. アイドル時間後に大きなコールド書き込みを生んでいるプロンプトはどれか?

cache_creation_input_tokensが高く、cache_read_input_tokensがほぼゼロのままなら、ブレークポイントが変化する内容の後ろにある可能性が高い。もっと前に動かす。

キャッシュ書き込みトークン、キャッシュ読み取りトークン、読み取り/書き込み比率、コールド書き込みを示す4パネルのコンパクトな可観測性ダッシュボードのモックアップ

5分か1時間か:ユーザー行動で選ぶ

密なリクエストループには5分キャッシュを使う。20秒ごとにツールを呼ぶコーディングエージェント、ユーザーがすぐ追撃メッセージを送るチャットアプリ、似た分類ジョブのバッチなどはそこから始めるべきだ。Anthropicのドキュメントによれば、書き込みプレミアムは1.25倍にすぎず、読み取りのたびにキャッシュ寿命は無料で更新される(Anthropic prompt caching docs)。

高価なプレフィックスが5分以上経ってから再利用されそうなら、1時間キャッシュを使う。典型例は人間参加型のワークフローだ。モデルが外部システムへ作業を送り、ブラウザ待ちをし、CIをポーリングし、承認待ちで止まるような長時間エージェントも同じだ。

小さなプロンプトはキャッシュしない。Anthropicはモデルとプラットフォーム別にキャッシュ可能な最小プロンプト長を記載している。Fable 5では、Claude APIの最小値は512トークンとされている一方、Bedrockでは一部モデルで異なる最小値がある(Anthropic prompt caching docs)。それより短いプロンプトは、単にキャッシュなしで処理されることがある。

実用的なチェックリストはこうだ。

  • 安定した内容を先に置く: ツール、システムプロンプト、例、参照ドキュメント。
  • 変化するデータはキャッシュ済みプレフィックスの後ろに置く: タイムスタンプ、リクエストID、ユーザーテキスト。
  • 会話では自動キャッシュから始める。
  • サフィックスが毎回変わるなら明示的ブレークポイントへ切り替える。
  • 1時間TTLは、アイドル時間が2倍の書き込みを正当化する場合だけ使う。
  • 勝ったと言う前にusageフィールドをログに出す。

5分キャッシュと1時間キャッシュの選択を比べる決定木。5分未満のホットループは5mへ、人間の停止やツール待ちなら1hへ進む

OneHop経由でつなぎ、それから測る

いちばんきれいな統合は、エンドポイントを1行変え、モデル選択を環境変数化することだ。

export ONEHOP_API_KEY="..."
export ANTHROPIC_BASE_URL="https://api.onehop.ai/v1"
export CLAUDE_MODEL="anthropic/claude-fable-5"

あとはAnthropic Messagesのコードを維持し、cache_controlを追加する。

OneHopのFable 5ページは現在、公式定価より低い価格、カード不要の10ドル初回クレジット、このモデル向けのAnthropic Messagesルートを打ち出している(OneHop)。ただし6月12日のAnthropic更新時点でFable 5へのアクセスは一時停止中なので、モデルフォールバックは後付けではなくロールアウト計画の一部にしておくべきだ。

リターンは単純だ。アプリが大きなプレフィックスを繰り返すなら、0.1倍のキャッシュ読み取りによって、プロンプトエンジニアリングはコストエンジニアリングになる。まずは5分キャッシュから始める。ログが、停止後のコールド再書き込みを示しているワークフローだけ1時間キャッシュへ移す。Claude Fable 5の提供が戻ったときに短い道で試したいなら、OneHopのClaude Fable 5を使い、10ドル無料で始めるといい。