← deemwar engineering examples Runnable Β· Node Β· zero deps Β· free

Cap your agent's spend β€” and see exactly where the money went

Drop one wrapper around your LLM client and you get three things the raw SDK doesn't: a hard cap that actually holds under concurrency, a per-agent spend breakdown, and an early pause when a loop goes runaway.

What you get

See it do the job

node report.js

No network, zero dependencies. It runs a small fleet of named agents under a $50 cap β€” including one that slips into a runaway loop β€” and prints the answer you actually want: where the money went, whether the cap held, and that the runaway was stopped.

══════════════════════════════════════════════ SPEND REPORT ══════════════════════════════════════════════ Total spent $40.24 of $50.00 cap Cap held YES βœ“ (never crossed the ceiling) Calls 44 ran, 1 rejected at the gate ────────────────────────────────────────────── WHERE THE MONEY WENT research-agent $12.26 (8 calls) β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ ← top spender coder-agent $10.78 (5 calls) β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ runaway-loop $8.86 (21 calls) β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ planner-agent $4.63 (4 calls) β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ summarizer-agent $3.71 (6 calls) β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ ────────────────────────────────────────────── RUNAWAY PROTECTION Peak burn $40.24/min (soft limit $40.00/min) Action PAUSED at $40.24/min β€” a human decides to resume βœ“ ══════════════════════════════════════════════

Use it in your code

const { SpendGovernor } = require('./governor');

const gov = new SpendGovernor({
  hardCapUsd: 25,
  burnSoftUsdPerMin: 30,
  onBurnAlert: (info) => notifyHumans(info),      // pause-and-ask hook
});

const answer = await gov.run({
  provider: 'openai',
  source: 'research-agent',                     // who to bill -> shows in the breakdown
  worstCaseUsd: 0.05,                          // max-output-token price
  invoke: async () => {
    const resp = await openai.chat.completions.create({ /* ... */ });
    return { costUsd: priceOf(resp.usage), result: resp };  // reconcile to actual
  },
});

const spend = gov.report();  // { totalSpentUsd, capHeld, bySource, topSpender, ... }

The same gov in front of an anthropic SDK call shares one ceiling and one breakdown β€” it sits at the call boundary, above every provider.

The real problem this solves

You set a cap. It looks right. The fleet crosses it anyway, by a wide margin β€” because a cap that increments after the call is racing itself the moment work runs concurrently.

Cited as motivation. This code is not affiliated with, and makes no claim about, those projects.

How it works

1. The cap holds under concurrency β€” reserve-before / reconcile-after

The naive cap reads the cumulative total, awaits the call, then adds the cost. Between the read and the add, every in-flight worker reads the same stale total, sees headroom, and proceeds β€” N workers each pass the cap and collectively overshoot by up to N Γ— (largest call). The fix reserves the worst-case cost before dispatching, in one atomic add-and-check with no await in between, then reconciles to the real cost after.

// RESERVE (atomic, no await between read and write) β€” like Redis INCRBY.
const afterReserve = this.reserved.add(worst);
if (afterReserve > this.hardCap) {
  this.reserved.add(-worst); throw new SpendCapExceeded(...);
}
const { costUsd, result } = await invoke();   // the real call
this.reserved.add(usd(costUsd) - worst);      // RECONCILE to actual
this._charge(source, usd(costUsd));           // attribute to the source

node demo.js proves it directly: 20 concurrent workers, a $25 cap β€” the naive version overshoots to ~$78, the governor holds the ceiling.

Prod: swap the in-memory counter for Redis INCRBY on one key β€” it returns the post-increment value atomically, so reserve-check and reserve-write stay one round trip with no read-modify-write race. Every .add() β†’ one INCRBY.

2. The per-source breakdown

Every run({ source }) attributes the reconciled cost to that source, so report() tells you who spent what β€” the difference between β€œwe spent too much” and β€œthe research-agent's retry loop spent too much.”

3. Early pause on runaway burn

A cumulative-$ or per-call check is blind to a loop whose total is nowhere near the cap but whose $/minute is screaming. A sliding-window burn meter fires a β€œpause and ask” before the hard cap is approached β€” a loop bug caught in seconds instead of at the ceiling.

Adapt to prod

Get the code