{"_id":"@agentrails/sdk","name":"@agentrails/sdk","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"@agentrails/sdk","version":"0.0.1","publishConfig":{"access":"public"},"description":"AgentRail SDK — detect AI agent traffic, gate it by purpose, and charge via HTTP 402 (AP2 / x402 / Bedrock Payments). Express middleware today; framework-agnostic adapters incoming.","main":"index.js","types":"index.d.ts","exports":{".":{"types":"./index.d.ts","require":"./index.js","default":"./index.js"},"./package.json":"./package.json"},"scripts":{"test":"node --test __tests__/*.test.js","prepublishOnly":"npm test"},"keywords":["ai","ai-agents","agents","agentic-web","monetization","paywall","http-402","payment-required","ap2","x402","bedrock-payments","express","middleware","rate-limiting","bot-detection"],"engines":{"node":">=18"},"peerDependencies":{"express":">=4"},"peerDependenciesMeta":{"express":{"optional":true}},"homepage":"https://github.com/mohitsudhakar/agentrail#readme","repository":{"type":"git","url":"git+https://github.com/mohitsudhakar/agentrail.git","directory":"packages/agentrail"},"bugs":{"url":"https://github.com/mohitsudhakar/agentrail/issues"},"author":{"name":"Mohit Sudhakar","email":"mohit.sudhakar@gmail.com"},"license":"MIT","gitHead":"5b88be41c981040c2f08b4f2025ddee6bead7174","_id":"@agentrails/sdk@0.0.1","_nodeVersion":"25.2.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-23WT3KkJyi51Kxw6ISHHn3VqokwQMbGPMWjqV0xn6LIHsqVlE2LeVEVY7x/XzSwXm8eNlyrMyLlUarhdZ9JYOg==","shasum":"f19c41303b2d1aa4504280eff63d54311f1e29e9","tarball":"https://registry.npmjs.org/@agentrails/sdk/-/sdk-0.0.1.tgz","fileCount":10,"unpackedSize":76087,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAQPxs8UogMj7h9HF9ybIP4vgnNP5SZTGevabiWyJH+6AiB2iGZG62QX2nfCs/WoqsHI0hTbHQtTYKvhB0F5m7U6sA=="}]},"_npmUser":{"name":"scholeteai","email":"founders@scholete.com"},"directories":{},"maintainers":[{"name":"scholeteai","email":"founders@scholete.com"},{"name":"mohitsu","email":"mohit.sudhakar@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_0.0.1_1779433820055_0.03285346071156581"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-22T07:10:19.926Z","0.0.1":"2026-05-22T07:10:20.236Z","modified":"2026-05-22T07:10:20.527Z"},"maintainers":[{"name":"scholeteai","email":"founders@scholete.com"},{"name":"mohitsu","email":"mohit.sudhakar@gmail.com"}],"description":"AgentRail SDK — detect AI agent traffic, gate it by purpose, and charge via HTTP 402 (AP2 / x402 / Bedrock Payments). Express middleware today; framework-agnostic adapters incoming.","homepage":"https://github.com/mohitsudhakar/agentrail#readme","keywords":["ai","ai-agents","agents","agentic-web","monetization","paywall","http-402","payment-required","ap2","x402","bedrock-payments","express","middleware","rate-limiting","bot-detection"],"repository":{"type":"git","url":"git+https://github.com/mohitsudhakar/agentrail.git","directory":"packages/agentrail"},"author":{"name":"Mohit Sudhakar","email":"mohit.sudhakar@gmail.com"},"bugs":{"url":"https://github.com/mohitsudhakar/agentrail/issues"},"license":"MIT","readme":"# @agentrails/sdk\n\nDrop-in Express middleware that detects AI agent traffic, gates it by purpose,\nand charges per call over HTTP 402 — with pluggable validators for AP2,\nx402, AWS Bedrock Payments, and your own custom rails.\n\n## Install\n\n```sh\nnpm install @agentrails/sdk\n```\n\n## Quick start\n\n```js\nconst express = require('express');\nconst {\n  agentrail,\n  makeAp2Validator,\n  makeX402Validator,\n  makeBedrockValidator,\n} = require('@agentrails/sdk');\n\nconst app = express();\n\napp.use(agentrail({\n  policies: {\n    '/api/products':       { priceCents: 1,   purposeAllow: ['browsing','answer'] },\n    '/api/products/:sku':  { priceCents: 1,   purposeAllow: ['browsing','answer'] },\n    '/api/reports/*':      { priceCents: 25,  purposeAllow: ['browsing','answer'] },\n  },\n  validators: {\n    ap2:     makeAp2Validator({  merchantId: 'merchant_acme_inc' }),\n    x402:    makeX402Validator({ recipientAddress: '0xYourTreasury...' }),\n    bedrock: makeBedrockValidator({ kmsKeyId: 'arn:aws:kms:...' }),\n  },\n  onEvent: (e) => analytics.record(e),\n}));\n\napp.get('/api/products', (req, res) => res.json({ products: [...] }));\napp.listen(3000);\n```\n\nA `ChatGPT-User` request to `/api/products` now gets:\n\n```\nHTTP/1.1 402 Payment Required\nX-Price-Cents: 1\nX-Payment-Methods: ap2,x402,bedrock\n```\n\nAfter paying through the agent's preferred rail and resending with\n`X-Payment-Receipt: ap2:<base64-jws>` (or `x402:<tx-hash>:<sig>`, or\n`bedrock:<base64-blob>`), the request gets `200 OK`. Human requests pass\nthrough unchanged.\n\n## Multi-rail routing\n\nThe `validators` map dispatches by the receipt's prefix:\n\n| Receipt prefix    | Goes to                  |\n|-------------------|--------------------------|\n| `demo:1:abc`      | `makeDemoValidator()`    |\n| `ap2:<jws>`       | `makeAp2Validator(...)`  |\n| `x402:<tx>:<sig>` | `makeX402Validator(...)` |\n| `bedrock:<blob>`  | `makeBedrockValidator(...)` |\n\nMount only the rails you accept. An agent presenting a receipt for an\nunmounted rail gets `402` with `reason: unsupported_rail`.\n\nEvery validator returns `{ ok, amountCents, rail }` on success and\n`{ ok: false, reason }` on failure (missing / invalid / replay / underpaid).\n\n## Validator factories\n\n```js\nmakeAp2Validator({\n  publicKeyUrl: 'https://ap2.google.com/.well-known/keys',  // for JWS verification\n  merchantId:   'merchant_acme_inc',                        // your AP2 merchant ID\n  clockSkewSec: 60,                                         // mandate expiry tolerance\n})\n```\n\n```js\nmakeX402Validator({\n  facilitatorUrl:   'https://facilitator.coinbase.com/x402/verify',\n  recipientAddress: '0xYourTreasury...',\n  chain:            'base',\n  acceptedTokens:   ['USDC'],\n})\n```\n\n```js\nmakeBedrockValidator({\n  kmsKeyId: 'arn:aws:kms:us-east-1:.../demo-signing-key',\n  region:   'us-east-1',\n})\n```\n\nAll three accept the same `{ req, requiredCents }` and return the standard\nresult shape. Implementations are stubbed in the prototype; the production\nverification work is documented inline in `src/rails.js`.\n\n## Bring your own validator\n\nIf you have a custom payment system, implement the same shape:\n\n```js\nfunction myCustomValidator({ req, requiredCents }) {\n  const proof = req.get('x-payment-receipt');\n  // ... verify against your service ...\n  return { ok: true, amountCents: 1, rail: 'custom' };\n}\n\napp.use(agentrail({\n  policies: { ... },\n  validators: { custom: myCustomValidator },\n}));\n```\n\n## What you get out of the box\n\n- **Detection** — known-bot UA fingerprinting (OpenAI, Anthropic, Google,\n  Perplexity, Meta, ByteDance, CommonCrawl, …), self-declared\n  `X-Agent-Identity` / `X-Agent-Purpose` headers, MCP protocol signals, and\n  behavioural heuristics. Sets `req.agentrail = { isAgent, identity, signals, confidence }`.\n- **Control** — per-resource policies with purpose gating\n  (allow `browsing`/`answer`, deny `training`, etc.).\n- **Monetize** — HTTP 402 with `X-Price-Cents` / `X-Payment-Methods`.\n  Multi-rail validator router supports AP2, x402, Bedrock, and custom rails\n  side-by-side.\n- **Analyze** — `onEvent` fires on every `visit` / `payment` / `blocked`\n  event so you can pipe into your analytics (Postgres, Segment, etc.). Each\n  payment event includes the rail used.\n\n## Configuration\n\n| Option              | Default                | Description |\n|---------------------|------------------------|-------------|\n| `policies`          | `{}`                   | Map of route patterns → policy. |\n| `validators`        | `{ demo: makeDemoValidator() }` | Rail-prefix → validator function. |\n| `validatePayment`   | —                      | Legacy single-validator override. Use `validators` instead. |\n| `paymentMethods`    | derived from validators | Override of `X-Payment-Methods` header. |\n| `onEvent`           | `() => {}`             | Callback for every analytics event. |\n| `treatPathAsAgent`  | `() => false`          | Predicate: if true for `req.path`, any caller is treated as an agent. Use for explicit `/api/agent/*` surfaces. |\n\n## Route patterns\n\n- Exact: `/api/data`\n- Wildcard prefix: `/api/reports/*`\n- Parameterized: `/api/products/:sku`\n\n## Serving agents\n\nOnce the middleware is installed, your route handlers decide what to return\nto an agent vs a human. The SDK identifies the caller and gates payment,\nbut **never transforms your response body** — the agent-facing JSON shape\nis your call. See **[docs/serving-agents.md](../../docs/serving-agents.md)**\nfor the canonical pattern, three good response shapes, anti-patterns, and a\ncheatsheet.\n\n## Verifying agent identity\n\nOut of the box, the SDK upgrades a *claimed* identity (`User-Agent`,\n`X-Agent-Identity`) into a *verified* verdict by checking the source IP\nagainst the operator's published ranges and confirming PTR + forward-DNS.\nThe result lands on `req.agentrail.verified`:\n\n| `verified`         | Meaning                                                                                            |\n|--------------------|----------------------------------------------------------------------------------------------------|\n| `'rdns'`           | IP is in the operator's published range **and** PTR resolves to an operator-owned host **and** forward-DNS includes the source IP. Strongest tier without HTTP signatures. |\n| `'ip-allowlist'`   | IP is in the operator's published range; PTR was missing or didn't match. Still useful — TCP source IPs are hard to spoof — but weaker. |\n| `null`             | Not in any range, or operator isn't known to the verifier. Identity is *claimed only*.             |\n\nVerification is **fail-open**: any network or DNS error returns `null`\nrather than throwing. The request flow is never broken by the verifier.\n\nUse it in policy:\n\n```js\napp.get('/api/agent/articles/:slug', (req, res) => {\n  // Optional: charge unverified callers more than verified ones.\n  if (req.agentrail.verified === 'rdns') return serveLowTier(req, res);\n  return serveHighTier(req, res);\n});\n```\n\nThe verifier supports four operators by default (OpenAI, Anthropic,\nGoogle, Perplexity). Override or inject:\n\n```js\nconst { agentrail, createVerifier } = require('@agentrails/sdk');\n\nconst verifier = createVerifier({\n  operatorConfig: { /* your override; see DEFAULT_OPERATORS export */ },\n  refreshIntervalMs: 6 * 60 * 60 * 1000,   // 6h list refresh, 24h per-IP cache\n  fetchImpl: globalThis.fetch,\n  resolver: require('node:dns/promises'),\n});\n\napp.use(agentrail({ /* ... */ verifier }));\n// or: agentrail({ verifier: false }) to disable verification entirely.\n```\n\nThe SDK also sets a `X-Agent-Verified: rdns | ip-allowlist` response\nheader alongside the existing `X-Agent-Recognized`, so agents can see\nthe merchant's verdict on their own identity.\n\n## Status\n\nThis is the prototype that ships with the AgentRail pitch site. The\ndetection, policy, and event layers are real. The four rail validators are\nstubs that match production shape with replay protection and rail-prefixed\nreceipts; each carries an inline `PRODUCTION` comment block describing the\nreal cryptographic / on-chain verification work that replaces the stub.\n","readmeFilename":"README.md","_rev":"1-2425010911c4233e7aeab3b498bf72dd"}