
agentpay
io.github.Hellotravisssv0.9.0Updated Oct 1, 2026
Enforced budgets for agents paying x402 APIs: the gateway holds the wallet, not the agent.
Installation
In SourceWeft
- Open agentpay in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
agentpay
[CI] [License: MIT] [node] [tests]
A cross-rail spend-policy gateway for AI agent payments. It sits between your agents and anything that charges them money — x402-style paid APIs, Alipay/WeChat-style agent payments, whatever comes next — and answers the question every company deploying paying agents will have to answer:
"How do I let my agent spend money — across several payment rails — without giving it my wallets?"
Agents never hold payment credentials. They call paid resources through the gateway, which:
- intercepts the
402 Payment Requiredhandshake and collects every payment option the merchant accepts, - routes to one rail (agent's rail preference first, ties broken by cheapest cost in the policy's base currency),
- checks the payment against that agent's spend policy — budgets and caps are denominated in one base currency and enforced across all rails and currencies via exact FX conversion,
- executes approved payments on the chosen rail,
- retries the request with the payment proof and returns the unlocked response,
- writes every decision — denials included — to an append-only audit log.
The built-in dashboard (GET /admin) — live spend vs. budgets, per-rail breakdown, and one-click approve/reject on held payments.
For how it's built and why — design principles, the full 402 request lifecycle, and where the simple parts grow — see docs/ARCHITECTURE.md.
Where it fits — the neutral layer
The platforms are racing to let agents spend, and each is building a closed loop: Alipay's ACT delegated-payment protocol, WeChat Pay's isolated "AI card" with user-set authorization scope and spend limits, x402 for crypto-native APIs. Every platform wants agents spending inside its wallet, on its rail — and the design they keep converging on (a wallet isolated from your real account, scoped authorization, per-spend limits, big payments held for confirmation, a full audit trail) is exactly the control surface this project is built around. The thesis is no longer speculative; it's where the giants are pointing their capex.
But a company running real agents doesn't get to live in one loop. Its agents pay an x402 API in USDC, a vendor in CNY, the next thing in whatever ships next quarter — and no single platform gives it one neutral view across all of them: one base-currency budget, one audit trail, one policy, one place where the agent never holds a credential. The more these closed loops fragment, the more that spanning layer is missing.
That layer is agentpay. It sits above the rails — x402, Alipay, WeChat, mock — behind a two-method interface (rails/rail.ts), so budget, policy, FX, routing, and audit are written once and every rail plugs in underneath. It's rail-neutral and self-hosted by design: the value is precisely the part no platform racing to own its own loop will build for you.
Quick start
From source:
The demo runs a merchant that accepts USDC (x402-style) or CNY (Alipay-style); two agents with different rail preferences get routed differently, and one USD budget governs both — a 0.36 CNY purchase consumes ~0.0504 USD of it. Per-transaction caps, payee blocklists, budget exhaustion, the per-rail spend breakdown, and the audit trail are all shown.
Install as an agent skill
There's a ready-to-install agent skill in skill/ — a step-by-step runbook an AI assistant (Claude Code, OpenClaw, …) follows to set agentpay up for you: install + self-test, write a deny-by-default policy, launch the gateway, reroute the agent's paid calls through /proxy, then operate it (spend, audit, approvals, live policy edits) and harden for production. It bundles policy templates and a troubleshooting + API reference. Point your assistant at skill/SKILL.md, or install it from a skill marketplace.
Use from Claude / Cursor (MCP)
Give an MCP agent a budget it cannot exceed. The agentpay-mcp server holds only
the agent's gateway API key — the wallet and the limits stay in the gateway. Unlike
honor-system budget tools, the agent is never asked to check its budget; a payment
over the limit simply isn't signed.
Tools: paid_fetch(url, method?, body?) — fetch any URL; the gateway pays x402/402
within policy. Denials and approval holds come back as tool errors the model can
explain. check_budget() — spent today/this month vs limits (via the agent-scoped
GET /v1/budget, which shows an agent only its own numbers).
Policies
Policies are deny-by-default: an agent with no policy entry cannot spend at all. See policies/example.json:
All money is exact decimal (bigint micro-units, 6 dp — USDC precision); FX conversions round up so budgets are enforced conservatively. No floats anywhere near amounts. Payments in a currency with no configured rate to the base currency are denied (no_fx_rate).
API
Successful paid responses carry X-Gateway-Payment-Id, X-Gateway-Rail, and X-Gateway-Payment-Amount headers. Denials return 403 with the violated rule id (per_transaction_max, daily_budget, payee_blocklisted, no_fx_rate, approval_rejected, ...) so the agent can explain itself or back off.
Human-in-the-loop approvals
Set requireApprovalOver on an agent and any policy-approved payment at or above that base-currency amount is held instead of executed: the proxy returns 202 with an approvalId rather than paying. An operator approves or rejects via POST /admin/approvals/:id; the agent's retry then executes (approved) or is denied with approval_rejected. Each approval is single-use, so it unlocks exactly one payment. Budgets are still re-checked at execution time on the retry.
Persistence
By default the ledger, audit log, and approvals live in memory. Point any of them at a file to make state survive restarts — .sqlite selects a transactional SQLite backend (Node's built-in node:sqlite, no extra dependency), anything else is append-only JSONL:
Live FX rates
FixedRateProvider is fine for static pairs; CachingRateProvider wraps any async rate source (a RateFetcher, default httpRateFetcher hits exchangerate.host) with a TTL and a hard staleness limit. Past that limit a cached rate is refused (no_fx_rate) rather than used — a payment is never priced on a stale rate. Stablecoin pegs can be pinned so they never expire or fetch.
Editing policies (live)
Policies change at runtime — no restart. The PolicyManager owns the live config; every decision reads through it, so an edit takes effect on the next request. Two ways in, kept in sync:
- Admin API / dashboard —
PUT/DELETE /admin/agents/:id(the dashboard's edit pencils and "add agent" button drive these). Each edit is validated, audited aspolicy_changed, and written back to the policy file. - The file itself —
npm run devwatches the policy file and hot-reloads out-of-band edits. The write-back and the watcher don't fight:reload()no-ops when the file is byte-identical to the in-memory state, so a self-write doesn't trigger a reload loop. (fxRatesare built once at startup and not hot-reloaded.)
Multi-tenant API keys
Agents authenticate with Authorization: Bearer <key>. Keys are minted per agent (an agent can hold several, for rotation) via POST /admin/keys or the dashboard — the raw secret is returned exactly once; only its SHA-256 hash is stored, so a leaked store yields no usable credentials. Keys support an optional expiry and can be revoked instantly (DELETE /admin/keys/:id); both are audited (apikey_created / apikey_revoked).
By default a valid Bearer key authenticates and X-Agent-Id still works (convenient for local dev). Set REQUIRE_API_KEY=1 (or requireApiKey: true) to reject X-Agent-Id so only a valid key authenticates. Persist keys across restarts with APIKEYS_FILE=./keys.sqlite.
Payment rails
Rails implement one interface (src/rails/rail.ts): supports(network) + pay(ctx) -> receipt. Adding a rail never touches policy, FX, or routing code. Included:
MockRail— instant in-process settlement; instantiate several to simulate a multi-rail deployment.X402Rail— adapter for Coinbase's x402 protocol, with a real client-side payment implementation:createEip3009Signerproduces signed EIP-3009transferWithAuthorizationpayloads for USDC on Base / Base Sepolia. Speaks both x402 v1 and v2: v1 (X-PAYMENT, body requirements) and v2 (PAYMENT-REQUIRED/PAYMENT-SIGNATURE/PAYMENT-RESPONSEheaders, CAIP-2 networks likeeip155:84532, atomicamount, the chosen requirement echoed verbatim asaccepted). Permit2-only requirements are refused rather than mis-signed. Signing is fully offline; the merchant's facilitator settles on-chain. Verified two ways: signatures are checked cryptographically in the test suite, and the rail has settled a real payment on Base Sepolia end to end (see below).AlipayActRail— adapter shaped for Alipay's agent-payment stack (AI付 under the ACT delegation model); bring your merchant integration viaexecutePayment.
Credentials live inside the rail callbacks you supply — the gateway core never touches keys. Planned: Google AP2.
Buying a real x402 resource on Base Sepolia
This has been run for real: the gateway settled 0.01 USDC on Base Sepolia through Coinbase's hosted testnet facilitator from a wallet holding zero ETH (the facilitator pays gas — x402 is gasless for the payer). On-chain proof: 0x3108b5…54ff9d (x402 v1). x402 v2 was then settled the same way against Coinbase's official @x402/express 2.27 merchant: 0x8c0256…f668c5.
To reproduce — public testnet endpoints come and go, so the reliable path is a local x402 merchant:
Or point TARGET_URL at any live x402 resource that settles on base-sepolia.
Security
It moves money, so the control plane is hardened, not just the math:
- Admin API auth — set
ADMIN_TOKENand every/admin/*data/mutation endpoint requires it (Authorization: BearerorX-Admin-Token, constant-time compared). Unset, the admin API is open, so the CLI binds127.0.0.1by default (override withHOST) and warns at startup. The dashboard carries the token (seed it once via/admin#token=…). - SSRF guard —
/proxyrefuses targets that resolve to private/loopback/link-local ranges (incl. the169.254.169.254cloud-metadata IP) by default. The guard runs at connect time via a pinned DNS lookup and is re-applied to every redirect hop, so neither DNS rebinding nor a redirect-to-internal can slip past. Opt in withallowPrivateTargetsonly for local testing. - x402 asset allowlist — the signer refuses to sign an EIP-3009 authorization for any token not on a per-network allowlist (default: canonical USDC), so a malicious
402can't trick the wallet into authorizing a transfer of a different, more valuable token. Authorization validity is clamped (maxAuthorizationSeconds). - No double-spend under concurrency — the decide→execute→record window is serialized per agent, so concurrent payments can't both pass the budget check before either is recorded.
- DoS limits — 1 MiB request-body cap (
413), 30 s upstream fetch timeout, and the upstream response is streamed (not buffered whole into memory). - Money integrity — exact
bigintarithmetic (no floats), API keys stored only as SHA-256 hashes (raw secret shown once), and the upstreamAuthorizationheader is never forwarded.
Deploy checklist: set ADMIN_TOKEN, enable REQUIRE_API_KEY=1, keep allowPrivateTargets off, and put the gateway behind TLS. Full threat model, hardening list, and checklist in docs/SECURITY.md.
Status & roadmap
This is an MVP. The policy engine, FX layer, cross-rail router, ledger, audit log, approvals, persistence, and 402 proxy flow are tested and working end to end against mock rails; the x402 rail has settled a real payment on Base Sepolia. Done since the first cut:
- Live FX rate provider with caching and staleness limits (
CachingRateProvider) - Persistent storage beyond JSONL — transactional SQLite via
node:sqlite - Human-in-the-loop approvals ("hold payments over $X for review")
- Web dashboard for spend + audit + approvals + policy editing (
GET /admin) - Policy hot-reload and an admin API for editing policies
- Multi-tenant API key management (hashed keys, mint/revoke, per-key expiry)
- End-to-end x402 v2 settlement against the official v2 merchant — 0.01 USDC on Base Sepolia
- End-to-end x402 settlement against a live facilitator — 0.01 USDC settled on Base Sepolia (reproduce: above)
Not yet built:
- Real Alipay AI付/ACT settlement (requires merchant onboarding)
Source: README.md at commit 6692274
Tools
0Version history
1- v0.9.0LatestOct 1, 2026


