コストと使用状況の追跡
Claude Agent SDK でトークン使用状況を追跡し、コストを見積もり、プロンプトキャッシングを設定する方法を学びます。
Claude Agent SDK は、Claude との各インタラクションの詳細なトークン使用情報を提供します。このガイドでは、使用状況を適切に追跡し、特に並列ツール使用とマルチステップ会話を扱う場合のコスト報告を理解する方法について説明します。
完全な API ドキュメントについては、TypeScript SDK リファレンスとPython SDK リファレンスを参照してください。
total_cost_usd および costUSD フィールドはクライアント側の推定値であり、権限のある請求データではありません。SDK はビルド時にバンドルされた価格表からローカルで計算するため、以下の場合に実際の請求額から乖離する可能性があります。
- 価格が変更された
- インストールされている SDK バージョンがモデルを認識しない
- クライアントがモデル化できない請求ルールが適用される
これらのフィールドは開発の洞察と概算予算作成に使用してください。権限のある請求については、Usage and Cost APIまたはClaude Consoleの Usage ページを使用してください。これらのフィールドからエンドユーザーに請求したり、財務上の決定をトリガーしたりしないでください。
トークン使用状況を理解する
TypeScript と Python SDK は、異なるフィールド名で同じ使用データを公開します。
- TypeScript は、各アシスタントメッセージ(
message.message.id、message.message.usage)のステップごとのトークン分解、結果メッセージのmodelUsage経由のモデルごとのコスト、および結果メッセージの累積合計を提供します。 - Python は、各アシスタントメッセージ(
message.usage、message.message_id)のステップごとのトークン分解、結果メッセージのmodel_usage経由のモデルごとのコスト、および結果メッセージの累積合計(total_cost_usdおよびusage辞書)を提供します。
両方の SDK は同じ基本的なコストモデルを使用し、同じ粒度を公開します。違いはフィールド命名とステップごとの使用がネストされている場所です。
コスト追跡は、SDK が使用データをどのようにスコープするかを理解することに依存します。
query()呼び出し: SDK のquery()関数の 1 つの呼び出し。単一の呼び出しは複数のステップを含むことができます(Claude が応答し、ツールを使用し、結果を取得し、再度応答します)。各呼び出しは最後に 1 つのresultメッセージを生成します。- ステップ:
query()呼び出し内の単一のリクエスト/レスポンスサイクル。各ステップはトークン使用情報を含むアシスタントメッセージを生成します。 - セッション: セッション ID でリンクされた一連の
query()呼び出し(resumeオプションを使用)。セッション内の各query()呼び出しは独立してコストを報告します。
次の図は、単一の query() 呼び出しからのメッセージストリームを示しており、各ステップでトークン使用が報告され、最後に累積推定値が表示されます。
各ステップはアシスタントメッセージを生成します
Claude が応答すると、1 つ以上のアシスタントメッセージを送信します。TypeScript では、各アシスタントメッセージには、ネストされた BetaMessage(message.message 経由でアクセス)が含まれており、id とトークン数(input_tokens、output_tokens)を含むusageオブジェクトがあります。Python では、AssistantMessage データクラスは message.usage と message.message_id 経由で同じデータを直接公開します。Claude が 1 つのターンで複数のツールを使用する場合、そのターンのすべてのメッセージは同じ ID を共有するため、ID でデデュプリケートして二重カウントを避けてください。
結果メッセージは累積推定値を提供します
query() 呼び出しが完了すると、SDK は total_cost_usd と累積 usage を含む結果メッセージを発行します。これは TypeScript(SDKResultMessage)と Python(ResultMessage)の両方で利用可能です。複数の query() 呼び出しを行う場合(たとえば、マルチターンセッション)、各結果はその個別の呼び出しのコストのみを反映します。推定合計のみが必要な場合は、ステップごとの使用を無視して、この単一の値を読むことができます。
クエリの総コストを取得する
結果メッセージ(TypeScript、Python)は、query() 呼び出しのエージェントループの終了をマークします。これには total_cost_usd が含まれており、その呼び出し内のすべてのステップにわたる累積推定コストです。これは成功とエラー結果の両方で機能します。セッションを使用して複数の query() 呼び出しを行う場合、各結果はその個別の呼び出しのコストのみを反映します。
次の例は、query() 呼び出しからのメッセージストリームを反復処理し、result メッセージが到着したときに総コストを出力します。
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({ prompt: "Summarize this project" })) {
if (message.type === "result") {
console.log(`Total cost: $${message.total_cost_usd}`);
}
}
from claude_agent_sdk import query, ResultMessage
import asyncio
async def main():
async for message in query(prompt="Summarize this project"):
if isinstance(message, ResultMessage):
print(f"Total cost: ${message.total_cost_usd or 0}")
asyncio.run(main())
ステップごとおよびモデルごとの使用状況を追跡する
このセクションの例は TypeScript フィールド名を使用します。Python では、同等のフィールドはステップごとの使用状況のAssistantMessage.usageと AssistantMessage.message_id、およびモデルごとの分解のResultMessage.model_usageです。
ステップごとの使用状況を追跡する
各アシスタントメッセージには、ネストされた BetaMessage(message.message 経由でアクセス)が含まれており、id とトークン数を含む usage オブジェクトがあります。Claude がツールを並列で使用する場合、複数のメッセージは同じ id と同一の使用データを共有します。既にカウントした ID を追跡し、重複をスキップして、インフレートされた合計を避けてください。
並列ツール呼び出しは、ネストされた BetaMessage が同じ id と同一の使用データを共有する複数のアシスタントメッセージを生成します。正確なステップごとのトークン数を取得するには、常に ID でデデュプリケートしてください。
次の例は、各ユニークなメッセージ ID を 1 回だけカウントして、すべてのステップにわたって入力トークンと出力トークンを累積します。
import { query } from "@anthropic-ai/claude-agent-sdk";
const seenIds = new Set<string>();
let totalInputTokens = 0;
let totalOutputTokens = 0;
for await (const message of query({ prompt: "Summarize this project" })) {
if (message.type === "assistant") {
const msgId = message.message.id;
// Parallel tool calls share the same ID, only count once
if (!seenIds.has(msgId)) {
seenIds.add(msgId);
totalInputTokens += message.message.usage.input_tokens;
totalOutputTokens += message.message.usage.output_tokens;
}
}
}
console.log(`Steps: ${seenIds.size}`);
console.log(`Input tokens: ${totalInputTokens}`);
console.log(`Output tokens: ${totalOutputTokens}`);
モデルごとの使用状況を分解する
結果メッセージにはmodelUsageが含まれており、これはモデル名からモデルごとのトークン数とコストへのマップです。これは複数のモデルを実行する場合(たとえば、サブエージェント用の Haiku とメインエージェント用の Opus)に便利で、トークンがどこに行っているかを確認したい場合に役立ちます。
次の例はクエリを実行し、使用されたモデルごとのコストとトークン分解を出力します。
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({ prompt: "Summarize this project" })) {
if (message.type !== "result") continue;
for (const [modelName, usage] of Object.entries(message.modelUsage)) {
console.log(`${modelName}: $${usage.costUSD.toFixed(4)}`);
console.log(` Input tokens: ${usage.inputTokens}`);
console.log(` Output tokens: ${usage.outputTokens}`);
console.log(` Cache read: ${usage.cacheReadInputTokens}`);
console.log(` Cache creation: ${usage.cacheCreationInputTokens}`);
}
}
複数の呼び出しにわたってコストを累積する
各 query() 呼び出しは独自の total_cost_usd を返します。SDK はセッションレベルの合計を提供しないため、アプリケーションが複数の query() 呼び出しを行う場合(たとえば、マルチターンセッションまたは異なるユーザー間)、合計を自分で累積してください。
次の例は 2 つの query() 呼び出しを順序立てて実行し、各呼び出しの total_cost_usd を実行中の合計に追加し、呼び出しごとのコストと合計コストの両方を出力します。
import { query } from "@anthropic-ai/claude-agent-sdk";
// Track cumulative cost across multiple query() calls
let totalSpend = 0;
const prompts = [
"Read the files in src/ and summarize the architecture",
"List all exported functions in src/auth.ts"
];
for (const prompt of prompts) {
for await (const message of query({ prompt })) {
if (message.type === "result") {
totalSpend += message.total_cost_usd;
console.log(`This call: $${message.total_cost_usd}`);
}
}
}
console.log(`Total spend: $${totalSpend.toFixed(4)}`);
from claude_agent_sdk import query, ResultMessage
import asyncio
async def main():
# Track cumulative cost across multiple query() calls
total_spend = 0.0
prompts = [
"Read the files in src/ and summarize the architecture",
"List all exported functions in src/auth.ts",
]
for prompt in prompts:
async for message in query(prompt=prompt):
if isinstance(message, ResultMessage):
cost = message.total_cost_usd or 0
total_spend += cost
print(f"This call: ${cost}")
print(f"Total spend: ${total_spend:.4f}")
asyncio.run(main())
エラー、キャッシング、トークン不一致を処理する
正確なコスト追跡のために、失敗した会話、キャッシュトークン価格、および時折の報告の不一致を考慮してください。
出力トークン不一致を解決する
まれに、同じ ID を持つメッセージに対して異なる output_tokens 値が観察される場合があります。これが発生した場合:
- 最高値を使用する: グループ内の最終メッセージは通常、正確な合計を含みます。
- 結果メッセージを優先する: 結果メッセージの
total_cost_usdは、すべてのステップにわたって SDK の累積推定値を反映するため、ステップごとの値を自分で合計するよりも信頼性が高くなります。これはまだ推定値であり、実際の請求額と異なる場合があります。 - 不一致を報告する: Claude Code GitHub リポジトリで問題をファイルしてください。
失敗した会話のコストを追跡する
成功とエラーの両方の結果メッセージには usage と total_cost_usd が含まれます。会話が途中で失敗した場合、失敗の時点までトークンを消費しています。その subtype に関係なく、常に結果メッセージからコストデータを読んでください。
キャッシュトークンを追跡する
Agent SDK は prompt caching を自動的に使用して、繰り返されるコンテンツのコストを削減します。キャッシングを自分で設定する必要はありません。使用オブジェクトには、キャッシング追跡用の 2 つの追加フィールドが含まれます。
cache_creation_input_tokens:新しいキャッシュエントリを作成するために使用されるトークン(標準入力トークンより高いレートで課金)。cache_read_input_tokens:既存のキャッシュエントリから読み取られるトークン(削減されたレートで課金)。
キャッシング節約を理解するために、これらを input_tokens とは別に追跡してください。TypeScript では、これらのフィールドは Usage オブジェクトで型付けされます。Python では、ResultMessage.usage 辞書のキーとして表示されます(たとえば、message.usage.get("cache_read_input_tokens", 0))。
プロンプトキャッシュ TTL を 1 時間に延長する
SDK によって書き込まれたキャッシュエントリは、API キーで認証するか、Amazon Bedrock、Google Cloud Vertex AI、または Microsoft Foundry で実行する場合、デフォルトで 5 分の TTL を使用します。ワークロードが同じシステムプロンプトとコンテキストに対して多くの短いセッションを実行し、セッション間に 5 分以上のギャップがある場合、キャッシュはセッション間で期限切れになり、各新しいセッションは完全な入力価格を支払います。
キャッシュ書き込みで 1 時間の TTL をリクエストするには、ENABLE_PROMPT_CACHING_1H 環境変数を設定します。シェルまたはコンテナ環境でエクスポートするか、options.env 経由で渡すことができます。
次の例は、Bedrock で実行されているエージェントの 1 時間 TTL を有効にします。
from claude_agent_sdk import ClaudeAgentOptions, query
import asyncio
async def main():
options = ClaudeAgentOptions(
env={
"CLAUDE_CODE_USE_BEDROCK": "1",
"ENABLE_PROMPT_CACHING_1H": "1",
},
)
async for message in query(prompt="Summarize this project", options=options):
print(message)
asyncio.run(main())
import { query } from "@anthropic-ai/claude-agent-sdk";
const options = {
env: {
...process.env,
CLAUDE_CODE_USE_BEDROCK: "1",
ENABLE_PROMPT_CACHING_1H: "1",
},
};
for await (const message of query({ prompt: "Summarize this project", options })) {
console.log(message);
}
1 時間の TTL を持つキャッシュ書き込みは、5 分の書き込みより高いレートで課金されるため、これを有効にすると、より高い書き込みコストとより多くのキャッシュ読み取りがトレードオフされます。詳細については、prompt caching pricing を参照してください。Claude サブスクリプションユーザーは既に 1 時間の TTL を自動的に受け取り、この変数を設定する必要はありません。
関連ドキュメント
- TypeScript SDK リファレンス - 完全な API ドキュメント
- SDK 概要 - SDK の使用を開始する
- SDK パーミッション - ツールパーミッションの管理