Skip to main content

Circuit breaker + hierarchical cost budgeting for AI agent workflows

Project description

Breakerbox

The visual agent builder that can't be hacked into — because there's nothing to hack.

No server execution · No stored keys · Codegen only

pip install breakerbox

🔗 Live site · The demo ↓ · Quickstart ↓

CI License: MIT Python 3.11+ Stars

A guarded LangGraph run tripping at $0.82 of a $0.90 budget — next hop blocked, 0 side effects fired

Prototype anywhere; ship with Breakerbox. You draw a workflow on a canvas, and it generates plain, editable LangGraph Python you download and run yourself — wrapped in guard(), a hierarchical dollar budget that stops runaway loops at a hop boundary and writes a receipt of exactly where the money went. In the bundled demo, a runaway retry loop that burns $12.63 unguarded stops at $0.82 under guard(). Three things make it different:

  1. Zero attack surface — codegen only. No endpoint ever executes your flows; no provider key is ever stored or transmitted. There's nothing on our side to compromise. (See Why no Run button?)
  2. Budget-first. The only builder where hierarchical budget escrow, trip rules, and side-effect tagging are part of the canvas itself.
  3. Code you own. The output is readable, hand-editable Python — scaffolding, not a walled garden.

Breakerbox is the product; the Python package is breakerbox (pip install breakerbox). The import, CLI, and API names are unchanged.

Contents

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 raises BudgetPaused; app.resume(checkpoint_id, extra_budget_usd=...) continues from where it stopped.
    • kill — stops, finalizes the receipt, raises BudgetKilled listing which side-effecting tools already fired (so you can compensate).
  • 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 usage field, never meters an unknown model as $0. If a call ran without max_tokens and 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

The Breakerbox builder: a graph canvas, a live Budget Tree, and guard config

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.

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/code endpoint that passed user input to exec(); 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. Set max_tokens and it stops strictly under budget.
  • Prices (prices.json, ~2000 models) are sourced from LiteLLM's community-maintained price table. Refresh them any time with breakerbox update-prices (bundled table is the offline fallback). Still spot-check the models you care about. Override per-model or set unknown_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

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

breakerbox-0.5.0.tar.gz (71.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

breakerbox-0.5.0-py3-none-any.whl (65.1 kB view details)

Uploaded Python 3

File details

Details for the file breakerbox-0.5.0.tar.gz.

File metadata

  • Download URL: breakerbox-0.5.0.tar.gz
  • Upload date:
  • Size: 71.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for breakerbox-0.5.0.tar.gz
Algorithm Hash digest
SHA256 0f918439a1e193775cd597f317710d3a73e10770f818d7870c4a3f1d95a6f46d
MD5 bcec2e4711810865218b3b64024cce18
BLAKE2b-256 0dc235506cb3daaaa025045a0804b7908d31d6b57f82adaad6af575ea189e38e

See more details on using hashes here.

Provenance

The following attestation bundles were made for breakerbox-0.5.0.tar.gz:

Publisher: publish.yml on Amitcoh1/agentbreaker

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file breakerbox-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: breakerbox-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 65.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for breakerbox-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f1998348200bc228f92e152c13b8ef52e427cb2283912dd06fe563dc64374798
MD5 46fd4526411b8473e20c2c87943bb769
BLAKE2b-256 957155ea1890a28039a9ab4944e97ba4120b08f69ba7eb4605e36dd494405cfa

See more details on using hashes here.

Provenance

The following attestation bundles were made for breakerbox-0.5.0-py3-none-any.whl:

Publisher: publish.yml on Amitcoh1/agentbreaker

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page