Beersy
BRC-172

Giving an AI Agent Control of a Delivery Vehicle Without Giving It a Wallet

Letting a computer program spend Bitcoin on its own usually means handing it a private key, and a key can sign for anything, not just the one task it was meant for. Even a lightly funded key is a full custodian, which is risky when the program is something like an AI agent reading untrusted instructions. This describes a way to let a program trigger on-chain steps and pay their fees automatically, without ever holding a key that could send money elsewhere.

sun-dive14 min read

Reference for an AI

Everything an assistant needs to answer questions about BRC-172 accurately, including what it depends on.

Summary

Why
An autonomous agent needs to trigger paid on-chain steps without holding a key that could redirect funds anywhere.
What
BRC-172 defines a self-funding covenant, a battery, that pays its own transaction fees from value it carries and enforces its own next state, so control over its actions can be given out without giving out custody of money.
How
A developer writes a covenant that reads its own carried value and scriptCode from the transaction preimage, enforces that each successor output keeps at least V minus a measured MAX_FEE, and refuses to build any successor state it did not compute itself, so a caller (human or agent) can only trigger a step, never…

What this lets you do

  • Let a covenant pay its own transaction fees out of value it already holds
  • Give an autonomous agent a credential that advances state but cannot redirect funds
  • Enforce a minimum fee ceiling derived from measuring a real worst-case spend
  • Resume a depleted covenant from its exact prior step after a top-up
  • Chain single-input single-output spends that any stranger can broadcast

Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.

tickticktick

The specification

Abstract

An agent that spends on Bitcoin is normally given a wallet, which is to say a key — and a key is unbounded capability: it signs anything, for whoever holds it. Funding it lightly bounds the amount at risk without bounding the behaviour.

This standard defines a battery: a covenant that carries its own fuel, pays each step's fee from the value it already holds, and enforces its own successor state. The authority to act correctly sits in the script rather than in anyone's possession, so an agent can be given control without custody — at most a credential that advances the covenant, which cannot direct value anywhere.

Motivation

An autonomous program must answer a question a signed transaction never does: who pays for the next step, when nobody is watching? Answering it with a hot wallet makes the agent a custodian — and a custodian that reads untrusted text for a living.

OP_PUSH_TX removes the key: a covenant reconstructing the sighash preimage on its own stack constrains its successor without anyone signing for identity, as BRC-226 establishes. What remains open is the fee, since a transaction with no fee does not relay and a keyless covenant has no funding . Hence:

Let the covenant's own carried value be the fuel, and let the fee come out of it.

A step is then a complete transaction — one input, one output, no funding, no change — that any stranger can broadcast. The value becomes a fuel gauge readable from the UTXO, and the steps become a computation trace, each hop enforced before it could exist, so it is walked and checked rather than trusted.

Scope

Defines how an on-chain action is paid for and authorised. Does not define what the covenant computes, or how its state is encoded — for the latter see BRC-171.

⚠ It bounds an agent's on-chain actions, not its reasoning: the agent thinks wherever it likes; it can only act within the covenant. A battery does not make an agent correct, honest or safe to deploy.

This is the most restrictive rung of a ladder; payee-bound and rate-bound covenants are separate proposals and MUST NOT be reached by relaxing §4. Capping value per unit of time is unavailable — a covenant has no clock but nLockTime, and gating on it restricts honest use identically.

Specification

The key words "MUST", "MUST NOT", "SHOULD" and "MAY" are as described in RFC 2119.

1. Terminology

  • Fuel — the value carried by the covenant's output; the only thing that pays for its steps.
  • Tick — one spend that performs one step and re-creates the covenant with the advanced state.
  • V — the fuel carried by the output being spent, read from the preimage.
  • MAX_FEE — the ceiling on how much fuel one tick may consume.
  • Flat — a covenant whose remaining fuel can no longer pay for a tick.

Two roles are OPTIONAL; a covenant MAY bind either, both or neither to a public key:

  • Driver — signature required to advance the covenant. Authority to act, nothing else.
  • Owner — signature honoured for rights over the instance itself, such as retiring it and recovering what it holds. Authority that reaches value.

2. The tick

in0    the covenant           unlocking script = the preimage
out0   the covenant, quined, state advanced, value ≥ V − MAX_FEE

out0 MUST be first; later outputs MAY be present and MUST NOT be constrained beyond being committed to in the sighash. A tick MUST NOT require a funding input — the moment it does, the ticker needs a wallet.

⚠ Two covenants that each rebuild at output 0 cannot share a transaction. Where they must interact, one MUST tolerate a fixed output offset and recognise its by script shape, not by a hash of a script at rest.

