Pre-flight safety check
preflightCheck if a x402 URL is safe to pay before processing payment. Returns ok status and warnings to avoid decoys, zombies, and dead endpoints.
Instructions
Ask x402station whether a given x402 URL is safe to pay. Returns {ok, warnings[], metadata}. Costs $0.001 USDC (auto-signed with AGENT_PRIVATE_KEY). Call this BEFORE any other paid x402 request to avoid decoys (price ≥ $1k), zombie services, and dead endpoints. ok:true only when no critical warning fires.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | The full URL of the x402 endpoint the agent is about to pay. |
Implementation Reference
- The `preflight` method is the handler function for the preflight tool. It takes a walletProvider and args (url), and calls the paid oracle endpoint /api/v1/preflight with the provided URL.
async preflight( walletProvider: EvmWalletProvider, args: z.infer<typeof PreflightSchema>, ): Promise<string> { return this.callPaid(walletProvider, "/api/v1/preflight", { url: args.url }); } - The `@CreateAction` decorator registers the `preflight` tool with name "preflight", description, and input schema (PreflightSchema).
@CreateAction({ name: "preflight", description: "Ask x402station whether a given x402 URL is safe to pay. Returns {ok, warnings[], metadata}. Costs $0.001 USDC (auto-signed via the wallet provider). Call this BEFORE any other paid x402 request to avoid decoys (price ≥ $1k USDC), zombie services, dead endpoints, and price/latency anomalies. ok:true only when no critical warning fires.", schema: PreflightSchema, }) - The `PreflightSchema` defines the input schema for the preflight tool: a single `url` field (string, must be a valid URL).
export const PreflightSchema = z.object({ url: z .string() .url() .describe( "Full URL of the x402 endpoint the agent is about to pay (must be http(s)://, max 2048 chars).", ), }); - The `callPaid` helper method is the underlying implementation that sends the POST request to the oracle. It uses the paying fetch (with x402 auto-signing), parses the JSON response, and extracts the payment receipt header.
private async callPaid( walletProvider: EvmWalletProvider, path: string, body: unknown, ): Promise<string> { const fetchPay = await this.getPayingFetch(walletProvider); const r = await fetchPay(`${this.baseUrl}${path}`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body ?? {}), }); const receiptHeader = r.headers.get("x-payment-response") ?? r.headers.get("payment-response"); let paymentReceipt: unknown = null; if (receiptHeader) { try { paymentReceipt = JSON.parse(atob(receiptHeader)); } catch { paymentReceipt = { raw: receiptHeader }; } } const raw = await r.text(); if (!r.ok) { const snippet = raw.length > 200 ? raw.slice(0, 200) + "…" : raw; return JSON.stringify( { error: true, status: r.status, message: `x402station ${path} returned ${r.status}`, details: snippet, }, null, 2, ); } let data: unknown; try { data = JSON.parse(raw); } catch { return JSON.stringify( { error: true, message: `x402station ${path} returned 200 with non-JSON body`, details: raw.slice(0, 200), }, null, 2, ); } return JSON.stringify({ result: data, paymentReceipt }, null, 2); }