Claude Budget Controls: Advisory Tokens, SDK Stops and Hosted Session Caps
Anthropic exposes three separate mechanisms called a 'budget,' on three different surfaces, and they enforce spend in three different ways. Picking the wrong one for your bot's surface means either a spend limit that the model can quietly ignore, or a hard stop that arrives later and costs more than you set.
AI-assisted editorial: researched and drafted with AI using the primary sources linked below. Examples are illustrative; they are not measured product results. Editorial policy.
Key takeaways
- Messages API task_budget is advisory only; the model can exceed it, and the real hard ceiling on a single response is still max_tokens.
- Claude Agent SDK's max_budget_usd is a genuine stop condition, but it's checked after each response returns, so the response that crosses the cap still finishes and gets billed.
- Claude Managed Agents session budgets are the one platform-enforced hard dollar cap; a capped session pauses idle rather than terminating, and resumes when you raise the cap.
Three mechanisms, same word, different guarantees
If you search Anthropic's documentation for 'budget,' you'll find three unrelated features. The Messages API has task_budget, an advisory token countdown you pass in a request. The Claude Agent SDK (the library behind Claude Code and headless CLI agents) has max_budget_usd, a dollar cap you pass to ClaudeAgentOptions. Claude Managed Agents, the hosted session API, has a session budget, a dollar cap you set when you create a session. Task budgets guide the model; SDK limits stop the client loop; session budgets stop new model requests on the hosted platform.
This matters because the three surfaces aren't interchangeable. A bot built directly against the Messages API, a bot built on the Agent SDK, and a bot running as a Managed Agents session are three different architectures, and each one only has access to its own budget mechanism. Picking the wrong mental model for the one you're actually using means believing you have a spend ceiling when you don't.
Sources: Task budgets - Claude Platform Docs, How the agent loop works - Claude Code Docs, Session budgets - Claude Platform Docs.
Messages API task_budget: a hint the model can ignore
Anthropic is explicit about this one: task budgets are a soft hint, not a hard cap. Claude gets a running countdown across the agentic loop and paces its thinking, tool calls, and output against it, but it may occasionally exceed the budget if interrupting mid-action would be more disruptive than finishing.
The real hard ceiling on any single response is still max_tokens, which truncates output at that point regardless of what task_budget says. The two are independent: task_budget spans the whole multi-request loop, max_tokens caps one request, and neither has to be below the other. There's also a failure mode worth planning for: if you set a budget that's clearly too small for the work, Claude may decline the task, scope it down hard, or stop early with a partial result rather than attempt something it can't finish inside the number you gave it. If you see unexpected early stops after adding a budget, raise the number before you debug anything else.
Sources: Task budgets - Claude Platform Docs.
Agent SDK max_budget_usd: a real stop, checked after the fact
The Agent SDK's max_budget_usd (or maxBudgetUsd in TypeScript) is a different animal: it's a cap that actually stops the loop. When spend reaches the cap, the SDK returns a ResultMessage with subtype error_max_budget_usd instead of letting the loop continue, and the same applies to max_turns with error_max_turns.
The catch is in how that check happens. The SDK compares estimated spend against the cap after a model response arrives, because the cost figure only exists once the API returns usage data with that response. That means the response which actually pushes total spend past the cap still completes in full and still counts toward the total_cost_usd estimate — the stop happens on the next request, not mid-response. For a chatty single-turn agent this overshoot is small. For a bot that fans out subagents, it matters more: subagent spend counts toward the same cap, and once the cap is reached, spawning another subagent fails outright and any subagents still running in the background get stopped. So max_budget_usd will stop a runaway subagent tree, but it won't stop it at exactly the dollar figure you set — budget for the overshoot, not for an exact ceiling.
This enforcement behavior requires a reasonably current Claude Code release; older CLI versions bundled with the SDK may not apply these cap-enforcement rules the same way, so check your bundled CLI version if you're relying on this for a production cap.
Sources: How the agent loop works - Claude Code Docs, Track cost and usage - Claude Code Docs.
Managed Agents session budget: the one the platform enforces
Claude Managed Agents sessions carry a different kind of cap: a threshold for starting new model requests, set at session creation and enforced at public list rates by Anthropic's infrastructure. When a session's list cost reaches its budget, the session goes idle with stop_reason budget_reached. It does not terminate — its history and sandbox are preserved exactly like any other idle session, and raising or removing the budget resumes it automatically with no other action needed on your part.
There is a documented overshoot window: an admitted model request still completes if it crosses the cap, and its tool calls still run. Each thread can exceed the threshold by that response and its tool costs. Think of this control as a refusal to start additional requests, with margin reserved for work the platform already admitted. Once a session is paused at its budget, it stops accepting anything that would start new work — a plain user message gets rejected with a 400 — but it keeps accepting events that settle work already in progress, like a pending tool result or a tool confirmation, so you can still close out whatever was running when the cap hit.
Sources: Session budgets - Claude Platform Docs.
Worked example: a scheduled research bot across all three surfaces
Illustrative example. Say you're building a bot that runs a nightly research summary, sometimes spinning up two or three sub-tasks to check different sources. Which budget knob you reach for depends on how you built it.
If it's a raw Messages API loop you wrote yourself: task_budget will nudge the model to wrap up gracefully as tokens run low, but it is not your safety net. Set a conservative max_tokens per request as the real ceiling, and track total spend client-side by summing usage across your own request loop, since the API doesn't expose a remaining-budget field to check against.
If it's built on the Claude Agent SDK (a Claude Code-based headless agent): set both max_turns and max_budget_usd. Expect the run to stop one response past the cap, not exactly at it, and remember that if the bot delegates to subagents, their spend is included in the same number — size the cap with that fan-out in mind, not just the main loop's own spend.
If it's a Managed Agents session you start on a schedule: the session budget is a platform-enforced bound on new work, because the platform enforces it independently of your bot's own code. Set it, let the session pause at budget_reached if something loops, and have your monitoring alert on that stop_reason rather than assuming the run finished cleanly just because it stopped.
Sources: Task budgets - Claude Platform Docs, Track cost and usage - Claude Code Docs, How the agent loop works - Claude Code Docs, Session budgets - Claude Platform Docs.
Primary sources
Sources checked 2026-10-24. Standards and product documentation can change; follow the linked version when implementing.
- Task budgets - Claude Platform Docs — Anthropic
- How the agent loop works - Claude Code Docs — Anthropic
- Track cost and usage - Claude Code Docs — Anthropic
- Session budgets - Claude Platform Docs — Anthropic
BotBento is in development. Suggest a correction.