コンピュータアクセスシステム

AIエージェントのキャッシュ戦略:品質を落とさずコストを削減する


AIエージェントのキャッシュ戦略:品質を落とさずコストを削減する

あなたのリサーチエージェントが1日50タスクを実行するとします。各タスクは毎回同じ3,000トークンのシステムプロンプト、同じ2,500トークンのツール定義、同じ5,000トークンのナレッジベースから始まります。これは10,500トークンが50回繰り返されることを意味し、1日あたり525,000トークンをモデルが毎回同一内容で読み込んでいます。標準の料金体系では、まったく同じコンテンツの処理に何度もお金を払い続けることになります。

キャッシュは、本番環境のエージェントに適用できる最も手軽でインパクトの大きい最適化です。プロンプトキャッシュだけでも、キャッシュされたコンテンツの入力トークンコストを**90%**削減できます。ツール結果キャッシュと組み合わせれば、品質・精度・柔軟性を犠牲にすることなく、エージェントの総コストをしばしば半減させることができます。

この記事では、エージェント向けの3つのキャッシュ層——プロンプトキャッシュツール結果キャッシュレスポンスメモ化——をClaudeのAPIを使った実装パターンとコスト分析とともに解説します。


セクション1:エージェントのコスト構造

最適化する前に、トークンがどこに使われているかを理解する必要があります。典型的なエージェントワークフローを分解してみましょう。

ターンごとのトークン内訳

標準的なエージェントアーキテクチャでは、モデルへのすべてのAPIコールに以下が含まれます:

コンポーネント概算トークン数繰り返し?
システムプロンプト〜1,500毎ターン
ツール定義〜2,000毎ターン
ナレッジベース / コンテキスト〜3,000毎ターン
会話履歴増加累積
ツール結果〜500(平均)ツール呼び出しごと

静的オーバーヘッド——システムプロンプト、ツール定義、ナレッジベース——は合計で1ターンあたり約6,500トークンとなり、毎回まったく同一です。

コストが複利的に増大する問題

エージェントはAPIを1回呼び出すだけではありません。ループします。典型的な15ステップのエージェント実行は次のようになります:

キャッシュなしの場合:

15ステップそれぞれでフルコンテキストを送信します。会話履歴が1ステップあたり平均〜300トークン増加すると仮定すると:

  • 1ステップあたりの静的トークン数:6,500
  • 15ステップの静的トークン合計:97,500
  • 会話履歴トークン数(累積):〜33,750
  • ツール結果トークン数:〜7,500
  • 入力トークン合計:〜138,750

Claude Sonnetの入力価格は100万トークンあたり$3なので、1タスクあたり約**$0.42になります。1日50タスク実行すると、入力トークンだけで1日あたり$21**になります。

プロンプトキャッシュありの場合:

キャッシュ読み取りは100万トークンあたり$0.30(90%割引)で課金されます。6,500の静的トークンをキャッシュすると:

  • 15ステップのキャッシュ読み取りトークン:97,500トークン × $0.30/M = $0.029
  • 非キャッシュトークンは標準価格:〜41,250 × $3/M = $0.124
  • キャッシュ書き込み(最初のステップ):6,500 × $3.75/M = $0.024
  • 入力コスト合計:1タスクあたり〜$0.18

キャッシュだけで57%削減となります。1日50タスクで1日あたり$12以上、つまり月〜$360の節約になります——コードの変更は最小限で済みます。


セクション2:Claudeによるプロンプトキャッシュ

ClaudeのプロンプトキャッシュAPIは、エージェントワークフローに適用できる最もインパクトの大きい単一の最適化です。「プロンプトのこの部分は変更されていないのでキャッシュされた計算を再利用してください」とAPIに伝えることができます。

プロンプトキャッシュの仕組み

キャッシュを有効にしたリクエストを送信すると、Anthropicのインフラは:

  1. マークされたプレフィックスのキャッシュ済みバージョンが存在するか確認する
  2. キャッシュミスの場合: フルプロンプトを処理し、プレフィックスをキャッシュし、キャッシュ書き込み料金(標準入力価格より25%割増)を課金する
  3. キャッシュヒットの場合: キャッシュされた計算を再利用し、キャッシュ読み取り料金(標準入力価格より90%割引)のみを課金する

