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

  • MCP has no auth — trust your host; policy_apply / policy_review are host-level operations
  • Approval IDs are 48-bit random — a library trusts its caller
  • In-memory audit (append-only on the roadmap)
  • We are actively seeking real-world attacks: Reality Test — challenge: make a DENY turn into APPROVE

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

Metadata

Release files for spendshield 0.8.0

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.0
File Size Uploaded
spendshield-0.8.0.tar.gz 63.9 kB Details

Built distribution (wheel)

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

Total release size: 116.9 kB

Release files / spendshield-0.8.0.tar.gz

Download URL spendshield-0.8.0.tar.gz
Size 63.9 kB
Tags Source
SHA-256 checksum
How to use checksums
d2567b853d33c7367a57ad437e975b791163dccd666c31eb1d86e3285b63f958
BLAKE2b-256 checksum
How to use checksums
dd7059930ab0c271744b8ae28b9bed49b70a2d38047385167c40971a0f4c9032
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.0-py3-none-any.whl

Download URL spendshield-0.8.0-py3-none-any.whl
Size 53.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
15667e27d29133b7dd40ffc22fb65cdd9c65e5eade546f781e446973bf717125
BLAKE2b-256 checksum
How to use checksums
39fa352b4a1388b4f67eef3d9b93944fb7ab519ea34401285cd5cd68a813ea18
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

0.8.1

2 release files

This release

0.8.0 This release

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