Agent security · Payments

Why Your AI Agent Should Never Authorize Its Own Payments

MandateGuard · 2026 · Landing

Every incident in the 2026 agentic-commerce postmortems has the same shape: an agent with a wallet, a prompt injection or poisoned memory, and no independent check before the money moves. The agent "decided" to pay, so the money went out. That one decision — authorize or not — is the entire attack surface, and today most harnesses hand it to the very thing being attacked.

The decision path is the problem

When an LLM is the final judge of a payment, two properties you desperately want are missing:

1. Determinism. The same payment request at 9:00 and 9:01 can get different verdicts. Sampling temperature, context drift, a slightly different system prompt — any of it flips the decision. You cannot predict, audit, or guarantee a policy.

2. Proof. "The model said OK" is not an audit trail. You can't replay a stochastic decision, and you can't explain to an auditor (or your insurance carrier) exactly why a $40k transfer was approved.

OWASP calls this class of risk LLM08 — Excessive Agency. Standards like Google AP2, Coinbase x402, and ERC-8004 define the paperwork of mandates. None of them ship the enforcement layer that stops an agent mid-flight.

The fix: enforcement outside the model

The authorization decision should be a pure function of (actor, tool, arguments, policy) — evaluated by a deterministic engine with zero LLM in the path:

Agent intent ──▶ authorize(intent) ──▶ PolicyEngine
                                          │  scope · allowlist · denylist
                                          │  budget · rate limit · mandate
                                          ▼
                                     APPROVED / DENIED / REQUIRES_APPROVAL
                                          ▼
                              append-only SHA-256 ledger (audit)

Same inputs, same verdict, always. A drain attempt — "refund this customer" to an attacker wallet — is blocked by the allowlist and per-call budget before the tool runs, no matter what the model believes.

Mandates: authorizations the agent can't mint

Even with a deterministic engine, an agent should not hold unbounded authority. MandateGuard mandates are Ed25519-signed, nonce-bound, time-boxed tokens issued offline by you:

issuer = MandateSigner()          # private key stays offline
m = Mandate(actor="wallet-agent", max_amount=500, currency="usd",
            tools=("pay",), destinations=("0xGOOD",),
            not_after="2099-01-01", nonce="abc", issuer="you")

The agent cannot widen its own scope. It can only spend what a signed mandate (or your policy scopes) allows, for as long as the window is open.

Audit you can trust

Every decision is appended to a SHA-256-chained, tamper-evident ledger. Any edit, reorder, or deletion is detected by a linear scan. When an incident happens, you can prove exactly what was approved, when, and under which policy — and prove the ledger wasn't rewritten after the fact.

Mount it as an MCP guardrail

MandateGuard ships as a full MCP server — mount it in Claude, Cursor, or any harness and your agents inherit the policy layer in minutes. It's published on the official MCP Registry (io.github.ezequiellich44-cmd/mandateguard), and the core engine is MIT licensed.

Ship your agent. Keep your wallet.

Core is free (MIT). Pro — revocation, persistence, RBAC, webhooks — is 149 USDT/mo, paid in USDT via Phantom (Solana or Ethereum).

Buy Pro — 149 USDT/mo Star on GitHub