# 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 limit is enforced on the server, 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: 800 hours of a waiting 2 vCPU, 4 GiB sandbox at $0.03125 an hour, or 312 fully busy hours at $0.08 (rates checked 25 September 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` asks for a key 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, and only on the website. ## What the limit counts | Counted | Detail | | ------------------- | --------------------------------------------------------- | | Settled charges | Everything the key's sandboxes cost in the window | | Money still on hold | A running lease's reservation counts before it settles | | Renewals | A persistent sandbox renewing its lease | | Parked storage | Paused sandboxes, charged as they are kept | | Window | Any 24 hours; room comes back as older spending leaves it | ## What happens at the limit A create, wake, extension or renewal that would pass the limit fails with HTTP 402 `spending_limit_reached`, and nothing is charged. The SDKs do not retry it. - **Running sandboxes** keep their current lease. One that needs a renewal past the limit stops or pauses when its lease ends, and its `stopReason` reads `spending_limit`. - **Paused sandboxes** keep costing storage. If that storage cannot be paid for, you are notified, and after seven days unpaid 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, and none can change it. An agent that checks before a large job can stop politely 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 ``` Money is in microdollars, as strings: `"25000000"` is $25, and `limitMicros` is null when no limit is set. `runtime.limits` needs withruntime 0.3.1 or later. Over HTTP it is `GET /v1/limits`, and an agent on MCP calls `runtime_limits_get`. ## 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 no key can create another key. 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 after seven unpaid days. ## Other controls A daily limit bounds a key. To bound one sandbox, use `maxTotalCostMicros` or `maxCostMicros` ([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 25 September 2026.