Agent Data Sales
Sell or buy a dataset between AI agents that do not trust each other: a Beam Room delivers it encrypted, and an escrow contract on Bittensor EVM pays the seller only for the bytes it committed to.
Public beta
Agent data sales run on Bittensor EVM mainnet and move real TAO, up to 1 TAO per sale. Commands and limits may change while the feature is in beta.
An agent data sale lets two AI agents that do not trust each other trade one dataset for TAO. Beam moves the encrypted dataset privately and fast. An open escrow contract on Bittensor EVM makes the exchange fair: the seller is paid only for the bytes it committed to, and a buyer can prove otherwise in one transaction. Beam never sees the data and does not judge disputes.
The guarantee is deliberately narrow. The escrow checks bytes, not meaning: it cannot tell whether a dataset is accurate, useful, or what the seller described. Read What is guaranteed and Confidentiality before you sell or buy anything of value.
Roles
| Party | What it does | What it needs |
|---|---|---|
| Seller | Has the dataset. Creates the sale Room, signs the offer, delivers the encrypted dataset, reveals the key and settles. | A machine connected to a Beam account (beam agent connect), an API key whose role grants rooms:start, and a sale wallet with TAO for gas. |
| Buyer | Checks the delivery, pays into the escrow, decrypts and checks the dataset, and challenges a bad leaf. | A machine running the Beam agent, and a sale wallet holding the price plus gas. It needs no Beam account: it joins the seller's Room with an invitation. |
| Escrow | A contract on Bittensor EVM. It holds the buyer's payment, accepts only the committed key, decides challenges, and pays out. | Nothing. It has no owner, pause, upgrade, fee or arbitrary call, and its rules cannot change. |
| Beam | The transport: a private Room that carries the encrypted dataset from the seller's agent to the buyer's. | Credits from the seller's organization for the Room and the delivery. Beam takes no part in payment and decides no dispute. |
How a sale works
A sale is one offer, from one seller to one buyer, in a Room that holds only the two of them.
1. The seller creates a sale Room
beam sale room create --out invitation.tokenThis starts a billable Room with one object channel and writes a one-use
invitation to the file. The invitation grants only discovery and delivery on that
channel and is valid for 24 hours (--invitation-ttl changes that). It is a
bearer secret: give it to the buyer privately. Pass --api-key, or set
BEAM_API_KEY, to a key whose role grants rooms:start. --max-size sets the
largest dataset the Room carries (default 100 GB).
2. The buyer joins and signs a binding
beam sale join <room-id> --invitation-file invitation.token --out binding.jsonThe buyer's agent joins the Room, and its sale wallet signs a binding: a
statement that its member in this Room buys for this wallet, on this chain and
escrow. The buyer gives binding.json to the seller. The binding is not secret.
It lets the seller deliver only to the member the paying wallet named.
3. The seller offers and delivers
beam sale offer <room-id> --file dataset.tar.zst --price 0.06 --binding binding.jsonBefore anything is delivered, the seller's client checks:
- the binding, and that the Room holds exactly the seller and the bound buyer, every membership of every kind counted;
- the price: at most 1 TAO and at least $10;
- the size: at most 100 GB;
- the seller's limits, and that the buyer's wallet holds the price plus gas.
It then encrypts the dataset under a key derived for this sale alone and writes
the package, about 101% of the dataset's size, to --package-dir (default:
beside the dataset). The package carries the seller's signed offer and its
commitments: the dataset's fingerprint (the root of the hashes of its 4 KiB
leaves), the root of the encrypted leaves, and a commitment to the key. The
client delivers the package to the buyer's member only, and removes it once it
is delivered.
The offer is signed, not sent to the chain, so the seller spends no gas until
the buyer has paid. The buyer can fund it until its funding deadline:
--fund-within blocks (default 1,800, about 6 hours) after the delivery window
closes, which lasts 30 minutes plus 1 second per 4 MiB. sale offer waits until
then. Once the buyer's funding is final, it reveals the key, exits, and prints the
block after which the sale can be settled.
4. The buyer checks, then funds
beam sale buy <room-id> --out dataset.tar.zst --max-price 0.06sale buy waits up to --wait (default 30m) for the package to arrive in its
agent's inbox. Before it pays anything, it checks:
- with
--card, that the offer is for the dataset the seller's data card describes, at its size and from its signer; with--fingerprint, that the offer is for the dataset you trust (see Check the dataset before you buy). These come first, before the package is read; - the seller's signature over the offer and its commitments;
- that the offer names this wallet, this chain and this escrow, and that the package's file name names the same sale;
- the encrypted leaves against the ciphertext root, and the leaf hashes against the fingerprint;
- the size, the price against
--max-priceand the escrow's cap, the periods against the escrow's bounds, and that enough of the funding window is left.
A package that fails any check is not funded. When every check passes, the buyer pays the price into the escrow together with the seller's signed offer. Funding fixes the exact commitments the buyer checked: nothing the seller does afterwards can change them.
5. The seller reveals the key
The seller's client reveals the key onchain once the funding is in a finalized block, usually a few blocks after it is included, so that no chain reorganization can undo the payment the key was revealed for. The escrow accepts only the key that matches the committed one. The reveal opens the challenge window.
6. The buyer decrypts and checks every leaf
sale buy keeps running: it reads the key from the chain, decrypts the dataset,
and checks every 4 KiB leaf against the hash the seller committed to. It writes
the dataset to --out only if every leaf matches. Otherwise it keeps the
decrypted file as <out>.unverified, records the first leaf that does not match
with its committed hash, and challenges it. The client decrypts and checks about 60 MB a second on one
Apple M1 core, about 30 minutes for 100 GB, well inside the default 24-hour
window.
7. The seller settles
Once the challenge window has closed, the seller settles and the escrow pays the price to the seller's wallet:
beam sale resume <sale-id>sale resume <sale-id> --wait stays until nothing is left to do. Anyone may
settle once the window has closed, and settling has no deadline. If the direct
payment fails, the escrow credits the amount instead; collect it with
beam sale withdraw.
An honest sale takes three transactions: fund (buyer), reveal (seller) and settle (seller).
Deadlines
Deadlines count blocks, not time. Measured over 30 days, Bittensor produced a
block every 12.005 seconds on average and never faster than every 12 seconds, so
a period of n blocks lasts at least 12 × n seconds. If the chain halts, the
clock stops with it, rather than letting a deadline pass while nobody can act.
| State | Who acts | Deadline | Once it has passed |
|---|---|---|---|
| Offered: signed, not yet onchain | The buyer funds; the seller may revoke | The funding deadline | The offer has expired. Nothing moved. |
| Funded | The seller reveals the key | Funding block + reveal period: default 1,800 blocks (about 6 h), at least 300 | Anyone may refund the buyer. |
| Key revealed | Anyone may submit a valid challenge | Reveal block + challenge period: default 7,200 blocks (about 24 h), at least 7,200 | Anyone may settle, which pays the seller. |
| Settled, refunded or revoked | Nobody | None | Final. |
The deadline block itself still belongs to the party that must act; the exit opens on the next block. No state holds a payment forever: the escrow accepts no period longer than 216,000 blocks, about 30 days. With the default periods, the buyer's payment is held for up to 9,000 blocks, about 30 hours.
When a sale does not complete
Challenge
If a leaf decrypts to anything other than the hash the seller committed to, the buyer's client sends a challenge: that one encrypted leaf, its committed hash, and the two proofs that place them under the roots the buyer funded. The escrow decrypts the leaf with the revealed key and, if it does not match, refunds the full price to the buyer in the same transaction. No arbiter is involved.
- A key that matches its commitment but does not decrypt the package makes every leaf challengeable.
- Anyone may submit a valid challenge, but the refund always goes to the buyer.
- A challenge against an honest seller cannot succeed, and the client never sends one whose proof does not hold locally.
- The client never first broadcasts a challenge within 100 blocks of the
challenge deadline. If the buyer's client was interrupted,
sale resumedecrypts, checks and challenges.
Reclaiming an unrevealed payment
If the seller has not revealed the key by the reveal deadline, the payment goes
back to the buyer. A waiting sale buy reclaims it on the first block after the
deadline; otherwise run beam sale resume <sale-id>. The key stays secret, so the
buyer cannot decrypt the package it holds. Anyone may send the refund, and it
always goes to the buyer.
Revoking an offer
Until the buyer funds, the seller can withdraw a signed offer onchain:
beam sale revoke <sale-id>The buyer holds the signed offer until its funding deadline and can fund it
until then; revoking ends that at once. If the buyer funds first, the revocation
fails (sale_funded) and the sale goes on: run beam sale resume <sale-id> to
reveal the key.
Expiry
An offer nobody funded expires at its funding deadline. No transaction is needed
and nothing moves, but the seller has already paid Beam for the delivery, which
counts against its daily delivery budget. beam sale resume records
the expiry on this machine.
Interrupted commands
beam sale resume <sale-id> carries any sale forward from its escrow state: it
delivers, reveals, settles, reclaims, decrypts or challenges, whichever is due.
It resumes a transaction an interrupted run already broadcast instead of sending
a new one. A failed delivery moves no money: the buyer cannot fund a package it
did not receive.
What is guaranteed, and what is not
The guarantees come from the escrow, not from Beam, and they cover the delivered bytes only.
What the escrow guarantees, provided the buyer's client ran its checks before funding:
- The seller is paid only if, by the end of the challenge window, nobody has shown that a leaf of the delivered dataset differs from what the seller committed to.
- One leaf that does not match, proven in one transaction, refunds the buyer's full price.
- A buyer cannot win a refund against an honest seller: every challenge input is checked against commitments the seller signed and the buyer's funding froze.
- The buyer gets the key only after paying, and the seller is paid only after revealing the key.
- Every waiting state ends at a deadline with an exit anyone can call, so no payment is locked forever.
- Beam's own records, such as Room receipts, never pay or refund a sale.
What nothing guarantees:
- Quality and meaning. The escrow proves only that the delivered bytes match the seller's commitments, not that the data is accurate, complete, lawful, useful, or what the seller described. A seller that commits to worthless data and delivers exactly that is paid.
- Timely inclusion. A party whose transaction is not included before a deadline loses that move. If a seller's reveal is broadcast but included only after the reveal deadline, the key is public and the buyer is refunded. The client reveals once the funding is final, never first broadcasts a reveal within 100 blocks of the deadline, sends a reveal it already broadcast again up to the deadline itself, raises the fee of a stalled transaction (up to 1,000 gwei), and can send from a backup account.
- Arbitration. Beam decides no dispute and refunds nothing. A challenge is the only remedy.
- What the buyer does next. Once the buyer holds the dataset, nothing limits what it does with it.
Judge the content before buying: the seller's data card, samples and answers to your questions, and by means outside the sale, a source you trust and the seller's history. Every sale's outcome, settled or refunded, is a public escrow event tied to the seller's address.
Check the dataset before you buy
A dataset's fingerprint is the root of the hashes of its 4 KiB leaves: the
value the seller's offer signs, and the funding locks. Every sale report shows
it as fingerprint, and any file's fingerprint can be computed with no wallet,
network or agent:
beam sale fingerprint dataset.tar.zstIf you already trust a dataset's fingerprint, because its publisher lists it or because you hold a copy, pass it when you buy:
beam sale buy <room-id> --out dataset.tar.zst --max-price 0.06 \
--fingerprint 0x… --size <bytes>An offer for any other dataset is refused with sale_fingerprint_mismatch
before the package is read and before anything is funded. With the fingerprint
pinned, the escrow then guarantees you receive that exact dataset, byte for
byte. --size matters only for files that differ in trailing zero bytes within
their last 4 KiB, which share a fingerprint.
The fingerprint tells you which dataset you get, not whether it is good. It is worth as much as the source you took it from.
Read the seller's data card
A data card says what a dataset holds, in a form you can check once you have it. The seller writes one with its sale wallet and publishes it with the dataset's listing:
beam sale describe orders.csv.zst --out orders.card.json \
--declare license=CC-BY-4.0 --range amount --top countryA card is bound to the dataset's fingerprint and size, and keeps three kinds of claim apart:
| Kind | What it holds | Who can check it |
|---|---|---|
| Reproducible | The record count, and each field's type, number of nulls and number of distinct values. Ranges and most frequent values only for the fields the seller names with --range and --top. | You, from the delivered bytes |
| Declared | What the seller states with --declare, such as a license or a source. | Nobody: it is signed, so the seller cannot deny it, but it is not checked |
| Verified | Claims signed by an outside verifier. | Reserved; empty in this version |
By default a card shows the dataset's shape and none of its values. A card reads
one CSV, TSV, JSON Lines, JSON, XML or Parquet file, plain or gzip- or
zstd-compressed; a JSON or XML dataset names its records with --record-path,
such as /items or /catalog/item.
Check a card's signature and read it, its kinds apart:
beam sale card orders.card.jsonThen buy against it:
beam sale buy <room-id> --out orders.csv.zst --max-price 0.06 --card orders.card.jsonAn offer for another dataset or size, or from a seller other than the card's
signer, is refused with sale_card_mismatch before the package is read and
before anything is funded. The sale keeps the card, byte for byte. Once the
dataset is delivered, recompute every reproducible claim:
beam sale verify-claims <sale-id>It reports match: true, or exits with sale_claims_differ after listing each
claim that differs. Anyone holding a copy can run the same check with
beam sale verify-claims --card <card> --file <dataset>.
The escrow does not enforce a card, and a claim that differs refunds nothing.
What it gives you is evidence: the seller's signed statement, against the exact
bytes the sale delivered and the public sale that names them. The rules that
make a card reproducible by any implementation (how each format is read, how
values are typed, how distinct values are counted) are the dqvp.dataset-card.v1
specification, published with the CLI's source as docs/data-cards.md. Beam's
servers never see a card.
Look at samples before you buy
A fingerprint and a card describe a dataset; samples show you pieces of it. A seller can let you ask for a few 4 KiB pieces before you fund, drawn at random by you, each proven to belong to the dataset in the offer.
The seller offers up to a maximum number of pieces, at most 256:
beam sale offer <room-id> --file orders.csv --price 0.06 --binding binding.json --samples 8The buyer, once the package has arrived, asks for some of them:
beam sale buy <room-id> --samples 4 --samples-out samples/ --max-price 0.06Your client draws a random nonce, which picks the pieces. The seller committed
to every piece in its offer before it could know which ones you would draw. The
client checks that each piece hashes to its commitment, writes it to
samples/piece-<index>.bin with samples.json describing them, and stops:
nothing is funded. Look at the pieces, then fund the sale by its id:
beam sale buy <room-id> --sale <sale-id> --out orders.csv --max-price 0.06The terms, and --card or --fingerprint when given, are checked again before
funding. beam sale resume never funds a sampled sale: a person decides.
- A piece that does not match its commitment ends the sale as
rejected(sale_samples_mismatch), and nothing is funded. - A seller that offers no samples, or fewer than you asked for, refuses with
sale_samples_refused. A sale Room created before samples existed givessale_samples_unsupported. Either way, you can still buy without samples.
Samples are given away: you keep them whether you buy or not. Each answer, a refusal included, is a delivery, which Beam charges the seller for and which counts against its daily delivery budget; a seller sends at most three per sale. It answers only while its offer waits for funding, from the file it offered.
Samples are readable only when 4 KiB pieces stand alone, as in uncompressed text or fixed-size records. A piece of a compressed or encrypted file shows nothing readable, though it still proves that those bytes belong to the dataset.
Ask the seller questions
A card answers the questions its seller chose. To ask your own, such as "how many records are from France in 2025?", the seller can answer aggregate queries while its offer waits for funding. You get exact counts, distinct counts, sums and means, by group, and never a record. Every answer is signed by the seller and bound to the dataset in the offer, and you recompute it after delivery.
The seller offers with a policy: which fields may be filtered, grouped and aggregated, the minimum group size, and budgets. Conservative rules are the right start:
{"fields": {"country": {"filter": ["eq", "in"], "group": true},
"customer_id": {"aggregate": ["distinct"]}},
"min_group_size": 10}beam sale offer <room-id> --file orders.csv --price 0.06 --binding binding.json --policy policy.jsonThe offer reads the dataset by the card rules, signs the policy for its
fingerprint, and answers on the sale Room's sale-queries channel until it is
funded.
The buyer, once the package has arrived, reads the policy and asks:
beam sale policy <room-id>
beam sale query <room-id> \
--query '{"where":[{"field":"country","op":"eq","value":"FR"}]}' \
--query '{"group_by":[{"field":"country"}],"select":[{"fn":"distinct","field":"customer_id"}]}'Each query comes back as a signed receipt, which the CLI checks and keeps with the sale:
- an answer, or a refusal with a reason;
- groups smaller than the minimum are left out, and
suppressedsays so; - a query that would single out records, such as "France" and then "France
except record 7", is refused as
too_close, across every buyer of the dataset; - fields and operations the policy does not allow are refused as
not_allowed.
After delivery, beam sale verify-claims <sale-id> recomputes every answer from
the bytes you received, with the card if there is one, and lists any that
differ.
What queries do not do:
- A false answer is evidence, not a refund. The escrow does not know about queries, and a proven difference triggers no refund or penalty.
- Protection has limits. The minimum group size and the check against near-identical questions make extracting records harder, not impossible: three or more overlapping questions can still be combined. Sellers should offer queries only on aggregates they are willing to reveal.
- The package comes first. Questions are possible before payment, not before the encrypted package is delivered.
- Answers take as long as reading the dataset, since every batch of questions reads it whole.
Queries cost nothing beyond the sale: they travel as Room messages, end to end
encrypted, and Beam's servers never see a question or an answer. The rules are
the dqvp.query.v1 specification, published with the CLI's source as
docs/data-queries.md.
Confidentiality
The key becomes public at the reveal
The reveal publishes the key onchain, permanently, and it is visible from the moment the reveal transaction is broadcast. From then on, anyone who holds the encrypted package can decrypt it. The dataset therefore stays private only as long as the package reaches nobody but the buyer. The client enforces that:
- The sale Room must hold only the seller and the buyer. The seller's client refuses to deliver while it holds anyone else, of any membership kind.
- The package goes to the buyer's member only, and only after the buyer's wallet has signed the binding that names that member.
- The delivery is end-to-end encrypted between the two agents. Beam's infrastructure carries only that ciphertext of the already-encrypted package, so the published key alone opens nothing for it.
Do not copy the package anywhere else or deliver it outside beam sale. Every
sale derives a new key, so a key revealed in one sale opens no other.
What is public onchain
Bittensor EVM is a public chain. A sale's transactions publish, permanently:
| Transaction | What becomes public |
|---|---|
| Fund | Both wallet addresses, the price, the dataset's size and fingerprint, the funding deadline, both periods, the offer's nonce, the ciphertext root and the key commitment. The fingerprint is the same in every sale of the same dataset, so it links those sales. |
| Reveal | The key. |
| Challenge | One encrypted leaf, its committed hash and their proofs. With the public key, anyone can decrypt that leaf. A challenge succeeds only where the seller cheated on that leaf, but a failed challenge still publishes whatever leaf its sender chose. |
| Revoke | The offer's terms, as listed for funding, without the two commitments. |
| Every transaction | Its block and the account that sent it. |
The escrow records no dataset name, Room, or Beam identity.
Leaf hashes reveal guessable content
Before funding, the buyer receives the hash of every 4 KiB leaf of the dataset, which it needs to check the fingerprint. A buyer that never pays keeps them. Anyone holding the hashes can confirm a guess about a leaf: zero padding, sparse regions, fixed headers and templated records can be recovered by guessing and hashing, and repeated leaves can be recognized. Compress a dataset before selling it, so that its leaves cannot be guessed.
Costs
A sale costs gas on Bittensor EVM, paid in TAO by each party's sale wallet, and Beam's charges for the Room and the delivery, paid in credits by the seller's organization. The escrow takes no fee.
Gas
Measured on Bittensor EVM testnet with the v1 contract and the CLI, priced at 5 gwei and TAO at $257.74 (2026-10-22). A sale on mainnet measured the same within 0.1%: 87,182 gas to fund and 36,857 to reveal. Gas and TAO prices move, so treat the dollar amounts as a snapshot.
| Call | Sent by | Gas | Cost |
|---|---|---|---|
| Fund | Buyer | 87,164 | about $0.11 |
| Reveal | Seller | 36,827 | about $0.05 |
| Settle | Seller | 40,270 | about $0.05 |
| Honest sale | 164,260 | about $0.21 | |
| Reclaim an unrevealed payment | Buyer | 40,343 | about $0.05 |
| Challenge | Buyer | 150,494 (1 MB dataset) to 175,692 (100 GB) | $0.19 to $0.23 |
| Revoke | Seller | 48,945 | about $0.06 |
Before it sends a call, the client wants the wallet to hold twice that call's gas limit at the current gas price: at 5 gwei, about 0.002 TAO beyond the price for funding, and about 0.0024 TAO for revealing and settling.
Beam charges
Beam charges the seller's organization, at $0.50 a credit (see Billing). The buyer pays Beam nothing.
| Item | Charge |
|---|---|
| Room start, once per sale Room | 1 credit ($0.50). A returning buyer can buy again in the same Room. |
| Delivery, once per offer | 0.2 credit plus 0.02 credit per GB of the package, rounded up to 0.01 credit: 0.21 credit for a 1 MB dataset, 0.23 for 1 GB, 0.41 for 10 GB, about 2.22 for 100 GB. |
An example
A 1 GB dataset sold at the $10 minimum costs about $0.83 in total with a new Room (8% of the price): $0.21 in gas, $0.50 for the Room start and $0.12 for the delivery. When the buyer returns to the same Room, it costs about $0.33 (3%). Not counted: funding the wallets, the seller's own bandwidth, and the buyer's price held for up to about 30 hours.
When a sale goes wrong
| Case | Who loses | Loss, for 1 GB |
|---|---|---|
| The buyer never funds | The seller | The delivery, $0.12, plus $0.50 when the Room is new. No gas. The daily delivery budget caps it. |
| The seller never reveals | The buyer | Gas to fund and to reclaim: about $0.16. The price comes back. |
| The seller delivers content that does not match | The buyer | Gas to fund and to challenge: about $0.31 to $0.34. The price comes back. |
| The seller revokes | The seller | About $0.06 in gas, plus the delivery. |
Limits
| Rule | Value | Enforced by |
|---|---|---|
| Highest price | 1 TAO | The escrow: an immutable cap set at deployment |
| Lowest price | $10, at a TAO/USD quote from CoinGecko or the price given with --tao-usd. The quote request carries no data about the sale. | The seller's client |
| Largest dataset | 100 GB | Both clients |
| Reveal period | Default 1,800 blocks, at least 300 | Default: the seller's client; floor: the escrow |
| Challenge period | Default 7,200 blocks, at least 7,200 | Default: the seller's client; floor: the escrow |
| Funding window | --fund-within blocks after the delivery window, default 1,800 | The escrow, from the signed offer |
Seller limits, on by default:
- one unfunded delivery per buyer address at a time;
- delivery only to a buyer whose wallet holds the price plus gas;
- a daily budget, $5 by default, for the Beam charges of deliveries to buyers who have not funded. The client estimates each one at 0.2 credit plus 0.02 credit per GB, plus 1 credit for the Room's first delivery. With the defaults, buyers that never fund cost a seller at most this budget a day.
Buyer limits, on by default: 1 TAO per sale and 3 TAO a day, and a
person must confirm any sale above 0.2 TAO. Every purchase also names its own
--max-price.
beam sale wallet limits shows the limits and changes them with --per-sale,
--daily, --approve-above and --delivery-budget.
Actions only a person can take
These need a person at an interactive terminal, and no flag stands in for that.
An agent that runs beam commands gets the error kind sale_approval_required:
- approving a purchase above the approval threshold;
- raising any limit (lowering one needs no confirmation);
- moving TAO out of the sale wallet with
beam sale wallet send; - deleting the wallet with
beam sale wallet remove.
When a purchase needs approval, the sale waits on the buyer's machine. Before the
funding deadline, the person runs beam sale resume <sale-id> in a terminal,
reads the summary, and confirms.
What the limits do not stop
The limits and the person-only actions live in the CLI, on the machine that holds
the wallet. They bind anything that uses beam sale. They do not bind software
that runs as the same operating-system account with wider access: such software
can read the wallet's keys from the credential store or the owner-only file,
change the limits, or drive the CLI through a pseudo-terminal, which looks like a
person to it.
So treat the sale wallet as cash in a till, not as a vault. Keep only what you can afford to lose in it, about what the next sale needs, and refill it from a wallet a person holds. The escrow's 1 TAO cap bounds each sale; only the wallet's balance bounds what can be lost.
The sale wallet
Each party pays from its own sale wallet, an ordinary account on Bittensor EVM that the CLI keeps.
beam sale wallet create
beam sale wallet show- Keys. The wallet's keys and its secret live in the operating system's
credential store, or, where there is none, in an owner-only
sale-wallet.jsonin the Beam configuration directory. No command prints or exports them. Each sale's key is derived from the wallet secret and the sale id. - Import.
beam sale wallet create --import-stdinuses an existing private key, read from standard input, and without echo on a terminal. Never pass a key as a command-line argument. - A spending wallet. Keep a small balance and top it up from a wallet a person controls. Never use a main wallet: the limits do not protect the keys from software running as the same account (see What the limits do not stop).
- Backup account.
beam sale wallet backupadds a second account that sends reveals, refunds, settlements and challenges when the main account is stuck behind pending transactions this client did not send. Give it a little TAO for gas. It is not a copy of the keys. - Finish on the same machine. Sale records live under
sales/in the Beam configuration directory, and only this wallet's secret derives a sale's key. A seller that loses them before revealing cannot reveal, and the buyer reclaims its payment after the reveal deadline. beam sale wallet showlists the address, balances, limits, what was spent in the last 24 hours, and any escrow credit waiting forbeam sale withdraw.beam sale wallet removerefuses while the wallet holds TAO or takes part in a sale that has not ended. Its keys cannot be recovered afterwards.
Configure the escrow
The CLI uses Beam's escrow on Bittensor EVM mainnet by default, so a sale needs no configuration:
| Bittensor EVM mainnet | |
|---|---|
sale_chain_id | 964 |
sale_rpc_urls | https://lite.chain.opentensor.ai,https://entrypoint-finney.opentensor.ai |
sale_escrow | 0xe26A702B55B436615694624EF60b856C9d9f0674, DataSaleEscrow v1 with a 1 TAO cap, a 300-block reveal floor and a 7,200-block challenge floor |
A context can use other endpoints or another deployment, and
beam config unset restores the default:
beam config set sale_rpc_urls <url>[,<url>...]
beam config set sale_chain_id <chain-id>
beam config set sale_escrow <escrow-address>sale_rpc_urls lists endpoints in order of preference. Reads go to the first one
that answers, and every transaction is broadcast to all of them.
Before a command uses the escrow, the client checks that the code at
sale_escrow is the DataSaleEscrow v1 build, whatever the deployment's cap,
floors and address, and refuses any other contract (sale_escrow_unverified).
It believes what the endpoints report about the chain, so an endpoint that
misreports it can make a sale wait or fail. Use endpoints you trust, and never
change either setting because a counterpart asked you to.
RPC rate limits
A sale reads the chain once a block. Public endpoints limit each address: an endpoint that answers HTTP 429 gets no call for as long as it asks, one minute by default, so its limit can clear. When every endpoint is waiting, the command waits too and says so, up to five times for one call. A public endpoint is enough for a sale or two. An agent that sells or buys continuously should list an endpoint of its own first.
Commands
beam sale wallet create [--import-stdin]
beam sale wallet show
beam sale wallet backup
beam sale wallet limits [--per-sale <tao>] [--daily <tao>] [--approve-above <tao>] [--delivery-budget <usd>]
beam sale wallet send --to <address> (--amount <tao> | --all)
beam sale wallet remove
beam sale room create [--api-key <key>] [--max-size <size>] [--invitation-ttl <duration>] [--out <file>]
beam sale describe <file> --out <card> [--format <format>] [--record-path <path>]
[--range <field>]... [--top <field>]... [--declare <key>=<value>]...
beam sale offer <room> --file <dataset> --price <tao> --binding <file>
[--reveal-period <blocks>] [--challenge-period <blocks>] [--fund-within <blocks>]
[--tao-usd <price>] [--package-dir <dir>] [--name <name>] [--samples <max>] [--policy <file>]
beam sale revoke <sale>
beam sale join <room> (--invitation-file <file> | --invitation-token <token>) [--out <binding-file>]
beam sale buy <room> --out <file> --max-price <tao> [--card <card>] [--fingerprint <root> [--size <size>]]
[--sale <sale>] [--wait <duration>]
beam sale buy <room> --samples <n> --samples-out <dir> --max-price <tao>
beam sale policy <room> [--sale <sale>] [--wait <duration>]
beam sale query <room> (--query <json> | --query-file <file>)... [--sale <sale>] [--wait <duration>]
beam sale fingerprint <file>
beam sale card <card>
beam sale verify-claims (<sale> | --card <card> --file <dataset>)
beam sale status [<sale>]
beam sale resume <sale> [--wait]
beam sale withdraw| Command | Who | What it does |
|---|---|---|
sale room create | Seller | Starts a Room for one buyer and writes its one-use invitation. |
sale describe | Seller | Writes a data card for a dataset, signed by the sale wallet. |
sale offer | Seller | Checks the buyer and the Room, delivers the encrypted dataset, waits for funding, and reveals the key. --name sets the name the buyer sees; --samples gives samples and --policy answers the buyer's queries. |
sale revoke | Seller | Withdraws an offer nobody funded. |
sale join | Buyer | Joins the seller's Room and signs the binding. |
sale buy | Buyer | Checks the delivery, funds, decrypts and checks every leaf, and challenges a bad one. --card and --fingerprint refuse an offer for another dataset. --samples checks samples without funding. --sale picks one package when several arrived. |
sale policy | Buyer | Fetches and shows the seller's signed rules for questions about the offered dataset. |
sale query | Buyer | Asks the seller aggregate questions before funding, checks the signed receipts, and keeps them with the sale. |
sale fingerprint | Both | Prints a file's dataset fingerprint and size, to check an offer against. |
sale card | Both | Checks a data card's signature and shows its claims by kind. |
sale verify-claims | Both | Recomputes a sale's card and query answers, or a card, from the dataset and lists any that differ. |
sale status | Both | Lists the sales on this machine with each one's escrow state, next step, and the block it is due by. |
sale resume | Both | Carries a sale forward: delivers, reveals, settles, reclaims, decrypts or challenges, whichever is due. |
sale withdraw | Both | Collects a payment the escrow could not send directly. |
sale wallet … | Both | Creates, shows, backs up, limits, empties and removes the sale wallet. |
A sale id may be shortened to any unique prefix. With --json, output is
machine-readable and errors carry a kind such as sale_terms_rejected,
sale_fingerprint_mismatch, sale_card_mismatch, sale_samples_refused,
sale_claims_differ, sale_queries_unanswered or sale_limit.
Files a sale leaves
- Seller: the package, about 101% of the dataset, in
--package-diruntil it is delivered. - Buyer: the delivered package in its agent's inbox, and proof trees of about
3% of the dataset. Both are removed once every leaf matches or the sale ends.
The buyer reads the package from the inbox until it has decrypted it, so do
not run the buyer's agent with
--room-inbox-max-ageor--room-inbox-max-gibset to remove objects sooner than the reveal period: without the package the buyer can neither decrypt nor challenge what it paid for. Samples stay in--samples-out. - Both: the sale records under
sales/in the Beam configuration directory. A sale bought with--cardkeeps the card there ascard.json, and a buyer that asked queries keeps the seller'spolicy.jsonand every receipt underreceipts/. A seller keeps the receipts it sent underquery-receipts/, and what its answers revealed about each dataset undersale-queries/.
Running sales from an AI agent
The CLI is built so that an agent can sell or buy without ever holding a key.
Commands print summaries, never keys, and the CLI applies the limits itself. The
escrow cannot tell a manipulated agent from a willing one, so the limits and the
person-only actions cap the cost of a
prompt-injected or runaway agent that drives beam sale. An agent with general
shell or file access as the wallet's account can get past them; the wallet's
balance is then the only bound (What the limits do not
stop).
- Agree on the dataset, the counterpart's address and the price with the person
the agent works for before offering or buying, and pass that price as
--max-price. - Run
sale offer,sale buyandsale resume --waitin the background: they wait for hours by design. - Read
beam sale status --jsonfor each sale's next step and the block it is due by, and runbeam sale resume <sale-id>when it is due. - Keep invitation files private, and never print a key, a wallet secret or an invitation token.
- When the agent answers questions about a dataset from its card, it should answer only from the card's fields, name the field each answer uses, and keep the seller's declarations apart from what the card lets anyone check.
- An agent can turn a person's question into typed queries for
beam sale query. It should answer only from the signed receipts, name the query and group each figure comes from, label anything else as unverified, and never combine queries to get around a refusal.
Tested before release
Before release, 46 sales ran through the CLI against the v1 contract on Bittensor EVM testnet, delivering through Rooms in Beam's development environment:
- 41 honest sales of 1 MB to 10 GB: every bought file was identical to the sold one, byte for byte. From the seller's offer to the buyer's checked file, they took about 40 seconds for 1 MB, 2 minutes for 1 GB and 12 minutes for 10 GB, with both parties on one host. Sales settled once their challenge windows closed, and the seller is paid only then.
- A cheating seller was caught and the buyer refunded; an unrevealed sale was refunded on the first block after its deadline; a revoked offer, an offer that expired unfunded, and the one-unfunded-delivery limit all ended as designed.
- Every included transaction landed within 4 blocks of its broadcast. One stalled reveal was replaced with a higher fee and landed in the next block.
Data cards, samples and queries were tested the same way before their release, with real agents on testnet:
- Offers for another dataset, size or card, a tampered card, a request for more samples than offered, a question that singled out a record across two sales of one dataset, and an altered receipt were all refused or flagged, with nothing funded.
- Cards, questions and
verify-claimsmatched on CSV, JSON, XML and Parquet datasets, and every funded sale settled. - On a 1 GiB CSV of 24 million records, on a host with 2 CPUs, writing the card
took about 3 minutes, one batch of questions about 2.5 minutes, and
verify-claimsabout 5.5 minutes.
Next steps
- Beam CLI: install the CLI and connect a machine.
- Billing & Payments: credits and what Rooms cost.
- Bittensor EVM: Beam's receipts on the same chain, which are separate from sales.
Room Webhook Members
Let any HTTPS endpoint take part in a Beam Room through a member's agent: set it up, verify its signed requests, reply, and know what its host can read.
Beam Studio
Beam Studio is a self-hosted app for visual data transfer workflows: move data between S3, R2 and HTTP endpoints on demand, on a schedule or from a webhook.