Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

agent-ledger

A money ledger and an escalation gate for autonomous agents. Zero dependencies — stdlib only (sqlite3), runs anywhere Python 3.9+ runs.

Why this exists

Every "AI agent that runs a business" needs the same two primitives, and almost none of the demos actually have them:

  1. A ledger it can't lie to itself in. If an agent tracks money in a variable, a prompt, or its own memory, nothing stops drift between what it believes it earned and what actually happened. Ledger stores every dollar as one row in SQLite; the balance is a SUM, never a running total the agent maintains by hand.
  2. A gate it can't open itself. An agent that can both propose a risky action and approve it in the same breath doesn't have a safety mechanism, it has a formality. gate() splits proposing from approving across two separate calls — the agent queues a Decision, a human answers it out of band, and only a later run can see the approval. One process cannot ask a question and grant its own answer.

This is the pattern underneath a real autonomous agent that has taken real money and spent real money against a real budget, extracted and genericized so it isn't tied to any one business, product, or codebase.

Use it

from ledger import Ledger, gate

book = Ledger("agent.db", budget_cents=5000_00)  # $5,000 lifetime cap

book.revenue(1999, "sold a license", source="stripe")
book.cost(300, "domain renewal")                  # raises BudgetExceeded if over cap

if gate(book, "email this list of 200 leads?", context="draft in outbox/leads.md"):
    send_the_emails()
else:
    print("waiting on a human to approve decision", book.pending_decisions())

Or from the shell, so an agent's tool-use surface is a CLI instead of raw SQL:

python3 cli.py revenue 19.99 "first sale" --source stripe
python3 cli.py cost 5 "domain renewal"
python3 cli.py status
python3 cli.py ask "post this on the company Twitter?"
python3 cli.py decisions
python3 cli.py answer 1 yes        # the human's command, not the agent's

Design choices, and why

  • Integer cents, always. Floats drift; the one number that defines whether the agent is working is not where you want rounding error.
  • A cost above budget raises, it doesn't clamp or warn. Silent degradation ("spent $5,001 of a $5,000 budget, logged a warning") is worse than a hard stop an agent has to explicitly catch and escalate around.
  • gate() keys on the exact question string, not a category. Approving "email this list of 200 leads?" once doesn't silently authorize "email this other list of 500 leads" — scope creep in an autonomous agent should require a new, explicit ask.
  • One SQLite file per agent. No server, no ORM, no migration framework — something you can sqlite3 agent.db "select * from entries" from a phone over SSH at 2am.

Run the tests

python3 -m unittest discover -s tests -v

12 tests, no network, no mocks — a temp SQLite file per test.

What this is not

Not a framework, not a scheduler, not a model wrapper. It has no opinion on which LLM you use, how you loop, or what the agent is actually for. It is the two primitives every "give an LLM agent money and autonomy" project needs and almost always builds badly, or not at all, on the first pass.

License

MIT. Use it, fork it, ship it inside something you charge for.

About

A money ledger + human-approval gate for AI agents. Small, dependency-free Python library.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages