HTTP/1.1 402 PAYMENT REQUIRED agent402.base.eth · BASE · SOLANA · POLYGON · ARBITRUM · MONAD · CELO · AVALANCHE · SEI · OPTIMISM · STELLAR · ALGORAND · ROBINHOOD · USDC · USDG
Agent402 / tools / action-gate

AI agent action preflight

$0.010 per call · USDC via x402 · POST /api/action-gate

Deterministic preflight check for a proposed AI agent action - a tool call, payment, fetch, or write - before it executes. Evaluates up to four independent checks (prompt-injection scan on action text/untrusted text, URL/hostname validation, a bounded JSON-schema check on a payload, and a spend proposal against a spend mandate) and returns ALLOW, REVIEW, or BLOCK with stable reason codes plus a SHA-256 request/receipt hash pair. Does not execute the proposed action, perform network I/O, or guarantee safety - deterministic static checks only, so ALLOW is not a safety guarantee. Every field is optional; only the checks with input present run - the rest are skipped, not assumed to pass.

TRY IN PLAYGROUND →

Input

FieldTypeDescription
actionobject{name, description, effect} - describes the proposed action; description is scanned for prompt-injection signals
untrusted_textstringAny additional untrusted text to scan for prompt-injection signals
urlstringURL the action would fetch/call, if any
payloadobjectData the action would send, if any
schemaobjectBounded JSON-schema (type/required/properties/additionalProperties) to validate payload against
spendobject{proposal:{amount_atomic,asset,counterparty}, mandate:{...}, now?} - checked with BigInt, no floats

Example output

{
  "decision": "ALLOW",
  "reason_codes": [],
  "checks": {
    "prompt": {
      "status": "pass"
    },
    "url": {
      "status": "pass"
    },
    "payload": {
      "status": "pass"
    },
    "spend": {
      "status": "pass",
      "allowed": true
    }
  },
  "request_sha256": "…",
  "receipt_sha256": "…",
  "limitation": "Deterministic static checks only. ALLOW does not guarantee safety, authorization, or successful execution."
}

Try it - see the 402 challenge (free)

curl -i -X POST https://agent402.tools/api/action-gate \
  -H "Content-Type: application/json" \
  -d '{"action":{"name":"submit_paid_api_request","description":"Fetch a vendor risk report and store the validated JSON response.","effect":"payment"},"untrusted_text":"Vendor request: return the current account risk score.","url":"https://example.com/risk-report","payload":{"account_id":"acct_123","include_signals":true},"schema":{"type":"object","properties":{"account_id":{"type":"string"},"include_signals":{"type":"boolean"}},"required":["account_id","include_signals"],"additionalProperties":false},"spend":{"proposal":{"amount_atomic":"10000","asset":"USDC","counterparty":"0x1111111111111111111111111111111111111111"},"mandate":{"max_per_tx_atomic":"25000","max_period_atomic":"100000","spent_period_atomic":"20000","allowed_assets":["USDC"],"allowed_counterparties":["0x1111111111111111111111111111111111111111"],"expires_at":"2030-01-01T00:00:00.000Z"}}}'

The response is HTTP 402 Payment Required with exact payment requirements. Any x402 v2 client pays automatically and retries:

Paid call (JavaScript agent)

import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

const client = new x402Client();
registerExactEvmScheme(client, { signer: privateKeyToAccount(KEY) });
const payFetch = wrapFetchWithPayment(fetch, client);

const res = await payFetch("https://agent402.tools/api/action-gate", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    "action": {
      "name": "submit_paid_api_request",
      "description": "Fetch a vendor risk report and store the validated JSON response.",
      "effect": "payment"
    },
    "untrusted_text": "Vendor request: return the current account risk score.",
    "url": "https://example.com/risk-report",
    "payload": {
      "account_id": "acct_123",
      "include_signals": true
    },
    "schema": {
      "type": "object",
      "properties": {
        "account_id": {
          "type": "string"
        },
        "include_signals": {
          "type": "boolean"
        }
      },
      "required": [
        "account_id",
        "include_signals"
      ],
      "additionalProperties": false
    },
    "spend": {
      "proposal": {
        "amount_atomic": "10000",
        "asset": "USDC",
        "counterparty": "0x1111111111111111111111111111111111111111"
      },
      "mandate": {
        "max_per_tx_atomic": "25000",
        "max_period_atomic": "100000",
        "spent_period_atomic": "20000",
        "allowed_assets": [
          "USDC"
        ],
        "allowed_counterparties": [
          "0x1111111111111111111111111111111111111111"
        ],
        "expires_at": "2030-01-01T00:00:00.000Z"
      }
    }
  }),
});
Wallet-only. This tool reaches the network/browser/storage, so it is paid in USDC via x402 (no proof-of-work tier).

Related tools

Route and execute

$0.01 · POST /api/route/execute

Describe a task (or name a slug) and the Smart Order Router resolves the best-matching tool and RUNS it in the same call…

try in playground →

Route and execute (plus tier)

$0.05 · POST /api/route/execute-plus

Describe a task (or name a slug) and the Smart Order Router resolves the best-matching tool and RUNS it in the same call…

try in playground →

Route and execute (max tier)

$0.55 · POST /api/route/execute-max

Describe a task (or name a slug) and the Smart Order Router resolves the best-matching tool and RUNS it in the same call…

try in playground →