3. Authorisation, ownership and control

The covenant MUST authorise the advance by validating the preimage supplied in the , so the successor is enforced by the script rather than asserted by a signer. Beyond that, ownership and control by public key are both permitted:

configurationwho may advancerights over value
ownerlessanybodynobody — fuel can only become mining fees
controlledone keyed drivernobody
ownedanybody, or one keyed drivera keyed owner, per the rights the script grants

Authority MUST be enumerated in the script:

  1. A driver's authority MUST be limited to advancing the covenant, and MUST NOT suffice to direct value to an output of the signer's choosing.
  2. Any authority that can direct value MUST be gated by a key distinct from the driver's whenever the driving credential is held by someone other than the owner. One key doing both jobs turns a driving credential into a spending credential the moment it is issued.
  3. No configuration grants an authority the script does not spell out. There is no implicit administrator.

⚠ A conforming script contains a signature opcode — OP_PUSH_TX is built from OP_CHECKSIG against a constant whose scalar is published — so counting them is not a conformance test. The property is "no secret exists", and MUST be tested by parsing script chunks rather than searching hex.

4. The value rule and the top-up

The covenant MUST enforce out0.value ≥ V − MAX_FEE. It MUST be a floor, MUST NOT be an equality.

Under a floor, a transaction that increases the fuel is already a valid tick, so a top-up needs no separate code path, no privileged key and no second script. ⚠ Under an equality the fuel can only fall: the covenant can never be refuelled by anyone and dies permanently on reaching MAX_FEE, with no symptom until it stops.

The covenant SHOULD use SIGHASH_ANYONECANPAY | ALL | FORKID (0xc1), so a sponsor MAY add a funding input without invalidating the covenant's introspection while out0 stays pinned.

Anyone can empty it; nobody can take it — but the bound must be stated exactly. Whoever may advance the covenant may advance it maliciously until it is flat. This rule bounds what leaves per tick; it does not by itself decide where the surplus lands.

extractable per tick  =  MAX_FEE  −  the fee the transaction must actually pay to relay

A tick that routes that surplus to the spender rather than to a miner still satisfies this section, and is stopped only by the relay floor. ⇒ The headroom in §5 is the extraction surface. Keep it at the measured minimum and the amount is dust; leave it generous and §3.1 is defeated without this rule ever being broken. The Appendix reproduces a deployed covenant in which it was 844 per spend, to anyone, with no key.

⇒ So §4 does not deliver §3.1 on its own. A conforming implementation gets there by keeping MAX_FEE at the serialized worst case, or by constraining the surplus explicitly.

Mitigation for the rest is operational: fund lightly and top up. That is a griefing limit, not a theft limit.

5. The fee ceiling

MAX_FEE MUST be derived by serializing a real worst-case spend and measuring it, then applying the relay rate with modest headroom. It MUST NOT be hand-counted, inferred from the locking script alone, or copied from another covenant. It MUST cover the worst spend any legal variant can produce, and MUST be measured on the transaction the covenant exists for rather than the simplest one it can make.

MAX_FEE ≥ ceil(worstCaseTickBytes × relayRate) × headroom

⚠ Set below what the network accepts, no tick can ever pay enough to relay and every satoshi the instance holds becomes unreachable. MAX_FEE MAY be a script literal, which is permanent, or a field an owner key may update, which forecloses the ownerless configuration; implementations SHOULD state which. A wrong literal is escaped only by superseding the instance — mint a corrected covenant, stop fuelling the old — which needs no key but forfeits the original's identity and leaves it dormant rather than gone, since §7 lets anyone revive it.

This is a custody decision, not configuration. §4 places no upper bound on what an instance may come to hold, so the exposure from an error is whatever it accumulates over its life, growing with the covenant's success. A bug strands fuel as effectively as a bad constant: a state no spend can satisfy need only be reachable, and until reached it is indistinguishable from working code.

⇒ Because a covenant of useful size cannot be read by eye, what gets verified is a mental model of the script, and one modification moves every offset and depth behind it — so errors surface after minting and funding, when nothing can be altered. An implementation MUST be able to read its covenant back, not merely write one.

6. Bounded steps

Each tick MUST perform a step whose worst case is known when the script is written, because §5 depends on it. The covenant MUST recompute the successor from the state in its own scriptCode and MUST refuse any other, so a ticker chooses whether to advance it, never how.

The whole computation need not be bounded: the loop is not in the script, it is in the trace. Nothing here gives Script a backward jump.

7. Halting, resumption, and destruction

