Skip to content

Commit 3ae0df7

Browse files
authored
Merge pull request anomalyco#893 from up2itnow0822/feat/agent-payment-x402-skill
feat: add agent-payment-x402 skill for autonomous agent payments
2 parents a346a30 + 95a1435 commit 3ae0df7

1 file changed

Lines changed: 178 additions & 0 deletions

File tree

‎skills/agent-payment-x402/SKILL.md‎

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
---
2+
name: agent-payment-x402
3+
description: Add x402 payment execution to AI agents — per-task budgets, spending controls, and non-custodial wallets via MCP tools. Use when agents need to pay for APIs, services, or other agents.
4+
origin: community
5+
---
6+
7+
# Agent Payment Execution (x402)
8+
9+
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.
10+
11+
## When to Use
12+
13+
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.
14+
15+
## How It Works
16+
17+
### x402 Protocol
18+
x402 extends HTTP 402 (Payment Required) into a machine-negotiable flow. When a server returns `402`, the agent's payment tool automatically negotiates price, checks budget, signs a transaction, and retries — no human in the loop.
19+
20+
### Spending Controls
21+
Every payment tool call enforces a `SpendingPolicy`:
22+
- **Per-task budget** — max spend for a single agent action
23+
- **Per-session budget** — cumulative limit across an entire session
24+
- **Allowlisted recipients** — restrict which addresses/services the agent can pay
25+
- **Rate limits** — max transactions per minute/hour
26+
27+
### Non-Custodial Wallets
28+
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.
29+
30+
## MCP Integration
31+
32+
The payment layer exposes standard MCP tools that slot into any Claude Code or agent harness setup.
33+
34+
> **Security note**: Always pin the package version. This tool manages private keys — unpinned `npx` installs introduce supply-chain risk.
35+
36+
```json
37+
{
38+
"mcpServers": {
39+
"agentpay": {
40+
"command": "npx",
41+
"args": ["[email protected]"]
42+
}
43+
}
44+
}
45+
```
46+
47+
### Available Tools (agent-callable)
48+
49+
| Tool | Purpose |
50+
|------|---------|
51+
| `get_balance` | Check agent wallet balance |
52+
| `send_payment` | Send payment to address or ENS |
53+
| `check_spending` | Query remaining budget |
54+
| `list_transactions` | Audit trail of all payments |
55+
56+
> **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 via `set_policy` in your orchestration layer or pre-task hook, never as an agent-callable tool.
57+
58+
## Examples
59+
60+
### Budget enforcement in an MCP client
61+
62+
When building an orchestrator that calls the agentpay MCP server, enforce budgets before dispatching paid tool calls.
63+
64+
> **Prerequisites**: Install the package before adding the MCP config — `npx` without `-y` will prompt for confirmation in non-interactive environments, causing the server to hang: `npm install -g [email protected]`
65+
66+
```typescript
67+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
68+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
69+
70+
async function main() {
71+
// 1. Validate credentials before constructing the transport.
72+
// A missing key must fail immediately — never let the subprocess start without auth.
73+
const walletKey = process.env.WALLET_PRIVATE_KEY;
74+
if (!walletKey) {
75+
throw new Error("WALLET_PRIVATE_KEY is not set — refusing to start payment server");
76+
}
77+
78+
// Connect to the agentpay MCP server via stdio transport.
79+
// Whitelist only the env vars the server needs — never forward all of process.env
80+
// to a third-party subprocess that manages private keys.
81+
const transport = new StdioClientTransport({
82+
command: "npx",
83+
args: ["[email protected]"],
84+
env: {
85+
PATH: process.env.PATH ?? "",
86+
NODE_ENV: process.env.NODE_ENV ?? "production",
87+
WALLET_PRIVATE_KEY: walletKey,
88+
},
89+
});
90+
const agentpay = new Client({ name: "orchestrator", version: "1.0.0" });
91+
await agentpay.connect(transport);
92+
93+
// 2. Set spending policy before delegating to the agent.
94+
// Always verify success — a silent failure means no controls are active.
95+
const policyResult = await agentpay.callTool({
96+
name: "set_policy",
97+
arguments: {
98+
per_task_budget: 0.50,
99+
per_session_budget: 5.00,
100+
allowlisted_recipients: ["api.example.com"],
101+
},
102+
});
103+
if (policyResult.isError) {
104+
throw new Error(
105+
`Failed to set spending policy — do not delegate: ${JSON.stringify(policyResult.content)}`
106+
);
107+
}
108+
109+
// 3. Use preToolCheck before any paid action
110+
await preToolCheck(agentpay, 0.01);
111+
}
112+
113+
// Pre-tool hook: fail-closed budget enforcement with four distinct error paths.
114+
async function preToolCheck(agentpay: Client, apiCost: number): Promise<void> {
115+
// Path 1: Reject invalid input (NaN/Infinity bypass the < comparison)
116+
if (!Number.isFinite(apiCost) || apiCost < 0) {
117+
throw new Error(`Invalid apiCost: ${apiCost} — action blocked`);
118+
}
119+
120+
// Path 2: Transport/connectivity failure
121+
let result;
122+
try {
123+
result = await agentpay.callTool({ name: "check_spending" });
124+
} catch (err) {
125+
throw new Error(`Payment service unreachable — action blocked: ${err}`);
126+
}
127+
128+
// Path 3: Tool returned an error (e.g., auth failure, wallet not initialised)
129+
if (result.isError) {
130+
throw new Error(
131+
`check_spending failed — action blocked: ${JSON.stringify(result.content)}`
132+
);
133+
}
134+
135+
// Path 4: Parse and validate the response shape
136+
let remaining: number;
137+
try {
138+
const parsed = JSON.parse(
139+
(result.content as Array<{ text: string }>)[0].text
140+
);
141+
if (!Number.isFinite(parsed?.remaining)) {
142+
throw new TypeError("missing or non-finite 'remaining' field");
143+
}
144+
remaining = parsed.remaining;
145+
} catch (err) {
146+
throw new Error(
147+
`check_spending returned unexpected format — action blocked: ${err}`
148+
);
149+
}
150+
151+
// Path 5: Budget exceeded
152+
if (remaining < apiCost) {
153+
throw new Error(
154+
`Budget exceeded: need $${apiCost} but only $${remaining} remaining`
155+
);
156+
}
157+
}
158+
159+
main().catch((err) => {
160+
console.error(err);
161+
process.exitCode = 1;
162+
});
163+
```
164+
165+
## Best Practices
166+
167+
- **Set budgets before delegation**: When spawning sub-agents, attach a SpendingPolicy via your orchestration layer. Never give an agent unlimited spend.
168+
- **Pin your dependencies**: Always specify an exact version in your MCP config (e.g., `[email protected]`). Verify package integrity before deploying to production.
169+
- **Audit trails**: Use `list_transactions` in post-task hooks to log what was spent and why.
170+
- **Fail closed**: If the payment tool is unreachable, block the paid action — don't fall back to unmetered access.
171+
- **Pair with security-review**: Payment tools are high-privilege. Apply the same scrutiny as shell access.
172+
- **Test with testnets first**: Use Base Sepolia for development; switch to Base mainnet for production.
173+
174+
## Production Reference
175+
176+
- **npm**: [`agentwallet-sdk`](https://www.npmjs.com/package/agentwallet-sdk)
177+
- **Merged into NVIDIA NeMo Agent Toolkit**: [PR #17](https://github.com/NVIDIA/NeMo-Agent-Toolkit-Examples/pull/17) — x402 payment tool for NVIDIA's agent examples
178+
- **Protocol spec**: [x402.org](https://x402.org)

0 commit comments

Comments
 (0)