文档索引
在此获取完整文档索引: https://code.claude.com/docs/llms.txt 使用此文件发现所有可用页面,然后再进一步探索。
跟踪成本和使用量
了解如何使用 Claude Agent SDK 跟踪令牌使用量、估算成本和配置提示缓存。
Claude Agent SDK 为每次与 Claude 的交互提供详细的令牌使用信息。本指南说明如何正确跟踪使用量和理解成本报告,尤其是在处理并行工具使用和多步对话时。
有关完整的 API 文档,请参阅 TypeScript SDK 参考和 Python SDK 参考。
total_cost_usd 和 costUSD 字段是客户端估算值,不是权威计费数据。SDK 从构建时捆绑的价格表本地计算这些值,因此在以下情况下可能与实际账单有偏差:
- 定价变更
- 已安装的 SDK 版本无法识别某个模型
- 客户端无法建模的计费规则
使用这些字段进行开发洞察和近似预算。要获取权威计费数据,请使用使用量和成本 API 或 Claude Console 中的使用量页面。不要根据这些字段向最终用户收费或触发财务决策。
理解令牌使用量
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()调用: SDKquery()函数的一次调用。单次调用可能涉及多个步骤(Claude 响应、使用工具、获取结果、再次响应)。每次调用在末尾产生一个result消息。- 步骤:
query()调用内的单个请求/响应循环。每个步骤产生带有令牌使用量的助手消息。 - 会话: 通过会话 ID 链接的一系列
query()调用(使用resume选项)。会话中的每个query()调用独立报告其自身的成本。
下图显示了单次 query() 调用的消息流,在每一步报告令牌使用量,在末尾报告累计估算值:
每一步产生助手消息
当 Claude 响应时,它发送一个或多个助手消息。在 TypeScript 中,每个助手消息包含一个嵌套的
BetaMessage(通过message.message访问),带有id和包含令牌计数(input_tokens、output_tokens)的usage对象。在 Python 中,AssistantMessage数据类通过message.usage和message.message_id直接公开相同的数据。当 Claude 在一轮中使用多个工具时,该轮中的所有消息共享相同的 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 只计数一次:
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() 调用(例如在多轮会话中或跨不同用户),请自行累加总数。
以下示例依次运行两次 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 自动使用提示缓存来减少重复内容的成本。您不需要自己配置缓存。使用量对象包含两个用于缓存跟踪的附加字段:
cache_creation_input_tokens:用于创建新缓存条目的令牌(收费高于标准输入令牌)。cache_read_input_tokens:从现有缓存条目读取的令牌(收费较低)。
将这些与 input_tokens 分开跟踪以了解缓存节省情况。在 TypeScript 中,这些字段在 Usage 对象上类型化。在 Python 中,它们作为 ResultMessage.usage 字典中的键出现(例如 message.usage.get("cache_read_input_tokens", 0))。
将提示缓存 TTL 延长至一小时
当您使用 API 密钥认证或在 Amazon Bedrock、Google Cloud Vertex AI 或 Microsoft Foundry 上运行时,SDK 写入的缓存条目默认使用 5 分钟 TTL。如果您的工作负载针对相同的系统提示和上下文运行多个短会话,且会话间隔超过 5 分钟,则缓存会在会话之间过期,每个新会话都要支付全额输入价格。
要请求缓存写入的 1 小时 TTL,请设置 ENABLE_PROMPT_CACHING_1H 环境变量。您可以在 shell 或容器环境中导出它,或通过 options.env 传递它。
以下示例为在 Bedrock 上运行的智能体启用 1 小时 TTL:
options = ClaudeAgentOptions(
env={
"CLAUDE_CODE_USE_BEDROCK": "1",
"ENABLE_PROMPT_CACHING_1H": "1",
},
)
const options = {
env: {
...process.env,
CLAUDE_CODE_USE_BEDROCK: "1",
ENABLE_PROMPT_CACHING_1H: "1",
},
};
具有 1 小时 TTL 的缓存写入收费高于 5 分钟写入,因此启用此选项是以更高的写入成本换取更多的缓存读取。有关详情,请参阅提示缓存定价。Claude 订阅用户已自动获得 1 小时 TTL,无需设置此变量。
相关文档
- TypeScript SDK 参考 - 完整 API 文档
- SDK 概述 - SDK 入门指南
- SDK 权限 - 管理工具权限