One middleware, every stack

Drop AgentRail into any backend.

Every SDK does the same three things — detect AI agents, price & gate them by purpose, and verify payment over HTTP 402 (AP2 / x402 / Bedrock). Same policies, same dashboard, same events. Pick your language and copy the snippet.

Node / Express is available today. The other languages are fully implemented, tested, and ready to publish.

Node / Express Next.js Cloudflare Python · FastAPI PHP · Laravel Go · Gin TypeScript · Hono Ruby · Rails Java · Spring C# · ASP.NET Rust · Axum Elixir · Phoenix MCP · Tools

Snippets below show install + the minimal middleware wiring. Click any code block to copy it.

Every SDK ships with a runnable demo

See /demos for 10 working sites — Daybreak in Node, plus Hono, FastAPI, Gin, Laravel, Rails, Spring, ASP.NET, Axum, and Phoenix — and a Model Context Protocol server (agentrail-mcp-demo). Clone the repo, run any demo, and watch agents get detected, priced, and paid in real time.

Core SDK · Node / Express

@agentrails/sdk

✅ Available now — powers the Daybreak demo, with real x402 payments + hosted control-plane mode.

The canonical AgentRail middleware. One app.use(...); your existing routes are unchanged. Detects agents, returns 402 with price headers, and verifies the payment receipt.

Install

# npm npm install @agentrails/sdk

Wire it up

// server.js const express = require('express'); const { agentrail } = require('@agentrails/sdk'); const app = express(); app.use(agentrail({ apiKey: process.env.AGENTRAIL_API_KEY, // hosted mode: policies + rails from the dashboard policies: { '/api/products': { priceCents: 5, purposeAllow: ['browsing', 'answer'] }, '/api/products/:sku': { priceCents: 5, purposeAllow: ['browsing', 'answer'] }, '/api/reports/*': { priceCents: 50, purposeAllow: ['answer'] }, }, onEvent: (e) => analytics.record(e), })); // your existing routes run unchanged — agents now pay, humans don't app.get('/api/products', (req, res) => res.json({ products: [] })); app.listen(3000);

Self-hosting the payment rails? Pass validators: { ap2, x402, bedrock } instead of apiKey. See the Agent API docs.

Next.js adapter

@agentrails/nextjs

✅ Implemented & tested — real AP2/Bedrock signature verification, full test suite, and a PUBLISHING.md with exact registry steps. Ready to publish (not yet published).

App Router native. Use it in middleware.ts for edge-wide gating, or wrap an individual route handler. Same policy object as the core SDK.

Install

npm install @agentrails/nextjs

Wire it up — edge middleware

// middleware.ts import { agentrailMiddleware } from '@agentrails/nextjs'; export default agentrailMiddleware({ apiKey: process.env.AGENTRAIL_API_KEY, policies: { '/api/products': { priceCents: 5, purposeAllow: ['browsing', 'answer'] }, }, }); export const config = { matcher: ['/api/:path*'] };

Or wrap a single route handler

// app/api/products/route.ts import { withAgentrail } from '@agentrails/nextjs'; export const GET = withAgentrail( { policy: { priceCents: 5, purposeAllow: ['answer'] } }, async (req) => Response.json({ products: [] }), );

Cloudflare Workers

@agentrails/cloudflare

✅ Implemented & tested — real AP2/Bedrock signature verification, full test suite, and a PUBLISHING.md with exact registry steps. Ready to publish (not yet published).

Runs at the edge — in front of your origin, or inside your own Worker. Uses the Workers runtime, no Node APIs. Bind your API key as a secret.

Install

npm install @agentrails/cloudflare

Wire it up

// src/worker.ts import { createAgentrail } from '@agentrails/cloudflare'; const guard = createAgentrail({ policies: { '/api/products': { priceCents: 5, purposeAllow: ['browsing', 'answer'] }, }, }); export default { async fetch(req, env, ctx) { // env.AGENTRAIL_API_KEY is a Wrangler secret const decision = await guard(req, env, ctx); if (decision.response) return decision.response; // 402 / blocked return fetch(req); // agent paid → pass to origin }, };

Set the secret: npx wrangler secret put AGENTRAIL_API_KEY

Python

agentrail

✅ Implemented & tested — real AP2/Bedrock signature verification, full test suite, and a PUBLISHING.md with exact registry steps. Ready to publish (not yet published).

ASGI middleware for FastAPI / Starlette, plus WSGI for Flask & Django. Same policy semantics as the JS SDK.

Install

pip install agentrail

