Loading...
Loading...
Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol.
npx skill4agent add affaan-m/ecc agent-payment-x402| Need | Recommended path |
|---|---|
| Agent pays a 402-gated API on Base or another agentwallet-supported chain | Use |
| Agent pays a 402-gated API on X Layer | Use OKX Agent Payments Protocol from |
| TypeScript API charges agents | Use OKX Payments TypeScript seller SDK docs for Express, Hono, Fastify, or Next.js |
| Go API charges agents | Use OKX Payments Go seller SDK docs for Gin, Echo, or |
| Rust API charges agents | Use OKX Payments Rust seller SDK docs for Axum |
| Java API charges agents | Use OKX Payments Java seller SDK docs for Spring Boot 2/3, Java EE, or Jakarta |
| Python API charges agents | Check the current OKX Payments repository before implementation; a Python seller guide may not be available |
agentwallet-sdkeip155:196402SpendingPolicySecurity note: Always pin the package version. This tool manages private keys — unpinnedinstalls introduce supply-chain risk.npx
{
"mcpServers": {
"agentpay": {
"command": "npx",
"args": ["agentwallet-sdk@6.0.0"]
}
}
}| 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
okx/onchainos-skillsskills/okx-agent-payments-protocol/SKILL.mdskills/okx-x402-payment/SKILL.md| Runtime | Current guide |
|---|---|
| TypeScript | |
| Go | |
| Rust | |
| Java | |
okx-agent-payments-protocolPrerequisites: 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
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;
});agentwallet-sdk@6.0.0list_transactionsagentwallet-sdkokx/paymentsokx/onchainos-skills