2026年6月時点、AIエージェントを本番稼働させている多くのチームが直面するのが「想定外のAPI費用」だ。
設計段階で見積もったトークン数を、実運用が軽く超えてくる。本記事では、実際の本番環境で検証した コスト削減テクニックを7つまとめる。
結論
| テクニック | 効果(目安) | 難易度 |
|---|---|---|
| プロンプトキャッシュの活用 | −40〜60% | ★★☆ |
| モデルルーティング(タスク別) | −30〜50% | ★★★ |
| コンテキスト圧縮 | −20〜35% | ★★☆ |
| バッチ処理への切り替え | −50%(Batch API) | ★☆☆ |
| ガードレールの前段配置 | −10〜20% | ★★☆ |
| 出力トークンの上限制御 | −15〜25% | ★☆☆ |
| Haiku/Flash でのフィルタリング | −20〜40% | ★★☆ |
複数を組み合わせると、同じワークロードで 30〜70%のコスト削減が現実的に達成できる。
1. プロンプトキャッシュの活用(Anthropic Prompt Caching)
確認できる事実
Anthropic の Prompt Caching は、同一の長いシステムプロンプト部分をキャッシュし、再利用できる仕組み。
キャッシュヒット時の入力トークンコストは 通常の10%(90%オフ)になる。
# Claude API でのキャッシュ有効化
messages = [
{
"role": "user",
"content": [
{
"type": "text",
"text": long_system_context, # 数千トークンのコンテキスト
"cache_control": {"type": "ephemeral"} # これだけで有効
},
{
"type": "text",
"text": user_query
}
]
}
]
実務解釈
- キャッシュが効くのは「同じ内容を繰り返し送る部分」。RAGで毎回同じドキュメントを渡す処理が典型的なターゲット
- 最小キャッシュ可能サイズ: 1,024 tokens(これ以下はキャッシュされない)
- TTL: 5分(5分以内の再アクセスでヒット)
- マルチターンの会話より、同一コンテキストで多数のユーザーを捌くシナリオで絶大な効果
2. モデルルーティング(タスク別最適モデル選択)
確認できる事実
すべてのタスクに最高精度のモデルを使う必要はない。
Anthropic のモデル価格(2026年6月時点):
| モデル | 入力(1Mトークン) | 出力(1Mトークン) |
|---|---|---|
| Claude Opus 4.8 | $15 | $75 |
| Claude Sonnet 4.6 | $3 | $15 |
| Claude Haiku 4.5 | $0.25 | $1.25 |
実務解釈
def route_to_model(task_type: str, content_length: int) -> str:
"""タスクの複雑さでモデルを振り分ける"""
if task_type in ("classification", "extraction", "filtering"):
return "claude-haiku-4-5-20251001" # 単純タスク
elif task_type in ("summarization", "translation", "qa"):
return "claude-sonnet-4-6" # 中程度のタスク
else:
return "claude-opus-4-8" # 推論・複雑な生成のみ
# 実装パターン: 2ステージ
# 1. Haiku でフィルタリング・分類
# 2. 複雑と判定されたものだけ Opus へ
このパターンで実際に Opus の呼び出しを70%削減できたケースがある。
3. コンテキスト圧縮
確認できる事実
会話が長くなると、古いターンをそのまま送り続けることでコストが指数的に増加する。
LangChain / LangGraph の ConversationSummaryBufferMemory はこの問題を扱う。
from langchain.memory import ConversationSummaryBufferMemory
from langchain_anthropic import ChatAnthropic
# 最近の10ターンだけを生のまま保持、それ以前はHaikuで要約
memory = ConversationSummaryBufferMemory(
llm=ChatAnthropic(model="claude-haiku-4-5-20251001"),
max_token_limit=2000,
return_messages=True
)
実務解釈
- 要約生成のコスト(Haiku利用)vs. 削減できる文脈コスト を必ず計算する
- 長期会話(20ターン以上)では、圧縮なしの場合に比べ 50%以上のコスト削減が見込める
- ただし、要約によって文脈が失われるリスクもある。重要情報は「エンティティメモリ」として別途保持するパターンが安全
4. Batch API(非同期処理)
確認できる事実
Anthropic の Message Batches API は、24時間以内の完了で良い処理を 50%引きで実行できる。
import anthropic
client = anthropic.Anthropic()
# バッチリクエストの作成
batch = client.messages.batches.create(
requests=[
{
"custom_id": f"task-{i}",
"params": {
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [{"role": "user", "content": task}]
}
}
for i, task in enumerate(tasks) # 最大100,000件/バッチ
]
)
# ポーリングして完了を待機
import time
while True:
result = client.messages.batches.retrieve(batch.id)
if result.processing_status == "ended":
break
time.sleep(60)
実務解釈
- 向いているワークロード: データ変換、コンテンツ生成、分析・ラベリング、テスト生成
- 向いていないワークロード: リアルタイム応答が必要なチャットボット、ユーザーが待っている処理
- 並列処理の制御も不要でシンプルに実装できる点がメリット
5. ガードレールの前段配置
確認できる事実
入力を高性能モデルに渡す前に、安価なモデルでフィルタリングする「前段ガードレール」パターン。
async def process_with_guardrail(user_input: str) -> str:
# Step 1: Haiku で入力を事前チェック(安価)
check_result = await haiku_client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=10,
messages=[{
"role": "user",
"content": f"以下の入力は有効なビジネス質問ですか? yes/no のみ答えてください。\n{user_input}"
}]
)
if "no" in check_result.content[0].text.lower():
return "有効なご質問をお願いします。"
# Step 2: 通過したものだけを Sonnet/Opus へ
return await main_agent.process(user_input)
実務解釈
- 入力の10〜30%が無効/スパム/意図しない入力というサービスでは効果が高い
- Haiku は速度も速いのでUX劣化が最小限
6. 出力トークンの上限制御
確認できる事実
max_tokens パラメーターを意識的に下げることが、最も手軽なコスト削減策の一つ。
デフォルト値のまま使っているケースで、実際には半分以下の出力しか使われていないことも多い。
# タスク別の適切な max_tokens 設定例
TASK_MAX_TOKENS = {
"classification": 10, # yes/no/分類ラベルのみ
"extraction": 200, # 構造化データ抽出
"summarization": 500, # 要約
"qa_short": 300, # 短答型Q&A
"code_generation": 2000, # コード生成
"report_generation": 4000, # レポート生成
}
実務解釈
- ストリーミングを使っている場合でも、
max_tokensは必ず設定する - 超過すると切り捨てられるが、適切に設定すれば出力品質に影響しない
- 実際のアプリログから「平均出力トークン数」を計測して設定値を調整する
7. Haiku/Flash でのファーストパスフィルタリング
確認できる事実
2ステージ処理パターン:
- Haiku で粗い回答を生成 → 閾値で「十分か」を判定
- 不十分なものだけ Sonnet/Opus で再処理
async def two_stage_process(query: str) -> str:
# ステージ1: Haiku で高速処理
haiku_response = await call_haiku(query)
# 信頼度スコアを自己評価させる
confidence_check = await call_haiku(
f"以下の回答はクオリティとして十分ですか?1-10で採点してください。\n{haiku_response}"
)
score = extract_score(confidence_check)
if score >= 7:
return haiku_response # Haiku の回答で十分
# ステージ2: 高品質モデルで再処理
return await call_sonnet(query)
実務解釈
- このパターンで、60〜80%のリクエストを Haiku で完結させられるケースが多い
- 自己評価の信頼度スコアは完全ではないが、明らかな失敗を弾くには有効
実装チェックリスト
- プロンプトキャッシュを有効化し、ヒット率をモニタリングしているか
- タスク別にモデルをルーティングしているか(全タスクを Opus で処理していないか)
- 長い会話セッションでコンテキスト圧縮を実装しているか
- リアルタイム性不要のバッチ処理を Batch API に移行しているか
-
max_tokensをタスク別に最適化しているか - 入力フィルタリングの前段ガードレールを設けているか
- API コストのモニタリングダッシュボードが存在するか(異常検知込み)
失敗パターン
「とりあえず全部 Opus」設計
→ 初期開発では合理的だが、スケール時にコストが爆発する。タスク分析を後回しにしない。
キャッシュ TTL を無視した設計
→ Anthropic の Prompt Cache は5分 TTL。低トラフィックのサービスではヒットしない。
出力トークン計測なしの max_tokens 設定
→ 計測なしで値を下げると、回答が途中で切れる問題が発生する。本番前に実際のログで検証する。
バッチ処理への移行時のレート制限無視
→ Batch API にもレート制限がある。大量のバッチを一度に投げると上限に当たる。
参考リンク
- Anthropic Prompt Caching Documentation
- Message Batches API
- Claude Models Overview
- LangChain ConversationSummaryBufferMemory
✏️ 山本勇志 — ITPRODX / 株式会社プロドウガ
AIエージェント・自動化システムの設計・構築を行っています。