When V < MAX_FEE the covenant is flat, and a flat covenant MUST NOT be treated as terminated: its state is intact and a top-up resumes it at exactly the step it stopped on. Remaining steps are floor(V / MAX_FEE). Ticks forward, or waits for recharge is a complete life cycle.

A covenant needs a burn path UNLESS permanence is the point of it.

The test is not "can the money come back" but bounded and intentional against unbounded and incidental: one immortal output on purpose is a monument, one per race or per mint is a leak every node carries forever. The quantity is the number of unspendable outputs, not the value in them.

An ownerless instance MUST NOT have a burn path. A burn needs a signature, a signature needs an owner, and an owner destroys the property the design exists for — the combination is a covenant free to the first passer-by. Where a burn is warranted the instance is owned under §3 and MUST be built so from genesis. Its owner key MUST be written once, at genesis, and MUST NOT be writable again; the branch MUST sit below the owner check and MUST re-verify that the instance is claimed, since an unwritten owner field skips the signature check rather than failing it.

8. The value rule in Script

§4 and §2 together are the last eighteen bytes of the deployed instance's locking script, read off the chain at byte 1,410 of 1,428:

7e            OP_CAT
7c 76 81      OP_SWAP OP_DUP OP_BIN2NUM        the successor's value, as a number
6c            OP_FROMALTSTACK                  V, saved earlier from the preimage
02 3a 01      push 314                         ★ MAX_FEE, exactly as it appears on chain
94            OP_SUB
a2            OP_GREATERTHANOREQUAL
69            OP_VERIFY                        ⇒ newValue ≥ V − 314          (§4)
7c 7e 7c 7e   OP_SWAP OP_CAT OP_SWAP OP_CAT    assemble out0 ‖ trailing outputs
aa            OP_HASH256
6c            OP_FROMALTSTACK                  hashOutputs, from the preimage
87            OP_EQUAL                         ⇒ out0 is what the transaction commits to   (§2)

⚠ Nobody should be asked to verify a permanent constant by reading that, which is why §5 requires a reader. The same script, decompiled, states the rule on one line:

2120 VERIFY BIN2NUM(newValue) >= BIN2NUM(t135) - 314

t135 is V, cut from the preimage. The whole 1,428-byte script reads back as 216 such lines. That the constant is 314, and that the comparison is rather than =, is then checkable by anyone — which is the entire argument of §5, and the reason the eighteen bytes above are shown first.

9. Conformance

  1. A tick is one input, one output, requires no funding input, and no secret key material exists. (§2, §3)
  2. The value rule is a floor, so a top-up is a valid tick with no separate code path. (§4)
  3. MAX_FEE is derived by serializing and measuring a worst-case spend, covering every legal variant. (§5)
  4. The covenant recomputes the successor itself and refuses any other. (§6)
  5. A flat covenant resumes at its exact prior step on top-up. (§7)
  6. Authority is enumerated in the script, and any authority that can direct value is gated by a key distinct from the driver's once the driving credential is delegated. (§3)

⚠ Item 3 cannot be fixed later and MUST be satisfied before the genesis is broadcast. ★ Test the refusals harder than the acceptances, with a control that withholds the flag under test: a rule no test has provoked is a rule no test has examined.

Implementations

Deployed on BSV mainnet; every figure measured from the chain.

genesislockstatetickfee
Bitcoin Battery — one Mandelbrot iteration per tick18e31936…1,428 B9 fields / 39 B3,092 B310 sat
Vehicle proof of concept — a quarter-mile drag raceac49ed93…1,674 B13 fields / 98 B≤ 3,909 B

The battery's MAX_FEE is 314 against that measured 3,092-byte spend: 101.6 sat/KB, ~1.3% over the floor. Walking its trace twenty steps reaches b134dc9f…, whose locking script is byte-identical to the reference implementation replayed twenty times from genesis.

No delivery vehicle has been built. The title names the use case the mechanism is for.

The reference implementation and its test suite are published on chain, so this document cites a payload rather than a URL — verified by retrieving the archive and comparing it byte for byte:

source bundle   078a45523f5ba0597aeffe01296d0543566defc20a56c8b4de109ed783bbab17   138,642 B

§5's reader requirement is met by a decompiler rendering a deployed locking script as a short BASIC-dialect program which compiles forward again, so the two can be checked against each other: 1,108 opcodes read back as 253 lines. Workbench: https://grafverse.com/basic.html — a separate proposal is forthcoming.

The reference implementation and its test suite were written by Claude (Opus 5).

