### What counts as a turn ### Worked example: budget counting across requests ### Worked example: budget counting across turns
The whole hunk
from line 248, old and new numbered
/
lines
from line 248
248248</Note>
249249
250250<Warning>
251 **The countdown reflects tokens Claude has processed in the current agentic loop, not tokens you resend between turns.** If your client sends the full conversation history on every follow-up request, your client-side token count may differ from the budget Claude is tracking. If you also decrement `remaining` while resending full history, the model sees an under-reported budget and the countdown drops faster than it should, causing Claude to wrap up earlier than the budget actually allows. Set a generous budget and let the model self-regulate against the countdown rather than trying to mirror it client-side.
251 **The countdown reflects tokens Claude has processed in the current agentic loop, not tokens you resend between requests.** If your client sends the full conversation history on every follow-up request, your client-side token count might differ from the budget Claude is tracking. If you also decrement `remaining` while resending full history, the model sees an under-reported budget and the countdown drops faster than it should, causing Claude to wrap up earlier than the budget actually allows. Set a generous budget and let the model self-regulate against the countdown rather than trying to mirror it client-side.
252252</Warning>
253253
254### Worked example: budget counting across turns
254### What counts as a turn
255255
256The task budget counts what Claude **sees** (thinking, tool calls and results, and text), not what's in your request payload. In an agentic loop your client resends the full conversation on every request, so the payload grows turn over turn, but the budget only decrements by the tokens Claude sees this turn.
256The budget covers one agentic turn, also called an agentic loop: everything Claude does in response to one user message that carries no tool results. A turn can span several requests.
257257
258A user message that carries no tool results starts a new turn with a fresh budget. Today, the countdown still counts earlier turns' history while it remains in the context. A common case is a follow-up after Claude has ended its turn, for example because the budget ran out:
259
260```json
261{ "role": "user", "content": "Continue." }
262```
263
264A user message that contains `tool_result` blocks continues the current turn, because your client is resolving tool calls that are part of that turn:
265
266```json
267{
268 "role": "user",
269 "content": [
270 { "type": "tool_result", "tool_use_id": "toolu_01", "content": "<npm audit output>" }
271 ]
272}
273```
274
275That holds even when the message adds new content alongside the tool results:
276
277```json
278{
279 "role": "user",
280 "content": [
281 { "type": "tool_result", "tool_use_id": "toolu_01", "content": "<npm audit output>" },
282 { "type": "text", "text": "Also check the Dockerfile." }
283 ]
284}
285```
286
287Server-side [compaction](https://platform.claude.com/docs/en/build-with-claude/compaction) during a turn does not reset the budget: tokens the turn consumed before the compaction still count against it. Tokens from before the turn began do not count, even when a compaction at the start of a turn summarizes them. Today, that exclusion applies only to the budget carried across a server-side compaction; earlier turns' history still counts while it remains in the context.
288
289### Worked example: budget counting across requests
290
291The task budget counts what Claude **sees** (thinking, tool calls and results, and text), not what's in your request payload. In an agentic loop your client resends the full conversation on every request, so the payload keeps growing, but the budget only decrements by what is new: the tokens Claude generates and the content it has not seen before. The following example is one [agentic turn](https://platform.claude.com/docs/en/build-with-claude/task-budgets#what-counts-as-a-turn) made of three requests: the first carries the user message, and the next two each resend the history with a tool result appended.
292
258293Consider a loop with `task_budget: {type: "tokens", total: 100000}` and a single `bash` tool.
259294
260**Turn 1.** You send the initial request:
295**Request 1.** You send the initial request:
261296
262297```json
263298{
from line 322
287322}
288323```
289324
290Suppose this assistant turn (thinking plus the tool call) totals 5,000 generated tokens. The countdown Claude saw during generation ended near `remaining` ≈ 95,000.
325Suppose this assistant message (thinking plus the tool call) totals 5,000 generated tokens. The countdown Claude saw during generation ended near `remaining` ≈ 95,000.
291326
292**Turn 2.** Your client runs the tool, then resends the full history with the tool result appended:
327**Request 2.** Your client runs the tool, then resends the full history with the tool result appended:
293328
294329```json
295330{
from line 356
321356}
322357```
323358
324The resent turn-1 user and assistant messages are not counted again, but the 2,800-token tool result is new content Claude sees this turn and counts against the budget. Claude spends another 4,000 tokens on thinking and a second tool call (`grep -rn "eval(" src/`). The countdown ends near `remaining` ≈ 88,200.
359The resent messages from request 1 are not counted again, but the 2,800-token tool result is new content and counts against the budget. Claude spends another 4,000 tokens on thinking and a second tool call (`grep -rn "eval(" src/`). The countdown ends near `remaining` ≈ 88,200.
325360
326**Turn 3.** Full history resent again with the second tool result (1,200 tokens of grep output) appended. Claude writes a 6,000-token final findings report and stops with `stop_reason: "end_turn"`. `remaining` ≈ 81,000.
361**Request 3.** Full history resent again with the second tool result (1,200 tokens of grep output) appended. Claude writes a 6,000-token final findings report and stops with `stop_reason: "end_turn"`. `remaining` ≈ 81,000.
327362
328Putting the three turns side by side makes the distinction between payload size and budget spend explicit:
363Putting the three requests side by side makes the distinction between payload size and budget spend explicit:
329364
330| Turn | Request payload (approx. input tokens you sent) | Tokens counted against budget this turn | Budget `remaining` after |
365| Request | Request payload (approx. input tokens you sent) | Tokens counted against budget this request | Budget `remaining` after |
331366| --------- | ----------------------------------------------- | --------------------------------------------------------- | ------------------------ |
332367| 1 | \~20 | 5,000 (thinking + `tool_use`) | \~95,000 |
333| 2 | \~7,800 (turn 1 history + tool result) | 6,800 (2,800 tool result + 4,000 thinking and `tool_use`) | \~88,200 |
368| 2 | \~7,800 (messages from request 1 + tool result) | 6,800 (2,800 tool result + 4,000 thinking and `tool_use`) | \~88,200 |
334369| 3 | \~13,000 (full history + second tool result) | 7,200 (1,200 tool result + 6,000 `text`) | \~81,000 |
335370| **Total** | **\~20,820 sent across requests** | **19,000 counted against budget** | N/A |
336371
337Your client sent the turn-1 user message three times and the turn-1 assistant message twice, but each was counted once. The budget spent 19,000 of 100,000 tokens, even though the cumulative payload your client transmitted was larger and the prompt-cached input on turns 2 and 3 was larger still.
372Your client sent the original user message three times and the first assistant message twice, but each was counted once. The budget spent 19,000 of 100,000 tokens, even though the cumulative payload your client transmitted was larger and the prompt-cached input on requests 2 and 3 was larger still.
338373
339374### Carrying a budget across compaction with `remaining`
340375
341If your agentic loop compacts or rewrites context between requests (for example, by summarizing earlier turns), the server has no memory of how much budget was spent before compaction. Pass `remaining` on the next request so the countdown continues from where you left off rather than resetting to `total`:
376If your own code compacts or rewrites the message history between requests (for example, by summarizing earlier messages), the server has no memory of how much budget was spent before compaction. Pass `remaining` on the next request so the countdown continues from where you left off rather than resetting to `total`:
342377
343378<CodeGroup exclude="shell">
344379 ```python Python
from line 476
441476
442477In this example, the tokens spent before compaction are the usage of all the messages you have removed from the history so far, measured as in [Measure your current usage](https://platform.claude.com/docs/en/build-with-claude/task-budgets#measure-your-current-usage). Leave out anything still present in the messages you send, including any summary you added, because the server counts those tokens itself. Update this figure only when you replace the history this way; don't decrement it per request. Pass the resulting `remaining` on every request, not only the one that compacts.
443478
444For loops that resend the full uncompacted history on every turn, omit `remaining` and let the server track the countdown.
479For loops that resend the full uncompacted history on every request, omit `remaining` and let the server track the countdown.
445480
446481## Changing the budget mid-conversation
447482
from line 631
596631* **`max_tokens`:** Orthogonal to task budgets. `max_tokens` is a hard per-request cap on generated tokens, while `task_budget` is an advisory cap across the full agentic loop (potentially spanning many requests). At `xhigh` or `max` effort, set `max_tokens` to at least 64k to give Claude room to think and act on each request.
597632* **[Effort](https://platform.claude.com/docs/en/build-with-claude/effort):** Effort controls how deeply Claude reasons per step. Task budgets control how much total work Claude does across an agentic loop. The two are complementary: effort tunes depth, task budgets tune breadth.
598633* **[Adaptive thinking](https://platform.claude.com/docs/en/build-with-claude/thinking):** Task budgets include thinking tokens in the count, so adaptive thinking scales down as the budget depletes.
599* **[Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching):** The budget-countdown marker is injected server-side per turn, so it does not match across requests. If your client decrements `task_budget.remaining` on each follow-up request, the changed value invalidates any cache prefix that contains it. To preserve caching, set the budget once on the initial request and let the model self-regulate against the server-side countdown rather than mutating the budget client-side.
634* **[Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching):** The budget-countdown marker is injected server-side on each request, so it does not match across requests. If your client decrements `task_budget.remaining` on each follow-up request, the changed value invalidates any cache prefix that contains it. To preserve caching, set the budget once on the initial request and let the model self-regulate against the server-side countdown rather than mutating the budget client-side.
600635
601636## Feature support
602637