エージェントコスト最適化:API費用を削減するための実践ガイド
エージェントコスト最適化:API費用を削減するための実践ガイド
あなたのエージェントは順調に動いている。1日200リクエストをこなし、ユーザーも満足している。そしてAPIの請求書を確認すると、今月は3,400ドル。数字を詳しく見ると、エージェントは1リクエストあたり平均12回のAPIコールを行い、それぞれに4,000トークンのシステムプロンプトが含まれていることがわかる。システムプロンプトだけで1日あたり960万の入力トークンになる。100万トークンあたり3ドルとすると、繰り返しコンテンツだけで月864ドルになる。
コストは、本番環境でのエージェント運用が縮小・廃止される最大の理由だ。最適化は時期尚早ではなく、生き残りのための手段だ。朗報としては、ほとんどのエージェント運用では、システム全体の再設計を必要としないシンプルな変更によって、50〜80%のコスト削減が可能だ。
このガイドでは、ROI(投資対効果)順に7つのコスト削減戦略を紹介する。上から順に取り組み、予算目標に達したら止めよう。各セクションには具体的な数字が含まれているため、コードを1行も書く前に削減効果を試算できる。
1. トークン計測:費用の発生源を把握する
計測できないものは最適化できない。何かを変える前に、エージェントワークフローのどこにすべての費用が発生しているかを完全に把握しよう。
入力トークンの内訳
Claudeへのすべてのアクシコールには、入力側にいくつかのトークンカテゴリが含まれる:
- システムプロンプト — 指示、ペルソナ、制約。多くの場合1,000〜5,000トークンで、すべてのコールで繰り返される。
- ツール定義 — エージェントが使用できる各ツールのJSONスキーマ。10個のツールで2,000〜3,000トークンを簡単に消費する。
- 会話履歴 — 会話内のすべての過去メッセージ。ステップごとに増加する。
- ツール結果 — 以前のツールコールの出力をコンテキストに注入したもの。非常に大きくなる場合がある(完全なウェブページ、データベースの結果など)。
出力トークンの内訳
出力トークンは入力トークンより3〜5倍高価であるため、重要な最適化対象となる:
- エージェントの推論 — 内部の思考連鎖(特に拡張思考を使用する場合)。
- ツールコールの生成 — ツール呼び出し用のJSON。
- 最終的な応答 — ユーザー向けの回答。
タスクあたりのコスト計算
1つのエージェントタスクの総コストは次のとおりだ:
総コスト = Σ (入力トークン数 × 入力単価 + 出力トークン数 × 出力単価) タスク内の各APIコールについてコスト内訳の例
Claude Sonnet(入力$3/M、出力$15/M)を使用した10ステップのリサーチエージェントタスクの現実的な内訳を示す:
| ステップ | コンポーネント | 入力トークン | 出力トークン | 入力コスト | 出力コスト | 合計 |
|---|---|---|---|---|---|---|
| 1 | 初期計画 | 4,200 | 800 | $0.0126 | $0.0120 | $0.025 |
| 2 | ウェブ検索コール | 4,800 | 200 | $0.0144 | $0.0030 | $0.017 |
| 3 | 検索結果の処理 | 8,500 | 600 | $0.0255 | $0.0090 | $0.035 |
| 4 | 精読(ページ1) | 12,000 | 500 | $0.0360 | $0.0075 | $0.044 |
| 5 | 精読(ページ2) | 15,200 | 500 | $0.0456 | $0.0075 | $0.053 |
| 6 | 追加検索 | 16,800 | 200 | $0.0504 | $0.0030 | $0.053 |
| 7 | 結果の処理 | 20,100 | 600 | $0.0603 | $0.0090 | $0.069 |
| 8 | 統合 | 22,500 | 1,200 | $0.0675 | $0.0180 | $0.086 |
| 9 | 検証 | 24,000 | 400 | $0.0720 | $0.0060 | $0.078 |
| 10 | 最終応答 | 25,500 | 1,500 | $0.0765 | $0.0225 | $0.099 |
| 合計 | 153,600 | 6,500 | $0.461 | $0.098 | $0.558 |
入力コストが支配的であり、会話履歴が蓄積されるにつれてステップごとに増加することに注目してほしい。ステップ8〜10はステップ数全体の30%に過ぎないにもかかわらず、総コストの47%を占めている。
コスト追跡コード
初日からトラッキングラッパーを実装しよう:
import anthropicimport timefrom dataclasses import dataclass, fieldfrom typing import Optional
@dataclassclass CostRecord: step: int model: str input_tokens: int output_tokens: int cache_read_tokens: int = 0 cache_creation_tokens: int = 0 input_cost: float = 0.0 output_cost: float = 0.0 total_cost: float = 0.0 duration_ms: float = 0.0
# Pricing per million tokens (as of early 2026)MODEL_PRICING = { "claude-haiku": {"input": 0.25, "output": 1.25, "cache_read": 0.025, "cache_write": 0.30}, "claude-sonnet": {"input": 3.00, "output": 15.00, "cache_read": 0.30, "cache_write": 3.75}, "claude-opus": {"input": 15.00, "output": 75.00, "cache_read": 1.50, "cache_write": 18.75},}
@dataclassclass TaskCostTracker: task_id: str budget_limit: Optional[float] = None records: list = field(default_factory=list) total_cost: float = 0.0
def record_call(self, step: int, model: str, usage) -> CostRecord: pricing = MODEL_PRICING.get(model, MODEL_PRICING["claude-sonnet"])
input_cost = (usage.input_tokens / 1_000_000) * pricing["input"] output_cost = (usage.output_tokens / 1_000_000) * pricing["output"] cache_read_cost = (getattr(usage, 'cache_read_input_tokens', 0) / 1_000_000) * pricing["cache_read"] cache_write_cost = (getattr(usage, 'cache_creation_input_tokens', 0) / 1_000_000) * pricing["cache_write"]
total = input_cost + output_cost + cache_read_cost + cache_write_cost
record = CostRecord( step=step, model=model, input_tokens=usage.input_tokens, output_tokens=usage.output_tokens, cache_read_tokens=getattr(usage, 'cache_read_input_tokens', 0), cache_creation_tokens=getattr(usage, 'cache_creation_input_tokens', 0), input_cost=input_cost + cache_read_cost + cache_write_cost, output_cost=output_cost, total_cost=total, )
self.records.append(record) self.total_cost += total
print(f" Step {step} [{model}]: {usage.input_tokens} in / {usage.output_tokens} out = ${total:.4f} (cumulative: ${self.total_cost:.4f})")
if self.budget_limit and self.total_cost > self.budget_limit: raise BudgetExceededError( f"Task {self.task_id} exceeded budget: ${self.total_cost:.4f} > ${self.budget_limit:.4f}" )
return record
def summary(self) -> dict: return { "task_id": self.task_id, "total_steps": len(self.records), "total_input_tokens": sum(r.input_tokens for r in self.records), "total_output_tokens": sum(r.output_tokens for r in self.records), "total_cost": self.total_cost, "cost_by_model": self._cost_by_model(), }
def _cost_by_model(self) -> dict: by_model = {} for r in self.records: if r.model not in by_model: by_model[r.model] = {"calls": 0, "cost": 0.0} by_model[r.model]["calls"] += 1 by_model[r.model]["cost"] += r.total_cost return by_model
class BudgetExceededError(Exception): pass最適化の前から今日すぐ計測を始めよう。改善を測定するためにベースラインの数字が必要だ。
2. タスクに応じたモデル選択
これはあなたが使える最大のコスト削減手段だ。すべてのエージェントステップに最も強力なモデルが必要なわけではない。
モデルのティアと価格
Claudeファミリーを参考として使用する:
| モデル | 入力(100万トークンあたり) | 出力(100万トークンあたり) | 最適な用途 |
|---|---|---|---|
| Haiku | $0.25 | $1.25 | 分類、ルーティング、抽出、シンプルなフォーマット |
関連記事
- AIエージェントのキャッシュ戦略:品質を落とさずコストを削減する
- エージェントワークフローにおける推論モデル:拡張思考が効果を発揮するとき
- マルチエージェントパターン:オーケストレーター、ワーカー、パイプライン
- 自律型エージェントシステムのデバッグと可観測性