Let agents move money inside limits the server enforces
Give each agent its own API key and a spending policy: allowed currencies, a per-transaction cap, a daily budget shared with any keys it delegates, and a threshold above which a different key must approve. The MCP server binds to that key, so every tool call carries the same limits.
Where this usually goes wrong
Prompts are not controls
"Never spend more than 50 dollars" in a system prompt is a suggestion. Nothing stops a confused or manipulated agent from sending a larger request.
Agents multiply their own allowance
An agent that can mint sub-keys or spawn sub-agents turns one budget into many, unless the budget is shared and enforced upstream.
Self-approval is no approval
If the credential that asked for a payment can also approve it, the approval step is decorative.
Primitives in the open-source core, not patterns you rebuild
Per-key spending policies
Allow specific currency and precision pairs, cap each transaction, limit spend per UTC day, require approval above a threshold and restrict which ledgers and balances a key can touch.
Durable reservations
Usage is reserved in PostgreSQL under locks before any asynchronous work, so concurrent requests can't overspend a daily limit.
Budgets shared by delegated keys
A child key inherits its parent's restrictions and draws on the same daily budget. Ten keys don't create ten allowances.
Independent approval holds
Above the threshold the server holds the funds. The initiating key and its delegation family can't approve or reject; a separately provisioned approver can.
MCP bound to a key
ledgerforge-mcp runs locally over stdio, read-only unless started with --allow-write. Bind it with LEDGERFORGE_MCP_API_KEY and every tool call carries that key's policy.
Capacity the agent can read
GET /policies/effective returns the effective rules and the remaining daily capacity across every charged budget, so an agent can plan before it asks.
A policy, a held payment, a refused self-approval and an independent approval
{ "rules": [ { "currency": "USD", "precision": 100, "max_transaction": "5000", "daily_limit": "10000", "approval_above": "2000" } ], "ledger_ids": [ "ldg_e04e431f-8a27-4b19-8744-eb1867ed7b23" ], "balance_ids": [ "bln_df56a248-7d7e-4c0c-8fbf-a5215c87b603", "bln_173d086e-57cb-4690-9abe-1cf060fafb13" ]}{ "api_key_id": "api_key_8224a822-7ec0-4e0e-8f8f-d95039fc8fb3", "version": 1, "rules": [ { "currency": "USD", "precision": 100, "max_transaction": "5000", "daily_limit": "10000", "approval_above": "2000" } ], "ledger_ids": [ "ldg_e04e431f-8a27-4b19-8744-eb1867ed7b23" ], "balance_ids": [ "bln_df56a248-7d7e-4c0c-8fbf-a5215c87b603", "bln_173d086e-57cb-4690-9abe-1cf060fafb13" ]}{ "precise_amount": 3000, "precision": 100, "transaction_id": "txn_1a536530-f07d-43a5-8f72-c89965d179cd", "reference": "payout-2207", "status": "INFLIGHT", "inflight": true, "meta_data": { "policy_admission_id": "adm_dbebd5ed-78e0-40ce-a4a2-ab598a95e254", "policy_approval": "pending" }}{ "error": "spending policy denied transaction"}{ "admission_id": "adm_dbebd5ed-78e0-40ce-a4a2-ab598a95e254", "api_key_id": "api_key_8224a822-7ec0-4e0e-8f8f-d95039fc8fb3", "identity": "payout-2207", "policy_version": 1, "day": "2026-10-10T00:00:00Z", "decision": "approved", "decided_by": "api_key_02790ec7-4f42-462b-8044-a0df92c70086", "legs": [ { "transaction_id": "txn_1a536530-f07d-43a5-8f72-c89965d179cd", "reference": "payout-2207", "source": "bln_df56a248-7d7e-4c0c-8fbf-a5215c87b603", "destination": "bln_173d086e-57cb-4690-9abe-1cf060fafb13", "source_ledger": "ldg_e04e431f-8a27-4b19-8744-eb1867ed7b23", "destination_ledger": "ldg_e04e431f-8a27-4b19-8744-eb1867ed7b23", "currency": "USD", "precision": 100, "amount": "3000" } ]}Boundaries
Policies constrain what an agent can submit through authenticated HTTP and identity-bound MCP. They don't protect against a database administrator, a master key, an MCP process started without a key, stolen approver credentials or a wrong but authorised business decision. A different key is an independent principal, not proof that a human reviewed the decision.
Put a provable ledger under your money movement
Start with the open-source core, or let the LedgerForge team run it for you on dedicated infrastructure.