Crux decides what information is worth buying about a company, under a strict USDC budget, paying for each source with real Circle Gateway nanopayments on Arc. The spending judgment is the product — not the report.
Entry for RFB-01 (Autonomous Paying Agents) of the Lepton Agents Hackathon (Canteen × Circle on Arc). Every purchase below is a real x402 nanopayment that is verified through Circle Gateway and batch-settled on Arc testnet.
This is not "a research agent." It's an autonomous paying agent whose spending decisions are the deliverable — the brief is just the vehicle.
The agent is given a due-diligence task and a strict USDC budget, and faces a marketplace of paid sources deliberately built so that no fixed heuristic wins:
- price ≠ quality — some cheap sources are signal, some pricey ones are noise;
- free previews on some sources — the agent must judge value before paying;
- overlap — two cheap sources are near-duplicates (dedup matters);
- an unreliable source that takes payment and sometimes returns nothing;
- a misleading source — cheap, advertises "high quality", reports a false acquisition rumor;
- a "wolf in sheep's clothing" — metadata identical to the best source, but its preview reveals it's industry-macro, useless for this company.
Only context-sensitive reasoning — previewing, matching source to question, skipping traps, stopping when enough — spends the budget well. That is what makes a real LLM load-bearing here, rather than decorative.
npm run compare runs the reasoning agent against two naive heuristics on the
same marketplace, budget, and seed — all paying real USDC on Arc — and scores
each brief against ground truth:
Strategy Spent Buys Facts Coverage False claim
reasoning-agent $0.045 3 5/5 11/11 (100%) no
buy-cheapest $0.0388 7 3/5 6/11 (55%) YES (rumor)
buy-by-quality $0.0353 4 3/5 6/11 (55%) YES (rumor)
Both heuristics spend less but capture barely half the facts and assert a
fabricated acquisition. buy-by-quality wastes $0.02 on the trap source, so it
can't afford the analysis that holds the governance red flags. The agent previews
past the trap, skips the rumor, and gets the complete, accurate picture. That gap
is judgment a rule can't replicate.
Every completed web run can persist a public receipt at /runs/<id>: the budget,
source previews, purchases, skips, rationales, final brief, benchmark score when
available, and Gateway settlement ids for every paid source. This is the async judging
artifact: a reviewer does not have to trust the live UI or the README; they can
open a single run and inspect what the agent decided and what actually settled.
Golden examples:
- Coinbase public-company run: https://crux-khaki.vercel.app/runs/6707c268-9a4e-4f9c-b197-e9e8f3ca410c
- OpenAI private-company run: https://crux-khaki.vercel.app/runs/e015e4c9-d14b-4e66-90e5-f3cb53e5924c
- Northwind scored benchmark: https://crux-khaki.vercel.app/runs/9859fecb-488b-478d-a5bc-fec3899d9229
- Agent-vs-baselines comparison: https://crux-khaki.vercel.app/runs/512afc48-1a8f-410d-89a4-64e63303b0f5
Crux is discoverable by other agents:
/agents— live developer page with integration snippets/.well-known/crux-agent.json— machine-readable capabilities and auth modes/openapi.json— route contract for x402 resources, visitor wallets, and runnersAGENT_INTEGRATION.md— copy-paste integration flowsARC_OSS.md— reusable Arc primitives for the Open Source ShowcaseDEMO.md— judge/demo runbook
Production public house-wallet runner access is disabled. External agents should either buy x402 resources directly, run from a visitor-funded wallet, or use a scoped Crux agent key.
research agent ──(Vercel AI SDK + AI Gateway)──► LLM reasoning
│ tools: list_marketplace · preview · purchase · check_budget · submit_brief
▼
marketplace (x402-protected Next.js routes)
│ GET 402 → sign EIP-3009 authorization → retry with payment
▼
Circle Gateway ──batches signed authorizations──► single on-chain settlement on Arc
│
▼
Supabase (payment ledger) lib/score.ts (objective brief scorer)
- Agent (
lib/agent.ts): an AI-SDK tool-calling loop. Model is routed through the Vercel AI Gateway — develop onclaude-haiku-4.5, swap one string toclaude-opus-4.8for the demo. - Marketplace (
lib/marketplace.ts): the decision space — 9 sources with varied price/quality/reliability, free previews, the trap, and a misleading rumor. Reliability is deterministic under a seed, so runs are reproducible. - Settlement (
lib/x402.ts): x402 + Circle Gateway batching on Arc. Eachpurchaseis a realgateway.pay()authorization that is settled through Circle Gateway. - Scorer (
lib/score.ts): grades a brief by weighted ground-truth facts captured, and flags whether it ingested the false rumor. - Baselines (
lib/baseline.ts): non-LLM buy-cheapest / buy-by-quality buyers for the comparison.
- Network: Arc testnet (
eip155:5042002), RPChttps://rpc.testnet.arc.network - USDC:
0x3600000000000000000000000000000000000000; Circle Gateway batching - Payments are gas-free for the agent (authorizations are batched into one
on-chain settlement); explorer:
https://testnet.arcscan.app - Receipts record Circle Gateway settlement references for each paid source. Crux links ArcScan only when Gateway exposes a real Arc EVM transaction hash; otherwise the durable proof is the Gateway ref stored in the receipt/payment ledger.
The agent's payment capability isn't limited to our own marketplace. npm run external-demo discovers real third-party x402 services via Coinbase's x402
Bazaar and pays one on Base Sepolia — proof of a genuine external counterparty,
not self-dealing (the one thing a pure-Arc, self-authored entry can't show).
Verified live: paid Node4All Fortune ($0.002 USDC, x402 v2 exact scheme),
settled on-chain on Base Sepolia
(example tx).
Uses the @x402/core v2 client (x402HTTPClient + ExactEvmScheme) — a
different rail (Coinbase facilitator) from the Circle Gateway batching on Arc.
- Node.js v22+
- A cloud Supabase project (free) — the seller's payment ledger
- A Vercel AI Gateway API key — routes the agent's LLM calls
npm install
cp .env.example .env.local
npm run generate-wallets # creates seller + house testnet wallets in .env.local
# Fund the house wallet at https://faucet.circle.com (Arc Testnet)Then add to .env.local:
NEXT_PUBLIC_SUPABASE_URL=... # your Supabase project URL + keys
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=...
SUPABASE_SERVICE_ROLE_KEY=...
AI_GATEWAY_API_KEY=... # Vercel AI Gateway
Generated wallet env names are testnet-scoped:
CRUX_KEY_SCOPE=arc-testnet
CRUX_SELLER_TESTNET_ADDRESS=...
CRUX_SELLER_TESTNET_PRIVATE_KEY=...
CRUX_HOUSE_TESTNET_ADDRESS=...
CRUX_HOUSE_TESTNET_PRIVATE_KEY=...
CRUX_WALLET_ENCRYPTION_KEY=... # generate with npm run wallets:keygen
The older SELLER_* and BUYER_* names are still accepted as aliases for
existing deployments. New setups should use the CRUX_*_TESTNET_* names so
demo keys cannot be confused with future production custody.
Apply the SQL migrations in supabase/migrations/ to your project (SQL Editor or supabase db push).
After a production deploy or database migration, run npm run verify:production
to smoke-check the live x402 challenge, wallet auth path, marketplace, stats,
agent topics, and public agent budget guard. Override the target with
CRUX_VERIFY_BASE_URL=https://your-domain.example.
- Seller testnet wallet: receives x402 payments and is used only for Gateway
admin withdrawals. Keep
CRUX_SELLER_TESTNET_PRIVATE_KEYout of preview/dev environments unless withdrawal testing is needed. - House testnet wallet: funds capped operator and trusted-agent runs. Keep its Gateway balance small and rotate it independently from the seller wallet.
CRUX_KEY_SCOPEmust stayarc-testnet,testnet, ordemo; the app refuses to use private keys when this scope is changed to a production-like value.- Visitor-wallet private keys are encrypted before storage when
CRUX_WALLET_ENCRYPTION_KEYis set. For existing plaintext rows, apply the20260310000009_encrypt_user_wallet_keys.sqlmigration, set the env key, then runnpm run wallets:encrypt -- --dry-runfollowed bynpm run wallets:encrypt. - Production backfills can also run through the protected
/api/admin/wallet-encryptionendpoint whenCRUX_MAINTENANCE_TOKENis set; remove or rotate that token after the maintenance run. - After all visitor-wallet rows are encrypted, set
CRUX_WALLET_REQUIRE_ENCRYPTED_WALLETS=trueto refuse legacy plaintext rows. - To rotate a wallet, generate a fresh keypair, fund/deposit the new address,
update both the address and private-key env vars together, redeploy, and run
npm run verify:production. Do not reuse hackathon demo keys for mainnet.
- The seller dashboard lives at
/admin/loginand remains disabled unlessADMIN_EMAIL, eitherADMIN_PASSWORDorADMIN_PASSWORD_SHA256, andADMIN_SESSION_SECRETare configured. Production sessions are signed, 12-hour, HTTP-only, same-site cookies. PreferADMIN_PASSWORD_SHA256for production; generate it withnode -e "crypto=require('crypto'); console.log(crypto.createHash('sha256').update(process.argv[1]).digest('hex'))" 'your-password'. - Set
CRUX_ALERT_WEBHOOK_URLin production to receive operational alerts for x402 settlement failures, payment ledger write failures, rate-limit/run-lock fail-closed events, and agent/receipt failures. - To notify more than one destination, set
CRUX_ALERT_WEBHOOK_URLto a comma- or newline-separated list of webhook URLs. CRUX_ALERT_WEBHOOK_TOKENis optional; when set, Crux sends it as anAuthorization: Bearer ...header to every configured destination.- Alerts are best-effort, time-bounded, deduped in-process, and redact private keys, bearer tokens, JWT-like tokens, and raw payment payloads.
- To test alert delivery without causing a fake production error, temporarily
set
CRUX_MAINTENANCE_TOKEN, redeploy, then runCRUX_MAINTENANCE_TOKEN=... npm run alerts:test. Remove or rotate the token after the test if it was created only for maintenance. - Payment reconciliation runs daily through Vercel Cron at
/api/admin/reconcile-payments(Hobby plan limit; use*/30 * * * *on Pro if you want 30-minute checks). It scans recentpayment_events, refreshes stale settlement proof columns, re-verifies Arc transaction hashes, and alerts if settlement records are missing, stale, failed, or inconsistent. - Set
CRON_SECRETin Vercel production for the reconciliation route. Crux does not trust cron user-agent headers; reconciliation requires eitherAuthorization: Bearer $CRON_SECRETorCRUX_MAINTENANCE_TOKEN. - Manual reconciliation can run locally with Supabase env vars loaded:
npm run reconcile:payments -- --dry-run, or against the deployed route withAuthorization: Bearer $CRON_SECRET. - Before submission windows or demos, run
npm run check:fuelwith production wallet env loaded. It prints house/seller public addresses plus on-chain and Gateway USDC balances without exposing private keys. - Keep
CRUX_PUBLIC_AGENT_RUNS_ENABLED=falsein production. The web demo uses admin/operator sessions for house-wallet runs, visitor mode uses funded visitor wallets, and trusted external agents use scoped Bearer keys.
npm run dev # start the seller (marketplace + x402 endpoints)
npm run research-agent # run the autonomous agent (brief + spend ledger + score)
npm run compare # the money-shot: agent vs. baselines, side-by-side
npm run external-demo # pay a REAL external x402 service on Base (via the Bazaar)
npm run check:migrations # verify Supabase migration naming/order
npm run verify:migrations # apply all migrations to disposable Postgres
npm run verify:production # smoke-check the deployed production app
npm run check:fuel # report house/seller Arc wallet and Gateway balances
npm run reconcile:payments # reconcile Supabase payment_events settlement proof
npm run alerts:test # send a protected operational-alert test
npm run wallets:keygen # generate a 32-byte visitor-wallet encryption key
npm run wallets:encrypt # backfill encrypted visitor-wallet key storageUseful env overrides: MODEL (e.g. anthropic/claude-opus-4.8), TOPIC, BUDGET, SEED, BASE_URL.
For production deploys, use RELEASE.md so Vercel deploys, Supabase migrations, smoke checks, and short-lived secrets are tracked together.
Next.js 16 · Vercel AI SDK v6 + AI Gateway · @circle-fin/x402-batching
(Circle Gateway batching + Circle Nanopayments on Arc) · x402 ·
Supabase · viem.
This project builds on Circle's reference implementation
circlefin/arc-nanopayments
(Apache 2.0) for the x402 + Circle Gateway settlement layer on Arc — we fixed a
validity-window bug in it (the facilitator now requires a 7-day minimum that the
reference hardcoded shorter; see lib/x402.ts).
Our contribution is everything that makes it an autonomous paying agent: the
research-agent reasoning loop (lib/agent.ts), the marketplace decision space
(lib/marketplace.ts), the objective scorer (lib/score.ts), and the baseline
comparison (lib/baseline.ts, compare.mts).
Licensed under Apache 2.0 (see LICENSE).