npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

agent402-client

v0.8.0

Published

Agent402 buyer SDK: resolve a task to a tool across 500+ pay-per-call endpoints and call it with payment handled - free via proof-of-work, or over x402 or MPP (a stock mppx fetch works) with a wallet you keep; the buy side of Agentic Finance. Caching, ide

Readme

agent402-client

A tiny buyer-side client for Agent402 (and any Agent402 instance) - the buy side of Agentic Finance, agents paying per request over x402 or MPP. Resolve a task to a tool, then call it - with payment handled for you. Free pure-CPU tools settle with a built-in proof-of-work (no wallet, zero dependencies); wallet-only tools settle via an x402- or MPP-wrapped fetch you provide, or by card through a prepaid credits key. Results are cached, and retries reuse an Idempotency-Key so a lost response never double-charges.

npm install agent402-client

Runnable copy of the free-tier quickstart below: examples/hello-agent402.js - discover a tool and call it in ~15 lines, no wallet.

Free tier (proof-of-work, no wallet)

import { Agent402 } from "agent402-client";

const a = new Agent402();                       // → https://agent402.tools

// Don't know the slug? Resolve a task in one call.
const matches = await a.find("extract the article from a url");
// → [{ slug: "extract", route, price, inputSchema, example, … }]

// Call it - proof-of-work is solved automatically for free tools.
const out = await a.call("hash", { text: "hello world", algo: "sha256" });
console.log(out.hex);

Paid tools: x402 or MPP, your choice of wire

Wallet-only tools settle in USDC. The SDK never touches your key: pass a payment-aware fetch and it pays 402s for you. Two wires work out of the box, because every paid route on Agent402 carries both offers on the same 402:

Over MPP (Machine Payments Protocol) with the mppx client - USDC on Base/Celo (evm), or natively on Tempo (tempo):

import { Fetch, evm, tempo } from "mppx/client";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.AGENT_KEY);
const mppFetch = Fetch.from({ methods: [tempo.charge({ account }), evm.charge({ account })] });

const a = new Agent402({ fetch: mppFetch, maxPerCallUsd: 0.05 });
const verdict = await a.call("sql-guard", { sql: "UPDATE users SET plan = 'pro' WHERE id = 42" });

The SDK's spending caps, reservations and caching apply identically on the MPP path (pinned by scripts/test-client-mpp.js in the parent repo, which buys through the SDK with a real mppx client).

Over x402 with @x402/fetch - USDC on any of the 12 x402 chains:

import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

const client = new x402Client();
registerExactEvmScheme(client, { signer: privateKeyToAccount(process.env.AGENT_KEY) });
const payFetch = wrapFetchWithPayment(fetch, client);

const a = new Agent402({ fetch: payFetch });
const article = await a.call("extract", { url: "https://example.com/article" });

Pay by card instead of a wallet (prepaid credits)

Buy a credits pack ($20 / $50 / $100) at https://agent402.tools/credits, claim the a402_... key once, and pass it as creditsKey. The SDK then sends Authorization: Bearer a402_... on wallet-only calls; the server authorizes against the key's balance before the handler runs and debits the list price only on a successful (200) response (the X-Credits-Balance header carries what is left; credits never expire). A refused call throws with the balance and a top-up link; nothing is debited.

const client = new Agent402({ creditsKey: "a402_..." });
await client.call("whois", { domain: "example.com" }); // debited per successful call

The same maxPerCallUsd / dailyLimitUsd / maxPerHostUsd caps apply (a credits call reserves its price like a wallet call). A payment fetch still wins when both are given, and free pure-CPU tools keep settling with proof-of-work. The same Bearer header also reads the balance directly, e.g. curl -H "Authorization: Bearer a402_..." https://agent402.tools/api/credits/balance.

Retries never double-charge

Every paid call the SDK makes carries an Idempotency-Key, so a retry of a call whose response was lost replays the original result instead of paying again. If your x402 client attaches the standard payment-identifier extension to its payloads instead, Agent402 honours that id the same way (an exact retry with the same credential replays; a fresh authorization with the same id is a new payment).

Workflows (skill packs)

For jobs that no single tool covers - e.g. "audit a domain", "build a stock brief" - Agent402 ships curated multi-tool skill packs: 5–7 catalog tools composed into a Claude-ready task template. Discover them the same way you'd discover a tool:

const packs = await a.findWorkflows("security audit");
// → [{ slug: "security-audit", title, tagline, toolSlugs, score, url, promptName }]

// Render the full prompt with arguments substituted in (same output as MCP prompts/get).
const { messages } = await a.getWorkflowPrompt("security-audit", { domain: "stripe.com" });
// → feed messages straight to any LLM

Discover the live x402 economy

Want to see who's actually getting paid on x402 right now - not just what tools this service exposes? topSellers() returns the live leaderboard of sellers settling USDC (primarily on Base) in the last ~24h, derived from on-chain transfers. Free to call (no payment, no proof-of-work):

const { window, asOf, results, totalSellers } = await a.topSellers({ limit: 10 });
// → { window: "24h", asOf, totalSellers, results: [{ rank, name, wallet, totalUsd, callsSettled, uniqueBuyers, ... }] }

// Rank by call volume instead of USDC, and include the host's own wallet:
await a.topSellers({ sort: "calls", include: "all" });

API

