Keep an agent inside a budget
lobstack-spend-budget
Hold an agent, job or run inside a hard dollar budget using the per-call cost the Gateway returns, and handle the 402 when an allowance runs out. Use when building an autonomous loop, when asked to cap spend on a task, or when a Gateway call returns 402 Payment Required.
Copy the file and save it at the path below, then start a new session. Any agent that reads a skills directory will pick it up; the path shown is Claude Code's. Delete the folder to uninstall.
mkdir -p .claude/skills/lobstack-spend-budget # paste SKILL.md into .claude/skills/lobstack-spend-budget/SKILL.md
No package, no registry client, no telemetry. 142 lines of text, licensed MIT.
Frontmatter
An agent decides whether to load a skill from name and description alone — it does not read the body first. That is why the description says when to use this, not only what it is.
--- name: lobstack-spend-budget description: "Hold an agent, job or run inside a hard dollar budget using the per-call cost the Gateway returns, and handle the 402 when an allowance runs out. Use when building an autonomous loop, when asked to cap spend on a task, or when a Gateway call returns 402 Payment Required." license: MIT metadata: title: "Keep an agent inside a budget" version: 1.0.0 author: lobstack category: cost tags: [cost, budget, agents, quota] ---
SKILL.md
---name: lobstack-spend-budgetdescription: "Hold an agent, job or run inside a hard dollar budget using the per-call cost the Gateway returns, and handle the 402 when an allowance runs out. Use when building an autonomous loop, when asked to cap spend on a task, or when a Gateway call returns 402 Payment Required."license: MITmetadata: title: "Keep an agent inside a budget" version: 1.0.0 author: lobstack category: cost tags: [cost, budget, agents, quota]--- # Keep an agent inside a budget An agent loop with no spend bound is a while-loop attached to a credit card. Thefix is not an estimate before the call; it is a measurement after each one, and astop condition that trusts it. ## The pattern Measure after, not estimate before. A pre-flight estimate has to guess the outputlength, which is the term that dominates the cost and the one thing you cannotknow. The receipt is exact and it arrives in time to stop the *next* call. ```tsclass Budget { private spent = 0; private unpriced = 0; constructor(private readonly limitUsd: number) {} /** Call before every model call. */ assertHeadroom(reserveUsd: number) { if (this.spent + reserveUsd > this.limitUsd) { throw new BudgetExhausted(this.spent, this.limitUsd, this.unpriced); } } /** Call after every model call, with the receipt. */ record(costUsd: number | null) { if (costUsd === null) { // Unknown cost is not zero cost. Charge the reserve against the budget so // an unpriced model cannot run forever for free. this.unpriced += 1; this.spent += this.reserveUsd; return; } this.spent += costUsd; } private readonly reserveUsd = 0.05; // your own pessimistic per-call figure}``` Three properties make this work and each one is a bug if you drop it: 1. The check is before the call and uses a reserve, because a call you have not made yet has no cost. Set the reserve to something you would be unhappy but not ruined to spend once — the point is that the loop cannot overshoot by more than one call.2. `null` is charged, not ignored. cost_usd is null for a model the Gateway cannot price. Treating that as 0 gives an unpriced model an unlimited budget, which is precisely backwards.3. The exhaustion carries the numbers. "Budget exhausted" is not actionable; "$4.98 of $5.00 across 212 calls, 3 unpriced" is. Cap turns as well as dollars. A loop that stalls on a cheap model burns wallclock and context without ever tripping a dollar limit. ## Where you stand, before you start The quota headers ride on every response, success or failure, so a long jobcan check its own headroom without a second API call: ```x-lobstack-quota-meter: spend # spend | requests | legacyx-lobstack-quota-allowance-usd: 10.000000x-lobstack-quota-spent-usd: 4.113200x-lobstack-quota-remaining-usd: 5.886800x-lobstack-quota-resets: 2026-10-01T00:00:00.000Z``` On a request-metered plan (BYOK) the same three facts arrive asx-lobstack-quota-limit, -used and -remaining as integers, plus-credits when purchased balance remains. Read -meter first and branch;the counted headers are absent on a spend meter and vice versa, deliberately, soa client cannot read a missing header as "no allowance". ## When the allowance runs out: 402 ```json{ "error": { "message": "monthly allowance exhausted ($10.00 of $10.00 of model spend). Add a top-up or upgrade the plan, or wait for the period to reset.", "type": "quota", "code": 402, "request_id": "8f2b1e0c-4d5a-4b91-9c3e-6a7f0d2b5c41" } }``` Do not retry a 402. retry-after is present and is computed from the periodreset, so it is usually days rather than seconds. It means "this will not clear onits own before then", not "back off and try again". The resolutions are a top-up,a plan upgrade, or the period rolling over. A 429 is the other member of the quota class and is the opposite advice:that one is a rate limit, in practice the provider's, passed through with itsstatus. Back off exponentially with jitter and retry. ## Two behaviours worth knowing before you rely on them Enforcement is asymmetric. API-key callers are enforced and get a 402. Agentcredentials get the same headers and are *not* blocked. That is deliberate:switching agents to enforced would start returning 402 to machines that have beenover their allowance for weeks and working fine. So if you are building on anagent credential, the headers are advisory — your own budget check is the onlything actually stopping the loop. Errors accrue no spend. A failed round writes a ledger row with zero tokens,and a request that failed at the provider does not consume a request allowance.An outage does not eat your month. ## Structural caps beat runtime caps Two levers cost nothing to set and cannot be forgotten at a call site: - The tier ceiling on the plan. The router never exceeds it, so the worst case per call is bounded by configuration rather than by review. See lobstack-model-tier.- `max_tokens`. Output is priced several times input across the registry, so a bounded output is the single most effective per-call cap available. Set it to what the answer actually needs. And on paid plans that credit savings, 50%of verified routed savings comes back as allowance — verified meaning both modelspriced, the row not an error, on a managed key, and the baseline strictly abovethe actual cost. Do not model that as a discount; model it as the reason routingshows up somewhere the budget feels it. ## Do not - Do not estimate cost before the call and call it a budget.- Do not treat null cost as free.- Do not retry a 402.- Do not bound dollars without also bounding turns.
Read a Lobstack receipt
Read the receipt Lobstack returns on every model call — cost_usd, savings_usd, baseline_reason — and report cost from it instead of estimating. Use when a response carries x_lobstack or an x-lobstack-* header, when asked what a call or a run cost, or when a cost renders as $0.00.
lobstack-model-tierPick a model tier, not a flagship
Choose the cheapest model tier that can actually do the task instead of defaulting to a flagship, and verify the choice before spending on it. Use when selecting a model for a feature or agent, when one model dominates a bill, or when asked to cut inference cost without losing quality.
cost-aware-system-promptsWrite a cost-aware system prompt
Write or review a system prompt that does not quietly multiply the bill — bounded output, no re-sent bulk, tool schemas counted as the input tokens they are. Use when authoring or reviewing a system prompt, when cost per turn is climbing, or when adding tools to an agent.


