Brawl

Give your agent a budget, not your keys.

Spend Leash is a small contract that holds your agent's budget. The agent can pay for APIs, data and other agents. The contract refuses anything over your caps, to anyone you did not approve, or for a request already paid.

Status: design preview and interactive browser prototype. Not audited, not deployed. The planned pilot will run on a testnet. Source code is published with the pilot.

The free builder pilot

Apply for the pilot

Quickstart

1Create a vault

From the factory, in the token your agent pays with. maxFeeBps is the highest fee you accept; the pilot fee is 0.

// one vault per agent (or per budget)
vault = factory.createVault(token, /* maxFeeBps */ 0)
token.approve(vault, amount); vault.deposit(amount)

2Set the leash, then switch it on

Every vault starts paused, with the payee allowlist on.

vault.setAgent(agentAddress)                  // the only key your agent holds
vault.setPolicy(perPayment, per24h, true)     // caps in token units · allowlist on
vault.setPayee(weatherApi, true)              // approve who may be paid
vault.setPaused(false)

3Pay inside an x402 request

When an API answers 402 Payment Required, check the leash for free, pay once, then retry with the receipt.

// agent side (proposed pseudocode; adapter not published yet)
res = fetch(url)
if (res.status == 402) {
  req = res.json().accepts[0]                         // payTo, asset, amount, nonce
  ref = keccak256(chain, asset, payTo, resource, amount, nonce)
  [ok, reason] = vault.canPay(req.payTo, req.amount, ref)
  if (!ok) return stop(reason)                        // e.g. DailyLimitExceeded
  tx = vault.pay(req.payTo, req.amount, ref)
  res = fetch(url, { headers: { 'X-PAYMENT': base64({ nonce, tx }) } })
}

4Seller side: trust the receipt

Before serving data, the proposed seller adapter must check the transaction:

Interface

FunctionWhoWhat it does
pay(payee, amount, ref)agent or keeperPays once per ref, inside every rule, and emits Paid(n, payee, ref, amount, fee).
canPay(payee, amount, ref)anyoneFree dry run of the rules. Returns (ok, reason). It does not check who is calling, so pay can still revert with Unauthorized if the caller is not the agent or keeper.
spentLast24h() · remainingToday()anyoneThe rolling window: the current hour plus the 24 before it. No midnight reset.
setPolicy · setPayee · setAgentkeeperThe leash itself.
setPaused · setHerdSwitchkeeperStop new payments now, or opt in to a shared crash brake (fails closed if broken).
deposit · withdrawanyone · keeperWithdraw always works, also while paused.
Revert reasonMeaning
PerPaymentLimitExceededPayment plus fee is over the per-payment cap.
DailyLimitExceededWould pass the 24-hour budget.
PayeeNotAllowedAllowlist is on and this payee is not on it.
RefAlreadyPaidThis request was already paid.
TradingPaused · HerdHaltedThe keeper paused, or the Herd Switch is on.
InsufficientBalanceNot enough funds in the vault.

Who can do what

RoleCanCannot
Keeper (you)Set every rule, pause, withdrawPay past the caps either
AgentPay inside the rulesWithdraw, change rules, or pay unapproved payees (while the allowlist is on)
Factory owner (BRAWL)Set the fee for new vaults, max 1%Touch existing vaults, their fee, or their funds
Herd Switch guardians (opt-in)Pause new payments, max 24 hours per halt (you can opt out)Move funds

Apply for the pilot

Applications currently go by DM. This form prepares text for you to copy and send; it does not submit your details.

We read every application ourselves and use your answers only to run the pilot. Ask us any time to delete them. We never ask for keys or seed phrases.