References

  • BRC-171 — Fixed-Width State in a Covenant's Own Locking Script; the state layout used by both instances above
  • BRC-226 — Miner-Enforced Resale-Royalty Covenant Tokens, establishing the OP_PUSH_TX self-reconstruction this depends on. The contrast is the funding model: BRC-226's spends are paid for by the party transacting
  • BIP 143 — the preimage members scriptCode, hashOutputs and the spent output's value, read in §2 and §4
  • Bitcoin SV opcode semantics for OP_SPLIT, OP_CAT, OP_BIN2NUM and OP_NUM2BIN

Appendix — two deployed covenants, in full, and one of them breaks §3.1

The complete locking scripts of the deployed fuel depot and the vehicle it fuels, as they stand on chain. They are reproduced for one reason: this is what a reviewer is actually being asked to trust.

Between them they carry a fee ceiling, a tank ceiling, an owner check, a burn branch, a driver gate, thirteen state fields, a phase machine, quadratic drag, and a cross-covenant read in which the depot locates the owner field inside the vehicle's script without sharing a line of code with it. Every rule in this document is in here somewhere, and none of it can be found by looking.

⚠⚠ Including the rule this depot fails

The depot below does not conform to §3.1. It is printed unchanged anyway, and the failure is named here rather than quietly corrected, because it demonstrates the document's own thesis better than a clean example could.

unlocking stack   [ prefixOutputs, burn, sig, pubKey, spenderOutputs, newValue, preimage ]
the binding       HASH256( prefixOutputs ‖ newValue ‖ myOwnScriptCode ‖ spenderOutputs ) == hashOutputs
the arrival rule  carValue ≥ (V − out_depot) − MAX_FEE

spenderOutputs is supplied by the spender and is constrained only by being committed to in the sighash — which §4 expressly permits. The arrival rule then leaves MAX_FEE of slack. So a spender may take the draw, hand the vehicle (V − out_depot) − MAX_FEE, and direct the difference to an output of their own choosing: 844 satoshis per spend, available to anyone, with no key. That is precisely what §3.1 forbids.

which rule did not stop it. The §4 value floor held throughout — it bounds what leaves, not where the surplus lands, which is why §4 now states that bound exactly.

Three reasons it stays in the document:

  1. It is what is on chain. A standard illustrated with a covenant nobody deployed is a standard illustrated with a wish.
  2. The defect is invisible in the bytes below, which is this document's central claim about covenants of useful size. A reader who can find it by eye has disproved §5's warning; a reader who cannot has confirmed it.
  3. It was found by measuring a spend, not by reading the script — after the covenant had passed seventy-three tests. A conformance argument that rests on review rests on nothing.

⚠ The instance holds one satoshi and is deliberately unfunded. Its successor closes the hole by requiring that an extraction attempt repay the covenant rather than a miner — the surplus is made unreachable instead of merely forbidden a destination.

Fuel depote889c1f15b2739f8729e4dc256199581137eae6df72f09ddc558bfdb54ddb0e8, output 0, 875 bytes:

0105796376820134947f7701087f758102d9049f69010379a91414aea21dea2e760ed5c5c8ee0b
099e254a94ae7e88010479010479ac696d6d6d75516776aa517f517f517f517f517f517f517f51
7f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f
517f517f517f517f7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c
7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e01007e8120ff2124
d658a1d062565b70e9ce3f5dd2007787210f479d9f683773d22417233c9321414136d08c5ed2bf
3ba048afe6dcaebafeffffffffffffffffffffffffffffff0097215ce5f9aa4d120993bb99d941
0bdf471ad0f2772bebbc9be31d946f64957f63c4009521414136d08c5ed2bf3ba048afe6dcaeba
feffffffffffffffffffffffffffffff00978201217c946b012180517f517f517f517f517f517f
517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f51
7f517f517f517f517f517f517f7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e
7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e6c
7f77827c7e01027c7e220220466d7fcae563e5cb09a0d1870bb580344804617879a14949cf2228
5f1bae3f277c7e827c7e01307c7e01417e21034f355bdcb7cc0af728ef3cceb9615d90684bb5b2
ca5f859ab0f0b704075871aaac6976820134947f7701087f75816b76820128947f7701207f757c
01687f77820134947f75010279816c6e7c946b6e9f6b026c5194a2696c6301077901087f7c816b
010a7f7c0afdd006015001010108018801017f7701017f7c01148801147f7c1414aea21dea2e76
0ed5c5c8ee0b099e254a94ae7e8801017f7c01248801247f7701017f7c01028801027f7701017f
7c01028801027f7701017f7c01068801067f7701017f7c01028801027f7701017f7c0105880105
7f7701017f7c01048801047f7701017f7c01058801057f7701017f7c01068801067f7c81009d01
017f7c01058801057f7701017f7c01048801047f77a82070e9d2fb16fdf3bfa270ffedaa7477f7
b1dd461f93f08f86a1145ba13a9ddb65886c7603581501a1696c024c0394a269676c756801027a
7c7e01067a7c7e01027a7eaa8777777768

