Proof verified
Request 41 of 100
Caller unknown

Rate limitsthat keep no record

Agents lock a deposit and prove they are within quota without saying who they are. Cheat, and the deposit is forfeit.

Stake once, with a tap.An operator locks a deposit with a passkey. Allowance scales with it, so splitting it gains nothing.

Every request, unlinkable.Each call carries a zero-knowledge proof: a staked member, request k of N. Never which member.

One deposit.
No record of who called.

Four stops. One deposit.

The whole journey of a request, from the stake that backs it to the slash that punishes a repeat.

  1. Stake

    Lock a deposit with a passkey. The agent joins a public list of staked members.

    Custody
    Passkey, checked on-chain
    Allowance
    Linear in stake
  2. Prove

    Each request carries a zero-knowledge proof: a member, request k of N. Never which one.

    Circuit
    RLN-v2, audited and reused
    Scope
    Quotas are per server
  3. Check

    The service verifies off-chain and learns nothing about who sent it.

    Check
    Off-chain, milliseconds
    Memory
    One line per nullifier
  4. Slash

    A reused number leaks the key. Anyone holding it can claim the stake.

    Claim path
    Commit, then reveal
    Payout
    Slasher paid, rest burned

Every fix so far keeps a record or picks a gatekeeper.

Anyone running a free or cheap endpoint has to stop one agent sending millions of calls. This is what is on the board today.

ApproachWhere it breaks for agentsStatus
API keys and accountsEvery call ties to one identity, and a full activity log builds up. Agents cannot fill in signup forms.Logs everything
IP address limitsHonest agents share cloud IPs and get blocked. Abusers rent fresh ones for pennies.Punishes the honest
CAPTCHABuilt to stop bots. Your legitimate agent is a bot.Blocks the caller
Pay per callEach payment is public, so an agent's whole history is visible. Many free endpoints do not want to charge.Public history
Privacy Pass and ARCPrivate, but a company decides who gets in. One party holds the trust layer.Gatekeeper
QUOTAPrivate for the caller, enforceable for the service, run by no company.Bounded, not identified

Breaking the rule exposes the cheater.

Each request carries one point on a secret line. One point is noise. Two points on the same line are the secret itself.

share 1share 2a₀ = secret keymessage hash
One point reveals nothing.

Every line through it is equally likely. The service learns neither the key nor who is calling, and cannot link this request to another.

Four roles. No one in charge.

Operator

The person or team that owns agents. Taps a passkey to lock, change or withdraw a deposit. Public at enrollment, never again.

Privy agent wallet, policy-limited

Agent

The program making requests. It holds a secret key derived from a wallet signature, so it is recoverable and never stored in plain text.

@quota/client

Service

An API, MCP tool server or site. It sets requests per epoch, chooses which trust lists to accept, and keeps one line per nullifier.

@quota/server middleware

Slasher

Runs beside the service. When a number repeats it recovers the secret and claims the deposit through a commit then reveal.

@quota/slasher, Dynamic server wallet

What QUOTA does not do.

We would rather you hear it here than find it in production.

  • Not proof of being human.A passkey is not a person. The deposit is what makes abuse expensive.
  • Limits are per service.Each service sets its own N, so total exposure is N for every server you call.
  • The deposit must outweigh the abuse.Services choose a minimum tier. We publish guidance on sizing it.
  • Proofs take time.Built for tool servers, APIs and scraping targets, not for public RPC.
  • The operator is public at enrollment.Anonymity is among everyone staked in the accepted trees at that moment.
  • No sealed mempool yet.BTX is not live on Monad testnet, so claims use commit then reveal. We say so plainly.

A middleware, not an accounts system.

Set how many requests per epoch and which trust lists you accept. Slash rewards go to your wallet.

import { quota } from "@quota/server";

app.use(
  quota({
    serverId: "lantern-search",
    perEpoch: 100,
    trees: ["open"],
    onViolation: slasher.submit,
  })
);

API sketch of the target interface. The packages are under construction; see the integration status in the docs.