Add spend limits for agents
Cap how many paid calls and how much spend a single payer can make.
Public Beta · early access
import { limit, payers } from "tollstile";
const guarded = toll.price("$0.40", {
require: [
limit({ perPayer: "100/hour", spendPerDay: "$20" }),
payers({ deny: ["0xBAD…"] }),
],
});limit()counts charges from the ledger that were not released, failed, or refunded. Concurrent requests can briefly exceed a limit by the number in flight.payers()matches payer ids case-insensitively (EVM addresses differ only by checksum casing).- Denials are
429for limits and403for payer rules, and nothing is reserved.
Only for expensive calls
import { amountOver, when } from "tollstile";
toll.price("$10", { require: [when(amountOver("$5"), strongerCheck)] });Write your own requirement
import type { Requirement } from "tollstile";
const businessHours: Requirement = {
name: "business-hours",
async check({ now }) {
const hour = now.getUTCHours();
return hour >= 9 && hour < 17 ? { ok: true } : { ok: false, status: 403, reason: "closed" };
},
};Requirements also receive claims, a single-use store for nonces, and the quote, which carries a fresh nonce for evidence bound to this request.
Retries
Send Idempotency-Key on the first paid request and keep it on retries of the same request (on MCP: _meta["tollstile/idempotency-key"]). A completed charge returns 409 already_paid; an in-flight charge returns 409 request_in_progress; an unknown outcome returns 503 payment_outcome_unknown. Do not start a new payment while the outcome is unknown. Released/refunded attempts may run again. See Idempotency for request matching and rail-specific key scopes.