Tollstile

Requirements

Conditions every admitted request must meet, checked after the payer is known and before anything is reserved.

Pre-release · planned API
toll.price("$0.40", {
  require: [
    limit({ perPayer: "100/hour", spendPerDay: "$20" }),
    when(amountOver("$5"), strongerCheck),
  ],
});

A requirement receives:

FieldUse
contextThe normalized request context
priceThe price being charged
payerThe rail payer or the policy account
quoteThe quote the proof carried, with a fresh nonce
ledgerRead access for limits
claimsA single-use store for nonces and replay windows
nowThe injected clock
signalAborted when the provider timeout elapses

and returns { ok: true } or { ok: false, status: 402 | 403 | 429 | 503, reason }.

When evidence cannot be checked right now, for example an agent's key directory is unreachable, answer 503 or throw TollstileError with PROVIDER_UNAVAILABLE or PROVIDER_TIMEOUT. Tollstile answers 503 requirement_unavailable, so a temporary outage never looks like a permanent 403.

Context

type Context = {
  transport: "http" | "mcp";
  request: Request | null;
  mcp: { tool: string; arguments: unknown; meta: object; clientCapabilities: object } | null;
  principal: { id: string } | null;
  resource: string;
  requestId: string;
  extras: unknown; // the framework object, as an escape hatch
};

Built-in and planned

RequirementStatus
limit(), payers(), when()Implemented
verifiedAgent() — HTTP message signatures, Web Bot AuthIn development
userMandate() — AP2 mandates bound to the quote nonceIn development

Tollstile verifies identity and authorization evidence. It never issues identities.

On this page