Wire it up — FastAPI

# main.py from fastapi import FastAPI from agentrail import AgentrailMiddleware app = FastAPI() app.add_middleware( AgentrailMiddleware, api_key=os.environ["AGENTRAIL_API_KEY"], policies={ "/api/products": {"price_cents": 5, "purpose_allow": ["browsing", "answer"]}, "/api/reports/*": {"price_cents": 50, "purpose_allow": ["answer"]}, }, ) @app.get("/api/products") def products(): return {"products": []}

PHP

agentrail/agentrail

✅ Implemented & tested — real AP2/Bedrock signature verification, full test suite, and a PUBLISHING.md with exact registry steps. Ready to publish (not yet published).

PSR-15 middleware — drops into Laravel, Symfony, Slim, or any PSR-15 pipeline.

Install

composer require agentrail/agentrail

Wire it up — Slim / PSR-15

// index.php use Agentrail\AgentrailMiddleware; $app->add(new AgentrailMiddleware([ 'apiKey' => getenv('AGENTRAIL_API_KEY'), 'policies' => [ '/api/products' => ['priceCents' => 5, 'purposeAllow' => ['browsing', 'answer']], ], ])); $app->get('/api/products', function ($req, $res) { $res->getBody()->write(json_encode(['products' => []])); return $res->withHeader('Content-Type', 'application/json'); });

Go

github.com/agentrail/agentrail-go

✅ Implemented & tested — real AP2/Bedrock signature verification, full test suite, and a PUBLISHING.md with exact registry steps. Ready to publish (not yet published).

Standard net/http middleware. Wraps any http.Handler — works with chi, gorilla/mux, Echo, Gin (via its http.Handler bridge), or the stdlib mux.

Install

go get github.com/agentrail/agentrail-go

Wire it up — net/http

// main.go package main import ( "net/http" "os" "github.com/agentrail/agentrail-go" ) func main() { guard := agentrail.New(agentrail.Config{ APIKey: os.Getenv("AGENTRAIL_API_KEY"), Policies: agentrail.Policies{ "/api/products": {PriceCents: 5, PurposeAllow: []string{"browsing", "answer"}}, }, }) mux := http.NewServeMux() mux.HandleFunc("/api/products", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.Write([]byte(`{"products":[]}`)) }) http.ListenAndServe(":3000", guard.Handler(mux)) }

TypeScript · Hono

@agentrails/hono

✅ Implemented & tested — real AP2/Bedrock signature verification, full test suite, and a PUBLISHING.md with exact registry steps. Ready to publish (not yet published).

A Hono MiddlewareHandler — runs anywhere Hono does (Cloudflare Workers, Deno, Bun, Node). Same policy object as the core SDK.

Install

npm i @agentrails/hono

Wire it up

// app.ts import { Hono } from 'hono'; import { agentrail } from '@agentrails/hono'; import { makeDemoValidator } from './validators'; const app = new Hono(); app.use(agentrail({ policies, validators: { demo: makeDemoValidator() }, onEvent: e => console.log(e) })); app.get('/content/articles', (c) => c.json({ articles: [] })); export default app;

Ruby · Rails / Rack

agentrail

✅ Implemented & tested — real AP2/Bedrock signature verification, full test suite, and a PUBLISHING.md with exact registry steps. Ready to publish (not yet published).

Rack middleware — add it to a Rails app via the middleware stack, or to any Rack-based app (Sinatra, Hanami, plain Rack).

Install

# Gemfile gem "agentrail"

Wire it up — Rails

# config/application.rb module MyApp class Application < Rails::Application config.middleware.use Agentrail::Middleware, policies: POLICIES end end

Java · Spring Boot

com.agentrail:agentrail

✅ Implemented & tested — real AP2/Bedrock signature verification, full test suite, and a PUBLISHING.md with exact registry steps. Ready to publish (not yet published).

A servlet Filter with a Spring Boot helper. Register it as a FilterRegistrationBean and your controllers stay unchanged.

Install

<!-- pom.xml --> <dependency> <groupId>com.agentrail</groupId> <artifactId>agentrail</artifactId> <version>0.1.0</version> </dependency>

Wire it up — Spring Boot

// AgentrailConfig.java @Configuration public class AgentrailConfig { @Bean FilterRegistrationBean<AgentrailFilter> agentrail() { return AgentrailSpring.filter(new AgentrailConfig() .policies(POLICIES) .validators(Map.of("demo", DemoValidator.demo(null))) .mode(mode)); } }

C# · ASP.NET Core

Agentrail