キャッシュのTTL(Time to Live:キャッシュデータが期限切れになるまでの時間)は5分です。キャッシュヒットのたびにTTLがリセットされるため、アクティブなエージェントは自然にキャッシュを維持します。呼び出し間隔が5分以上あるバッチジョブでは、キャッシュ書き込みコストがより頻繁に発生します。

キャッシュすべき内容

すべてをキャッシュできるわけでも、すべきでもありません。安定した繰り返しのプレフィックスをキャッシュしましょう:

  • システムプロンプト — 実行をまたいでほぼ常に同一です。まずここからキャッシュしましょう。
  • ツール定義 — ツールスキーマは呼び出し間でほとんど変わりません。
  • 静的ナレッジベース — 参照ドキュメント、ガイドライン、ポリシー。
  • 会話プレフィックス — マルチターン会話では、変更されない前半のターンをキャッシュします。

重要な制約:

  • キャッシュはプレフィックスベースです——プロンプトの先頭から順番にしかキャッシュできません。前のセクションをキャッシュせずに中間のセクションだけキャッシュすることはできません。
  • Claude SonnetとHaikuでは最小キャッシュ可能長は1,024トークンです(Opusは2,048)。
  • 1つのリクエストに最大4つのキャッシュブレークポイントを設定できます。

実装

エージェントのセットアップにプロンプトキャッシュを適用した完全なサンプルを示します:

変更前(キャッシュなし):

import anthropic
client = anthropic.Anthropic()
SYSTEM_PROMPT = """You are a research assistant specializing in market analysis.
You have access to tools for searching databases, reading files, and performing
calculations. Always cite your sources and provide confidence levels for your
findings. [... detailed instructions totaling ~1,500 tokens ...]"""
TOOLS = [
{
"name": "search_database",
"description": "Search the company database for market data, competitor info, or financial records.",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Search query"},
"database": {"type": "string", "enum": ["market", "competitors", "financial"]},
"limit": {"type": "integer", "description": "Max results", "default": 10}
},
"required": ["query", "database"]
}
},
{
"name": "read_file",
"description": "Read the contents of a research file.",
"input_schema": {
"type": "object",
"properties": {
"file_path": {"type": "string", "description": "Path to the file"}
},
"required": ["file_path"]
}
},
# ... more tools totaling ~2,000 tokens in definitions
]
KNOWLEDGE_BASE = """## Company Policies and Guidelines
[... reference material totaling ~3,000 tokens ...]"""
def run_agent(user_query: str):
messages = [{"role": "user", "content": user_query}]
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=4096,
system=f"{SYSTEM_PROMPT}\n\n{KNOWLEDGE_BASE}",
tools=TOOLS,
messages=messages,
)
# Log token usage
print(f"Input tokens: {response.usage.input_tokens}")
return response

変更後(プロンプトキャッシュあり):

import anthropic
client = anthropic.Anthropic()
SYSTEM_PROMPT = """You are a research assistant specializing in market analysis.
You have access to tools for searching databases, reading files, and performing
calculations. Always cite your sources and provide confidence levels for your
findings. [... detailed instructions totaling ~1,500 tokens ...]"""
KNOWLEDGE_BASE = """## Company Policies and Guidelines
[... reference material totaling ~3,000 tokens ...]"""
TOOLS = [
{
"name": "search_database",
"description": "Search the company database for market data, competitor info, or financial records.",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Search query"},
"database": {"type": "string", "enum": ["market", "competitors", "financial"]},
---
## 関連記事
- [エージェントコスト最適化:API費用を削減するための実践ガイド](/ja/blog/agent-cost-optimization-a-practical-guide-to-reducing-api-spend/)
- [エージェントのエラー回復:本番環境の信頼性のための5つのパターン](/ja/blog/agent-error-recovery-patterns/)
- [ツール使用パターン:信頼性の高いエージェント-ツールインターフェースの構築](/ja/blog/agent-tool-use-patterns/)