agent-payment-x402
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAgent Payment Execution (x402)
Agent支付执行(x402)
Enable AI agents to make autonomous payments with built-in spending controls. Uses the x402 HTTP payment protocol and MCP tools so agents can pay for external services, APIs, or other agents without custodial risk.
支持AI Agent在内置支出控制的前提下进行自主支付。采用x402 HTTP支付协议和MCP工具,让Agent无需承担托管风险即可向外部服务、API或其他Agent支付费用。
When to Use
适用场景
Use when: your agent needs to pay for an API call, purchase a service, settle with another agent, enforce per-task spending limits, or manage a non-custodial wallet. Pairs naturally with cost-aware-llm-pipeline and security-review skills.
适用于以下场景:你的Agent需要支付API调用费用、购买服务、与其他Agent结算、执行单任务支出限制,或是管理非托管钱包。可天然与cost-aware-llm-pipeline和security-review技能搭配使用。
How It Works
工作原理
x402 Protocol
x402协议
x402 extends HTTP 402 (Payment Required) into a machine-negotiable flow. When a server returns , the agent's payment tool automatically negotiates price, checks budget, signs a transaction, and retries — no human in the loop.
402x402将HTTP 402(需要付款)扩展为机器可协商的流程。当服务器返回时,Agent的支付工具会自动协商价格、检查预算、签署交易并重试,全程无需人工介入。
402Spending Controls
支出控制
Every payment tool call enforces a :
SpendingPolicy- Per-task budget — max spend for a single agent action
- Per-session budget — cumulative limit across an entire session
- Allowlisted recipients — restrict which addresses/services the agent can pay
- Rate limits — max transactions per minute/hour
每次支付工具调用都会强制执行规则:
SpendingPolicy- 单任务预算 — 单个Agent动作的最高支出额度
- 单会话预算 — 整个会话期间的累计支出上限
- 收款方白名单 — 限制Agent可向哪些地址/服务付款
- 速率限制 — 每分钟/小时最多可执行的交易次数
Non-Custodial Wallets
非托管钱包
Agents hold their own keys via ERC-4337 smart accounts. The orchestrator sets policy before delegation; the agent can only spend within bounds. No pooled funds, no custodial risk.
Agent通过ERC-4337智能账户持有自己的密钥。编排器在下发任务前设置策略,Agent仅可在限制范围内支出。没有资金池,不存在托管风险。
MCP Integration
MCP集成
The payment layer exposes standard MCP tools that slot into any Claude Code or agent harness setup.
Security note: Always pin the package version. This tool manages private keys — unpinnedinstalls introduce supply-chain risk.npx
json
{
"mcpServers": {
"agentpay": {
"command": "npx",
"args": ["agentwallet-sdk@6.0.0"]
}
}
}支付层暴露标准MCP工具,可嵌入任何Claude Code或Agent框架配置中。
安全提示:务必固定包版本。该工具管理私钥——未固定版本的安装会引入供应链风险。npx
json
{
"mcpServers": {
"agentpay": {
"command": "npx",
"args": ["agentwallet-sdk@6.0.0"]
}
}
}Available Tools (agent-callable)
可用工具(Agent可调用)
| Tool | Purpose |
|---|---|
| Check agent wallet balance |
| Send payment to address or ENS |
| Query remaining budget |
| Audit trail of all payments |
Note: Spending policy is set by the orchestrator before delegating to the agent — not by the agent itself. This prevents agents from escalating their own spending limits. Configure policy viain your orchestration layer or pre-task hook, never as an agent-callable tool.set_policy
| 工具 | 用途 |
|---|---|
| 查看Agent钱包余额 |
| 向地址或ENS发送付款 |
| 查询剩余预算 |
| 所有支付的审计追踪记录 |
注意:支出策略由编排器在向Agent下发任务前设置,而非Agent自身设置。这可以防止Agent自行提升支出限额。请通过编排层的或任务前置钩子配置策略,绝对不要将其设为Agent可调用工具。set_policy
Examples
示例
Budget enforcement in an MCP client
MCP客户端中的预算强制执行
When building an orchestrator that calls the agentpay MCP server, enforce budgets before dispatching paid tool calls.
Prerequisites: Install the package before adding the MCP config —withoutnpxwill prompt for confirmation in non-interactive environments, causing the server to hang:-ynpm install -g agentwallet-sdk@6.0.0
typescript
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
async function main() {
// 1. Validate credentials before constructing the transport.
// A missing key must fail immediately — never let the subprocess start without auth.
const walletKey = process.env.WALLET_PRIVATE_KEY;
if (!walletKey) {
throw new Error("WALLET_PRIVATE_KEY is not set — refusing to start payment server");
}
// Connect to the agentpay MCP server via stdio transport.
// Whitelist only the env vars the server needs — never forward all of process.env
// to a third-party subprocess that manages private keys.
const transport = new StdioClientTransport({
command: "npx",
args: ["agentwallet-sdk@6.0.0"],
env: {
PATH: process.env.PATH ?? "",
NODE_ENV: process.env.NODE_ENV ?? "production",
WALLET_PRIVATE_KEY: walletKey,
},
});
const agentpay = new Client({ name: "orchestrator", version: "1.0.0" });
await agentpay.connect(transport);
// 2. Set spending policy before delegating to the agent.
// Always verify success — a silent failure means no controls are active.
const policyResult = await agentpay.callTool({
name: "set_policy",
arguments: {
per_task_budget: 0.50,
per_session_budget: 5.00,
allowlisted_recipients: ["api.example.com"],
},
});
if (policyResult.isError) {
throw new Error(
`Failed to set spending policy — do not delegate: ${JSON.stringify(policyResult.content)}`
);
}
// 3. Use preToolCheck before any paid action
await preToolCheck(agentpay, 0.01);
}
// Pre-tool hook: fail-closed budget enforcement with four distinct error paths.
async function preToolCheck(agentpay: Client, apiCost: number): Promise<void> {
// Path 1: Reject invalid input (NaN/Infinity bypass the < comparison)
if (!Number.isFinite(apiCost) || apiCost < 0) {
throw new Error(`Invalid apiCost: ${apiCost} — action blocked`);
}
// Path 2: Transport/connectivity failure
let result;
try {
result = await agentpay.callTool({ name: "check_spending" });
} catch (err) {
throw new Error(`Payment service unreachable — action blocked: ${err}`);
}
// Path 3: Tool returned an error (e.g., auth failure, wallet not initialised)
if (result.isError) {
throw new Error(
`check_spending failed — action blocked: ${JSON.stringify(result.content)}`
);
}
// Path 4: Parse and validate the response shape
let remaining: number;
try {
const parsed = JSON.parse(
(result.content as Array<{ text: string }>)[0].text
);
if (!Number.isFinite(parsed?.remaining)) {
throw new TypeError("missing or non-finite 'remaining' field");
}
remaining = parsed.remaining;
} catch (err) {
throw new Error(
`check_spending returned unexpected format — action blocked: ${err}`
);
}
// Path 5: Budget exceeded
if (remaining < apiCost) {
throw new Error(
`Budget exceeded: need $${apiCost} but only $${remaining} remaining`
);
}
}
main().catch((err) => {
console.error(err);
process.exitCode = 1;
});构建调用agentpay MCP服务器的编排器时,在调度付费工具调用前先执行预算校验。
前置要求:添加MCP配置前先安装包——不带参数的-y在非交互环境下会弹出确认提示,导致服务器挂起:npxnpm install -g agentwallet-sdk@6.0.0
typescript
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
async function main() {
// 1. 构建传输层前验证凭据。
// 缺少密钥必须立即失败——绝对不要让子进程在没有认证的情况下启动。
const walletKey = process.env.WALLET_PRIVATE_KEY;
if (!walletKey) {
throw new Error("WALLET_PRIVATE_KEY未设置——拒绝启动支付服务器");
}
// 通过stdio传输层连接到agentpay MCP服务器。
// 仅将服务器需要的环境变量加入白名单——绝对不要将整个process.env转发给管理私钥的第三方子进程。
const transport = new StdioClientTransport({
command: "npx",
args: ["agentwallet-sdk@6.0.0"],
env: {
PATH: process.env.PATH ?? "",
NODE_ENV: process.env.NODE_ENV ?? "production",
WALLET_PRIVATE_KEY: walletKey,
},
});
const agentpay = new Client({ name: "orchestrator", version: "1.0.0" });
await agentpay.connect(transport);
// 2. 向Agent下发任务前设置支出策略。
// 务必验证设置成功——静默失败意味着没有任何控制生效。
const policyResult = await agentpay.callTool({
name: "set_policy",
arguments: {
per_task_budget: 0.50,
per_session_budget: 5.00,
allowlisted_recipients: ["api.example.com"],
},
});
if (policyResult.isError) {
throw new Error(
`支出策略设置失败——请勿下发任务:${JSON.stringify(policyResult.content)}`
);
}
// 3. 任何付费操作前执行preToolCheck
await preToolCheck(agentpay, 0.01);
}
// 工具前置钩子:关闭式失败预算校验,包含4条独立错误路径。
async function preToolCheck(agentpay: Client, apiCost: number): Promise<void> {
// 路径1:拒绝无效输入(NaN/Infinity会绕过<比较)
if (!Number.isFinite(apiCost) || apiCost < 0) {
throw new Error(`无效的apiCost:${apiCost} —— 操作已拦截`);
}
// 路径2:传输/连接失败
let result;
try {
result = await agentpay.callTool({ name: "check_spending" });
} catch (err) {
throw new Error(`支付服务不可达——操作已拦截:${err}`);
}
// 路径3:工具返回错误(例如认证失败、钱包未初始化)
if (result.isError) {
throw new Error(
`check_spending调用失败——操作已拦截:${JSON.stringify(result.content)}`
);
}
// 路径4:解析并验证响应格式
let remaining: number;
try {
const parsed = JSON.parse(
(result.content as Array<{ text: string }>)[0].text
);
if (!Number.isFinite(parsed?.remaining)) {
throw new TypeError("缺少'remaining'字段或该字段值不是有限数");
}
remaining = parsed.remaining;
} catch (err) {
throw new Error(
`check_spending返回意外格式——操作已拦截:${err}`
);
}
// 路径5:超出预算
if (remaining < apiCost) {
throw new Error(
`超出预算:需要$${apiCost},但仅剩$${remaining}`
);
}
}
main().catch((err) => {
console.error(err);
process.exitCode = 1;
});Best Practices
最佳实践
- Set budgets before delegation: When spawning sub-agents, attach a SpendingPolicy via your orchestration layer. Never give an agent unlimited spend.
- Pin your dependencies: Always specify an exact version in your MCP config (e.g., ). Verify package integrity before deploying to production.
agentwallet-sdk@6.0.0 - Audit trails: Use in post-task hooks to log what was spent and why.
list_transactions - Fail closed: If the payment tool is unreachable, block the paid action — don't fall back to unmetered access.
- Pair with security-review: Payment tools are high-privilege. Apply the same scrutiny as shell access.
- Test with testnets first: Use Base Sepolia for development; switch to Base mainnet for production.
- 下发任务前设置预算:生成子Agent时,通过编排层附加SpendingPolicy。绝对不要给Agent无限制的支出权限。
- 固定依赖版本:务必在MCP配置中指定确切版本(例如)。部署到生产环境前验证包完整性。
agentwallet-sdk@6.0.0 - 审计追踪:在任务后置钩子中使用记录支出明细和原因。
list_transactions - 关闭式失败:如果支付工具不可达,拦截付费操作——不要回退到无计量访问。
- 搭配安全审查:支付工具属于高权限工具,要采用和shell访问同等的审查标准。
- 先使用测试网测试:开发阶段使用Base Sepolia;生产环境再切换到Base主网。
Production Reference
生产参考
- npm:
agentwallet-sdk - Merged into NVIDIA NeMo Agent Toolkit: PR #17 — x402 payment tool for NVIDIA's agent examples
- Protocol spec: x402.org
- npm:
agentwallet-sdk - 已合并到NVIDIA NeMo Agent工具包: PR #17 — 为NVIDIA的Agent示例提供x402支付工具
- 协议规范: x402.org