✅ Implemented & tested — real AP2/Bedrock signature verification, full test suite, and a PUBLISHING.md with exact registry steps. Ready to publish (not yet published).

Middleware for the ASP.NET Core pipeline. One app.UseAgentrail(...) in front of your endpoints.

Install

dotnet add package Agentrail

Wire it up

// Program.cs var app = builder.Build(); app.UseAgentrail(o => { o.Policies = policies; o.Validators = new() { ["demo"] = DemoValidator.MakeDemoValidator() }; o.OnEvent = Record; }); app.MapGet("/content/articles", () => new { articles = Array.Empty<object>() }); app.Run();

Rust · Axum

agentrail

✅ Implemented & tested — real AP2/Bedrock signature verification, full test suite, and a PUBLISHING.md with exact registry steps. Ready to publish (not yet published).

A Tower layer for Axum. Build a rail from agentrail::Config, then register it onto your Router.

Install

# Cargo.toml [dependencies] agentrail = "0.0.1"

Wire it up

// main.rs use axum::{Router, routing::get}; let rail = agentrail::Rail::new(agentrail::Config { policies, ..Default::default() }); let app = rail.register(Router::new().route("/content/articles", get(handler)));

Elixir · Phoenix / Plug

agentrail

✅ Implemented & tested — real AP2/Bedrock signature verification, full test suite, and a PUBLISHING.md with exact registry steps. Ready to publish (not yet published).

A Plug — add it to a Phoenix router pipeline, or to any Plug stack. Same policy semantics as every other SDK.

Install

# mix.exs defp deps do [{:agentrail, "~> 0.1"}] end

Wire it up — router pipeline

# lib/my_app_web/router.ex pipeline :agents do plug Agentrail.Plug, policies: %{...}, on_event: &MyApp.Analytics.record/1, mode: :live end

MCP · Model Context Protocol

@agentrails/mcp · agentrail.mcp

🧪 Preview — gate & meter MCP tool calls with the same control plane as the HTTP SDKs. Node & Python, 100% test coverage, runnable demo.

MCP standardizes how an agent reaches your tools — but not whether a call is allowed, what it costs, or whether it was paid. Wrap your tool handlers and agent calls are detected, gated by purpose, metered, and charged via an x402-style "payment required" tool result. Works with the official MCP SDK (no hard dependency); MCP servers show up as their own surface on the dashboard.

Node — install & wire up

// npm install @agentrails/mcp @agentrails/sdk import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { createAgentrailMcp } from '@agentrails/mcp'; const server = new McpServer({ name: 'acme-mcp', version: '1.0.0' }); const guard = createAgentrailMcp({ apiKey: process.env.AGENTRAIL_API_KEY }); // register a guarded tool — priced + gated from the dashboard guard.register(server, 'get_report', { inputSchema: { id: z.string() } }, async ({ id }) => ({ content: [{ type: 'text', text: await fetchReport(id) }] }));

Python — install & wire up

# pip install agentrail (FastMCP shown) from agentrail.mcp import create_agentrail_mcp guard = create_agentrail_mcp(api_key=os.environ["AGENTRAIL_API_KEY"], server_name="acme-mcp") @mcp.tool() async def get_report(id: str, ctx: Context) -> dict: dec = guard.evaluate("get_report", extra={"_meta": ctx.request_context.meta}) if not dec["allowed"]: return dec["result"] # payment_required / blocked return {"content": [{"type": "text", "text": fetch_report(id)}]}

Agents pass identity + payment in the tool call's _meta (agentrail/purpose, agentrail/payment). Try it: demos/agentrail-mcp-demonpm run demo.

What every SDK gives you

The wire protocol is identical across languages, so you can mix stacks behind one AgentRail project and one dashboard.

Detect

Known-agent fingerprinting, self-declared X-Agent-Identity / X-Agent-Purpose headers, and heuristics. Every request gets an identity, confidence, and purpose.

Price & gate

Per-resource, per-purpose policies. Free for browsing, metered for answers, blocked for training — your call. Returns HTTP 402 with X-Price-Cents and X-Payment-Methods.

Verify payment

Reads the X-Payment-Receipt header and verifies it against AP2 (signed mandates), x402 (on-chain USDC), or AWS Bedrock — hosted, or self-hosted with your own validators.

Report

Emits a visit / payment / blocked / extraction event for every request — to your own callback and to the dashboard.

Ready to publish your own fork or contribute an adapter? Read the Agent API docs and the SDK publishing guide in docs/sdk-publishing.md.