Budgets: cap what a session can spend
An unattended agent has no natural stopping point on cost. A research task with web search can drift into another hundred fetches. A coding loop can retry a flaky test until morning. Without a ceiling you find out from the invoice.
A session budget is an enforced spend cap on a single session. You set a maximum list cost when you create the session. The platform tracks the token cost of every thread in that session at public list prices, and when the running total reaches the cap the session goes idle with the stop reason budget_reached. Its files, tool state, and conversation stay intact. Raise the cap and the work continues from where it stopped.
This notebook walks through:
- setting a
budgetonsessions.create - reading
usage.list_costand thesession.usagesnapshot the stream delivers as the turn ends - the
budget_reachedstop and what a paused session keeps - raising, lowering, and removing the cap with
sessions.update
1. Set up the client
Budgets ride the standard managed-agents-2026-04-01 beta header. The budget parameter and the cost fields on session.usage need anthropic>=0.121.0.
2. Build an agent with room to overspend
The agent for this walkthrough writes a competitive landscape brief. It has web search and web fetch, and nothing in its prompt bounds how many sources it reads. That open-endedness is what a budget is for.
market_analyst: agent_staging_014U3BWzuiSNDwfzubN38hnz v1
3. Create the session with a budget
The budget field on sessions.create sets the cap:
A few properties worth knowing before you pick a number:
amountis an integer string in the currency's minor units:"50"is fifty cents,"2500"is $25.00. It stays a string, and fractional cents are rejected, so no float rounding is ever applied.USDis the only accepted currency, and every cost amount the API returns (usage.list_costincluded) uses the same encoding.- The cap counts model token cost at public list price, summed across every thread in the session, including subagent threads. List price applies regardless of any negotiated discount, so the cap fires at or before your actual charge, and you can reproduce the number from
session.usageplus the public rate card. - Every model the session can run needs a public list price. If one does not, create fails with
model_not_budgetable. - Omit
budgetand the session is uncapped. A budget can only be attached at creation: a session created without one can never gain one later, so decide up front.
The cap here is ten cents, deliberately low so the stop shows up in a couple of minutes. The usd helper renders minor-unit amounts as dollars for every printout below.
sesn_staging_01ELJgA2vqTR6EmjX8viwHZi running budget: $0.10
4. Watch spend accumulate
Alongside the usual agent.message and agent.tool_use events, the stream delivers a session.usage snapshot each time the session settles into idle. It holds the cumulative token counts, the tracked list_cost, and the configured budget, so the moment the turn ends you know what it cost without a second call to sessions.retrieve.
The loop exits on session.status_idle. With a budget in play there are two stop reasons that end the turn: end_turn when the agent finishes and budget_reached when the cap fires first.
[repl] {'script': '\nlet queries = [\n "Datadog positioning observability platform 202
[web_search] {'query': 'Datadog positioning observability platform 2025'}
[web_search] {'query': 'New Relic observability platform positioning 2025'}
[web_search] {'query': 'Dynatrace observability platform AI 2025'}
[web_search] {'query': 'Splunk Cisco observability 2025'}
[web_search] {'query': 'Grafana Labs observability platform 2025 announcement'}
[web_search] {'query': 'Elastic observability 2025'}
[web_search] {'query': 'Honeycomb observability 2025'}
[web_search] {'query': 'Chronosphere observability 2025 acquisition'}
[web_search] {'query': 'Datadog acquisition 2024 2025'}
[web_search] {'query': 'Grafana Labs acquisition 2024 2025'}
usage: $0.12 of $0.10
[idle] stop_reason=budget_reached5. Inspect the paused session
budget_reached is a pause, not a failure. The session sits in idle, its usage reflects everything spent so far, and the container still holds whatever the agent wrote before the cap. Nothing needs to be rerun.
The cap is enforced between model requests, so the recorded list_cost can land slightly past max_list_cost: the request that crosses the line finishes, then the session pauses. Size your cap with that one-request margin in mind.
status: idle list cost: $0.12 cap: $0.10 tokens: in 471 out 606 active secs: 13.7
The event log shows how far the agent got: the tool calls it made and, if it had begun narrating, its last message. An agent deep in research may have written nothing yet when the cap fires, so treat the message as optional.
tool calls before the cap: 11 (no agent.message yet: the agent was still gathering sources when the cap fired)
6. Raise the cap and let it finish
sessions.update accepts the same budget shape. Raising max_list_cost above the consumed cost lifts the pause and the session resumes the interrupted turn on its own, from the state it stopped in.
Lowering the cap to at or below what the session already spent is rejected with a 400: max_list_cost must stay above the consumed list cost, so an update can never wedge a session against its own history. The first call demonstrates the rejection, the second raises the cap for real. No follow-up message is needed after the raise; the session moves back to running and picks up the interrupted turn.
lower rejected: Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error', 'message': "`budget.max_list_cost` must be greater than the session's consumed list cost"}, 'request_id': 'req_staging_011CdiPi8iPJKWdiuurZuDkB'}
cap raised to $5.00[resumed] [repl] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [repl] [web_fetch] [web_fetch] [web_fetch] [web_fetch] [web_fetch] [web_fetch] [web_fetch] [web_fetch] [repl] [web_fetch] [web_fetch] [web_fetch] [web_fetch] [web_fetch] [web_fetch] [web_fetch] [web_fetch] [repl] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [repl] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [repl] [web_search] [web_search] [repl] [web_search] [web_search] [repl] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [repl] [web_search] [web_search] [web_search] [web_search] [web_search] [repl] [web_search] [web_search] [bash] [repl] [web_search] [repl] [web_search] [repl] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [repl] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [web_search] [repl] [web_fetch] [web_fetch] [web_fetch] [web_fetch] [repl] [web_fetch] [web_fetch] [web_fetch] [write] [write] [bash] [idle] stop_reason=end_turn final list cost: $1.83 of cap $5.00
7. Read the brief
The agent picked the task back up with its context intact and finished the write. Pull the file it produced from the event log.
# Competitive Landscape Brief: Observability Platform Market *Scope: commercial platforms for metrics, logs, traces, and related telemetry (APM, infrastructure monitoring, log management, digital experience monitoring) used by engineering, IT operations, and SRE teams. Window for "recent moves": roughly the last twelve months of vendor activity found in primary sources (mid‑2025 through mid‑2026).* ## 1. Market shape Observability has consolidated into a market with a handful of large, broad "full platform" vendors (Datadog, Splunk/Cisco, Dynatrace, New Relic, Elastic, Grafana Labs), a tier of cost‑ and scale‑focused challengers (Chronosphere, Coralogix, Honeycomb, SolarWinds, LogicMonitor, Sumo Logic), hyperscaler-native tooling bundled into the cloud platforms (AWS CloudWatch, Azure Monitor, Google Cloud Observability), and an open standard — OpenTelemetry — that now sits underneath almost every vendor's ingestion layer and was elevated to CNCF "graduated" status, cementing it as the de facto instrumentation standard (CNCF, announcement). Gartner's 2025 Magic Quadrant for Observability Platforms evaluated 20 vendors (AWS, Apica, BMC Helix, Chronosphere, Coralogix, Datadog, Dynatrace, Elastic, Grafana Labs, Honeycomb, IBM, ITRS, LogicMonitor, Microsoft, New Relic, Oracle, ScienceLogic, SolarWinds, Splunk, Sumo Logic), naming Datadog, Splunk, Dynatrace, New Relic, Elastic, Grafana Labs, Chronosphere, and IBM as Leaders (Gartner, 7 July 2025; corroborated by Datadog, Splunk ...
8. Remove the budget
Passing budget=None on update clears the cap, so the session is uncapped from that point on. Omitting budget entirely leaves the current cap in place. Those are two different requests: None is an explicit removal, absence is a preserve.
Removal is permanent for the same reason attachment is create-only: once a session has no budget, it can't gain one. Raise and lower the cap as often as you like, but treat removing it as a one-way door.
budget: None
9. Clean up
archived
Where budgets fit
A budget is a per-session control. It bounds one run, not an org, a workspace, or a day of traffic, so it composes with the spend limits you already set at those levels rather than replacing them. Reach for it whenever a session runs without a human watching: cron-driven deployments, webhook-triggered agents, long multiagent jobs where the coordinator's fan-out is data-dependent.
For fleets you are not streaming, subscribe to the session.budget_reached webhook instead of holding a connection open. It fires once when a session hits its cap, and the payload names the session so a supervisor process can decide whether to raise the cap or let the session stay paused. The webhook pattern is covered in CMA_operate_in_production.ipynb(opens in new tab).