Runtime spend enforcement for AI agents — trip, degrade, and stop, not just alert.
A runaway retry loop that burns $12.63 unguarded stops at $0.82.
In-process — no proxy, no gateway, no stored keys.
pip install breakerbox
🔗 Live site · The demo ↓ · Quickstart ↓
Wrap the compiled LangGraph app you already have in guard() and it enforces a spend policy
between every step. The one-line dollar cap is the hook — a 33-star side project reinvented that in
~400 lines. The part you can't build in an afternoon is everything else. In the
bundled demo, a retry loop that burns $12.63 unguarded stops at $0.82.
Enforcement lives inside your process — no proxy, no gateway, no server of ours ever sees your
keys or your data. What teams don't self-build:
- Enforce, don't just alert — and degrade before you die. A provable worst-case cost ceiling before the run; semantic loop detection that catches the runaway your stop-condition misses; hierarchical budget escrow; a degradation ladder that swaps to a cheaper model and narrows tools at 80% before a graceful stop at 100%; and shadow mode to see what would trip before you enforce anything. Plus a security suite that scans the flow for embedded creds and audits MCP configs — findings you can prove, not just observe.
- In-process — nothing to compromise. No proxy or gateway executes your flows; no provider key is ever stored or transmitted. (See Why no Run button?)
- Code you own. The output is readable, hand-editable Python — scaffolding, not a walled garden. Prefer to start visually? A drag-and-drop builder writes this guarded Python for you.
Breakerbox is the product; the Python package is
breakerbox(pip install breakerbox). The import, CLI, and API names are unchanged.
Contents
- Capabilities at a glance
- Quickstart
- The demo
- What it actually does
- Build it visually
- Gate cost in CI
- More than a budget: cost governance
- Why no Run button?
- How it compares
- Notes & limitations
- Cloud dashboard (optional)
- Roadmap
- Contributing
- License
Capabilities at a glance
The whole surface on one screen — full catalog with maturity labels → CAPABILITIES.md.
One enforcement core, three ways to attach it, and a static half that never runs your agent.
| Area | What you get |
|---|---|
Enforce at runtime — guard(...) |
Hard budget_usd · hierarchical sub_budgets · max_hops / max_depth / ttl_seconds · velocity_usd_per_min burn-rate · 8 trip reasons |
| Catch runaways | detect_loops=True — semantic repeat detection, no LLM |
| Degrade, don't die | ladder — swap to a cheaper model + narrow tools at 80%, graceful stop at 100% |
| Trip actions | on_trip="pause" → checkpoint + resume(), or "kill" → lists side-effects that fired |
| Try before you enforce | shadow=True → logs what would trip; breakerbox shadow-report → "$ prevented" |
| Explain every stop | TripDecision (stable JSON) + single-file HTML receipt (per-hop cost, trip reason, blast radius) |
| Prove cost before running | breakerbox ceiling (or UNBOUNDED) · lock --check · diff --fail-on-increase · policy · egress |
| Security suite (0.11.0) | breakerbox dow (denial-of-wallet) · flow (Langflow creds) · mcp (server posture) · baseline (CI gate) · capability_lock |
| Attach it 3 ways | guard() (LangGraph) · BreakerboxMiddleware (LangChain 1.x) · breakerbox claudecode init (Claude Code) |
| Observe | live spend line · alerts · otel spans · tags for per-team attribution |
| Build | breakerbox init / validate / build · a drag-and-drop visual builder that emits the same guarded Python |
| Optional cloud | Live runs dashboard · remote pause/kill · shareable receipts — codegen/observe only, no keys stored |
Quickstart
pip install breakerbox
Wrap the compiled LangGraph app you already have — the call site doesn't change:
from breakerbox import guard
app = guard(
my_langgraph_app,
budget_usd=5.00, # hard ceiling for the whole workflow DAG
max_hops=50, # total model/tool steps across all branches
ttl_seconds=600, # wall-clock limit
velocity_usd_per_min=2.0, # trip if the burn rate spikes
on_trip="pause", # "pause" | "kill"
)
result = app.invoke(inputs) # the same call you already make
Every model and tool dispatch inside the graph — including sub-agents and subgraphs — inherits one real-dollar budget. When a limit trips, the workflow stops at the next hop boundary (never mid-call) and drops a shareable HTML receipt. No proxy, no Docker, no gateway to run: enforcement lives inside your process, so there's no direct-call bypass.
Prefer to start on the canvas? Open the builder, draw the graph, and let it write this for you:
cd cloud/dashboard && npm install && npm run dev # http://localhost:3000/builder
The demo
A broken retry loop that never drops its context, so each hop costs more than the last
(examples/runaway_demo) — no API keys required:
==============================================================
UNGUARDED runaway : ran 60 hops, spent $12.63
GUARDED : killed early, spent $0.82 (budget $0.90)
AVERTED : $11.81
==============================================================
It stops strictly under budget — because the model declares a real max_tokens, the
reserve estimate is a true upper bound, so the call that would cross the line is blocked
before it runs. Every run also writes a self-contained report.html:
────────────────────────────────────────────────────────
breakerbox receipt · killed (budget)
stopped at $0.8157 budget $0.9000 hops 13
projected (naive linear extrapolation, likely an underestimate): $3.13
────────────────────────────────────────────────────────
(See sample_receipt.html for the full HTML.)
What it actually does
- Hierarchical budget escrow. Not a flat session counter. A parent sub-allocates budget
to child agents; a child can never spend beyond its allocation; a parent's remaining is
budget − Σ(child allocations) − own spend. Accounting is reserve → execute → reconcile (a credit-card hold), so parallel branches can't race past the ceiling. Concurrency-safe and property-tested (Σ spent + Σ reserved ≤ root budget, always). - Graceful trip actions.
pause— checkpoints via LangGraph's native checkpointer and raisesBudgetPaused;app.resume(checkpoint_id, extra_budget_usd=...)continues from where it stopped.kill— stops, finalizes the receipt, raisesBudgetKilledlisting which side-effecting tools already fired (so you can compensate).
- Runaway protection (opt-in). Catch a loop before the dollar budget pays for it.
detect_loops=Truetrips when a node keeps re-firing with near-identical input — a no-LLM fuzzy-repeat detector (character-shingle similarity), so nudging an argument doesn't evade it.live=Truestreams a$spent / $budgetcounter to your terminal as each hop reconciles, so you watch it climb in real time instead of finding out from the invoice. - Self-metering. Counts input tokens locally (tiktoken) and meters streamed output
chunks, then reconciles against the provider's reported usage and flags discrepancies —
never trusts a single
usagefield, never meters an unknown model as$0. If a call ran withoutmax_tokensand the cap landed one hop late, the receipt flags that hop explicitly. - The receipt. Terminal summary + single-file
report.html(inline CSS/SVG, no JS, no external assets) + JSON. Leads with the indisputable number — stopped at $Y, budget $Z — with the projection as clearly-labelled fine print.
Build it visually
cloud/dashboard/app/builder is a drag-and-drop canvas
(model / tool / router / start / end nodes) with a live Budget Tree — root budget →
per-node allocations → unallocated remainder. Over-allocate and it turns red and blocks
export. Hit Generate and you get the guarded Python above, ready to copy or download.
Everything runs in your browser; the spec → Python codegen is shared with the breakerbox build spec.json CLI and locked to it by golden-fixture tests (Python and TS, enforced in CI).
Cost forecast (before you run). The canvas forecasts a run's cost while you design it — a p50–p95 band per node and for the whole graph, with a what-if loop slider and a per-node model swap, all computed in the browser with no API calls. It's a labelled estimate and advisory-only: it never changes the generated Python. Most builders show cost after a run; this shows it first.
AI suggest (bring your own key). Any model/tool/router node has an optional "Suggest code" helper: describe the step, and it drafts a Python body for you to copy in. It calls the model directly from your browser with your own API key — the key is stored only in your browser and sent only to the provider, never to a Breakerbox server (there is no server in this path). Anthropic supports browser-direct calls; OpenAI blocks browser CORS, so for OpenAI you point the base URL at your own CORS-enabled proxy. The suggestion is copy-paste scaffolding — it's never written into the saved graph, so codegen stays deterministic.
Gate cost in CI
Make your agent's cost a unit test. The provable cost ceiling — every reachable hop at full
max_tokens, a loop charged max_hops × the costliest hop — is computed with zero API calls,
so it runs in CI and fails a pull request that pushes a graph past your budget:
# .github/workflows/cost-ceiling.yml
- uses: actions/checkout@v4
- uses: Amitcoh1/agentbreaker@main # pin a released tag (e.g. @v0.6.0) for reproducible CI
with:
spec: "specs/*.spec.json"
max: "2.00" # red PR if any spec's ceiling exceeds $2.00 (or is unbounded)
Same check locally or in any pipeline — breakerbox ceiling specs/*.spec.json --max 2.00 exits 1
when over-limit or unbounded. See CI budget gate.
Needs
breakerbox >= 0.6.0(the release that shipsbreakerbox ceiling).
More than a budget: cost governance
Because cost is static and deterministic, Breakerbox can do things an observe-after-the-fact dashboard or a gateway/proxy structurally can't. Everything here is local — no server, no stored keys, no LLM in the loop.
Prove & pin the cost
breakerbox ceiling— a provable worst-case dollar bound, computed with zero API calls, and baked into the header of the generated Python so the proof travels with the code.breakerbox lock/--check— pin the price table + each spec's ceiling tobreakerbox.lock; CI fails on drift.package-lock.json, for dollars.breakerbox diff— the ceiling delta between two versions;--fail-on-increasereddens a PR that quietly raises your ceiling from $2 to $9.
Catch runaways before the bill
detect_loops— trips on near-identical repeats before the budget (no LLM; paraphrase-resistant).live=True— a real-time$spent / $budgetcounter in your terminal, so you watch it climb instead of finding out from the invoice.max_depth— cap sub-agent nesting so a run can't spawn its way around its own cap.alerts— a graduated warn rail (50/80/95%) before the hard trip.
Govern & attribute
breakerbox.yaml— policy-as-code the build refuses to violate (max ceiling,max_hops, banned models, no destructive tools). A precondition of the artifact, not removable server config.breakerbox egress— certify exactly which network endpoints the generated code can reach.tags={"team": ...}— per-team/customer/env chargeback on every receipt.- The receipt is an audit artifact — who/what/how-much/when, plus a blast-radius compensation checklist of side-effecting tools that fired before a trip.
otel=True— GenAI-semantic-convention spans into Phoenix / Arize / Langfuse.
Why no Run button?
Server-side flow builders that run your graphs and hold your provider keys have been a repeated remote-code-execution target. In Langflow (the category leader — 150k+ GitHub stars, backed by DataStax, an IBM company) the pattern is well documented and public:
- CVE-2025-3248 (CVSS 9.8) — unauthenticated RCE via the
/api/v1/validate/codeendpoint that passed user input toexec(); on CISA's KEV (added 2025-05-05), exploited by the Flodrix botnet. - CVE-2025-34291 (CVSS 9.4 v4.0 / 8.8 v3.1) — a CORS/CSRF account-takeover chain (a victim visits a malicious page) that exfiltrates the API keys and tokens stored in a workspace; on CISA KEV (added 2026-05-21). Reportedly used by the MuddyWater APT for initial access (Ctrl-Alt-Intel via The Hacker News; not confirmed by CISA).
- CVE-2026-33017 (CVSS 9.8) — unauthenticated RCE via the public flow-build endpoint
(
/api/v1/build_public_tmp/…); on CISA KEV (added 2026-03-25), exploited within ~20 hours of disclosure (Sysdig) and separately used to drop Monero/XMRig cryptominers (Trend Micro). - CVE-2026-5027 (CVSS 8.8) — path-traversal arbitrary file write via
/api/v2/files, escalatable to RCE; ~7,000 instances exposed (Censys, incl. historical scan data) with active exploitation observed (VulnCheck). Not on CISA KEV.
This isn't a knock on Langflow's product — it's an architectural fact: a server that runs your flows and holds your keys is a high-value target. Breakerbox removes the target. The canvas only ever produces a Python string you run yourself, and your API keys live in your own environment — never in a dashboard, database, or edge function. There's no endpoint to exploit because no endpoint executes anything. That's the trade: you give up one-click cloud runs, and in exchange there is nothing to breach. Prototype in a tool like Langflow if you like; ship the production-safe version here.
How it compares (facts only)
| Langflow | LiteLLM budgets | Breakerbox | |
|---|---|---|---|
| Visual graph building | ✅ rich | — | ✅ budget-first |
| Server executes your flows | ✅ (attack surface) | n/a | ❌ by design |
| Stores your provider keys | ✅ | ✅ (proxy) | ❌ never |
| Hierarchical per-agent dollar escrow | — | — (flat, per-key) | ✅ |
| Graceful pause/resume at a hop boundary | — | — (hard error) | ✅ |
| Catches a runaway run under the org ceiling | — | — (never fires) | ✅ |
| Output is plain, editable Python | partial (export) | n/a | ✅ core promise |
LiteLLM/Portkey/Kong-style gateways solve a different layer (org-wide per-key spend) and compose fine alongside this — the gateway caps the org, Breakerbox governs one workflow's internal structure.
Behind a gateway (LiteLLM / Portkey): point your model at the gateway's base URL and wrap the
compiled app in guard(). Metering is a LangChain callback, not a network hook, so it composes
with any OpenAI-compatible proxy with no extra wiring:
model = ChatOpenAI(model="openai/gpt-4o", base_url="http://localhost:4000", api_key="sk-litellm-…")
app = guard(compiled_app, budget_usd=5.00) # gateway routes + holds the key; guard budgets the run
The catch most gateway users miss: a key limit has to sit high enough not to block real work, so a single runaway run can burn $180 while still under a $500 ceiling — the key never fires until the damage is already account-wide, and then it 429s everyone. Breakerbox trips that one run at $2, at a hop boundary. A key limit is the fuse box for the building; Breakerbox is the breaker on this circuit.
vs LiteLLM / vs Langflow, in one line: a gateway like LiteLLM guards the key — one flat ceiling, blind to a single run's internal structure. A builder like Langflow runs your flow — server-side, holding your keys. Breakerbox guards the workflow and runs nothing: a hierarchical per-agent budget baked into plain Python you own. Prototype with either; ship the guarded version here.
Every claim above maps to a public, verifiable fact.
Notes & limitations (read before you rely on it)
on_trip="pause"needs a checkpointer. Compile your graph with one (.compile(checkpointer=MemorySaver()));guard()raises if it's missing.- The overshoot rule: the guard never interrupts a call mid-flight. If your model has
no
max_tokens, the reserve estimate can under-count and the cap is enforced one hop late (overshoot bounded by a single call) — the receipt flags that hop. Setmax_tokensand it stops strictly under budget. - Prices (
prices.json, ~2000 models) are sourced from LiteLLM's community-maintained price table. Refresh them any time withbreakerbox update-prices(bundled table is the offline fallback). Still spot-check the models you care about. Override per-model or setunknown_model="default_rate"to meter unknown models at a conservative rate instead of failing.
Cloud dashboard (optional)
→ Open the dashboard — watch runs stream live, and sign in to keep runs private to your account.
Everything above works with zero cloud. If you want a shared, live view of runs, point the guard at a Supabase-backed dashboard:
app = guard(my_app, budget_usd=5.00, report_to="https://YOUR_REF.functions.supabase.co/ingest")
Events stream to the dashboard as the run executes (best-effort and non-blocking — a cloud outage never affects the run); each run gets a shareable, unlisted URL with a live timeline.
To keep runs private to your account, sign in to the dashboard, create a key under Settings → Your ingest key, and set it where your agents run:
export BREAKERBOX_INGEST_KEY="abk_…" # from the dashboard; runs become private to you
Without a personal key the legacy shared key still works and runs stay public (shareable link).
Deploy runbook and code in cloud/ (Supabase + Next.js on Vercel).
Roadmap
Where this is headed — horizons, what we will and won't build — is public in
ROADMAP.md. The codegen-only, no-stored-keys architecture is a permanent
constraint, not a phase.
Contributing
Issues and PRs welcome. Good first stops: the open issues
and the ROADMAP.md horizons. To work on it locally:
pip install -e ".[dev]"
pytest -q # pricing, ledger (+ hypothesis), tripwire, meter, guard, report, sink
ruff check .
The dashboard (cloud/dashboard) has its own checks: npm run typecheck, npm run lint,
npm test (codegen + price-table parity), npm run build. CI runs both suites on every push.
License
Metadata
Release files for breakerbox 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| breakerbox-1.0.0.tar.gz | 125.5 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| breakerbox-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 231.6 kB
Release files / breakerbox-1.0.0.tar.gz
| Download URL | breakerbox-1.0.0.tar.gz |
|---|---|
| Size | 125.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5ed5f3edbdf3515ef05a4485f49bb6c6b4a31af52c8af20092cbdd306d379af4
|
|
BLAKE2b-256 checksum How to use checksums |
1bb6275897d437e4e9012a4673319085126eb38c60e155942ae9aff98752ead6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.
Transparency logRelease files / breakerbox-1.0.0-py3-none-any.whl
| Download URL | breakerbox-1.0.0-py3-none-any.whl |
|---|---|
| Size | 106.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
52af4cf6dfb405fee2d810c11c98f33695cd96f2bb7a1fcee5237bded3ac59cf
|
|
BLAKE2b-256 checksum How to use checksums |
4dd97f83b3d9cc75aa1816f765ef47a74c2dda1911258539479375a0c94505fe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.
Transparency logSecurity for breakerbox 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for breakerbox-1.0.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.