New to Claude Skills? Learn how to install them →

How Budgets Work in Claude Managed Agents

How Claude Managed Agents session and deployment budgets cap spend at public list rates: max_list_cost, the budget_reached stop reason, and multiagent sharing.

August 26, 2026
Get Claude Skills
9 min read

A Claude Managed Agent can run for a long time on its own, especially once it's coordinating other agents or running unattended on a scheduled deployment. Budgets are the platform's answer to "what stops this from running up an unbounded bill": a hard, dollar-denominated spend ceiling you attach to a session or a deployment, enforced by Anthropic's own infrastructure rather than by anything your client has to watch for. This covers exactly how that cap is measured, what happens the moment it's reached, and the details worth knowing before you set one, drawn directly from Anthropic's own budgets documentation.

Setting a budget at session creation

Pass an optional budget field when you create the session:

ant beta:sessions create \
  --agent "$AGENT_ID" \
  --environment-id "$ENVIRONMENT_ID" \
  --budget '{type: limit, max_list_cost: {amount: "125", currency: USD}}' \
  --transform id --raw-output

The budget object has two fields. type is always "limit". max_list_cost is the cap itself: amount is a whole number of US cents written as a string, "125" is $1.25, and it must be greater than zero. Decimal forms like "25.00" are rejected outright. The amount is a string specifically so no float rounding is ever applied to it. currency is an uppercase ISO-4217 code, and USD is currently the only value accepted.

A budget can only be attached at creation. Trying to add one to an existing session that doesn't already have one fails with a 400 error, though a budgeted session's cap can be changed or removed at any time, covered below.

The same shape works from any SDK. In Python:

session = client.beta.sessions.create(
    agent=agent.id,
    environment_id=environment.id,
    budget={
        "type": "limit",
        "max_list_cost": {"amount": "125", "currency": "USD"},
    },
)
print(session.id, session.budget.max_list_cost.amount)  # sesn_01... 125

And in TypeScript:

const session = await client.beta.sessions.create({
  agent: agent.id,
  environment_id: environment.id,
  budget: {
    type: "limit",
    max_list_cost: { amount: "125", currency: "USD" }
  }
});
console.log(session.id, session.budget?.max_list_cost.amount); // sesn_01... 125

