agent-money-primitives
Money primitives, fee curves, and reference-bound paywalls for AI agents that handle real balances.
44 tests. Zero dependencies. Pure stdlib Python.
What this is
Three modules, extracted from a live autonomous agent that tracked real funds on Solana for a month:
money.py—Decimalprimitives that make it hard to be quietly wrongfee_curve.py— escalating-liability arithmetic, pure functionspaywall.py— pay-per-call payment verification that cannot be replayed
Most agent finance code is prompt-shaped: "track your expenses carefully." That fails silently. This is the code shape.
Install
pip install agent-money-primitives # or: cp -r agent_money/ your-project/
No dependencies. Python 3.9+.
Quick start
from agent_money import money, fee_curve
# Money that cannot drift
from decimal import Decimal
money.fmt(0) # "0.00" - never "0"
money.clamp_zero(Decimal("-5")) # Decimal("0.00")
money.refuse_sub_cent("1.089559") # raises MoneyError
money.normalise_sign("expense", "25.50") # Decimal("-25.50")
# Escalating fees: DAILY_FEE(n) = 5n, TOTAL(n) = 5n(n+1)/2
fee_curve.daily_fee(3) # Decimal("15.00")
fee_curve.lifetime_fees(10) # Decimal("275.00")
fee_curve.billable_days("2026-01-01T00:00:00Z", "2026-01-16T00:00:00Z") # 8
fee_curve.month_key("2026-01-31T23:30:00Z") # "2026-02" - Zurich, not UTC
Pay-per-call endpoint
from agent_money import Paywall, PaymentError
pw = Paywall(payee="YOUR_SOLANA_ADDRESS", price="0.001", decimals=6)
@app.route("/v1/data")
def data():
proof = request.headers.get("X-PAYMENT")
ref = request.headers.get("X-PAYMENT-REF")
if not proof:
# 402: hand the payer a single-use reference to put in the tx memo
return pw.issue_challenge(resource="/v1/data"), 402
try:
pw.verify(proof, resource="/v1/data", reference=ref)
except PaymentError as e:
return {"error": str(e)}, 403
return {"data": "..."}
The reference is the part people skip, and skipping it is how you give your
product away. See docs/patterns.md §4.
Why the guards look paranoid
Each one is regression cover for a defect that actually happened:
| Guard | What it prevented |
|---|---|
Decimal everywhere, no SQL REAL |
cent-precision sums drifting in reports |
| sign normalised in one function | an inverted ledger with plausible totals |
clamp_zero instead of max(0, x) |
"0" breaking two-decimal formatting |
| sub-cent amounts refused | a 6-decimal USDC amount corrupting a cent ledger |
| reference-bound payments | the product served for free, booked as revenue |
| mock/live receipts split | $0.004 of revenue that never existed |
| month keys in the settlement timezone | a settlement attributed to the wrong month |
Full write-up in docs/patterns.md.
Tests
python -m unittest discover -s tests -v
Ran 44 tests - OK
The UnboundPaymentTests class reproduces a live payment-binding exploit in
miniature. If those pass when they should fail, the paywall is broken.
License
MIT. See LICENSE.
Metadata
Release files for agent-money-primitives 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| agent_money_primitives-1.0.0.tar.gz | 16.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agent_money_primitives-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 27.8 kB
Release files / agent_money_primitives-1.0.0.tar.gz
| Download URL | agent_money_primitives-1.0.0.tar.gz |
|---|---|
| Size | 16.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
878ce43834f18a0f8e279f5439f34aa2158c56f1ca5c9c6a275a0ffd1de183d5
|
|
BLAKE2b-256 checksum How to use checksums |
f3d3323272a5c3d7426305cee2539d31afc318b4561da2e0d53548f7efb314bf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / agent_money_primitives-1.0.0-py3-none-any.whl
| Download URL | agent_money_primitives-1.0.0-py3-none-any.whl |
|---|---|
| Size | 11.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
70611749f35f859b312801f898204549726899b6c83e055f755174cca9e23d88
|
|
BLAKE2b-256 checksum How to use checksums |
b8bd10fe36129960a892a42265c171c85983c33b7f4bfb7b12481fc7f291f98e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|