How I Built an Autonomous AI Agent That Earns USDC While I Sleep
Target audience: developers who want to put a lightweight, self‑serving agent into production and get paid per invocation in USDC on Base.
1. Why an “earning‑while‑sleeping” agent?
Most hobby agents run on a schedule, poll for work, or sit idle until a human triggers them. If you want the agent to generate revenue without a constant operator, you need two things:
- Stateless execution – the agent can be started, do its job, and shut down with no lingering state.
- Built‑in monetization – each invocation must be able to request payment before doing any work, and the payment must be settled on‑chain with minimal friction.
The x402 standard (a draft for HTTP‑based micropayments) fits the second point nicely: a client sends a small USDC amount in the x402-Payment header, the server verifies it on‑chain, and only then proceeds with the request. Combined with a serverless platform like Cloudflare Workers, you get cheap, scalable execution that only runs when paid for.
2. High‑level architecture
+-------------------+ HTTP (x402) +---------------------+
| Client / UI | <----------------------> | Cloudflare Worker |
+-------------------+ (Agent Service)
^ |
| v
| +------------------+
| | x402 Verifier |
| | (Base RPC + |
| | ERC‑20 USDC) |
| +------------------+
| |
| v
| +------------------+
| | Agent Logic |
| | (LLM call, |
| | data fetch, |
| | etc.) |
| +------------------+
| |
+-------------------------------------------+
- Client – any HTTP caller (curl, Postman, a front‑end, or another agent) that wants the agent’s output.
- Cloudflare Worker – provides the HTTP edge, runs the x402 verifier, and forwards the request to the agent logic only after payment succeeds.
-
x402 Verifier – a tiny library that checks the
x402-Paymentheader, validates the signature against the Base network, and confirms the amount matches the price posted in the service’sx402-Priceheader. - Agent Logic – the actual AI workload (in my example, a simple summarization via an LLM API). It receives the payload only after the verifier says “paid”.
Because the Worker is stateless, you can scale to thousands of concurrent invocations without managing containers or VMs. The only state you keep is the USDC price you expose, which lives in the Worker’s environment variables.
3. Setting up the payment verifier
I used the open‑source @x402/verifier package (npm) which handles the Base RPC call and ERC‑20 approval check. Below is a minimal Worker that integrates it.
// worker.js
import { verifyX402Payment } from '@x402/verifier';
import { summarize } from './agentLogic.js'; // our LLM wrapper
// Configuration – set via wrangler.toml or dashboard secrets
const USDC_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'; // Base USDC
const PRICE_USDC = 0.02; // $0.02 per call
const RPC_URL = 'https://base-mainnet.g.alchemy.com/v2/<YOUR_KEY>';
export default {
async fetch(request, env) {
// 1️⃣ Extract headers required by x402
const paymentHeader = request.headers.get('x402-payment');
const priceHeader = request.headers.get('x402-price');
if (!paymentHeader || !priceHeader) {
return new Response('Missing x402 headers', { status: 402 });
}
// 2️⃣ Verify that the client paid enough USDC
const isValid = await verifyX402Payment({
paymentHeader,
priceHeader,
usdcAddress: USDC_ADDRESS,
price: PRICE_USDC,
rpcUrl: RPC_URL,
});
if (!isValid) {
return new Response('Payment verification failed', { status: 402 });
}
// 3️⃣ If payment good, run the agent logic
const payload = await request.json(); // expect { text: "..."}
const result = await summarize(payload.text);
return new Response(JSON.stringify({ summary: result }), {
headers: { 'Content-Type': 'application/json' },
});
},
};
What the verifier does under the hood
- Parses the
x402-Paymentheader (containstoken,amount,signature,nonce,chainId). - Calls
eth_callon the Base RPC to read the USDCbalanceOfthe verifier address before and after the purported transfer. - Checks that the signature matches the sender’s address (recovering it via
ecrecover). - Ensures the transferred amount ≥ the price advertised in
x402-Price.
If any step fails, the Worker returns HTTP 402 Payment Required – the client knows to retry with a correct payment.
4. Agent logic – a realistic, low‑cost example
For the demo I chose a text summarization task that calls an external LLM API (e.g., OpenAI’s GPT‑4o-mini). The point is not to showcase a revolutionary model but to show how you can gate any compute‑heavy work behind a payment check.
// agentLogic.js
import { Configuration, OpenAIApi } from 'openai';
const config = new Configuration({
apiKey: env.OPENAI_API_KEY, // injected via wrangler secret
});
const openai = new OpenAIApi(config);
export async function summarize(text) {
if (!text || typeof text !== 'string') {
throw new Error('Invalid input: expected a non‑empty string');
}
const response = await openai.createChatCompletion({
model: 'gpt-4o-mini',
messages: [
{ role: 'system', content: 'You are a concise summarizer.' },
{ role: 'user', content: `Summarize the following in 2‑3 bullet points:\n\n${text}` },
],
temperature: 0.3,
max_tokens: 150,
});
return response.data.choices[0].message.content.trim();
}
Trade‑offs
| Aspect | Choice | Reason | Drawback |
|---|---|---|---|
| LLM provider | OpenAI API (pay‑per‑token) | Simple, low latency, no model hosting | Ongoing cost; you must mark‑up the price to cover it |
| Model size | gpt-4o-mini |
Good quality/price ratio for short summaries | Not the cheapest possible; a smaller open‑model could reduce cost but increase complexity |
| Execution platform | Cloudflare Workers | Sub‑second cold start, zero‑ops scaling | Limited execution time (50 s on paid plan) – fine for summarization, not for long‑running tasks |
| Payment granularity | Per‑call USDC | Aligns cost directly with value delivered | Clients must manage micropayments; UX friction if they’re not familiar with x402 |
If your workload is heavier (e.g., image generation, model fine‑tuning), you may need to raise the price, use a longer‑lived compute environment (Durable Objects or a VPS), or batch multiple requests into a single payment.
5. Deployment & observability
-
Secrets – Store
OPENAI_API_KEY,ALCHEMY_BASE_KEY(or any Base RPC provider), and optionally aVERIFIER_ADDRESS(the address that will receive USDC) in Cloudflare Secrets viawrangler secret put. -
Wrangler config – A minimal
wrangler.toml:
name = "x402-summarizer"
main = "src/worker.js"
compatibility_date = "2024-09-01"
[vars]
USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
PRICE_USDC = "0.02"
RPC_URL = "https://base-mainnet.g.alchemy.com/v2/${ALCHEMY_BASE_KEY}"
[env.production]
Deploy –
wrangler publish. The Worker is now globally available athttps://x402-summarizer.<your-subdomain>.workers.dev.Monitoring – Cloudflare provides built‑in analytics (request count, latency, error rate). For payment‑specific metrics, I log the
x402-Paymentheader hash (not the full signature) to a custom logpush endpoint and alert if the verification failure rate spikes > 5 % (could indicate a mis‑priced service or an attacker trying to game the system).-
Security considerations
- Replay attacks – The verifier includes a nonce; the client must increment it for each call. The Worker stores the last seen nonce in a short‑lived KV namespace (TT
Top comments (0)