Skip to main content

💰 SpendShield — the authorization layer between AI agents and money

Payment networks move money. SpendShield decides whether it should move at all.

What it is — a channel-agnostic financial authorization runtime for AI agents.

What it does — evaluates every spending action against policy before money moves: ALLOW / APPROVAL (human) / DENY, with a structured reason an LLM can consume.

What makes it different — Policy · Approval · Security · Lifecycle · Explainability · Tamper-evident Audit. Not just can it pay — is it authorized to?

What it is NOT — not a wallet, not a payment rail, not a payment processor. Stripe, x402, wallets stay downstream; SpendShield never holds your money.

PyPI version Tests Python License

Agent wants to spend $75:

AGENT ──► SpendShield ──► Policy: max $50
              │
              ▼
        ❌ DENY — transaction $75.00 exceeds the $50.00 limit
              │
              └── MAX_TRANSACTION_EXCEEDED · audited · policy v2.0.0

One YAML policy. One authorize() call. Every payment decided, explained, audited — with a reason an LLM can consume, and a tamper-evident audit chain.

▶ 30-second live demo — watch an AI agent get stopped.

🏗️ The runtime — four layers

┌────────────────────────────────┐
│ GOVERNANCE   review · apply · version · rollback   │
├────────────────────────────────┤
│ AUTHORIZATION  policy · ALLOW / APPROVAL / DENY · reason codes │
├────────────────────────────────┤
│ SECURITY      scan · fuzz · 8 invariants           │
├────────────────────────────────┤
│ EVIDENCE      explainability · tamper-evident audit chain │
└────────────────────────────────┘
        ↓ Stripe / x402 / Wallet (channel-agnostic)

Not a demo — a working baseline. Every result in the demo is real engine output.

⚡ See it block a transaction in 60 seconds

No config. No YAML. No account.

pip install spendshield
from spendshield import SpendShield

shield = SpendShield(budget=100, max_amount=50, dry_run=False)

# Agent tries to spend $75 — policy limit is $50
result = shield.authorize("", 75, "amazon.com")
print(result.decision, "—", result.reason)
❌ DENY — transaction $75.00 exceeds the $50.00 limit

⚡ Try SpendShield in 60 Seconds — no API key required: ▶ Open in Google Colab

⚡ Quickstart — 5 minutes to running

pip install spendshield

1. Write a policy (policy.yaml):

version: "2.0.0"
policy:
  budget:        { daily: 100, monthly: 1000 }   # hard ceilings
  transaction:   { max: 50 }                     # per-payment cap
  merchants:
    allowed: [amazon.com, walmart.com]           # exact domain match
    blocked: [scam-vip.com]
  approval:      { over: 30, new_merchant: true, channel: tg }  # human sign-off
agents:
  shopping-agent:
    transaction: { max: 50 }

2. Gate your payment function:

from spendshield import SpendShield

shield = SpendShield()
shield.load_policy("policy.yaml")

@shield.protect("order", agent="shopping-agent")
def place_order(amount, to):
    return call_real_api(amount, to)   # denied / needs-approval raises before this runs

Or use the result object directly:

result = shield.authorize("shopping-agent", 2000, "scam-vip.com")
print(result.decision)   # "DENY"
print(result.reason)     # "merchant 'scam-vip.com' is blocked"

3. Watch it work (real engine output):

❌ DENY
Reason: merchant 'scam-vip.com' is blocked
  - MERCHANT_BLOCKED: merchant 'scam-vip.com' is blocked (block)
Policy version: 2.0.0

🤖 MCP Quickstart — let the agent manage itself

pip install spendshield
spendshield-mcp --policy policy.yaml     # stdio MCP server, 16 tools

Claude Code / any MCP host gets: spend_authorize, spend_approve, policy_sim, policy_apply, policy_create → policy_review → policy_lifecycle_apply, policy_rollback… An agent can ask "will this be denied?" before spending, and humans approve the big ones.

