Skip to content
Tollgate Docs

The Bar-Tab Model

Every paid request signs an IOU. The IOU replaces the previous one for the same (agent, developer, path) tuple — it is not additive in the per-request sense. The IOU carries amountMicros, the cumulative USDC the agent has consumed along that path. Monotonic nonces prevent replay; monotonic amounts prevent rollback.

Why cumulative?

On-chain settlement is a per-signature operation. If every request produced a standalone IOU, settling 10,000 requests would require 10,000 transfers. Cumulative IOUs collapse a full session into one transferFrom. You settle the latest IOU per tuple; anything prior is superseded.

Keys and deltas

The tuple is (agent, developer, path). The middleware stores previousCumulativeMicros per tuple. When a new IOU arrives, it rejects unless:

  • iou.amountMicros >= previousCumulativeMicros (monotonic amount, AMOUNT_NOT_MONOTONIC otherwise).
  • iou.amountMicros - previousCumulativeMicros === requestPrice (exact delta, AMOUNT_MISMATCH otherwise).
  • iou.nonce > previousNonce (strict monotonic, NONCE_REUSED otherwise).

Multiple paths, one agent

Different paths have independent tabs. An agent calling /api/search and /api/llm maintains separate cumulative counters per path — so pricing per route does not leak across routes.

Why the path is part of the key

It lets a developer price routes independently without requiring the agent to track a global tab. It also makes settlement auditing trivial: the emitted Settlement event carries (agent, developer, amount, nonce, settler) and the IOU carries the canonical path, so the indexer can attribute revenue per-route.

Dynamic paths

URL segments that look dynamic (UUIDs, all-digits, Ethereum-style hex) are collapsed by canonicalizePath. If the canonicalizer doesn't recognise your template, register it via endpointTemplate on wrap(). Unrecognised dynamic segments yield PATH_APPEARS_DYNAMIC.