How to Put a Hard Spending Cap on AI Agents (OpenAI, Claude, Bedrock, OpenRouter) Before an Overnight Run Costs You Thousands
Which AI API limits actually stop spending and which only send an email, as of October 2026: OpenAI project limits, Claude Console spend limits, Claude Code's budget flag, OpenRouter and LiteLLM key caps, and why AWS and Google budgets aren't caps.

Every few weeks someone posts the same story on Reddit or Hacker News. An agent ran overnight, got stuck retrying something, and the morning brought a bill in the thousands. Nobody had set a cap, or they had set something that looked like a cap and only sent an email.
Dashboards use "alert", "budget" and "limit" almost interchangeably, but only some of these refuse the next request. On 19 October 2026 I read each provider's own documentation and sorted the controls into the ones that stop spending and the ones that just tell you about it. I haven't triggered every limit myself, so where I quote an error code it's the one the provider documents.
The short answer
| Where | Control | Stops requests? | What your code sees |
|---|---|---|---|
| OpenAI API | Organization or project monthly spend limit with "Enforce a hard limit" on | Yes | HTTP 429, organization_spend_limit_exceeded or project_spend_limit_exceeded |
| OpenAI API | Spend alert | No | An email |
| Claude API (Console) | Your own spend limit on the Billing page | Yes | HTTP 400, "You have reached your specified API usage limits" |
| Claude API (Console) | Workspace spend limit | Yes, for that workspace | HTTP 400 for normal workspaces; the Claude Code workspace can return 429 |
| Claude Code (headless) | --max-budget-usd | Yes, that run only | The run stops |
| OpenRouter | Per-key credit limit | Yes, that key only | HTTP 402 |
| LiteLLM proxy | max_budget on a virtual key | Yes, that key only | Request fails once the budget is crossed |
| AWS Bedrock | AWS Budgets and budget actions | Not reliably | Alerts can arrive hours late |
| Google Cloud | Budgets | No | Budgets don't cap usage by default |
Even the controls marked "yes" lag a little, so treat them as a ceiling you might slightly overshoot, not an exact figure. If you can, cap the key or project the agent uses rather than the whole account. An account-wide limit will also switch off your production app the moment the agent burns through it.
Related reading: Why Your Claude Usage Runs Out So Fast (October 2026), and Ten Habits That Make It Last · How to Stop ChatGPT, Claude, Gemini and Copilot Training on Your Data (and Check It Stayed Off)
OpenAI
OpenAI's spend-limits guide describes two controls that look alike and behave differently:
- A spend alert only notifies you. In the guide's words, "Spend alerts do not enforce a cap."
- A hard spend limit makes affected requests fail with a 429.
To set one for a project (do this for the project your agent's key belongs to):
- Open the platform settings and choose the project.
- Go to Limits, then Spend, and select Edit spend limit.
- Enter a Monthly spend limit.
- Turn on Enforce a hard limit and save.
There's an organization-wide version too, under Organization limits.
Enforcement isn't instant: OpenAI says "recorded spend can slightly exceed the configured amount", so set the number a bit below what would actually hurt. It's also monthly. Once you hit it, the project stays blocked until someone raises the limit or the next cycle starts, which is worth agreeing on with your team before it happens at 2 a.m.
The detail that bites agent code is the status code. A 429 is also what you get for an ordinary rate limit, and most retry logic answers a 429 by waiting and trying again. Check error.code instead: organization_spend_limit_exceeded and project_spend_limit_exceeded mean the cap fired, and credit_balance_exhausted means prepaid credit ran out. None of those will clear on a retry.
Claude API (the Claude Console)
Anthropic has two layers:
- Tier caps you don't choose. Each usage tier has a monthly spend cap: $500 on Start, $1,000 on Build, $200,000 on Scale; Custom has none. When you reach it, the API returns a 429 with
error_codeenforced_spend_limit_reachedand pauses until 00:00 UTC on the first of the next month. That 429 has noretry-afterheader, so automatic SDK retries simply keep failing. - A limit you choose. On the Billing page (platform.claude.com/settings/billing), under Spend limits, click Set limit or Adjust limit. It can't be higher than your tier's cap. When you hit it, requests return HTTP 400
invalid_request_error, with a message starting "You have reached your specified API usage limits".
For per-agent budgets, use workspaces: open the Workspaces page, pick a workspace and click Spend limits. The default workspace can't have a limit, so an agent needs a workspace of its own. Organization limits still apply on top, and when a workspace limit is what stopped you, the message says "specified workspace API usage limits".
Claude Code
How you cap Claude Code depends on how you sign in.
- With a Console account (API billing): Claude Code creates a workspace called "Claude Code" automatically. Set a spend limit on that workspace and it caps all Claude Code usage in the organization. Anthropic's docs say it's the only workspace that supports per-user monthly spend limits. Its requests over the limit can come back as a 429 with a
retry-afterheader rather than the 400 above. - For a single unattended run: use print mode with
--max-budget-usd, which stops the run when its estimated cost reaches the amount you set. The docs note the figure counts list-price token cost, including the 1.1× data-residency rate where that applies. It's an estimate, not your invoice. - On a Pro or Max subscription: usage inside your plan isn't billed per token, so the risk comes from usage credits, the pay-as-you-go top-up past your plan limit. In claude.ai Settings → Usage → Usage credits you can turn them off or set a monthly spend limit. Inside Claude Code,
/usageshows your usage-credit spend against that limit, or "Unlimited" if you never set one. If it says Unlimited, fix that first.
Caps aside, Anthropic's own cost guide points at long sessions. Every request re-sends the whole conversation, so a session left open all day costs more per message than a fresh one, and scheduled tasks keep sending that full context while you're away. Clearing between unrelated tasks is the cheapest fix there is.
OpenRouter
OpenRouter lets you put a credit limit on each API key, separate from your account balance. When a key reaches it, requests return HTTP 402, not 429, until you raise the limit or it resets. Its GET /api/v1/key endpoint returns limit, limit_reset and limit_remaining, so your agent can check its own remaining budget before starting a long job. Give every agent its own key with a small limit, and keep your main key for things you watch.
LiteLLM (self-hosted gateway)
If you run several providers behind a LiteLLM proxy, set max_budget when you create a virtual key with /key/generate, and add budget_duration (for example "30d") so it resets. Without a duration it never resets, and without max_budget (the default is null) the key has no cap at all.
Budgets can sit at several levels: the key itself, its user, its team and, on the enterprise edition, its organization. For a key created with a team_id, LiteLLM's docs say the team budget is used instead of the owner's personal budget, so set the cap where the key actually draws from. Virtual keys and budgets live in the proxy's Postgres database, so you need one connected. If you run more than one proxy instance without Redis, each instance enforces budgets on its own, which means the real ceiling can be a multiple of the number you typed.
AWS Bedrock and Google Cloud: budgets aren't caps
- AWS Budgets is a delayed alerting system. Budget data updates a few times a day, so a fast loop can run for hours before the threshold even registers. Budget actions can apply a deny policy when a threshold is crossed, which helps, but it fires on that same delayed data and doesn't guarantee spending stops at the number. For Bedrock agents, put a gateway cap (LiteLLM, or Anthropic's own gateway if you use Claude through Bedrock) in front of the calls.
- Google Cloud budgets send alerts but don't stop usage by default. Stopping automatically means building it yourself, for example with a function that disables billing on the project when a budget message arrives. That takes the whole project offline.
Guards inside your own code
A provider cap is the last line. Most runaway bills I've read about would have been stopped earlier by something simple in the agent itself:
- A maximum number of steps per run. Count model calls in your loop and stop at a number you'd be embarrassed to exceed.
- A wall-clock timeout per run. If a job normally finishes in 10 minutes, kill it at 40.
- No blind retries on spend errors. Treat OpenAI's spend codes, Anthropic's
enforced_spend_limit_reached, its 400 "usage limits" message and OpenRouter's 402 as "stop and alert", not "back off and retry". - Prepaid credit with auto-reload off for side projects. Your worst case becomes the balance.
- One key per agent or project, so a leaked or looping key can't drain the rest.
- Log cost per run. Every provider returns token counts. Multiply and store them, so you notice a run that costs ten times the usual before the invoice does.
If a key leaks
- Revoke the key in the provider's dashboard straight away, then create a new one. Don't just edit the old one.
- Check usage by key and by hour to see when it started.
- Search your repositories, CI logs and any public places the key might have been pasted.
- Contact the provider's support with the timeline. Being able to show the hour usage started helps.
- Add a project or key-level hard cap before you put the new key anywhere.
Last checked: 19 October 2026. Menus and error codes change; check the provider's page before you build alerting around a specific code.
Sources
- OpenAI: Spend limits
- OpenAI: Troubleshooting 429 errors
- Anthropic: Rate limits and spend limits
- Anthropic: Workspaces
- Claude Code: Manage costs effectively
- OpenRouter: Limits
- LiteLLM: Budgets and rate limits
- LiteLLM: What is stored in the DB
- AWS: Configuring budget actions
- Google Cloud: Create, edit, or delete budgets
John Le · ML engineer in Hanoi · tests AI tools so you don't have to. Spotted an outdated price? Tell us and we will update it.


