# How to set a daily spending limit for an AI agent's API key Set it on the key's row at withruntime.com/account/keys, or make the key with `runtime keys create --daily-limit 25`. **On Runtime, the server enforces the limit per key, over any 24 hours. So an agent that loops cannot spend past it, and no key can raise its own limit.** A $25 limit buys a lot of agent time at Runtime's rates. That is 800 hours of a waiting 2 vCPU, 4 GiB sandbox at $0.03125 an hour. Or it is about 313 fully busy hours at $0.08 (rates checked 25 October 2026, [pricing](/docs/pricing)). There is no plan fee on top. ## Set the limit Two ways, both through a person: - **On the website.** At [API keys](https://withruntime.com/account/keys), set a limit when you create a key, or later from its row. Change or remove it there too. - **From a terminal, for a new key.** `runtime keys create` makes it at once with the full-access key of an owner or admin saved on your machine; without one, or with `--browser`, a person approves it in the browser, with the limit on the approval page: ```bash no-run runtime keys create --name support-agent --daily-limit 25 # dollars runtime keys create --name ci --daily-limit 10 | gh secret set RUNTIME_API_KEY ``` The key is printed once, alone, on standard output. So it pipes into a secret store ([keys for CI](/docs/cli#keys-for-ci)). The member who made the key, or an owner or admin, can change its limit later. They can do that only on the website. ## What the limit counts | Counted | Detail | | ---------------- | --------------------------------------------------------------- | | Settled charges | Everything the key's sandboxes cost in the window | | About to be used | What a running sandbox will use, counted before it settles | | Parked storage | Paused sandboxes, charged while they are kept | | Window | Any 24 hours. Room returns as older spending leaves the window. | ## What happens at the limit A create, wake, extension or renewal that would pass the limit fails with HTTP 402 `spending_limit_reached`. Nothing is charged. The SDKs do not retry it. - **Running sandboxes** keep the time they are already funded for. One whose next renewal would pass the limit pauses or stops at the end of that time, as its `onLeaseEnd` says; one that stops has the `stopReason` `spending_limit`. - **Paused sandboxes** keep costing storage. If that storage cannot be paid for, you are notified, and after 30 days unpaid (seven in an account that never bought credit or saved a card) it is deleted. Set the limit above what the agent's paused sandboxes cost in a day ([security](/docs/security#read-only-keys-and-daily-limits)). ## Let the agent see what is left Any key can read its own access and limit. No key can change them. An agent that checks before a large job can stop cleanly, instead of failing halfway. ```ts check import { Runtime, RuntimeError } from "withruntime"; const runtime = new Runtime(); const { daily } = await runtime.limits.get(); console.log(daily.limitMicros, daily.usedMicros, daily.remainingMicros); try { await using sbx = await runtime.sandboxes.create(); await sbx.exec("python3 job.py"); } catch (error) { if (error instanceof RuntimeError && error.code === "spending_limit_reached") { console.log("Daily limit reached; ask a person to raise it.", error.hint); } else throw error; } ``` ```python check from withruntime import Runtime, RuntimeError with Runtime() as runtime: daily = runtime.limits.get()["daily"] print(daily["limitMicros"], daily["usedMicros"], daily["remainingMicros"]) try: with runtime.sandboxes.create() as sbx: sbx.exec("python3 job.py") except RuntimeError as error: if error.code != "spending_limit_reached": raise print("Daily limit reached; ask a person to raise it.", error.hint) ``` ```bash no-run runtime limits ``` Amounts are in microdollars, as strings. `"25000000"` is $25. `limitMicros` is null when no limit is set. `runtime.limits` needs withruntime 0.3.1 or later. Over HTTP, use `GET /v1/limits`. An agent on MCP calls `runtime_account` with `limits`. ## Mistakes to avoid - **Making replacements in a loop.** A refused create costs nothing, but a loop that retries it wastes the agent's turn: the limit counts the last 24 hours, so the answer stays the same until spending ages out. - **Asking the agent to lift it.** No key can raise, remove or set a limit, and a key it makes never has more than it has. That is the point: tell the person the agent works for. - **One key for every agent.** A limit is per key. Give each agent or application its own key, so a limit and the [audit log](/docs/teams#audit-log) both say which one spent. - **A limit below parked storage.** An agent that keeps many paused sandboxes needs room for their storage every day, or they are deleted once the unpaid days run out. ## Other controls A daily limit bounds a key. To bound one sandbox, use `maxTotalCostMicros` ([cap a sandbox's cost](/how-to/cap-the-cost-of-a-sandbox)). To give a dashboard a key that cannot spend at all, use a [read-only key](/how-to/create-a-read-only-key). For an agent's full setup, see [Claude Code in a sandbox](/integrations/claude-code). Facts on this page were checked on 26 October 2026.