| Method | What | |---|---| | new Agent402({ baseUrl?, fetch?, creditsKey?, cache?, fetchImpl?, maxPerCallUsd?, dailyLimitUsd?, maxPerHostUsd?, maxResponseBytes? }) | fetch is your x402- or MPP-wrapped fetch for paid tools (optional); creditsKey is a prepaid card-credits key (a402_...) used for paid tools when no fetch is given; cache (default true) memoizes deterministic results; the three USD caps set optional spending limits (see below); maxResponseBytes (default 32MB, null to disable) refuses an oversized response body before it is parsed | | await a.find(task, { k = 5 }) | Resolve a plain-language task to the best-matching tools (route, price, schema, example) | | await a.findWorkflows(task, { k = 2 }) | Resolve a task to matching multi-tool workflow templates (skill packs) | | await a.getWorkflowPrompt(slug, args) | Fetch the rendered prompt messages for a skill pack with arguments substituted in | | await a.topSellers({ limit?, sort?, include? }) | Live x402 leaderboard: which sellers are settling the most USDC (primarily on Base) in the last ~24h (free, no payment) | | await a.call(slug, params, { idempotencyKey?, cache?, maxResponseBytes? }) | Call a tool; auto-pays (PoW for free tools; your payment fetch or the credits key for wallet-only); returns the JSON result | | Agent402.solvePow(pow) | Solve a proof-of-work challenge object → an X-Pow-Solution value | | a.spendingSummary() | Rolling-24h paid spend so far: { dailyUsd, calls, byHost, limits } | | a.clearCache() | Drop the in-memory result cache |

Response size ceiling

You are calling strangers and paying them, and the seller chooses the response. By the time r.json() resolves, a multi-gigabyte body is already in your agent's memory, so this is one of the few checks that cannot be done after the fact in your own code.

Every call is capped at 32MB by default. The declared content-length is refused before a byte is read, and the stream is counted as it arrives, because content-length is the seller's claim about their own body.

const a = new Agent402({ maxResponseBytes: 1_000_000 });   // 1MB everywhere
await a.call("hash", { text: "x" }, { maxResponseBytes: null });  // or per call

An oversized body throws ResponseTooLargeError carrying size, cap, source and paid. Check paid: on a wallet-only tool the money moved before the body arrived, so a refused response is still a spend you made.

Spending caps (never overpay)

By default the client pays whatever a tool costs. Set optional hard ceilings and a call that would exceed one is refused before any payment is signed (it throws SpendingLimitError - no funds move):

import { Agent402, SpendingLimitError } from "agent402-client";

const a = new Agent402({
  fetch: payFetch,
  maxPerCallUsd: 0.05,   // reject any single call priced above $0.05
  dailyLimitUsd: 5,      // rolling-24h ceiling across all sellers
  maxPerHostUsd: 1,      // rolling-24h ceiling per seller host
});

try {
  await a.call("some-expensive-tool", { … });
} catch (e) {
  if (e instanceof SpendingLimitError) console.log(e.limit, e.priceUsd, e.cap);
}

Only settled paid calls count against the rolling window - a blocked or failed call never consumes budget. Free proof-of-work calls are never counted. Omit a cap (or leave it null) for no limit; with none set, behavior is unchanged.

What the caps check. When a cap is set, the client preflights the 402 and checks the ceiling against the larger of the advertised price (from the seller's /api/pricing) and the amount the 402 challenge actually quotes - so a server that under-advertises and then quotes more in the 402 is refused before your wallet fetch signs anything. If the 402 can't be read (FREE_MODE, or an unrecognized challenge shape) it falls back to the advertised price rather than block a legitimate payment. Caps hold under concurrency too: each call reserves its amount synchronously, so N simultaneous calls can't each pass against the same pre-commit total. (The 402 amount is derived assuming stablecoin settlement - atomic / 10^decimals ≈ USD - which matches x402's USDC/USDG rails.)

  • Zero dependencies for the free/proof-of-work path (uses node:crypto).
  • Non-custodial: paid settlement is your @x402/fetch / mppx fetch + wallet (or a prepaid credits key you bought); this client never sees a private key.
  • MIT licensed. Part of Agent402.

Pick the settlement chain (withNetworkPreference)

Multi-chain sellers list Base first, so an unmodified x402 client effectively always settles there. To pin a chain - e.g. USDG on Robinhood Chain - wrap your client before building the fetch:

import { withNetworkPreference } from "agent402-client";
import { x402Client } from "@x402/core/client";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { wrapFetchWithPayment } from "@x402/fetch";

const client = new x402Client();
registerExactEvmScheme(client, { signer });
withNetworkPreference(client, ["robinhood"]);   // or ["base","solana"], or ["eip155:4663"]
const payFetch = wrapFetchWithPayment(fetch, client);

Short names map to CAIP-2 (base, solana, polygon, arbitrum, robinhood); unknown entries pass through verbatim so future chains work without a package update. If the preference matches none of a seller's payment options it throws before any payment is signed.

Only pay who you meant to (withPayeeAllowlist)

The buyer-side mirror of a spend control: bound WHO gets paid, not just how much. Wrap your x402 client before wrapFetchWithPayment and any 402 whose accepts would send funds to an address outside the list is refused before a signature exists (a routed or redirected seller can never collect).

import { withPayeeAllowlist } from "agent402-client";
withPayeeAllowlist(client, ["0xYourSellerPayTo", "0xAnother"]);   // 0x addresses compare case-insensitively
const payFetch = wrapFetchWithPayment(fetch, client);

Pairs with maxPerCallUsd / dailyLimitUsd (how much) and withNetworkPreference (which chain).

Legal

Use of the hosted instance at agent402.tools is subject to its Terms of Service (acceptable-use policy included) and Privacy Policy. This package is MIT-licensed; the hosted server is AGPL-3.0. Both are provided as-is without warranty, and self-hosted deployments are their operator's responsibility.