Skip to main content

llm-circuit-breaker

PyPI Python License: MIT

A tiny, readable circuit breaker for LLM calls. When your budget runs out, it doesn't raise an exception or let the bill run — it falls through to a free local model so your agent keeps working.

Why

Agent API costs are unpredictable: most runs cost a few cents, but a stuck loop or an unbounded retry can burn tens of dollars in minutes. Most LLM gateways solve observability (dashboards, logs) or routing (pick the cheapest/best model) — but none of the popular ones hard-stop into free local compute the moment you're about to overspend.

This library does one thing: try providers in order, and once you've hit your budget, skip straight to a local model instead of failing or overspending. No hosted proxy, no dashboard, no vendor lock-in — about 150 lines you can read in five minutes and vendor straight into your own project.

Install

pip install llm-circuit-breaker
# or, with Anthropic support:
pip install "llm-circuit-breaker[anthropic]"

Quickstart

from llm_circuit_breaker import LLMCircuitBreaker, anthropic_tier, ollama_tier

breaker = LLMCircuitBreaker(
    tiers=[
        anthropic_tier(api_key="sk-ant-...", model="claude-sonnet-4-5"),
        ollama_tier(model="gemma:2b"),  # local, free, always-on fallback
    ],
    daily_limit_usd=5.0,
    ledger_path="llm_spend.jsonl",
)

result = breaker.complete(system="You are terse.", user="2+2?")
print(result.text, result.tier_used, result.cost_usd)

Once llm_spend.jsonl shows $5 spent today, every subsequent call for the rest of the day skips Anthropic entirely and goes straight to your local Ollama model — automatically, no code change, no surprise bill.

v0.2 — streaming, async, and a cost CLI

Stream tokens as they arrive (complete_stream) — same tiers, same budget fallback, just yielded piece by piece. Built-in Anthropic / OpenAI / Ollama tiers stream natively; any tier without streaming yields its whole result once.

for chunk in breaker.complete_stream(system="You are terse.", user="Explain RAG in 2 lines"):
    print(chunk, end="", flush=True)

Async (acomplete) — keep many calls in flight at once:

import asyncio
results = asyncio.run(asyncio.gather(*[
    breaker.acomplete(system="s", user=q) for q in questions
]))

See where the money went — a budget breaker you can actually inspect:

llm-cb cost                 # today / total / per-tier, straight from the ledger
llm-cb cost --ledger path   # point at a different ledger, or --json for raw
LLM spend  (llm_spend.jsonl)
   today : $2.3100
   total : $45.8700   (1240 calls)
   by tier:
     anthropic:claude-sonnet-4-5      980 calls   $44.2000
     ollama:gemma:2b                  260 calls   $0.0000

How it decides

  1. Check today's + all-time spend against your limits (a plain JSONL ledger file — human-readable, no database).
  2. Under budget: try each tier in order, return the first success.
  3. Over budget: skip every paid tier and try only the tiers marked is_local=True.
  4. If every attempted tier fails (or the budget is blown with no local tier configured), raise a clear exception instead of failing silently.

Built-in tiers

anthropic_tier, openai_tier, gemini_tier, openrouter_tier, and ollama_tier (local, via Ollama) — or write your own in about 5 lines; a Tier is just a name and a (system, user, max_tokens) -> (text, cost_usd) function:

from llm_circuit_breaker import Tier

def _call(system, user, max_tokens):
    text = my_provider_sdk.chat(system, user, max_tokens)
    return text, my_own_cost_estimate

my_tier = Tier(name="my-provider", call=_call, is_local=False)

What this is not

Not a hosted gateway, not a dashboard, not a replacement for LiteLLM or Portkey if you need enterprise routing, guardrails, or a proxy server in front of a team's traffic. This is the opposite trade-off: minimal, in-process, one job — for solo builders and small agent projects who want a hard stop before overspend without standing up another service.

Pricing table

pricing.py ships an approximate per-model $/1M-token table used only to estimate spend for the budget check. Prices change and vary by region/tier; override PRICING["your-model"] = {"input": ..., "output": ...} for accuracy, or return your own cost from a custom tier.

Development

pip install -e ".[dev,anthropic]"
pytest

License

MIT

Download files

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

Source Distribution

llm_circuit_breaker-0.2.1.tar.gz (15.6 kB view details)

Uploaded Source

Built Distribution

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

llm_circuit_breaker-0.2.1-py3-none-any.whl (12.8 kB view details)

Uploaded Python 3

File details

Details for the file llm_circuit_breaker-0.2.1.tar.gz.

File metadata

  • Download URL: llm_circuit_breaker-0.2.1.tar.gz
  • Upload date:
  • Size: 15.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.11.9

File hashes

Hashes for llm_circuit_breaker-0.2.1.tar.gz
Algorithm Hash digest
SHA256 559b40aabcdec8e2d929c9cbdb34b3d3bb93bc0f24ac327cff25fa2a2199e000
MD5 d6ef03751e6fb1dbf86c654fbb123193
BLAKE2b-256 860b4d69a1f439fe0c0f07c4fb406e07d76efbb64ef67aa003a766250bcb7acc

See more details on using hashes here.

File details

Details for the file llm_circuit_breaker-0.2.1-py3-none-any.whl.

File metadata

File hashes

Hashes for llm_circuit_breaker-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 621292665cdc4834ded1df809e4e8a356dffbd430b33856a9f7965e1a34935b1
MD5 1c72f351808d5d4ea5b5262ba49efbb0
BLAKE2b-256 bf0554642b3d2f4117261924aa5cbd0d96a64649995466c151df32b6afdc3da1

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 files

0.2.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page