I built the missing piece for multi-agent spend: a supervisor can hand each worker a scoped budget it cryptographically cannot exceed
The problem, if you've run a supervisor/worker loop against paid APIs:
You give the supervisor credentials. It spawns workers. Now either every worker
shares one key (one buggy worker burns the whole budget) or you provision a
separate account per worker and manage that by hand. And when it's done, you
have no artifact showing what was actually bought — just a total.
Tollgate is a gateway that sits in front of paid APIs and fixes those three
things:
Hard caps. Per-request and total, checked and decremented atomically before the
upstream API is ever called. Not reconciled afterwards. A runaway loop stops at
the cap, not at your credit limit.
Scoped sub-agent budgets. The supervisor signs a capability for each worker
offline — no server round trip, no shared key. The worker presents it on every
request. Every charge draws down every level of the chain, so the supervisor's
pool drains as its workers spend. If the supervisor's pool empties, all three
workers stop at once even though none of them hit its own cap. You can also
revoke a worker mid-run, and revoking a parent kills every child under it.
Receipts. One signed receipt per charge naming the endpoint, the sub-agent and
the upstream status code, plus a signed expense report rolling up the whole
delegation tree. Failed upstream calls aren't charged — a 5xx or timeout voids
the reservation and credits every level back.
There's a Python client, so from an agent's side it's:
chain = supervisor.delegate(subject=worker, max_total="0.10",
max_per_request="0.05")
and the worker just makes requests.
Cost: 3 ms added p50 latency, measured. Payment rail is x402 over USDC on Base
Sepolia — testnet only, no real money, no token, Apache-2.0. Rust gateway,
Python client, Next.js dashboard showing the delegation tree draining live.
https://github.com/sanjayrohith/Tollgate
Genuinely want to know: for those running supervisor/worker setups, is
per-request payment the right granularity, or would you rather cap by task?
---
r/CryptoTechnology
Strictly no-shill sub. This must read as a design discussion, not an announcement.
Title:
Why agent API payments need stablecoins and not cards — and what x402 still leaves unsolved
Body:
I spent a few weeks building a control plane for x402 payments and want to lay
out the design tradeoffs, because two of them I'm still not happy with.
First, why this can't be a Stripe problem. Card rails have a hard floor:
interchange plus fixed fees make a $0.0004 charge impossible, so providers batch
into subscriptions, which reintroduces the account, which needs a legal person
with a bank account. Cards also need a merchant of record and a chargeback
window, and an ephemeral agent supplies neither. Stablecoin transfers on an L2
have near-zero marginal cost, and that's the only reason per-request pricing
works at all. Nothing else in the design needs a chain except settlement.
x402 solved the payment half. It deliberately did not solve control: nothing
stops a runaway loop, a parent agent can't give a sub-agent a scoped budget
without sharing its key, and a transfer on a block explorer doesn't tell you
which endpoint was called or whether it even returned 200.
Two design decisions I'd like argued with:
- Delegation funding. The version I shipped ("Resolution A") has the parent
send USDC to each child wallet up front, with the capability chain acting as
pure policy constraining money the child already holds. Consequence: the parent
cannot claw back unspent funds without the child's cooperation, and each child
costs one on-chain transfer. The alternative is channel-backed delegation, which
fixes both but is materially more machinery. For short-lived agents I think A is
right and B is over-engineering. I might be wrong.
- Settlement is effectively-once, not exactly-once, and I think that's the
honest ceiling. The EIP-3009 nonce is the idempotency key at every layer:
gateway dedup, stream dedup, Postgres primary key, and USDC's authorizationState
on-chain. On-chain that composition is at-most-once and the chain enforces it;
off-chain the settler is at-least-once with idempotent retries. Compose them and
you get effectively-once. I've seen a lot of projects claim exactly-once for
this shape and I don't believe any of them.
Revocation is off-chain, in a Redis set, and I'd argue that's correct rather
than lazy — the gateway is the enforcement point, so nothing needs to reach a
chain for a revocation to take effect. On-chain revocation would add block-time
latency to solve a problem the architecture doesn't have.
Testnet only, no token, Apache-2.0, and the live settlement run hasn't happened
yet — that's in the README rather than buried.