Cost
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.
Cost · For developers · MIT
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.
# In Lobstack: Skills › Add a skill, then paste the file or drop the folder # In Claude Code: mkdir -p .claude/skills/lobstack-spend-budget # paste SKILL.md into .claude/skills/lobstack-spend-budget/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 (the BYOK plan, no longer sold) 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 paid plan's own provider keys are the exception: with the allowance spent,calls to providers the organization holds a key for still go through, becausethey spend no allowance. auto then routes only among those providers. A 429 is the other member of the quota class and is the opposite advice:that one is a rate limit — the Gateway's own (120 requests a minute per API key,error_code: "RATE_LIMITED") or the provider's, passed through with itsstatus. Back off exponentially with jitter and retry, honouring retry-after. ## Two behaviours worth knowing before you rely on them Every credential is enforced. API keys and legacy agent credentials alike geta 402 once the allowance is spent. A client tag with a monthly budget and a hardstop gets its own 402, error_code: "CLIENT_BUDGET_EXHAUSTED", once thatclient's spend reaches the budget. 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.
Cost
Read the receipt Lobstack returns on every model call — cost_usd, savings_usd, baseline_reason — and report cost from it instead of estimating.
Cost
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.
Cost
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.
Migration
Move existing OpenAI or Anthropic SDK code onto the Lobstack Gateway by changing the base URL and the key, and verify it actually routed.
Observability
Find model calls that bypass the gateway and therefore appear on no bill anyone reads, and detect the opposite fault of counting one call twice.