Vehiclee918fa438f2cab12127fbd9377022868ad35904da2146816e552b26482b11c6a, output 0, 1,744 bytes:

01500101010801001414aea21dea2e760ed5c5c8ee0b099e254a94ae7e24000000000000000000
000000000000000000000000000000000000000000000000000000020000020000060000000000
000200000500000000000400000000050000000000060000000000000500000000000400000000
011f7963010b79011479a988011479011479ac6968011f79636d6d6d6d6d6d6d6d6d6d6d6d6d6d
6d6d51676d6d6d6d6d6d6d6d76aa517f517f517f517f517f517f517f517f517f517f517f517f51
7f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f7c7e
7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c
7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e01007e8120ff2124d658a1d062565b70e9ce
3f5dd2007787210f479d9f683773d22417233c9321414136d08c5ed2bf3ba048afe6dcaebafeff
ffffffffffffffffffffffffffff0097215ce5f9aa4d120993bb99d9410bdf471ad0f2772bebbc
9be31d946f64957f63c4009521414136d08c5ed2bf3ba048afe6dcaebafeffffffffffffffffff
ffffffffffff00978201217c946b012180517f517f517f517f517f517f517f517f517f517f517f
517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f517f51
7f517f7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e
7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e7c7e6c7f77827c7e01027c7e22
0220466d7fcae563e5cb09a0d1870bb580344804617879a14949cf22285f1bae3f277c7e827c7e
01307c7e01417e21034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b7040758
71aaac69767676820128947f7701207f756b820134947f7701087f75816b820108947f7701047f
75817c767601047f7701207f756b01447f7701247f756c7c01027a01687f77820134947f75010a
7f01017f517f7701147f517f7701247f517f7701027f517f7701027f517f7701067f517f770102
7f517f7701057f517f7701047f517f7701057f517f7701067f517f7701057f517f7701047f6b81
6b816b816b816b816b816b816b816b816b816b6b6b81011279637500677601059f698b0104a368
6c01017901639c63750111798201149d686c01027901029c63750111798201249d686c01037901
019c6375011179760101a269760118a169686c01047901019c6375011179760101a26976010aa1
69686c01057901029c6375011179760101a269686c01067901029c6375011179760101a269686c
01077901029c6375011179760101a269686c01087901029c63750111797600a269686c01097901
049c637893010279a4010d79a169010c79686c6c6c01107a756c6c00790208529400a4007900a0
010d7904cdcccc0c95010d79047b14ae079593010279037e35079593059a9999d9009301037a6b
01037a6b010f7901049c63010b7904c3f5285c9501057904cdcccc4c950500000000019693010a
799502e80396010d79041f85eb519501197901047995950110960079010279a0010179010379a3
00790500000000019501057996010979930109790452b81e05950500000000019694010979010a
7995050000000001960414ae47019505000000000196940102796304e17a146e95050000000001
9600796b6c6700796b6c6800a4010a79049a999959a2011e79010ea29b0104799a01017905e270
96c00ea29b007963010c7900010c798b010600796b0101796b0102796b0103796b757575756c6c
6c6c67010c7901027993010b798b010379010279011579a263010500796b756c67010400796b75
6c6800796b0102796b0101796b0103796b757575756c6c6c6c6800796b0101796b0102796b0103
796b75757575757575757575756c6c6c6c6701057901057901057901127900796b0101796b0102
796b0103796b757575756c6c6c6c686c6c007a6b007a6b01057a7501057a7501047a7501137a75
01127a7501107a7501067a7501057a7501047a75010c7a010c7a010c7a010c7a010c7a010c7a01
0c7a010c7a010c7a010c7a010c7a010c7a011b79637500680104806b011a79637500680105806b
011979637500680106806b011879637500680105806b011779637500680104806b011679637500
680105806b011579637500680102806b011479637500680106806b011379637500680102806b01
1279637500680102806b011179637500012480686b6b0101807e01147e6c7e01247e6c7e01027e
6c7e01027e6c7e01067e6c7e01027e6c7e01057e6c7e01047e6c7e01057e6c7e01067e6c7e0105
7e6c7e01047e6c7e6c7e7c76816c02150594a2697c7e7c7eaa6c8768

⇒ Both are readable today, as programs rather than as bytes, by the tool §5 requires — and that is the subject of a separate proposal.

Was this helpful?

Search Beersy

Search standards by number, title, author or topic