Run Skim from a Cloudflare Agent
Ten lines of Worker code, no API key, $0.002 a read.
Cloudflare has gone further than any other platform in making agent payments a first-class feature. The Agents SDK ships with built-in x402 support: servers can charge for tools, clients can pay for them, and the docs assume your agent has a wallet the same way older docs assumed it had an API key. If you are building on Workers or the Agents SDK, your agent is already running in the most x402-friendly environment there is.
Skim fits into that environment with less machinery than you might expect, because Skim is not an MCP server you have to connect to — it is a plain x402 HTTP endpoint. One POST, one 402 handshake, clean markdown back. Here is the whole setup.
1. Install the x402 client
Two packages: an x402-aware fetch wrapper and viem for wallet signing. Both run on Workers without polyfills.
npm install x402-fetch viem2. Store the wallet key as a secret
Your agent pays from its own wallet — a dedicated one, funded with a few dollars of USDC on Base, never your personal wallet. Store the private key the way Cloudflare stores any secret:
# Local development — .dev.vars (gitignored)
SKIM_WALLET_PRIVATE_KEY="0x..."
# Production
npx wrangler secret put SKIM_WALLET_PRIVATE_KEYThe key never leaves your Worker. It is only used to sign a USDC transfer authorization locally; the signed payload travels, the key does not.
3. Wrap fetch, point it at Skim
wrapFetchWithPayment gives you a fetch that handles the 402 handshake automatically: first call gets the price quote, the wallet signs, the retry carries the payment, and Skim returns the page.
// src/skim.ts — a paid web-read helper for any Worker or Agent
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { base } from "viem/chains";
import { wrapFetchWithPayment } from "x402-fetch";
export function makeSkimReader(privateKey: `0x${string}`) {
const account = privateKeyToAccount(privateKey);
const wallet = createWalletClient({ account, transport: http(), chain: base });
const fetchWithPayment = wrapFetchWithPayment(fetch, wallet);
return async function skimRead(url: string) {
const res = await fetchWithPayment("https://skim402.com/api/v1/read", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ url }),
});
if (!res.ok) throw new Error(`Skim ${res.status}: ${await res.text()}`);
return (await res.json()) as {
markdown: string;
text: string;
metadata: { title?: string; byline?: string; publishedAt?: string };
};
};
}4. Call it from your Agent
// src/agent.ts — inside a Cloudflare Agent
import { Agent } from "agents";
import { makeSkimReader } from "./skim";
export class ResearchAgent extends Agent<Env> {
async readPage(url: string) {
const skimRead = makeSkimReader(
this.env.SKIM_WALLET_PRIVATE_KEY as `0x${string}`,
);
const page = await skimRead(url);
// page.markdown is clean, agent-ready — hand it to your model.
return page;
}
}That is the entire integration. No account with Skim, no key rotation, no billing dashboard. Each read settles $0.002 in USDC on Base at call time, and the settlement receipt comes back in the X-PAYMENT-RESPONSE header (base64-encoded JSON with the transaction hash) if you want to log it — the JSON body itself is just the clean content.
What about withX402Client?
The Agents SDK also ships withX402Client, which wraps an MCP client connection so your agent can pay for x402-protected MCP tools, with an optional human-in-the-loop confirmation callback before each payment. That is the right tool when the paid service only exists as a remote MCP server. Skim does not require it — the plain HTTP endpoint above is fewer moving parts — but the two coexist fine: use withX402Client for paid MCP tools, and the wrapped fetch for paid HTTP APIs like Skim.
If you want a spending guardrail either way, the fetch wrapper accepts a maximum payment amount, and Skim's prices are fixed and published: $0.002 for a basic read, $0.005 with JavaScript rendering, $0.015 for schema-typed extraction.
Why this pairing makes sense
Cloudflare is building the paid-web rails — its Monetization Gateway lets any site behind Cloudflare charge agents over x402. As more of the web starts answering agents with 402, the agents that thrive will be the ones whose reading layer already speaks payment natively. A Cloudflare agent with a funded wallet and a Skim tool reads the open web today and is positioned for the tolled web tomorrow.
Full API reference, response shapes, and error semantics are in the docs. Wallet setup, if you have not done it before, is a five-minute job — here is the walkthrough.