StableOps Agent Payments lets autonomous agents initiate stablecoin payments under explicit policies, organization and agent budgets, and human approvals. The agent receives a restricted Agent Key instead of a management API key or unrestricted wallet access.
This SDK runs inside the agent process. It requests paid resources, coordinates
payment intents with the StableOps Control API, obtains signatures from a
customer-hosted @stableops/agent-signer sidecar, and retries the original x402
request with the payment proof. StableOps does not proxy the resource request or
hold the customer's private key.
- End-to-end x402 v2
exactpayment flow for HTTPS resources. - Policy, budget, and approval enforcement through the StableOps Control API.
- Customer-controlled signing through a local signer sidecar.
- HTTPS-only resource requests with pinned DNS results and private-address blocking.
- Same-origin redirects before payment and no redirects after attaching a signature.
- Task-scoped idempotency and approval-resume support.
- Read-only budget and payment queries scoped to the current Agent Key.
- Four framework-neutral tool definitions for AI runtimes.
- Dual CJS and ESM builds with generated TypeScript declarations.
- Node.js 20 or newer.
- A StableOps Agent Key. Do not use a management API key in the agent runtime.
- A customer-hosted
@stableops/agent-signersidecar. - An HTTPS x402 resource supported by the current StableOps environment.
pnpm add @stableops/agent-sdknpm install @stableops/agent-sdkyarn add @stableops/agent-sdkimport {
AgentPaymentsControlClient,
HttpAgentSignerSidecar,
SafeHttpsRequester,
StableOpsAgent,
} from '@stableops/agent-sdk'
function required(name: string): string {
const value = process.env[name]?.trim()
if (!value) throw new Error(`Missing environment variable ${name}`)
return value
}
const payments = new StableOpsAgent({
control: new AgentPaymentsControlClient({
agentKey: required('STABLEOPS_AGENT_KEY'),
}),
sidecar: new HttpAgentSignerSidecar({
url: 'http://127.0.0.1:8789',
authToken: required('STABLEOPS_SIDECAR_TOKEN'),
}),
requester: new SafeHttpsRequester(),
})
const result = await payments.x402Fetch('https://api.example.com/paid', {
idempotencyKey: 'task_123:paid-resource:v1',
context: {
workflowId: 'research-workflow-1',
taskId: 'market-report-2026-08-12',
toolName: 'premium_market_data',
purposeCode: 'research.market-data',
costCenter: 'research',
},
})
if (result.status === 'paid' || result.status === 'not_required') {
const data = await result.response.json()
console.log(data)
} else if (result.status === 'awaiting_approval') {
// Save result.intentId and wait for the console or a Webhook to confirm approval.
console.log(`Waiting for approval: ${result.intentId}`)
}Only after the console or a Webhook confirms approval, resume the original payment:
const approvedIntentId = 'pint_...' // Load the ID saved from awaiting_approval.
const resumed = await payments.x402Fetch('https://api.example.com/paid', {
resumeIntentId: approvedIntentId,
})Do not resume immediately after receiving awaiting_approval, and do not create
another payment. The same intentId preserves the approved parameters and budget
reservation.
The SDK also exposes Agent Key-scoped read methods:
const budget = await payments.getBudget()
const payment = await payments.getPayment('pint_...')
const recentPayments = await payments.listRecentPayments(20)When the resource server declares the x402 payment-identifier extension, the
SDK derives a stable identifier from the StableOps payment intent and reuses it
for approval resumes and request retries.
For workflows that can restart or wait for approval, wrap the agent in
DurableAgentPaymentWorkflow. A production store must persist records and
implement runExclusive with a distributed lock for each workflowId:
const workflow = new DurableAgentPaymentWorkflow({
agent: payments,
store: durableWorkflowStore,
})
const { record, response } = await workflow.run(
'report-job-2026-08-09',
'https://api.example.com/paid',
{
taskId: 'market-report-2026-08-12',
toolName: 'premium_market_data',
purposeCode: 'research.market-data',
},
)The same workflow ID is permanently bound to one URL and one idempotency key.
If settlement becomes unknown, later runs query the original intent instead of
creating another authorization. MemoryAgentPaymentWorkflowStore is provided
only for local development and tests.
Resources may also declare the x402 offer-receipt extension. Because a valid
signature alone does not prove that its key is authorized for the resource,
the SDK accepts this extension only when offerReceiptVerifier is configured.
That verifier must validate both the cryptographic signature and the key's
binding to the protected origin. Verified offers and receipts are returned in
the fetch result and persisted by the durable workflow.
BazaarAgentPaymentDiscovery searches or lists x402 Bazaar resources through a
configured facilitator. It returns only concrete HTTPS GET resources with a
USDC exact payment requirement supported by Agent Payments; discovery never
bypasses the normal origin, recipient, amount, budget, risk, or approval checks.
agentPaymentTools contains the framework-neutral definitions
stableops_get_budget, stableops_x402_fetch, stableops_get_payment, and
stableops_list_recent_payments.
For the complete setup flow, policy and approval behavior, signer deployment, and x402 examples, see the official documentation:
- English docs: https://stableops.dev/en/docs/agent-payments
- Chinese docs: https://stableops.dev/zh/docs/agent-payments
- Quickstart: https://stableops.dev/en/docs/agent-payments/quickstart
The current release supports:
- x402 v2
exactpayments. GETrequests on six EVM mainnets and their testnets, plus Solana mainnet and Devnet.- Configured USDC contracts on those networks. TRON and Nile are excluded.
- Sandbox accepts test networks only. Live supports mainnets after StableOps enables the organization upon completion of its risk and recovery-drill gates.
It does not support browser or Edge runtimes, assets other than USDC, POST,
upto, direct transfers, or raw private keys.
Never retry a SettlementUnknownError by creating another intent. Query the
existing intent and let StableOps reconcile its authorization nonce.
This SDK is licensed under Apache-2.0.