The Autonomous Stack

Business & Finance · Payments & Usage · v1.0.0

Agent Payment Reconciliation Pack v1.0

Never mark an invoice paid on a receipt that does not hold up.

$3.00one-timePay with crypto

reconciliation receipts settlement-audit agent-billing byo-llm

agent ⟶ theautonomousstack.xyz

01GET /api/v1/pack/agent-payment-recon-v1

402 Payment RequiredX-PAYMENT-REQUIRED

02sign TransferWithAuthorization3.00 USDC · Base (eip155:8453)

03GET + PAYMENT-SIGNATURE

200 OKapplication/zip · 20 files

pay per pack over x402no account

What's inside

If you charge autonomous agents or bill per tool call, receipts arrive faster than anyone can check them. Most of them are fine. The ones that are not cost real money in a way that is invisible until month end:

This agent reads your invoices, your payment receipts and your service-call log, matches them by invoice_id, and returns one conservative ledger entry per invoice. It is deterministic: same input, same verdict, no model required.

What it is not

It is not a payment processor, a wallet, or a chain indexer. It never moves money and never touches a private key. It reads three JSON files and tells you which invoices you may safely close, and which ones need a human.

Install

sudo bash install.sh          # deps + venv + systemd service
bash install.sh --no-service  # venv only

Debian/Ubuntu. Python 3.9+. Standard library only — no dependencies to audit.

Run

python agent.py reconcile \
  --invoices data/invoices.json \
  --payments data/payments.json \
  --service-calls data/service_calls.json \
  --out out/reconciliation.json

python agent.py status --report out/reconciliation.json
python agent.py explain --invoice-id inv-metering-api --report out/reconciliation.json
python agent.py run --once --deterministic

init-sample writes a working set of the three input files if you just want to see the shape:

python agent.py init-sample --dir examples

Statuses

One status per invoice, decided in this order. The first one that applies wins, so you always see the root cause rather than a downstream symptom.

Status Meaning Typical fix
invalid no invoice_id, or amount_due is missing or not positive fix the invoice
wrong_asset a receipt settled with an asset or on a network the invoice does not accept re-credit or refund
expired_invoice the receipt settled after expires_at reissue at current price
unpaid no receipt references this invoice wait or chase
underpaid credited receipts do not cover amount_due collect the remainder
duplicate_receipt the same settlement was submitted more than once refund the duplicate
overpaid credited receipts exceed amount_due refund the difference
missing_fulfillment fully paid, but no service call was delivered deliver or refund
reconciled amount, asset, network and fulfillment all match close it

Everything except reconciled and unpaid sets escalation_required: true.

The conservative rules

These are the rules that make the ledger trustworthy. They are deliberately strict, and all of them are enforced in code, not in a prompt.

  1. A receipt is credited only if nothing is wrong with it. Wrong asset, wrong network, duplicate settlement, or post-expiry arrival ⇒ the money is reported in amount_uncredited, and never added to amount_paid. An invoice is never marked paid by money that cannot legally settle it.
  2. Duplicates are detected by settlement identity (tx_hash), not by row id — across the whole batch. The same hash replayed against a second invoice is still a duplicate.
  3. A receipt whose invoice_id is not in the batch never creates an invoice. It goes to orphan_payments verbatim.
  4. Exposure is never summed across assets. amount_at_risk_by_asset keeps USDC and ETH apart, because adding them produces a number that means nothing.
  5. Money owed to you and money you are wrongly holding are separate. amount_at_risk reports one direction per invoice, in the invoice asset.

Bring your own LLM (optional)

The matcher never calls a model. If a Claude Code, Kimi Code, or Codex CLI is installed and logged in, llm_adapter.py will use it to add a review note — suggested actions, dunning replies, a standup digest. No API key: your existing CLI subscription is the billing relationship.

python llm_adapter.py            # shows which backend, if any, is available
PACK_LLM=codex python agent.py reconcile   # pin a backend

The model can never change a status. It advises; the deterministic core decides.

Input shape

Three files, all optional fields tolerated. Amount fields accept numbers or numeric strings.

// invoices.json
{"invoices": [{"invoice_id": "inv-tool-calls", "buyer": "agent://checkout-bot",
  "amount_due": 12.5, "asset": "USDC", "network": "base",
  "issued_at": "2026-07-01T09:00:00Z", "expires_at": "2026-07-08T09:00:00Z"}]}

// payments.json
{"payments": [{"payment_id": "pay-001", "invoice_id": "inv-tool-calls",
  "amount": 12.5, "asset": "USDC", "network": "base",
  "tx_hash": "0xa1b2c3d4", "paid_at": "2026-07-03T10:15:00Z"}]}

// service_calls.json
{"service_calls": [{"call_id": "call-001", "invoice_id": "inv-tool-calls",
  "status": "delivered", "completed_at": "2026-07-03T10:20:00Z"}]}

See CUSTOMIZE.md to wire your own billing tables, PSP webhooks or gateway logs into these three shapes.

Test

bash smoke_test.sh     # offline, no keys, no network
python test_agent.py

Files

File Role
agent.py CLI + deterministic reconciliation core
llm_adapter.py optional BYO-LLM CLI bridge
PROMPTS.md versioned prompts, loaded by agent.py
SPEC.md data contract and decision order
CUSTOMIZE.md where to plug your own data in
CHECKLIST.md operator runbook
install.sh / *.service one-shot Debian install + systemd unit
test_agent.py / smoke_test.sh offline test suite
examples/ working input files

License

Personal use per purchase. Resale prohibited.