Every official SDK (Python, TypeScript, Go, Java, Ruby, PHP, C#) exposes the same two-field budget object; only the surrounding syntax changes. Managed Agents API requests need the managed-agents-2026-04-01 beta header, which the SDKs and the ant CLI's beta: namespace set automatically; a raw curl call has to add -H "anthropic-beta: managed-agents-2026-04-01" itself.

How list cost is measured

The platform continuously prices what a session consumes, at public list rates rather than your organisation's contracted price:

  • Model tokens, at each served model's list price
  • Web searches, at $10 per 1,000 searches
  • Session running time, at $0.08 per hour

This running total is the session's list cost, and it's what the budget compares against. If your organisation has negotiated discounts, a session still reaches its cap when the list-price total does, so your actual billed spend can land below the number you capped it at. Enforcement uses the exact, unrounded figure; the list_cost reported on the session and its events is rounded to the nearest cent, so a reported value can read up to half a cent either side of what enforcement actually used.

What happens when a session reaches its budget

The cap is checked between model requests, never mid-request. Before each new model request, the platform checks the session's consumed list cost. Once that total reaches the cap, every thread pauses before its next request, but the request that carried the total past the cap was admitted while the session was still under budget and runs to completion. That means a session capped at 50 cents can pause with a recorded list_cost of 53 cents. This is expected behaviour, not a billing error, and the overshoot is bounded to at most one model request per thread. Size your cap with that one-request margin in mind rather than treating it as an exact stopping point.

A session at its budget goes idle, with stop_reason: "budget_reached". It does not terminate. Its history and sandbox are preserved exactly like any other idle session's, and changing or removing the budget resumes it automatically with no other action needed. On the event stream, you'll see, in order:

  1. A session.thread_status_idle event with stop_reason: "budget_reached" as each thread pauses
  2. A session.usage event carrying the session's cumulative usage and list cost
  3. A session.status_idle event with stop_reason: "budget_reached"

A thread whose final request both crosses the cap and completes its turn cleanly reports end_turn on its own thread-level event, even while the session as a whole reports budget_reached. Treat the session-level stop_reason as the authoritative signal that the session paused at its budget, not any individual thread's own status.

What a budget-capped session will still accept

While paused at its cap, a session accepts only events that settle work already in progress: user.tool_confirmation, user.tool_result, user.custom_tool_result, and user.interrupt. Anything that would start new work, user.message included, is rejected with a 400 error naming that same list. An interrupt sent while every thread is already paused at the cap is accepted and silently ignored, since there's nothing new for it to stop.

Resuming a session at its budget

Change or remove the budget with a session update, and the session's paused work resumes automatically with no further client action needed.

Changing the budget requires the new max_list_cost to be strictly greater than the session's already-consumed list cost, or the update is rejected with a 400 naming exactly that condition. Because the consumed cost usually sits a fraction past the old cap when a session pauses, base your new value on the session's reported usage.list_cost, not on the old max_list_cost, and set it at least a cent above that figure since the reported number is itself rounded.

ant beta:sessions update \
  --session-id "$SESSION_ID" \
  --budget '{type: limit, max_list_cost: {amount: "500", currency: USD}}'

Removing the budget entirely sets budget to null, and the resulting session.updated event carries budget: null back. This is one-way: once you've removed a session's budget, you cannot give it a new one. If you expect to want a cap again later, change the number instead of clearing it.

Monitoring spend without waiting for the cap

The session object always carries its budget and a usage object: usage.list_cost is the consumed total the budget is checked against, and usage.active_seconds is the running time its runtime cost is priced on. Session-level active_seconds counts overlapping activity from concurrent threads only once. Thread-level retrieval responses carry their own usage too, priced per thread, but those figures are rounded independently and exclude the session's running-time cost, so they won't sum exactly to the session-level list_cost, which is the number enforcement actually uses.

The session.usage event is a full snapshot: token totals, list_cost, active_seconds, web_search_requests (priced into list cost per request), web_fetch_requests (always 0, since web fetch carries no per-request charge and isn't metered), and an echo of the current budget, or null if the session has none. One always fires immediately before the session goes idle, whatever the stop reason, so a session that hits its budget always emits a usage snapshot right before its budget_reached idle event.

Budgets in multiagent sessions

A multiagent session has exactly one budget, shared across every thread, with no per-thread caps of its own. Each thread's consumption is priced at whatever model actually serves it, so a coordinator on Opus and a specialist thread on Haiku draw against the same pool at different rates. Threads pause independently as the shared cap is approached, meaning one thread can sit paused at budget_reached while another finishes an in-flight request. Advisor consultations count against the same shared budget too, priced at the advisor model's own rates.

A pending action request outranks the budget: if one thread is waiting on requires_action while another has paused at its cap, the session as a whole reports requires_action. Answering that pending request is a settle event the budget doesn't block, regardless of whether the session is also sitting at its cap.

Budgets on deployments

A scheduled deployment accepts the same budget object when you create or update it:

{
  "budget": {
    "type": "limit",
    "max_list_cost": { "amount": "2000", "currency": "USD" }
  }
}

The key difference from a session budget: the cap is copied onto each session the deployment starts, so it bounds every individual run separately rather than the deployment's cumulative spend across all its runs. Changing a deployment's budget only affects sessions it starts afterward, not ones already running. Unlike a plain session budget, a deployment's budget isn't one-way: it can be cleared with null and set again later.

Models without a list price

A budget can only track spend the platform can actually price. Creating a budgeted session whose agent, or any agent or advisor on its multiagent roster, uses a model with no public list price is rejected outright with a 400 error. If a budgeted session's usage later comes to include such a model, the budget stops being able to measure spend: the session can still pause with budget_reached, but changing the budget from there is rejected, and removing it is the only way to resume.

Error reference

ConditionStatus
A work-starting event (user.message, for example) is sent while the session is at or over budget400
The new budget is set at or below the session's already-consumed list cost400
A budget is added to a session created without one, or re-added after removal400
amount isn't a whole number of cents, is zero or negative, or currency isn't USD400
A budgeted session references a model with no public list price400

Session budgets vs Messages API task budgets

It's worth keeping these two apart, since the names invite confusion. A Managed Agents session budget is a hard cap in US dollars, written in cents, enforced by the platform itself: the session physically stops issuing new model requests once list cost reaches it. The Messages API's task budgets are advisory and token-denominated: they're a number the model itself uses to self-regulate within a single agentic loop, with no platform-side enforcement stopping the request if the model ignores it. If you need a spend ceiling you can actually rely on rather than one the model is merely asked to respect, the session budget covered here is the one that does that.

Where to go next

Anthropic's own session budgets page is the full reference this article draws from. For the broader Managed Agents model, see Claude Managed Agents explained; for running a budgeted agent unattended, see scheduled deployments; and for coordinating several agents inside one budgeted session, see multiagent orchestration in Claude Managed Agents. The ant beta:sessions commands used throughout are covered in full in Anthropic's ant CLI. Browse the wider catalogue at getclaudeskills.com/skills or by category.

Verified 26 August 2026 directly against Anthropic's Managed Agents budgets documentation at platform.claude.com/docs/en/managed-agents/budgets, read in full.

Frequently asked questions