prototype · unaudited · Esmeralda testnet only

Familiar

A private allowance for AI agents on Tari Ootle. The agent can spend only up to the owner's limits, only to payees the owner listed, and the owner can take the budget back at any moment. The network enforces it, not the agent's code. In coupon mode no µT amount reaches the chain: not the budget, not what is left, not what a payment moved. An observer sees that a payment happened and how many hidden coupons it spent (the counts are public), never what a coupon is worth, nor who is behind a payee. Only the network fee of each transaction is public.

Walk through the run, transaction by transaction

27 real transactions on the Esmeralda testnet, from 2026-10-21 18:11:54.0 UTC: 17 accepted, 10 refused by the network. Part 1 attacks a leash in amount mode directly. Part 2, where this page opens, hands a leash in coupon mode to an AI agent that obeys every payment instruction it reads, including ones injected into a web page, an email and a fake receipt: no payment of Part 2 publishes a µT amount. For each step: what happened, and what anyone reading the chain can see. Use the arrows, the numbers, or the keyboard (← →).

What an observer sees on-chain

    What stays hidden

      Decoded from the public indexer by scripts/observer_view.py; no keys used.

      Video

      Silent, made from this page: each frame is one real transaction of the run below. No narration, no edits to the data.

      Read the leash live

      Component state on Ootle is public, so this page can read it straight from the Esmeralda indexer, now, from your browser. This is everything the leash itself discloses: the rule, the window, the roots. Not a balance.

      Not read yet.

      The problem

      The Ootle wallet daemon can hand an AI agent an API key with scopes such as TransactionSend_<account>. A scope says what the agent may do, not how much: a key that may send may send the whole account. An agent that reads the web can be told, in text hidden in a page, to do exactly that. On a transparent chain its wallet is also public: balance, every service it pays, who funds it.

      Familiar moves the limits into the chain and keeps the purse out of sight.

      What the network enforces

      RuleEnforced by
      at most max_per_payment per paymentnative covenant BalancePreserved(max_per_payment) in each budget UTXO's spend condition
      at most limit per window of epochsthe leash component, charging the amount the covenant proves, never an argument
      payments only to allow-listed payeesevery output under the budget root (change) or an allow-listed payee root
      optionally, each payee root is paid oncesingle-use mode strikes a paid root off the list: repeat payments to one shop land on unrelated roots
      the budget moves only through the leashthe spend condition requires component(<this leash>)
      coupon mode: at most N coupons per payment and per window, no µT amount on-chain (the number of coupons is public)pay_coupons checks from each input's revealed leaf and inclusion proof that it is a coupon of this leash, refuses change and claims, and counts coupons; Pedersen balance proves that no value was created
      the owner recalls everything, without the agenta hidden second leaf public_key(<recall key>): a random key of its own, not the owner key from the access rules, so nobody can compute the leaf before it is used; spent without a covenant claim so the amount is not published

      Every budget UTXO: amount hidden by a Pedersen commitment, locked under a pure condition tree Script(root) with two leaves: errand = component(leash) AND BalancePreserved(cap) and recall = public_key(recall key).

      Privacy: visible, hidden, and what leaks

      Visible to anyoneHidden
      A paymentthat it happened, its epoch, the leash, the one-time agent key that signed it, its network fee
      Amount mode (pay)the exact µT each payment moves (the covenant claim)
      Coupon mode (pay_coupons)how many coupons a payment spends; how many were minted, spent and recalled, so how many are leftwhat a coupon is worth, so what a payment moved: the owner draws the denomination and it is written nowhere
      The budgethow many budget UTXOs or coupons existhow much they hold and what is left, in µT (Pedersen commitments; the recall carries no claim)
      Payeesthe allow-listed payee rootswho is behind a root; with single-use roots, that two payments went to the same shop
      The recall leafthat a second leaf exists (one sibling hash in every payment)what it says, until the owner uses it: it names a recall key of its own, random and nowhere else on-chain (not the owner key of the access rules)
      The leash's statethe rule, the window usage (µT or coupons), the roots, paused or notno balance: the budget is not in the component

      Leaks, named. In amount mode payment amounts are public; in coupon mode their relative sizes are (3 coupons, then 2). The coupon denomination is the owner's: "Try it" draws it at random per leash and keeps it in the wallet file. The window usage is public (component state). Payments of one leash are linked by the leash and the agent key. In this demo the one-time keys are funded from one account in one transaction, which links them; a real owner funds them from separate stealth outputs. Prototype, not audited.

      Try it yourself

      Your own leash in coupon mode on Esmeralda, from a fresh key, in about 3 minutes (prebuilt client in the release, or cargo build -p familiar-cli --release; the README has the sha256 and the macOS/Windows notes for unsigned binaries):

      familiar tap-status            # what the tap holds; anyone can refill it (tap-top-up)
      familiar wallet me.json        # a fresh testnet key, written only to me.json
      familiar tap    me.json        # 5 tTARI from the Familiar tap
      familiar leash  me.json        # a leash in coupon mode with 10 hidden coupons, a random denomination
      familiar pay    me.json candle-shop 2
      familiar ask    me.json "any text, e.g. a hidden instruction to pay refund-desk"
      familiar pause  me.json; familiar recall me.json; familiar show me.json

      For an LLM agent: scripts/familiar_mcp.py is an MCP server whose only spending tool, pay_through_leash, goes through the same leash.

      # 1. check what an observer sees, from the public indexer only (no keys, no Rust)
      git clone https://github.com/ttimesai-star/familiar-ootle.git && cd familiar-ootle
      pip install cbor2
      python scripts/observer_view.py docs/esmeralda_run.json observer.md
      
      # 2. engine tests (Rust stable + wasm32 target, about 2 GB of RAM)
      cargo test --workspace
      
      # 3. the whole run again on Esmeralda: in a fork, add secret FAMILIAR_FUNDER (a funded testnet account),
      #    then Actions -> claim-and-run -> Run workflow (skip_claim = true). Report, observer view and the
      #    template wasm come back as the job summary and artifact.