Skip to content
AI agents

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.

Spending policiesShared budgetsApproval holdsMCP
agent key · policy v1USD · precision 100
daily_limit · USD30.00 / 100.00
max_transaction 50.00approval_above 20.00
service keytransactions:write
agent keyinherits limits
sub-agent keyshares budget
old agent keyrevoked
Illustration using the values in the API example below.
The problem

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.

API example

A policy, a held payment, a refused self-approval and an independent approval

Captured from a local LedgerForge build with the hash chain enabled. The same sequence is runnable from the repository's agent-policy example.
PUT /policies/:api_key_idRequest
{  "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"  ]}
Response200 OK
{  "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"  ]}
POST /transactions (agent key, 3000 units)201 Created
{  "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"  }}
POST /approvals/:admission_id/approve (agent key)403 Forbidden
{  "error": "spending policy denied transaction"}
POST /approvals/:admission_id/approve (approver key)200 OK
{  "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.