An offline-first budget guard for operators running several LLM agents. It turns
provider usage exports into deterministic daily, monthly, per-project, and
per-request decisions: continue, review_usage, or block_new_llm_calls.
It does not intercept provider traffic or guarantee that a remote API stops billing. It produces a machine-readable gate that your scheduler, proxy, or CI job can enforce. The core requires no network and no LLM. An optional local Claude, Kimi, or Codex CLI can explain incidents after the hard rules run.
Who it is for
- operators running autonomous jobs with shared provider accounts;
- teams needing project-level limits before receiving a monthly invoice;
- self-hosters who want auditable policy decisions without a billing SaaS.
Quick start
cp policy.example.json policy.json
cp sample_usage.jsonl usage.jsonl
python3 agent.py --policy policy.json --ledger usage.jsonl check
python3 test_agent.py
Ingest an export without duplicating known request IDs:
python3 agent.py --ledger usage.jsonl ingest provider-export.jsonl
Use the exit status as a gate: 0 means ok or warn; 2 means a hard stop.
python3 agent.py --policy policy.json check || systemctl stop my-llm-worker
Architecture
provider exports / proxy logs
|
v
validate + deduplicate
|
v
append-only JSONL
|
v
OBSERVE -> ORIENT -> DECIDE -> ACT
| | | |
totals policy severity JSON gate
|
+---- optional BYO-LLM incident explanation
Event contract
Each JSONL row must contain timestamp, project, provider, model, and
cost_usd. Token counts and request_id are optional. Timezones are mandatory.
Rows with duplicate non-empty request IDs are ignored during ingestion.
Included operational paths
check: evaluate once and writelatest-report.json;watch: reevaluate continuously for systemd;report --llm: add a non-authoritative incident explanation;backend: show whether an optional supported CLI is available.
See CUSTOMIZE.md for adapters, SPEC.md for exact semantics, and
CHECKLIST.md for deployment.