Track cost and usage changedagent-sdk/cost-tracking
Nearest release: v2.1.290, published 3 hours before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Upstream edited this page at 5 Oct 2026 22:11 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 22 Oct 2026 18:07 UTC.
Upstream edited
Recorded here
Lines+16added
Lines−16removed
From line
4
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits12to this page, all time
The whole hunk
from line 4, old and new numbered
/
from line 4
44
55The Claude Agent SDK provides detailed token usage information for each interaction with Claude. This guide explains how to properly track usage and understand cost reporting, especially when dealing with parallel tool uses and multi-step conversations.
66
7For complete API documentation, see the [TypeScript SDK reference](/docs/en/agent-sdk/typescript) and [Python SDK reference](/docs/en/agent-sdk/python).
7For complete API documentation, see the [TypeScript SDK reference](/docs/en/agent-sdk/typescript.md) and [Python SDK reference](/docs/en/agent-sdk/python.md).
88
99> [!WARNING]
1010>
from line 29
2929
3030Cost tracking depends on understanding how the SDK scopes usage data:
3131
32* **`query()` call:** one invocation of the SDK's `query()` function. A single call can involve multiple steps: Claude responds, uses tools, gets results, and responds again. Each call produces one [`result`](/docs/en/agent-sdk/typescript#sdkresultmessage) message at the end, except in [streaming input mode](/docs/en/agent-sdk/streaming-vs-single-mode), where one `query()` call carries multiple user turns and each turn emits its own `result` message.
32* **`query()` call:** one invocation of the SDK's `query()` function. A single call can involve multiple steps: Claude responds, uses tools, gets results, and responds again. Each call produces one [`result`](/docs/en/agent-sdk/typescript#sdkresultmessage) message at the end, except in [streaming input mode](/docs/en/agent-sdk/streaming-vs-single-mode.md), where one `query()` call carries multiple user turns and each turn emits its own `result` message.
3333* **Step:** a single request/response cycle within a `query()` call. Each step produces assistant messages with token usage.
3434* **Session:** a series of `query()` calls linked by a session ID through the `resume` option. A resumed call's results report the session's whole spend, not just that call's own. See [Accumulate costs across multiple calls](#accumulate-costs-across-multiple-calls) for how the totals carry over.
3535
from line 51
5151
5252## Track costs in streaming input mode
5353
54In [streaming input mode](/docs/en/agent-sdk/streaming-vs-single-mode), one `query()` call carries multiple user turns and each turn emits its own result message. The result fields differ in scope:
54In [streaming input mode](/docs/en/agent-sdk/streaming-vs-single-mode.md), one `query()` call carries multiple user turns and each turn emits its own result message. The result fields differ in scope:
5555
5656* **`usage`**: covers only that turn, and within it only the main agent loop, not any subagents it ran.
5757* **`total_cost_usd` and `modelUsage`, or `model_usage` in Python**: carry the running total for the whole call so far, plus any spend restored when the call resumed a session.
from line 79
7979
8080In streaming input mode, read call totals as described in [Track costs in streaming input mode](#track-costs-in-streaming-input-mode).
8181
82The three result-level fields differ in what they count when the agent spawns [subagents](/docs/en/agent-sdk/subagents). Use `modelUsage`, or `model_usage` in Python, for whole-tree token accounting; the `usage` field undercounts as soon as nesting occurs.
82The three result-level fields differ in what they count when the agent spawns [subagents](/docs/en/agent-sdk/subagents.md). Use `modelUsage`, or `model_usage` in Python, for whole-tree token accounting; the `usage` field undercounts as soon as nesting occurs.
8383
8484| Field | Subagent activity |
8585| - | - |
from line 87
8787| `total_cost_usd` | Included. Counts subagent requests alongside the top-level loop |
8888| `modelUsage` / `model_usage` | Included. Counts subagent requests alongside the top-level loop, broken down by model |
8989
90In [single message input mode](/docs/en/agent-sdk/streaming-vs-single-mode#single-message-input), when background subagents are still running at the end of the final turn, Claude Code waits for them, up to the cap described in [background tasks at exit](/docs/en/headless#background-tasks-at-exit), before emitting the result. The result's `total_cost_usd`, `duration_api_ms`, and `modelUsage`, or `model_usage` in Python, include the work done during that wait.
90In [single message input mode](/docs/en/agent-sdk/streaming-vs-single-mode.md#single-message-input), when background subagents are still running at the end of the final turn, Claude Code waits for them, up to the cap described in [background tasks at exit](/docs/en/headless.md#background-tasks-at-exit), before emitting the result. The result's `total_cost_usd`, `duration_api_ms`, and `modelUsage`, or `model_usage` in Python, include the work done during that wait.
9191
9292The following examples iterate over the message stream from a `query()` call and print the total cost when the `result` message arrives:
9393
from line 129
129129asyncio.run(main())
130130```
131131
132To bound how much subagents can add to `total_cost_usd`, set the [depth, concurrency, and spend limits](/docs/en/agent-sdk/subagents#cap-subagent-depth-concurrency-and-spend) on the query.
132To bound how much subagents can add to `total_cost_usd`, set the [depth, concurrency, and spend limits](/docs/en/agent-sdk/subagents.md#cap-subagent-depth-concurrency-and-spend) on the query.
133133
134134## Track per-step and per-model usage
135135
from line 216
216216Each `query()` call returns `total_cost_usd` on its results. How you combine the values depends on whether the calls share a session:
217217
218218* **Independent calls, with no `resume` or `continue` option**: each result covers only its own call, so add the totals yourself, as the examples below do.
219* **Calls that resume the same session**: Claude Code saves the session's totals to its [transcript](/docs/en/sessions#where-transcripts-are-stored) when the process exits normally and restores them when a later call resumes or forks the session. Each result already includes the session's earlier spend. Read the latest result for the session total; summing results double-counts the restored spend. Before v2.1.277, a session that you resumed through the SDK or `claude -p` started its totals at zero, so each call's results covered only that call.
219* **Calls that resume the same session**: Claude Code saves the session's totals to its [transcript](/docs/en/sessions.md#where-transcripts-are-stored) when the process exits normally and restores them when a later call resumes or forks the session. Each result already includes the session's earlier spend. Read the latest result for the session total; summing results double-counts the restored spend. Before v2.1.277, a session that you resumed through the SDK or `claude -p` started its totals at zero, so each call's results covered only that call.
220220
221221Either way, the combined figure is still a [client-side estimate](#estimates-not-billing).
222222
from line 333
333333
334334### Extend the prompt cache TTL to one hour
335335
336Your own turns fall in the [main conversation TTL bucket](/docs/en/prompt-caching#which-ttl-each-request-gets), together with the helpers Claude Code runs inline with them. The requests Claude Code makes outside that conversation, such as [subagents](/docs/en/agent-sdk/subagents), have a [separate TTL control](/docs/en/prompt-caching#choose-the-ttl-yourself).
336Your own turns fall in the [main conversation TTL bucket](/docs/en/prompt-caching.md#which-ttl-each-request-gets), together with the helpers Claude Code runs inline with them. The requests Claude Code makes outside that conversation, such as [subagents](/docs/en/agent-sdk/subagents.md), have a [separate TTL control](/docs/en/prompt-caching.md#choose-the-ttl-yourself).
337337
338Cache entries for your own turns use a 5-minute TTL by default when you authenticate with an API key or run on Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry, or [Claude Platform on AWS](/docs/en/claude-platform-on-aws). If your workload runs many short sessions against the same system prompt and context with gaps longer than 5 minutes between them, the cache expires between sessions and each new session pays full input price.
338Cache entries for your own turns use a 5-minute TTL by default when you authenticate with an API key or run on Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry, or [Claude Platform on AWS](/docs/en/claude-platform-on-aws.md). If your workload runs many short sessions against the same system prompt and context with gaps longer than 5 minutes between them, the cache expires between sessions and each new session pays full input price.
339339
340340To request a 1-hour TTL on cache writes, set the [`ENABLE_PROMPT_CACHING_1H`](/docs/en/env-vars) environment variable. You can export it in your shell or container environment, or pass it through `options.env`.
341341
342The following example enables 1-hour TTL for an agent running on Amazon Bedrock. Because it sets `CLAUDE_CODE_USE_BEDROCK`, it requires working AWS credentials for [Amazon Bedrock](/docs/en/amazon-bedrock); without them the query fails.
342The following example enables 1-hour TTL for an agent running on Amazon Bedrock. Because it sets `CLAUDE_CODE_USE_BEDROCK`, it requires working AWS credentials for [Amazon Bedrock](/docs/en/amazon-bedrock.md); without them the query fails.
343343
344344```python Python theme={null}
345345from claude_agent_sdk import ClaudeAgentOptions, query
from line 381
381381
382382`ENABLE_PROMPT_CACHING_1H` asks for the 1-hour TTL on every request in both buckets. To choose a TTL for each bucket separately, use these controls instead. Each takes `5m` or `1h` and takes precedence over `ENABLE_PROMPT_CACHING_1H`:
383383
384* Main conversation: the `CLAUDE_CODE_PROMPT_CACHE_TTL` [environment variable](/docs/en/env-vars), or the [`promptCacheTtl`](/docs/en/settings-reference#promptcachettl) setting
384* Main conversation: the `CLAUDE_CODE_PROMPT_CACHE_TTL` [environment variable](/docs/en/env-vars.md), or the [`promptCacheTtl`](/docs/en/settings-reference#promptcachettl) setting
385385* Everything else: the `CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL` environment variable, or the [`subagentPromptCacheTtl`](/docs/en/settings-reference#subagentpromptcachettl) setting
386386
387Setting `promptCacheTtl` to `1h` keeps the 1-hour cache on the main conversation while you're drawing on usage credits. For the full precedence order, see [choose the TTL yourself](/docs/en/prompt-caching#choose-the-ttl-yourself).
387Setting `promptCacheTtl` to `1h` keeps the 1-hour cache on the main conversation while you're drawing on usage credits. For the full precedence order, see [choose the TTL yourself](/docs/en/prompt-caching.md#choose-the-ttl-yourself).
388388
389389## Related documentation
390390
391* [TypeScript SDK Reference](/docs/en/agent-sdk/typescript) - Complete API documentation
392* [SDK Overview](/docs/en/agent-sdk/overview) - Getting started with the SDK
393* [SDK Permissions](/docs/en/agent-sdk/permissions) - Managing tool permissions
391* [TypeScript SDK Reference](/docs/en/agent-sdk/typescript.md) - Complete API documentation
392* [SDK Overview](/docs/en/agent-sdk/overview.md) - Getting started with the SDK
393* [SDK Permissions](/docs/en/agent-sdk/permissions.md) - Managing tool permissions
394394
No line in this hunk matches that.