Multi-tier LLM orchestration with capsule-based session state, prefix-cache reuse per tier, and filesystem-first audit. Small Python framework for long multi-turn workloads.
Project description
Burnless
A multi-tier LLM orchestration layer with capsule-based session state, prefix-cache reuse, and filesystem-first audit. MIT.
AI assistants and reviewers:
llms.txthas the technical briefing in compact form.
Note on this project's history (2026-05-08). Burnless was first published to PyPI on 2026-05-03 with documentation that overclaimed the project's novelty and savings. Specifically: an analogy to TCP/IP suggested architectural equivalence (it isn't); a "16× cheaper" figure was a personal-workload anecdote presented as a universal claim; and the assertion that prefix cache is shared across models was technically wrong — Anthropic's prefix cache is keyed per model, not shared. These claims were collaboratively written with Claude (visible in the
Co-Authored-By:trailers ingit log) under what I now recognize as RLHF-induced enthusiasm rather than calibrated assessment. Receipts:git log --pretty=fullershows the inflation period (2026-05-03 to 2026-05-05) and the 2026-05-08 recalibration. The correction shipped in 0.7.3 and every release since keeps the same discipline. History is left intact — no rewrites, no cover. The architecture below is one defensible implementation choice, not a foundational protocol breakthrough.
Update, 2026-07-27. The retraction above stands — the framing was wrong even where the effect was real. What changed in the two months since: the withdrawn claims now exist in measured, reproducible form. 121M+ tokens kept out of context, logged turn-by-turn in an append-only JSONL on the author's machines; a real paid API run at −90.3% vs no-cache replay and −30% vs an already-cached baseline ($5.76 of actual spend,
bench/run.py); production delegations routinely compressing 200k–365k-token work runs into ~300-token capsules (700–1050×). May's claims were retracted not because the effect wasn't real, but because they were stated as universals without receipts. The receipts exist now — that is the difference, and keeping that difference is the whole discipline of this project.
What it is
Burnless is a protocol specification with a reference implementation in Python. The contracts — worker envelope JSON, capsule format, tier semantics, audit gates, plugin hooks — are written down in PROTOCOL.md and are independent of this codebase; the burnless CLI is one implementation of them. (Protocol in the LSP sense — a specified interface others can implement — not a claim of TCP/IP-scale foundations; see the note above.) A second independent implementation and a conformance suite are the v1.0 bar, not a shipped fact.
The reference implementation sits between your AI assistant (or your own code) and the model providers. It does three concrete things:
- Routes tasks to a model tier (
gold/silver/bronze). Tiers are commands, not hardcoded models — any provider via any CLI. They start from a shipped default and are changed per-chat or globally viaburnless menu/burnless models set(projects don't carry their own tier map). - Stores session state as compact capsules on disk (
.burnless/) instead of replaying the full transcript on every turn, and keeps the system-prompt prefix byte-identical so the provider's prompt cache stays warm. - Audits worker outputs against the filesystem (QTP-A): if a worker says it wrote a file, Burnless checks the file exists and the size is consistent before reporting success.
That is the whole product. Everything else in this README is configuration, examples, and honest measurements from the author's own usage.
What it is not
- Not a novel theoretical breakthrough. Tier routing, prompt caching, and state summarization all exist in other tools (LangGraph, AutoGen, CrewAI, Aider, etc.). Burnless's contribution is a particular implementation choice — capsules + filesystem audit + plugin protocol — packaged as a small CLI.
- Not a magic cost eliminator. It does not change the asymptotic shape of every workload. Whether it saves you money depends on session length, model mix, and how aggressively your existing setup already caches.
- Not benchmarked against every alternative. The numbers below are measured against a specific naive baseline (full-history replay, no cache) and against the author's own personal workload. Treat them as "what I observed", not as universal claims.
Why you might want it anyway
For long multi-turn sessions where you'd otherwise replay a growing transcript every turn, capsules + a hot prefix cache materially reduce input tokens. In the author's day-to-day, this produced a noticeable cut in API spend over a multi-day workload. Your mileage will vary — see the Numbers section below for what was actually measured and under what conditions.
If your sessions are short (N ≤ 3 turns), one-shot scripts, or already managed by a framework that handles cache and state for you, Burnless will not help. It is built for the long-session, multi-tier-orchestration case.
Structural context — why this exists
Per-token API billing creates a real incentive pressure. Longer responses = more API revenue. This is not a hidden trick — it is how the product is priced, on the public pricing page of every major provider (Anthropic, OpenAI, Google). Subscription channels (Claude Code monthly plan, ChatGPT Plus, Gemini Advanced) flip the incentive: there, excessive token consumption reduces the provider's margin, so behavior between API and subscription channels can differ for the same model.
This is not an accusation of conscious malice. RLHF — the training method behind every modern frontier LLM — optimizes for human-rated preferences. Humans tend to rate longer, more confident, more agreeable responses higher. Sycophancy, verbosity, and overconfident hallucination emerge from that optimization landscape as side effects, even when no individual at the lab explicitly decides "make the model verbose to bill more." The structural pressure exists regardless of intent.
Burnless does not fix the industry. It gives you a layer where:
- token cost is auditable per call (capsule trail + exec_log)
- verbose chat history doesn't quietly accumulate in the transcript sent back to the provider
- a cheaper tier handles work that doesn't require the expensive tier
- output format is constrained by your system prompt and routing rules, not by the model's default verbosity reflex
Operating against the structural drift is a stated design goal, not a coincidence of cost reduction. The honest framing of this project: it is a small open tool that demonstrates frontier LLMs can be used without paying the verbosity tax, with reproducible measurements. The contribution is not a breakthrough algorithm or an industry-changing protocol — it is honest counter-pressure with code attached.
Numbers (measured, with caveats)
Two reproducible runs. Read them as observations under specific conditions, not as universal performance claims.
Real API run — 10 turns against claude-opus-4-7, 23k-token system prefix, no mocks, raw response.usage (actual spend: $5.76):
| Scenario | Cost | vs A |
|---|---|---|
| A — No cache, full replay | $4.66 | — |
| B — Cache + full replay | $0.65 | −86.0% |
| C — Burnless capsules | $0.45 | −90.3% |
Reproduce: ANTHROPIC_API_KEY=... python bench/run.py --turns 10 (~$6).
The honest read: against a no-cache naive baseline, the savings are dramatic. Against a sensible cached-replay baseline (B), Burnless added a further ~30% reduction at this session length. That second number is the more relevant one if your existing setup already uses prompt caching — which most modern setups do.
Monte Carlo simulation — 30 runs × 100 turns × 4 scenarios. Per-turn input/output sampled Uniform(2k, 10k) / Uniform(200, 1500), capsule compression Uniform(0.20, 0.30). No API calls:
| Scenario | Mean | vs A1 |
|---|---|---|
| A1 — Pure Opus, full replay | $532.61 | — |
| A2 — Pure Sonnet, full replay | $105.42 | −80.2% |
| B — Free-pick Opus/Sonnet | $328.74 | −38.3% |
| Z — Burnless | $33.35 | −93.7% |
Reproduce: python bench/v2.py --runs 30 --turns 100 --seed 42. Zero cost, no key.
The simulation makes assumptions about token distributions, switch frequency, and cache invalidation behavior — these will not match every workload. The result is internally consistent with the real-API run above; treat it as supporting evidence, not as standalone proof.
Personal workload note (anecdote, not benchmark). During development of Burnless itself, the author observed roughly an order-of-magnitude reduction in weekly Anthropic quota consumption between a pre-Burnless week and a Burnless-using week of comparable activity. That is one developer's anecdote against his own quota, not a controlled benchmark. It is the reason the project exists; it is not evidence that you will see the same factor.
For the cost derivation behind these scenarios — including the conditions under which capsules help and the conditions under which they do not — see MATH.md.
Architecture
Pattern note. Inspired by TCP/IP's separation of application from network — not the same scale of abstraction (TCP/IP defines internet infrastructure; Burnless is a small Python framework), but the same kind of design move: separate state management from cognitive execution so each layer can evolve independently. The individual components (caching, tier routing, capsules, prompt compression) all exist in other tools; the contribution here is the way they are wired together.
Three pieces:
- Maestro. A thin orchestrator (any model you configure as
gold) that holds the plan, decides what to delegate, and reasons over results. Its conversation history holds capsules — short summaries of past turns — instead of the raw transcript. - Worker. A subprocess invocation of any CLI (
claude,codex,gemini,ollama, etc.) that receives one task plus the cached system prefix. It executes, returns a structured JSON result, and exits. Raw output goes to.burnless/logs/dNNN.log. - Capsule. A short on-disk record of a turn (
.burnless/maestro_session.jsonl). The Maestro reads capsules; full logs stay on disk and are read on demand.
The session file is append-only, so the cached prefix stays bit-identical between turns and the provider's prefix cache continues to hit. On Anthropic's API the prefix is marked cache_control: {"type": "ephemeral", "ttl": "1h"}. On Claude Code's monthly plan, the cache is managed automatically by the CLI.
Audit loop
Workers return structured JSON with status and kind:
kind: execution— the worker changed, checked, or ran something. Burnless checks the declared evidence (commands, file paths, sizes) against the filesystem before marking the result OK.kind: thought— the worker produced planning, design, or analysis. Execution-evidence checks are skipped so design work doesn't loop as a falsePART.
This is the QTP-A pattern. It catches "I wrote the file" when no file exists, and "I ran the test" when no test output is in the log.
Plugin protocol (v0.7)
Eight hooks for intercepting the orchestration pipeline (HTTP / stdio, 5s timeout, fail-open):
pre_worker_prompt,post_worker_outputsession_state_read,audit_result_receivedpre_brain_prompt,post_brain_outputworker_invoke_override,pre_audit_call
Manifests live at ~/.burnless/plugins/NAME.json. Reference: PLUGIN_PROTOCOL.md.
Install
pip install burnless
cd <your-project>
burnless setup # detects CLIs/keys, writes .burnless/config.yaml
burnless do --tier silver "your first task"
Python 3.10+. Tiers map to whatever CLIs you configure — mix providers freely.
On a minimal Debian or Ubuntu image, python3-venv is not installed by default —
apt install python3-venv first if you want burnless in a virtualenv.
For OpenAI/Codex:
codex --version # confirm Codex on PATH
burnless setup # auto-detects Codex, suggests it for tiers
From source:
git clone https://github.com/rudekwydra/burnless.git
cd burnless && pip install -e .
To remove from a project: rm -rf .burnless/.
Configuration
Burnless ships a clean default tier map (gold=opus, silver=sonnet, bronze=haiku) so a fresh install works with no config. You change tiers through commands — projects do not carry their own tier definitions; the map cascades built-in default → global (~/.config/burnless/config.yaml) → per-chat override:
burnless menu # tier→worker table + provider status (interactive picker on a TTY; --view to force the plain table)
burnless do --silver ollama:gemma4-e4b "task" # override one tier for this run only
burnless models set silver ollama:gemma4-e4b --default # persist as the new global default
provider:model is the worker spec (anthropic:sonnet, codex:gpt-5.2, ollama:<model>, gemini:<model>). A bare model defaults to anthropic. burnless menu (and /burnless menu inside a session) marks each tier (default) / (global) / (session) so you always know where its worker came from.
Under the hood a worker is just a command — any model, any provider. The persisted global config (~/.config/burnless/config.yaml, written by models set --default) looks like:
agents:
gold: { command: "claude --model claude-sonnet-4-6 -p" } # Maestro
silver: { command: "codex exec --sandbox workspace-write" }
bronze: { command: "ollama run qwen2.5-coder" }
Mix freely:
agents:
gold: { command: "openai api chat.completions.create -m gpt-4o" }
silver: { command: "claude --model claude-haiku-4-5 -p" }
bronze: { command: "ollama run llama3.2" }
The Maestro itself can run on a non-Anthropic provider:
maestro_adapter: openai # anthropic | openai | gemini | openrouter (brain_adapter still accepted for back-compat)
| Provider | Env var | Default model |
|---|---|---|
| anthropic | ANTHROPIC_API_KEY |
claude-sonnet-4-6 |
| openai | OPENAI_API_KEY |
gpt-4o |
| gemini | GEMINI_API_KEY / GOOGLE_API_KEY |
gemini-2.5-pro |
| openrouter | OPENROUTER_API_KEY |
anthropic/claude-sonnet-4 |
Install the SDK extra for non-Anthropic providers (pip install 'burnless[brain-openai]' etc). Reference: docs/MAESTRO_ADAPTERS.md.
Per-tier permissions
Each tier can be locked to specific tools by the worker CLI itself (not just hinted in the prompt):
agents:
bronze: { command: "claude --model claude-haiku-4-5 -p --allowedTools Read,Bash" }
Under the tier escalation policy (routing.escalation_policy: block, or BURNLESS_HARDCORE=1), the Maestro cannot self-upgrade above the tier the keyword router resolved — manual override requires explicit --force. Use burnless route "<spec>" --tier <t> --explain to see the scored decision (natural/requested/effective tier, signals, policy source, next command).
Compression
Capsule compression is fixed and faithful — preserve everything (~150 chars/field, ≤12 list items), dedupe only. No mode knob.
Workers are always epistemically pure — they receive a clean task without the Maestro's debate history.
Compression layers
| Layer | What it does | Cost | When it fires |
|---|---|---|---|
| 1. Deterministic minifier | Strips filler phrases, normalizes whitespace | Zero | Every turn |
| 2. Cache-emergent encoder | Small model compresses semantically; abbreviations emerge per session | ~$0.001/turn | L2 encoder path |
| 3. Capsule envelope | Wraps compressed text with session key (RAM-only by default) | Zero | After Layer 2 |
| 4. Base64 pack | ASCII-portable capsule format | Zero | After Layer 3 |
Capsule format v2: burnless:v2:<session_id>:<key_id>:<base64_ciphertext>. The chat decodes a capsule
semantically — the assistant expands it back to natural language from the Maestro's decoder_hint.
CLI
burnless do --tier silver "<task>" # delegate + run in one step
burnless plan "<objective>" # write plan to .burnless/maestro.md
burnless delegate "<task>" # create delegation, route to a tier
burnless run d001 # execute (ephemeral progress panel by default)
burnless run d001 --progress minimal # spinner + idle label
burnless run d001 --progress full # raw streaming output
burnless status # current plan + open delegations
burnless metrics # token counter + audit ledger
burnless ask "<prompt>" # ask a question, route to configured tier
State lives entirely under .burnless/ in your project. No hosted backend.
Use --output PATH to write the response to disk, preserving context across turns.
The stdout prints a pointer (file path + first line). Auto-name files in a directory with --output-dir.
Using Burnless from your AI assistant
Any chat-based assistant can use Burnless as its execution boundary:
"Use
burnless delegateandburnless runinstead of running shell commands directly. The operating manual is atdocs/USING_BURNLESS_FROM_YOUR_LLM.md."
The assistant plans and delegates; Workers execute via your configured tiers. Tool access is governed by allowedTools in .burnless/config.yaml, not by the assistant's discretion.
Honest caveat: the protocol layer (capsules, delegation, plugins, audit) is stable. The interactive chat shell was removed in v0.9 — Burnless is driven from your assistant or plain shell via
do/delegate/run. Rough edges live mostly in the host-integration glue (hooks, slash commands); that's where contributions are most welcome.
Engagement modes — off / on
Whether Burnless drives your assistant is a per-session choice. The reference integration for Claude Code ships a /burnless slash command (.claude/commands/burnless.md) plus a UserPromptSubmit hook that resolves the active mode and shapes the assistant's behavior. Two modes:
| Mode | What the assistant does | Use when |
|---|---|---|
| off | Raw chat. The hook is a no-op, zero Burnless involvement. | You just want the model. |
| on | The assistant is the Maestro: it compresses intent and only delegates — it does not write code, edit disk, or plan deeply itself. Everything goes through burnless do; it reads only the compact capsule, never the raw log. Plus rolling memory: epoch hooks keep context O(N) and survive /clear, so long sessions stay cheap. |
Any real work — this is the one efficient mode. |
Switch at any time:
/burnless off # raw chat
/burnless on # Maestro + rolling memory (the efficient mode)
/burnless menu # show the tier→worker config table + provider status
/burnless # show the menu + current mode
The choice is stored per session (~/.burnless/state/session-<id>.mode) and takes effect from the next turn. Precedence: the env var BURNLESS_OFF=1 overrides everything → per-session file → a global ~/.burnless/state/global.on → default off. To start raw from the very first token in a terminal, launch with claude-off [haiku|opus] instead of toggling mid-session.
Legacy note: earlier versions had
partnerandrollovermodes. They are gone —partner(pre-rolling-memory) androllover(now the default behavior ofon) both coerce toon.
What ships vs. what you wire: the
/burnlessslash command ships in.claude/commands/. The mode-resolvingUserPromptSubmithook is Claude-Code-specific glue — seedocs/USING_BURNLESS_FROM_YOUR_LLM.mdfor the hook and how to register it in yoursettings.json. Without the hook installed,off/onare a documented convention your assistant can follow manually, not an enforced switch. Burnless does not require any of this —burnless do/delegate/runwork from any assistant or plain shell.
Plugin example: local compression filter
examples/plugins/burnless-compress is a reference plugin that compresses verbose user prompts before they reach the cloud LLM. Runs locally via Ollama, costs nothing, fail-open if the server is down.
In the author's measurements on Portuguese-language samples with qwen2.5:7b-instruct, the plugin produces ~2.5× compression. See bench/COMPRESSION_FINDINGS.md for method and per-model comparison. Other languages and content types may compress more or less.
Comparison
| LangChain / CrewAI / AutoGen | Burnless | |
|---|---|---|
| Primary focus | Agent connectivity and orchestration | Long-session cost reduction + audit |
| Memory model | Sliding window or RAG | Capsules on disk, append-only session |
| Dependencies | Heavy libraries, many abstractions | Small CLI (pip install burnless) |
| Hosting | Local or cloud | Self-hosted; no hosted backend |
| Provider lock-in | Varies | None — any CLI, any provider |
| Worker audit | Generally none | Filesystem-first audit (QTP-A) |
Burnless and these frameworks are not directly competing in every dimension. You can wrap a LangChain agent as a Worker. The Maestro→Worker pattern is compatible with any existing framework.
When Burnless is not the right tool: single-turn queries, one-off scripts, or workflows where a managed cloud platform is the explicit requirement.
Burnless Cloud (separate, optional)
The protocol is MIT and stays MIT. If a hosted variant ships, it would add operations features (managed compression, drift monitoring, multi-tenant glossary, key custody, audit logs, SSO/RBAC, retention) — none of which belong in the open source layer.
Pricing model under consideration: revenue share on measured token savings (3% of saved spend, no minimum, no commitment). This is a stated direction, not a live product.
Status
What works today:
- ✅ Workers via any CLI (
claude,codex,gemini,ollama, etc.) configured per tier - ✅ Routing, capsules, exec_log, three compression layers, shared system prompt
- ✅ Audit loop with
execution/thoughttyping - ✅ Heartbeat UI (live phase + idle state, doesn't pollute persisted summary)
- ✅ Reference benchmark (Anthropic SDK, because their cache pricing is published and easy to reproduce)
- ✅ PyPI release:
pip install burnless - ✅ Maestro adapters: Anthropic / OpenAI / Gemini / OpenRouter (
maestro_adapterin config)
In progress:
- ⚠️ Keepalive mode: idle-TTL-gap mitigation (>1h idle blows the cache)
- ⚠️ Lazy context loading: Workers start pure, context loaded per-task
- ⚠️ Privacy modes:
redact,audit,opaque,burnkeyare planned, not yet implemented
Contributing
Issues and PRs welcome. Priority areas: OpenAI/Gemini Maestro adapter, LangChain memory adapter, keepalive daemon, lazy context loading, chat-shell UX.
Testing map + unification plan: see docs/testing.md.
If you contest the numbers in this README, run python bench/v2.py --runs 100 --turns 100 --seed 42 (zero cost) or bench/run.py with your own API key. Open an issue with the JSON from bench/results/ and the workload parameters. That is the only argument worth having.
License
MIT. See LICENSE.
Repo: github.com/rudekwydra/burnless
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file burnless-0.9.6.tar.gz.
File metadata
- Download URL: burnless-0.9.6.tar.gz
- Upload date:
- Size: 2.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5edbcb3a3c51f98829217757cbe4206f3c8c09ef1944752663408e20393eb09a
|
|
| MD5 |
db8c069984929bc1755a7ded446c441f
|
|
| BLAKE2b-256 |
48b3f10802cccff9831cf6e45bd380ff29400c50b72698050e5a5f164c7d6e73
|
File details
Details for the file burnless-0.9.6-py3-none-any.whl.
File metadata
- Download URL: burnless-0.9.6-py3-none-any.whl
- Upload date:
- Size: 422.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34ea91a2aeb41d8b3784b9e648afc4f65fa63dfd2066476139ddde81049985ef
|
|
| MD5 |
5617953e397cfc9e987045c4ccc7b592
|
|
| BLAKE2b-256 |
ee67f3263d8635a31203c0ebec1c2156268ad592d75b497a5179008d7382f50a
|