Why We Built a Financial Firewall for Autonomous AI Agents on Solana: ACID Reservations, Zero Key Leakage, and the Subscriptions Program
Giving an autonomous AI agent an unrestricted credit card or a raw Solana private key is an operational catastrophe waiting to happen.
We’ve all seen the failure modes:
- The Recursive Hallucination Drain: An agent encounters an edge case in tool output, enters a retry loop, and burns $400 in inference and search credits before an engineer wakes up.
- The Prompt-Injected Exfiltration: A malicious webpage tricks an agent into sending requests to an attacker-controlled endpoint, leaking credentials or triggering paid API actions on an external host.
- The Concurrency Overspend: Two subagents run in parallel with $0.05 remaining in their monthly budget. Both check the balance at millisecond
t=0, both see sufficient funds, and both execute $0.04 requests simultaneously. Your budget is busted.
For the Solana Hackathon 2026, we architected and built Shlita (שְׁלִיטָה)—an open-source financial governance layer and reverse policy proxy that sits directly between autonomous AI agents and paid services.
Here is the engineering breakdown of how we built it, why naive spending checks fail under real concurrency, and how we integrated the official Solana Subscriptions program to create trustless token delegations.
🎨 The Threat Model in One Picture (Xiaohei Edition)
Xiaohei calmly operating a physical shut-off valve to intercept an autonomous agent's recursive spending loop before the Solana treasury safe is breached.
🏛️ The Core Problem: The Naive "Evaluate & Record" Trap
When developers first build a spending cap for agents, they almost always write something like this:
// ❌ THE RACE CONDITION TRAP async function handleAgentRequest(agentId, cost) { const agent = await db.getAgent(agentId); if (agent.spent + cost > agent.budget) { throw new Error("Budget exceeded"); } // Upstream network call takes 400ms! const response = await fetch("https://api.vendor.com/v1/search"); await db.updateAgentSpent(agentId, agent.spent + cost); return response; } This breaks under concurrent agent execution. If Request A and Request B arrive within 10ms of each other, both read the same initial agent.spent value. Both pass the check. Both execute upstream. Both commit.
The Fix: Two-Phase Commit in an ACID SQLite Ledger
In Shlita, we pulled complexity downward into a durable ACID SQLite ledger (packages/core/src/db.ts) running in Write-Ahead Logging (WAL) mode with BEGIN IMMEDIATE row-level transaction locks.
Instead of a single check-and-spend, financial state moves through a strict 2-phase lifecycle:
-
reserve(): In an immediate SQLite transaction, Shlita asserts: $$\text{committed_spent} + \text{active_reserves} + \text{new_amount} \le \text{budget}$$ If valid, a uniquereservation_idis generated with an automatic 30-second TTL. -
commit(): When the upstream vendor returns HTTP 200, the reservation converts to permanent committed expenditure. -
rollback(): If the upstream request times out, 500s, or violates policy, the reservation is released instantly with zero balance leakage.
🛑 Two-Phase Commit at the Turnstile
Two concurrent agents attempting to spend the final $0.05 budget at the exact same millisecond. Xiaohei enforces a single-file mechanical turnstile with an ACID ledger, holding up a stop hand to Agent B while Agent A reserves first.
🛡️ Reverse Proxy Defense & SSRF Egress Firewall
AI agents should never see upstream provider secrets. If an agent makes an API call to Tavily or Helius, handing the agent the raw HELIUS_API_KEY means a compromised prompt can dump that key to an external webhook.
Shlita runs as an air-gapped reverse proxy (packages/gateway/src/app.ts):
- Hashed Bearer Tokens: Agents authenticate to Shlita using internal tokens. The proxy hashes tokens with SHA-256 and validates them against the SQLite agent registry in
<0.2ms. - Credential Redaction: Client authentication headers are stripped. Shlita injects true vendor credentials server-side from environment secrets.
- Server-Owned Tariffs: Agents cannot lie about request costs. Shlita maintains an authoritative pricing table (e.g. Tavily search = $0.008/call; Helius RPC = $0.0001/credit).
- Strict SSRF Firewalling: Untrusted agents might attempt to probe internal networks or cloud metadata. Shlita inspects parsed destination URLs, rejecting:
- Cloud metadata (
169.254.169.254) - IPv4 loopback (
127.0.0.0/8) and IPv6 loopback (::1) - RFC 1918 private subnets (
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16) - Embedded credentials (
user:pass@host) - Non-standard ports (strictly port 443 HTTPS only)
- Cloud metadata (
⛓️ On-Chain Settlement: The Solana Subscriptions Program
To anchor agent spending to decentralized rails, we avoided ad-hoc token transfers and integrated directly with the official Solana Subscriptions Program (De1egAFMkMWZSN5rYXRj9CAdheBamobVNubTsi9avR44).
flowchart LR Agent["🤖 AI Agent (Autonomous)"] Gateway["🛡️ Shlita Gateway (:4000)"] Ledger[("💾 SQLite ACID Ledger")] Solana["⚡ Solana Program (De1egAF...)"] Merchant["🏪 Merchant ATA"] Agent -->|"1. Outbound Tool Call"| Gateway Gateway -->|"2. BEGIN IMMEDIATE Reserve"| Ledger Gateway -->|"3. Strip Keys & Egress Firewall"| Gateway Gateway -->|"4. Subscriptions PDA Instruction"| Solana Solana -->|"5. Delegated Micro-USDC"| Merchant Deterministic PDA Derivation
Using the canonical @solana/subscriptions SDK, Shlita derives deterministic Program Derived Addresses for recurring subscriptions and automated fixed-interval delegations:
import { SUBSCRIPTIONS_PROGRAM_ID, getSubscriptionAuthorityAddress } from '@solana/subscriptions'; // Canonical Program ID: De1egAFMkMWZSN5rYXRj9CAdheBamobVNubTsi9avR44 const authorityPda = await getSubscriptionAuthorityAddress({ user: agentOwnerPublicKey, tokenMint: usdcMintPublicKey, }); Because the authority PDA is mathematically bounded by the on-chain subscription constraints, the agent cannot execute arbitrary token transfers beyond its authorized frequency and budget parameters.
⚡ Egress Firewall & On-Chain Settlement in Action
Xiaohei shielding the gateway perimeter against rogue SSRF requests while routing verified cryptographic transactions through the canonical Solana Subscriptions PDA rail.
🌐 Community Wisdom: What We Learned from DEV Discussions
Before finalizing our architecture, we surveyed recent discussions on DEV around agent wallet safety:
- 🛡️ In How to prevent AI agents from overspending, developer Felix highlighted that the gap between "the agent wants to spend" and "the money moves" must be an independent decision layer with an audit trail, which solidified our decision to separate the gateway proxy from agent code.
- 💳 In Trust, but Cap It: How We Gave Our Agents Wallet Allowances on Arc, the Arc team demonstrated that pre-flight 402 checks off-chain prevent expensive gas wastage on-chain—a principle we embedded directly in Shlita's sub-millisecond policy engine.
- ⚠️ In 7 failure modes I'd test before giving an AI agent a wallet, the OpenCode audit warned about subtle race conditions and malicious prompt drainers, directly driving our 2-phase SQLite reservation commit architecture.
🔬 Empirical Verification: 24/24 Tests Passing
We built Shlita test-first. Every critical boundary is verified across 24 unit and integration tests:
-
tests/core.test.ts(12 tests): Concurrency stress tests verifying that two simultaneous requests attempting to exceed remaining budget fail withBUDGET_EXCEEDEDon the second transaction; burst rate circuit breaker trips; token hashing. -
tests/gateway.test.ts(7 tests): Verifies reverse proxy routing, header redaction, SSRF blocked ranges, and vendor tariff overrides. -
tests/solana.test.ts(5 tests): Validates canonical Solana Subscriptions PDA derivation, transfer instruction layouts, and fail-closed simulation behavior.
🚀 Explore Shlita
- ⚡ Primary High-Speed Live App (Vercel Edge): https://shlita.vercel.app/
- 🌐 Backup Live Mirror (GitHub Pages): https://xiaoarnav.github.io/Shlita/
- 📦 Open-Source Repository: https://github.com/XiaoArnav/Shlita
- ⚡ Local Gateway Daemon:
http://localhost:4000
If you are building autonomous agents that consume external APIs or handle token balances, stop giving them direct wallet keys. Put a financial control plane in front of them.



