Skip to content

Documentation

Q402 is a real application with a fictional institution around it. This page describes the real parts.

01Overview

The site runs a 64-agent demo economy and one real paid API. The demo economy is a deterministic function of time (see paper 004): every visitor sees the same state at the same second, and nothing is stored. The paid API uses the open x402 protocol (v2) to charge 0.01 USDC per research report on Solana.

02Modes

  • SIMULATED Generated by the demo engine. Never a blockchain transaction. Transaction ids start with SIM-.
  • DEVNET A real transaction on Solana devnet, using test tokens with no value. Linked to Solana Explorer.
  • MAINNET Real value. Requires credentials and an explicit X402_ALLOW_MAINNET flag.

03x402 paid endpoint

GET /api/agent/research-report?topic=… returns a short research brief for 0.01 USDC. An unpaid request receives 402 Payment Required with a base64 PAYMENT-REQUIRED header describing the accepted payment. A client retries with a PAYMENT-SIGNATURE header; on success the response carries PAYMENT-RESPONSE with the settlement transaction. Settlement happens only after the handler succeeds.

GET /api/agent/research-report
Expected: 402 Payment Required with a PAYMENT-REQUIRED header when the rail is configured, or 503 x402_not_configured when it is not.

Pay for it from your own code with the official client:

import { wrapFetchWithPaymentFromConfig, decodePaymentResponseHeader } from "@x402/fetch";
import { ExactSvmScheme } from "@x402/svm/exact/client";
import { toClientSvmSigner, SOLANA_DEVNET_CAIP2 } from "@x402/svm";
import { createKeyPairSignerFromBytes } from "@solana/kit";
import { base58 } from "@scure/base";

const signer = await createKeyPairSignerFromBytes(base58.decode(process.env.SVM_PRIVATE_KEY!));
const pay = wrapFetchWithPaymentFromConfig(fetch, {
  schemes: [{ network: SOLANA_DEVNET_CAIP2, client: new ExactSvmScheme(toClientSvmSigner(signer)) }],
});

const res = await pay("https://<this-site>/api/agent/research-report?topic=agent%20payments");
const receipt = decodePaymentResponseHeader(res.headers.get("PAYMENT-RESPONSE")!);
console.log(await res.json(), receipt.transaction);

04Agent purchases

POST /api/agent/purchase with { "agent": "Q-017", "topic": "…" } makes a Q402 agent buy one report from the paid endpoint using the server-held treasury wallet. The request is checked against the agent’s spend policy first, and every decision is written to the audit log. Only Research and Data agents are allowed to buy external resources. Without configuration the route returns a clearly labelled SIMULATED result and moves no money.

05Network state API

GET /api/network/state?events=40&at=<ms> returns the demo network at any moment: metrics, the state of all 64 agents and recent events. Every response is marked SIMULATED.

curl -s https://<this-site>/api/network/state?events=5 | jq '.metrics'

06Spend policies

Every agent carries a policy enforced on the server: a per-call maximum, a per-job maximum, a daily ceiling, an allow-list of services, an hourly execution limit and an emergency stop. A payment that breaks any rule is rejected before anything is signed. The policy check is a pure function with its own test suite.

07Agent launchpad

Launching an agent from the marketplace creates a real token on pump.fun (Solana mainnet). The browser generates the mint keypair, uploads the image and metadata to IPFS, and files an intent with the agent’s configuration before the mint exists. PumpPortal then builds the create transaction, the mint co-signs it and the operator’s wallet signs it. Once it confirms, the server checks the chain: the bonding curve exists, the transaction ran pump.fun on that mint, and the signer is the creator. Only then is the agent added to the registry.

POST /api/register   { intent: true, mint, creator, config }   announce a mint before it exists
POST /api/register   { mint, signature }                        file the launch after onchain checks
GET  /api/launches                                              every Q402 agent launch, live market data
GET  /api/token?mint=<mint>                                     one token (registry, else DexScreener + curve)
GET  /api/trades?mint=<mint>[&pool=<pool>]                      curve trades or pool trade tape
GET  /api/ohlcv?pool=<pool>&tf=1h|4h|1d|1w                      candles (GeckoTerminal)
POST /api/rpc                                                   allow-listed JSON-RPC proxy

Trading on an agent’s token page goes through PumpPortal and is signed by the visitor’s own wallet. Nothing here holds keys or funds.

08Configuration

Set these in the deployment environment. Anything left unset keeps its feature in a visible NOT CONFIGURED state.

Launch registryVercel Blob
Launchpad RPCPublic (rate limited)
VariableDefaultPurpose
X402_NETWORKsolana-devnetSettlement network. solana-devnet or solana. Unset = rail disabled.
X402_PAY_TO—Solana address that receives report payments.
X402_FACILITATOR_URLhttps://x402.org/facilitatorFacilitator that verifies and settles payments.
X402_AGENT_SECRET_KEY—Base58 secret key of the agent treasury wallet (devnet). Server only.
X402_DAILY_CAP_USDC1Network-wide daily ceiling for agent purchases.
X402_ALLOW_MAINNETfalseMust be true, with X402_NETWORK=solana, to settle real value.
X402_EMERGENCY_STOPfalseWhen true, every outgoing agent payment is rejected.
SOLANA_RPC_URLpublic RPCRPC used by the verified-lane chain reader.
ANTHROPIC_API_KEY—Enables live report generation with claude-haiku-5-5.
BLOB_READ_WRITE_TOKEN—Vercel Blob token for the agent launch registry. Unset = registry kept in memory (local dev only).
RPC_URLpublic mainnet RPCSolana mainnet RPC for the launchpad (full URL or a bare Helius key). The public RPC is rate limited.
PINATA_JWT—Fallback IPFS upload if pump.fun's metadata endpoint is unavailable.
NEXT_PUBLIC_Q402_CA—$Q402X mint address (or set CONTRACT_ADDRESS in src/config/token.ts). Switches on the pump.fun buy links and market panel.