The financial operating system for AI agents. A single HTTP client that intercepts '402 Payment Required', routes across x402, L402, and MPP, persists credentials as recoverable assets, enforces per-envelope budgets, and emits a structured trace.
routeweiler-python-sdk is a growing Python project in the AI payments / x402 ecosystem, focused on agentic, agentic-commerce, agentic-payments, bitcoin. It currently has 31 GitHub stars and 1 forks, and sits alongside related tools like mpp-swift, 402index-mcp-server, inflow-cli, lightning-wallet-mcp, toll-booth, mcp-pay.
The financial operating system for AI agent fleets. An async HTTP client —
await routeweiler.get(url) — that transparently handles 402 Payment Required across
x402 (EVM), L402 (Lightning), MPP-Tempo (stablecoin), and MPP-SPT (Stripe), routes to the best rail, enforces spend caps, recovers credentials, emits audit traces, and keeps your keys entirely in your own process.
Documentation: docs.routeweiler.com
pip install routeweiler
Python 3.11+ required.
import asyncio
import os
from eth_account import Account
from routeweiler import Routeweiler, Funding
signer = Account.from_key(os.environ["PRIVATE_KEY"])
async def main():
async with Routeweiler(funding=[Funding.base_usdc(wallet=signer)]) as client:
response = await client.get("https://api.example.com/data")
print(response.json())
asyncio.run(main())
| Rail | Method | Funding source | Networks |
|---|---|---|---|
| x402 | EVM signed transaction | EvmFundingSource |
Base, Base-Sepolia |
| L402 | BOLT-11 Lightning invoice | LightningFundingSource |
Bitcoin, Regtest |
| MPP-Tempo | Tempo 0x76 stablecoin tx | TempoFundingSource |
Moderato testnet |
| MPP-SPT | Stripe Shared Payment Token | StripeFundingSource |
USD, EUR, GBP |
Each rail accepts a typed FundingSource holding the credentials it uses to sign or authorise payments. Key material stays in your process; Routeweiler never transmits private keys.
EvmFundingSourceAn eth_account.LocalAccount that signs EIP-3009 transferWithAuthorization for USDC on Base.
from eth_account import Account
from routeweiler import Funding
wallet = Account.from_key(os.environ["PRIVATE_KEY"]) # 64-char hex secp256k1 key, 0x prefix optional
funding = Funding.base_usdc(wallet=wallet) # mainnet (chain 8453)
# funding = Funding.base_sepolia_usdc(wallet=wallet) # testnet (chain 84532)
LightningFundingSourceWraps an LND gRPC client. Bring a running LND node and pass its admin macaroon + TLS cert; Routeweiler pays BOLT-11 invoices through it.
from routeweiler.funding.lightning import LightningFundingSource, LndClient
lnd = LndClient(
grpc_host="localhost",
grpc_port=10009,
macaroon_path="/path/to/admin.macaroon",
tls_cert_path="/path/to/tls.cert",
)
funding = await LightningFundingSource.create(lnd, network="bitcoin")
# network: "bitcoin" | "bitcoin-testnet" | "bitcoin-regtest" | "bitcoin-signet"
TempoFundingSourceSigns Tempo's type-0x76 charge transactions with an eth_account.LocalAccount — same key shape as x402, different chain. The same wallet can fund both rails.
from eth_account import Account
from routeweiler import Funding
wallet = Account.from_key(os.environ["PRIVATE_KEY"]) # 64-char hex secp256k1 key, 0x prefix optional
funding = Funding.tempo_usdc(wallet=wallet) # mainnet, USDC
# funding = Funding.tempo_pathusd_moderato(wallet=wallet) # testnet, pathUSD
StripeFundingSourceNo on-device signing. Stripe holds the card; you supply a secret API key, a customer id, and a saved payment method id. Routeweiler asks Stripe to mint a Shared Payment Token at pay-time.
from routeweiler import Funding
funding = Funding.stripe(
api_key=os.environ["STRIPE_API_KEY"], # sk_live_... / sk_test_...
customer="cus_ABC123", # buyer's Stripe customer id
payment_method="pm_XYZ789", # saved card / bank
currency="usd", # ISO-4217: usd | eur | gbp | ...
)
Pass any combination to Routeweiler(funding=[...]). The router picks the best rail per challenge based on Policy and what the server accepts.
Enable local tracing with TraceSink.sqlite. Every call (paid or free) produces
exactly one TraceEvent row, including the on-chain tx hash and the payment outcome:
from routeweiler import Routeweiler, Funding, TraceSink
async with Routeweiler(
funding=[Funding.base_usdc(wallet=signer)],
trace_sink=TraceSink.sqlite("./routeweiler.db"),
) as client:
response = await client.get("https://api.example.com/data")
# Inspect with the sqlite3 CLI:
# sqlite3 ./routeweiler.db \
# 'SELECT request_id, selected_rail, http_status FROM trace_events;'
Enforce per-session or per-agent spend caps with local SQLite budget envelopes.
Without a budget_envelope, tracing still works but no cap is enforced.
from routeweiler import BudgetEnvelope, Funding, Routeweiler, TraceSink
async with Routeweiler(
funding=[Funding.base_usdc(wallet=signer)],
trace_sink=TraceSink.sqlite("routeweiler.db"),
budget_envelope=BudgetEnvelope(
id="session-abc",
cap_minor_units=500, # 5.00 USD (in cents)
cap_currency="usd",
allowed_rails=["x402", "l402"],
ttl_seconds=3_600, # 1 hour
),
) as client:
response = await client.get("https://api.example.com/data")
budget_envelope accepts three forms:
None (default) — no cap enforcement.str — ID of a pre-existing envelope; raises EnvelopeNotFoundError at
construction time if the row is missing.BudgetEnvelope — declarative spec; If an envelope with the same id already exists it is reused unchanged.Envelopes track reserved and settled amounts with Ed25519-signed draw receipts.
BudgetExceededError is raised if a payment would breach the cap.
Control which rails are used, set per-call spend limits, or deny specific URLs:
from routeweiler import Policy, PolicyRule, RuleMatch, Routeweiler
async with Routeweiler(
funding=[...],
policy=Policy(
currency="usd", # reference currency for max_per_call_minor_units
rules=[
PolicyRule(
name="deny analytics",
when=RuleMatch(url_matches="*.tracking.io"),
deny=True,
),
PolicyRule(
name="cap per call",
when=RuleMatch(url_matches="*"),
max_per_call_minor_units=500, # 5 USD cents
),
]
),
) as client:
...
url_matches patterns without a / are host globs matched case-insensitively against
the URL's hostname (*.tracking.io matches https://api.tracking.io/v1/events); patterns
containing / are matched against the full URL (https://api.example.com/*).
max_per_call_minor_units requires a reference currency to compare rail-native quotes
against. Set Policy(currency="usd") (or any supported currency) when no
budget_envelope is configured. The envelope's cap_currency takes precedence when
both are present. If neither is provided and a rule uses max_per_call_minor_units,
Routeweiler raises ValueError at construction time.
Releases follow SemVer. Pre-1.0 minors (0.1.0 → 0.2.0) may include breaking changes.
| Tag format | Channel | Install |
|---|---|---|
v0.2.0 |
Stable | pip install routeweiler |
v0.2.0b1 |
Beta | pip install --pre routeweiler |
Apache 2.0 — see LICENSE.
Canonical Swift SDK for the Machine Payments Protocol (MPP) — pay for and charge for machine-to-machine API calls over HTTP 402.
MCP server for 402 Index: discover 15,000+ paid API endpoints across L402, x402, and MPP
A wallet for your agents to onboard and pay. Agentic MPP / x402 payments from your machine - CLI + MCP server.
MCP Server for Lightning Faucet - Give your AI agent a Bitcoin wallet
Any API becomes a Lightning toll booth in one line. L402 middleware for Express, Hono, Deno, Bun, and Workers.
Payment awareness layer for MCP (Model Context Protocol)
540 security tests for AI agent systems — MCP, A2A, x402/L402, decision governance, benchmark integrity, skill supply chain. AIUC-1 pre-cert, NIST AI 800-2 aligned, MCP tool-poisoning reproduction. v4.9.1
A neutral landscape analysis of AI agent payment protocols (x402, MPP, L402, Google AP2, Visa TAP + ICC, Mastercard Agent Pay, Amex ACE, Google/Shopify UCP, OpenAI ACP, and others). Maintained by Genesis Software Group, Copenhagen. Updated April 2026. CC BY 4.0.
Give your AI agents a fetch() that pays. Multi-protocol, multi-chain, open source.
Sovereign oracle protocol — cryptographically signed data over Lightning sats (L402) and USDC on Base (x402). 11 feeds, 9 exchanges, DLC attestations, MCP server. No API keys, no accounts, no trust.
Enable AI agents to access paid APIs across multiple protocols and chains with automated payment and data retrieval in one call.
Announce HTTP 402 services on Nostr for decentralised discovery. Kind 31402 parameterised replaceable events.