Metadata-Version: 2.4
Name: burnmap
Version: 0.2.0
Summary: Budget enforcement for LLM agents
License-Expression: MIT
Project-URL: Homepage, https://burnmap.dev
Project-URL: Repository, https://github.com/remonpinto/burnmap
Keywords: llm,agents,budget,anthropic,openai,cost
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.20.0; extra == "anthropic"
Provides-Extra: openai
Requires-Dist: openai>=1.0.0; extra == "openai"
Provides-Extra: all
Requires-Dist: anthropic>=0.20.0; extra == "all"
Requires-Dist: openai>=1.0.0; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
Dynamic: license-file

# Burnmap

Budget enforcement for LLM agents. One line of code, no proxy, hard-stop before costs spiral.

## Install

```bash
pip install burnmap
# with SDK support
pip install "burnmap[anthropic]"
pip install "burnmap[openai]"
pip install "burnmap[all]"
```

## Quickstart

```python
import burnmap

with burnmap.run("auth-refactor", budget=2.00) as r:
    response = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=1024,
        messages=[{"role": "user", "content": "Refactor the auth module"}],
    )

print(r.report.summary())
# Run 'auth-refactor' completed in 1.23s. 1 call(s), $0.0842 of $2.00 budget...
```

If spend hits the budget limit, `BudgetExceededError` is raised before the next call executes:

```python
from burnmap import BudgetExceededError

try:
    with burnmap.run("agent-loop", budget=0.50) as r:
        while True:
            client.messages.create(...)   # raises BudgetExceededError at the limit
except BudgetExceededError as e:
    print(f"Stopped at ${e.spent_so_far:.4f} after {e.call_count} calls")
```

Per-user budget enforcement for multi-tenant products:

```python
with burnmap.run("summarise", budget=0.10, user_id="usr_123"):
    client.messages.create(...)
```

## CLI — wrap any agent command

```bash
burnmap wrap --budget 5.00 --job "auth-refactor" -- claude --dangerously-skip-permissions "refactor auth"
burnmap wrap --budget 10.00 -- python my_agent.py
```

Burnmap scans the subprocess output for API usage JSON, accumulates cost in real time, and kills the process if spend exceeds `--budget`. Prints a cost summary on exit.

## What it does

- **Hard-stop budget enforcement** — raises `BudgetExceededError` before the call that would push spend over the limit.
- **Run-level attribution** — groups all LLM calls inside one `with` block, tracks cost per run rather than per API call.
- **Per-call breakdown** — `r.report.cost_by_call` shows each call's model, tokens, cost, and running total.
- **Loop detection** — kills runaway agents that are hammering the API or accumulating context geometrically.
- **Async-native** — works with `async with` and is safe across `asyncio.gather` and `asyncio.create_task`.

## What it doesn't do

- No proxy. API calls go directly from your code to Anthropic/OpenAI. No latency added, no single point of failure, API keys stay local.
- No dashboard (yet). Cost data lives in `r.report` — export it however you like.
- Does not intercept calls made outside a `burnmap.run()` block.

## License

MIT — see [LICENSE](LICENSE).