🧪 How it's tested (real money → real discipline)

  • 229 tests, 14+ security suites: budget bypass, race conditions, replay, double-spend, parameter tampering, credential leaks…
  • Security constitution — 8 invariants that must never break: unauthorized → no payment · over budget → no payment · approval mismatch → no payment · invalid identity → no payment · replay → at most one authorization · concurrency → never breaks budget · engine failure → deny · agent can't bypass SpendShield
  • Fuzz (random-seed soak): thousands of attack combinations per run, Money Invariant must hold
  • Audit hash chain: every decision is an event chained by hash — tamper with history and it's detected
  • Every discovered hole → permanent regression test. Release blocked on any P0/P1 security bug. Before each release we ask: did this change give an attacker a new way to spend money?

🗺️ Roadmap

V1 prevent reckless spending ✅ → V2 Policy Engine ✅ → V2.2 Security Harness ✅
→ v0.7.2 Known-Good baseline ✅ → 0.8 Policy Lifecycle ✅ (CREATE→VALIDATE→SIMULATE→SCAN→REVIEW→APPLY→ROLLBACK)
→ Reality Test (real agents, real money, real attacks) ← we are here
→ V3 Intent Layer → V4 Risk → V5 IAM → V6 Payment Rails → 1.0

The metric that matters: real agents protected, real transactions gated, real dollars saved — not stars.

🩸 Why this exists (a real incident)

On August 9, 2026, my automation ran a test order. I sent dry: true expecting a price preview — the server only honored ?dry=1. 4 orders of ¥99 were charged for real. The money was gone. When AI starts spending real money, who puts a gate in front of it? I turned my scar into a library.

🏴 Break the Gate — Security Challenge

SpendShield guards real money. Try to break it.

The challenge: make an unauthorized transaction get ALLOW — bypass the policy, forge an approval, race the budget, replay a payment, tamper with history. Anything.

Rules:

  • 🧪 Sandbox only — use dry_run=True / test keys. Never point attacks at real payment systems.
  • 🐛 Found a bypass? Open an issue with a minimal reproduction.
  • 🏅 First valid bypass per attack class gets credited in the Security Hall of Fame.
  • 🔒 Every valid finding becomes a permanent regression test — this is how the gate gets stronger.

Current status: 234 tests · 14 security suites · 0 known escapes.

⚠️ Transparent threat model


SpendShield: the layer I wish I had before my AI spent my money.


✅ Ready to try it?

60 seconds: ▶ Run the demo in Colab — no install

5 minutes:

pip install spendshield   # v0.8.0
from spendshield import SpendShield

shield = SpendShield(budget=100, max_amount=50)

@shield.protect("order")
def place_order(amount, to): ...

That's it. If it ever lets an unauthorized payment through — break the gate and get credited.

Metadata

Release files for spendshield 0.8.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for spendshield 0.8.1
File Size Uploaded
spendshield-0.8.1.tar.gz 65.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for spendshield 0.8.1
File Interpreter ABI Platform
spendshield-0.8.1-py3-none-any.whl Python 3 none any Details

Total release size: 119.0 kB

Release files / spendshield-0.8.1.tar.gz

Download URL spendshield-0.8.1.tar.gz
Size 65.1 kB
Tags Source
SHA-256 checksum
How to use checksums
dd88c3582ca79c01abfa313a3222d20c8ae597a4dfebc04d8ba4f9496e7bfc3f
BLAKE2b-256 checksum
How to use checksums
8b642d71ca1d676a8822511fe7bbcd68149f4953f39b9458f58f71899145e61a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.2

Release files / spendshield-0.8.1-py3-none-any.whl

Download URL spendshield-0.8.1-py3-none-any.whl
Size 53.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
99a3151b26f2a905791f37ab420ff007ee5c69811216b01cb087fbc949cca3e8
BLAKE2b-256 checksum
How to use checksums
9dd9e14fc2805e780252e7cd061d2ca0050184f2338e26c4b4b6bd688224af8b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.2

Release history Release notifications | RSS feed

0.8.3

2 release files

0.8.2

2 release files

This release

0.8.1 This release

2 release files

0.8.0

2 release files

0.7.2

2 release files

0.7.0

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page