x402 spend controls compared: Shotoku, AgentPay MCP, x402-cfo and PolicyLayer
· By the Shotoku team
Short answer: x402 defines how an agent pays for a request. A budget that spans many requests has to come from something else, and the check has to run after the 402 response and before the agent signs. Four tools do this in different ways:
- x402-cfo if you want a drop-in client with hourly, daily and session budgets, analytics and anomaly detection.
- AgentPay MCP if you want the wallet and the payment tools in one MCP server, with optional limits on-chain.
- Shotoku if you want a deterministic local policy, human approval and a tamper-evident record, in a tool that never touches your keys.
- PolicyLayer needs a check first. Its x402 SDK was last published in January 2026, and its website now describes a different product.
How do the four tools compare?
| Shotoku | AgentPay MCP | x402-cfo | PolicyLayer SDK | |
|---|---|---|---|---|
| What it is | Policy engine and ledger. Authorizes payments, never makes them. | MCP server with wallet and payment tools | Client library around your x402 wallet | SDK around your wallet, with decisions from a hosted API |
| Version reviewed | main branch (npm: @shotoku/core 0.2.2) | 4.3.0 | 0.5.0 | 1.4.0 |
| Last npm release | August 2026 | October 2026 | March 2026 | January 2026 |
| License | MIT | MIT | MIT, with paid hosted dashboard tiers | MIT SDK. Needs a PolicyLayer API key. |
| Signing key | Never sees it | Loaded into the server process | Stays in the wallet you pass in | Stays on your server, per its README |
| Where the decision runs | Your machine | Your machine, in the server process | Your machine, in your process | api.policylayer.com |
| Spend limits | Per payment, per rule per day, per agent per day | Spend policy in the process, plus optional on-chain limits | Per request, hourly, daily, session | Set in PolicyLayer, plus optional client-side limits |
| Recipient rules | Pin allowed payTo addresses per rule | Not covered in the README | Host allowlist and blocklist | Allowed and blocked recipients |
| Human approval | Built in: terminal, local dashboard, Telegram | Approval queue. A real gate only if the owner key is separate from the agent key. | None documented. Anomaly detection has a review mode. | None documented in the SDK README |
| Payment record | Hash-chained JSONL, checked against signed snapshots | On-chain wallet events. x402 receipts are in memory, capped at 256. | Ledger with JSON and CSV export | None documented in the SDK README |
| After a restart | Ledger and budgets persist | Rolling policy state is cleared | Persists with JsonFileStorage | Held by the service |
| x402 integration | You call authorize, then sign | x402_pay tool | agent.fetch() replaces fetch | x402Client.pay() |
Where should an x402 budget check run?
Between the 402 response and the signature. Before the 402, there is no amount to check. After the signature, the payment can settle. That gap is the only point where the agent knows the full cost and nothing irreversible has happened. All four tools work there. What differs is who can override the check and what is left afterward.
What should you check in any x402 spend control?
- Can the agent change its own limit?AgentPay’s README is direct about this: the same agent can call
set_spend_policyagain. Its on-chain limits avoid that, but only if the wallet owner sets them on the contract. - Does spending history survive a restart? If rolling totals live in memory, a restart resets the budget. AgentPay documents this. x402-cfo fixes it with a storage adapter, so make sure you configure one.
- Is the human gate separate from the agent? An approval the agent can grant itself is not an approval. Check where the approval key or command lives.
- Does it trust the 402 body? The server asking to be paid writes that response. A hostile server can name an allowlisted vendor as the resource and put its own address in
payTo. Ask which fields come from the server and which come from your own request. - Can you prove the log later? A plain log can be edited without trace. A hash chain breaks if a past entry changes.
What does this look like in Shotoku?
This policy allows small payments to one API at one address, caps every agent at $5 a day, and sends everything else to a human:
The check goes between the 402 and your signing code:
We ran this policy against five simulated 402 responses, using USDC on Base:
| 402 response | Result |
|---|---|
| $0.05 from the allowed host to the allowed address | approved |
| $0.50 from the allowed host | denied: over the $0.10 limit |
| $0.05 from the allowed host to a different address | pending_approval |
| $0.05 from an unknown host | pending_approval |
| Unknown host claiming to be the allowed API | rejected before evaluation: resource and request host differ |
Where does Shotoku fall short?
- It isn’t drop-in for x402. You add the call yourself. x402-cfo wraps
fetch, and AgentPay gives the agent anx402_paytool. - Code that skips the check isn’t stopped.Shotoku holds no key, so if your agent can sign directly, it can pay without asking. To close that route, keep the key behind a service that verifies Shotoku’s signed receipts. AgentPay’s on-chain limits are stronger here, because the contract enforces them whatever the process does.
- No analytics or anomaly detection. Rules are deterministic by design. If you want burn rate, cost estimates or statistical anomaly blocking, x402-cfo has them.
- Budgets are daily only. There are no hourly or session windows yet.
- Only USDC on Base works by default. Other assets must be registered. Unknown tokens are refused.
- It’s beta, and npm is behind main. Recipient rules, agent budgets, the request-host check above and the local dashboard and Telegram approvals are in the repo but not in the current npm release. The table describes main.
Which x402 spend control should you use?
| If you need | Use |
|---|---|
| The fastest setup, with budgets and analytics | x402-cfo |
| An agent wallet and payments in one MCP server | AgentPay MCP |
| Limits a compromised process can't change | AgentPay MCP with on-chain limits and a separate owner key |
| Human approval for anything outside policy | Shotoku |
| A record you can verify later | Shotoku |
| The same policy across x402, PayPal and MCP tools | Shotoku |
| No signing key in the tool that decides | Shotoku or x402-cfo |
These aren’t all exclusive. On-chain limits work as a hard ceiling underneath a local policy that decides each payment.
Common questions
Can a prompt enforce an x402 budget?
No. A prompt is an instruction the model can misread or ignore, and a prompt injection can override it. A budget has to be enforced by code outside the model.
Does a spend control need to hold my private key?
No. A decision only needs the amount, the recipient and the resource. Shotoku and x402-cfo leave signing to your wallet, and PolicyLayer says keys stay on your server. AgentPay loads the key because it is also the wallet.
What about AWS, Visa and Mastercard?
Platforms such as Amazon Bedrock AgentCore Payments are adding agent payments with their own limits. We left them out because this post covers tools you can add to an x402 client yourself.
Try it
Read the x402 guide or start with the quickstart. Shotoku is open source, deterministic, holds no funds and runs on your machine.
Sources
- agentpay-mcp on npm and GitHub
- x402-cfo on npm and GitHub
- @policylayer/sdk on npm and policylayer.com
- Shotoku on GitHub
- x402.org