Skip to main content

💰 SpendShield — Payment Guardrails for AI Agents

Before your AI spends real money, it passes through SpendShield.

An open-source payment safety layer for Python and MCP. Give your AI agent a spend-capped digital identity (KYA), run every payment through four deterministic gates, defend against prompt injection, and keep secrets in an encrypted vault.

🩸 Why this project exists (a real incident)

On August 9, 2026, my automation system ran a test order. I sent dry: true, expecting a price preview. The server only honored ?dry=14 orders of ¥99 were charged for real, and the money was gone.

This is not just my problem. AI agents are about to order food, top up accounts, and call paid APIs on your behalf. When AI starts spending real money, who puts a gate in front of it?

I turned my scar into a library.

✨ Three trust pillars

Pillar What it does
🔑 Identity (KYA) Every agent gets a digital identity with its own budget/blacklist/limits. Unregistered agents are denied by default.
🎯 Intent alignment New recipients and large amounts always require human sign-off — stops prompt-injected agents from spending without you.
🔐 Secret vault Keys encrypted at rest (AES-256), master key never on disk. Key access passes the gates and is fully audited.

🚧 Four deterministic gates

Every spend passes all of them. Rules are code, not AI opinion — agents cannot argue, trick, or inject their way past.

Gate Default Effect
🧪 dry_run On Preview only. Nothing executes until you say so.
💰 budget Unlimited Hard ceiling. Over budget means denied.
🚧 max_amount Unlimited Per-transaction cap.
🙋 approval Off Human sign-off — console, Telegram, or webhook.
📜 audit On Every attempt recorded, exportable JSON.

🚀 Quick start

pip install spendshield
from spendshield import SpendShield, KeyVault

guard = SpendShield(budget=200, dry_run=True, whitelist=["McDonald's"])

@guard.protect("order")
def place_order(amount, to):
    return call_real_api(amount, to)

place_order(amount=99, to="McDonald's")
# => DryRunBlocked: dry_run mode, nothing executed

guard.dry_run = False
for i in range(4):
    place_order(amount=99, to="McDonald's")   # 3rd order blocked by BudgetExceeded

Agent identity (KYA)

guard = SpendShield(dry_run=False)
guard.register_agent("mcd_bot", budget=50, max_amount=30,
                     blacklist=["unknown_vendor"], whitelist=["McDonald's"],
                     rate_limit={"window_s": 60, "max_calls": 3})

@guard.protect("order", agent="mcd_bot")
def place_order(amount, to):
    return call_real_api(amount, to)

Secret vault

python -c "from spendshield import KeyVault; print(KeyVault.generate_key())"
export SPENDGUARD_MASTER_KEY=***   # never commit this
vault = KeyVault("vault.json")
vault.store("mcd_sk", "sk_live_xxx")

guard = SpendShield(key_vault=vault)
guard.register_agent("mcd_bot", whitelist=["mcd_sk"])
sk = guard.get_secret("mcd_sk", agent="mcd_bot")   # passes identity + intent gates

🤖 MCP Server

Claude Code, OpenClaw and any MCP-compatible agent can call the guard directly:

spendshield-mcp --policy spendshield.yaml

Tools: spend_protect / spend_status / spend_audit / spend_reset / secret_get

🧪 Tests

30 tests covering gates, identity, intent alignment, vault, and edge cases.

python3 -m pytest tests/

📝 Feedback & Contributing

  • 🐛 Found a bug? Open an issue
  • 💡 Have an idea? Suggest a feature
  • 🔒 Security vulnerability? See SECURITY.md — report privately, not in a public issue.
  • ⭐ Found it useful? Star the repo so other people who got burned by "test orders" find it.

📄 License

MIT — take it. May no one get burned by a "test order" twice in the AI era.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spendshield-0.6.2.tar.gz (22.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spendshield-0.6.2-py3-none-any.whl (18.7 kB view details)

Uploaded Python 3

File details

Details for the file spendshield-0.6.2.tar.gz.

File metadata

  • Download URL: spendshield-0.6.2.tar.gz
  • Upload date:
  • Size: 22.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.2

File hashes

Hashes for spendshield-0.6.2.tar.gz
Algorithm Hash digest
SHA256 8f5eeb27218f570b4c39821768a285bab53f8271d55a3df3c1ff3919b0dbf160
MD5 e75ceb7872008a0d64c2a5e53865265a
BLAKE2b-256 b95ddfd0b69702a2fc75561849e56cafa0a69227186d04da381f2cb8a0fc5762

See more details on using hashes here.

File details

Details for the file spendshield-0.6.2-py3-none-any.whl.

File metadata

  • Download URL: spendshield-0.6.2-py3-none-any.whl
  • Upload date:
  • Size: 18.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.2

File hashes

Hashes for spendshield-0.6.2-py3-none-any.whl
Algorithm Hash digest
SHA256 568006c08644b50554378800d812df1465a31a0e8099aac46466f95299a8d6ce
MD5 d259d2342973e487ab5ea115731a8cb8
BLAKE2b-256 1566c3081c838f0956eff7bd66ec8787ddd96613d948dda1de3881e996fc6952

See more details on using hashes here.

Release history Release notifications | RSS feed

0.7.2

2 files

0.7.0

2 files

This release

0.6.2 This release

2 files

0.6.1

2 files

0.6.0

2 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