Run it yourself, or reach it over HTTP.
Two ways to use AgentRail, off the same engine. The library is real today — see /status. The hosted service is planned, not built — its section below says so plainly.
Quickstart
You hold the keys and fund the wallets; nothing here ever touches your money on your behalf.
npm install @pyco404/agentrailThat gives you the core types, the pure policy engine, the reservation/idempotency layer, the chain submission path, and LocalKeyProvider. The demo agent below isn't part of the published package — it needs the repository itself.
Run the demo agent
The clearest way to see the whole path — policy check, reservation, signing, on-chain settlement — is to watch an agent actually pay for something. src/agent/ is a small agent that pays a local x402-gated endpoint per call: it gets a 402 challenge, runs it through the real policy engine, signs and submits on Solana devnet, and only unlocks the response once that payment actually confirms on-chain.
This uses a throwaway SPL token on devnet, not anything with real value — safe to run and re-run. It needs a passphrase for the local encrypted keystore and, for setup, some devnet SOL (the setup script requests an airdrop automatically; if devnet's faucet is rate-limited, it prints the address to fund manually at faucet.solana.com).
export WALLET_KEYSTORE_PASSPHRASE=$(openssl rand -base64 32)
npm run demo:setup # provisions a demo mint + two devnet wallets, funds them
npm run demo # runs the pay-per-call loop against a local x402 endpointThe loop pays a few times, then hits a real policy denial once its lifetime cap is spent — not a simulated one. Press k at any point while it's running to engage the kill switch live and watch the next call get refused before it ever reaches the signer.
Run it on mainnet
Same agent, same policy engine, pointed at Solana mainnet instead of devnet — priced in real USDC by default, or AgentRail's own $AGENTRAIL token. This moves real value, and the CLI says so loudly every time it starts.
npm run demo:setup:mainnet # provisions USDC + $AGENTRAIL token accounts — you fund it manually
DEMO_NETWORK=mainnet npm run demo # USDC, $0.02/call by defaultNothing here airdrops itself. The setup script prints exactly which address to send SOL and USDC (or$AGENTRAIL) to, then refuses to go further until it sees the balance actually land. This has already run for real — five confirmed mainnet payments, then a genuine policy denial the moment the wallet's lifetime cap was spent. See /status.
Evaluating a payment
evaluate() is a pure function — a policy, an intent, the wallet's spend history, and a clock in, exactly one decision out. Nothing about it depends on I/O, so the same four inputs always produce the same result.
import { evaluate } from './src/policy/engine';
const verdict = evaluate(policy, intent, history, new Date());
// { type: 'allow' }
// { type: 'requiresApproval' }
// { type: 'deny', reason: { code: 'per_transaction_cap_exceeded', token, cap } }Reserving a payment against a wallet's actual, persisted history — the version that mints a reservation id and holds budget against future requests — goes through evaluateAndReserve()instead, which wraps the same evaluation in the wallet's transaction lock. See /policy for the full rule set and the exact deny reason codes.
The hosted service
planned — not built yet. Nothing on this page describes something you can call today.
Same policy engine, same KeyProvider interface, same schema as the library above — the service is that library plus routes plus auth, not a fork of it. When it exists, it will stay devnet-only until custody moves off the local encrypted keystore (see /custody): one shared passphrase on one disk, with no rotation path, is correct custody for you running your own process, and disqualifying for us holding anyone else's real funds.
Authentication is a single API key scoped to a principal — no OAuth, no session management.
- POST /intents
- Submit a payment intent for evaluation — the hosted equivalent of
submitPaymentIntent(). - GET /intents/:id
- Check an intent's terminal status. Authoritative and cheap by design — see docs/operations.md — so a retrying agent can check before minting a new idempotency key instead of guessing.
- POST /approvals/:id
- Resolve a pending, escalated request — approve or reject it, re-evaluated fresh against current policy.
- POST /kill-switch
- Engage or release the kill switch for a wallet. Stops new authorizations immediately; cannot recall a transaction already on the wire — see docs/operations.md for exactly what that does and doesn't guarantee.