User guide

How It Works

The overview gave you the short version: your main wallet stays yours, the agent gets a separate errand wallet holding only what you allot, and no single party can move the money. This page looks a little closer at why that arrangement actually holds — not with heavy technical detail, but enough that you can see the shape of it and trust it for the right reasons.

Two wallets, one boundary

The whole design rests on keeping two pools of money apart.

Your main wallet is where your real funds live. You control it with a key that never leaves your device and that no software agent ever sees. It has exactly two jobs in this story: it is where you fund an errand wallet from, and where you sweep leftover money back to. It is never the place an agent's payment comes out of.

The errand wallet is a separate account, one per agent, funded by you with a deliberately small amount. This is the only pool the agent can reach. Because it is a genuinely distinct account — not a compartment inside your main wallet, and not a spending limit bolted onto it — the balance you put in it is a real, physical ceiling on how much could ever go wrong. Nobody has to promise to respect that ceiling; it is simply how much money is there.

Here is the flow, and the line the money cannot cross:

flowchart TB
    subgraph you["Yours — you hold the key"]
        main["Main wallet<br/>your real funds"]
    end

    subgraph errand["Errand wallet — its own account, one per agent"]
        bal["Balance you allotted<br/>= hard ceiling on any loss"]
        rule["Two-signature rule<br/>agent key + Tidal co-signer"]
    end

    merchant["Merchant or service<br/>often paid via x402"]

    main -->|"you fund it<br/>(signed with your master key)"| bal
    bal -.->|"sweep back anytime<br/>(signed with your master key)"| main

    agent["AI agent<br/>holds its own key"] ==>|"signs half of the payment"| pay(["Payment"])
    check{"Policy &amp; risk check<br/>within your limits?"}
    agent --> check
    check -->|"approved"| cosign["Tidal co-signer<br/>signs the other half"]
    check -->|"over a limit / suspicious"| stop(["Held — you decide"])
    cosign ==> pay
    pay ==>|"two signatures → settles"| merchant

    main -- "agent can never reach this" --x errand

The dashed line at the bottom is the point of the whole thing: there is no path from the agent to your main wallet. The agent operates entirely inside the errand wallet, and the most it can ever spend is what you funded that wallet with.

Why the agent can't cross the line

An errand wallet is set up so that a payment from it is only valid when it carries two signatures — one from the agent, and one from Tidal's co-signer. This is a rule the XRP Ledger itself enforces, called a two-of-two signer arrangement. It has a few consequences that are worth spelling out:

  • The agent acting alone cannot produce a valid payment. Its single signature is not enough.
  • Tidal acting alone cannot either. Tidal holds only one of the two signatures and can never produce a valid payment by itself.
  • Even if both were somehow compromised at once, the worst case is still just the balance of the errand wallet — because that is all the account holds, and the account is walled off from your main funds.

Tidal's half of the signature is not given automatically. Before the co-signer signs, a policy and risk check runs: is this payment within the caps you set, going to an allowed destination, inside the authorization's lifetime? If anything is off, Tidal simply withholds its signature, and without that second signature the payment cannot happen. When a payment is unusual rather than clearly wrong, Tidal pauses and asks you — a challenge you answer in the app.

Where the limits really live

It is worth being precise about one thing, because it is where careless wallets tend to exaggerate. The limits you set — a cap per payment, a daily cap — are enforced by Tidal choosing not to co-sign a payment that would break them. They are real, they are logged, and you can audit them. But they are enforced by the service, not written into the ledger.

What the ledger enforces entirely on its own, with no trust in any service, is just two things: the two-signature rule, and the errand wallet's balance. Everything finer than that — a daily cap, an allowed-merchant list — lives in Tidal's policy layer. This is not a weakness to hide; it is the honest boundary. Your outermost protection (the hard ceiling) is on the ledger and trusts nobody. Your finer controls (the caps and lists) are enforced by a service and are auditable. A wallet that tells you a daily cap is an unbreakable on-chain guarantee is overselling; we won't.

Why you are never locked out

Because the errand wallet is a real account that you set up with your own master key, you keep an exit that depends on no one. At any time you can sweep the remaining balance back to your main wallet, and you can remove the two-signature arrangement entirely. Crucially, this works even if Tidal disappears — if the servers are down, if the company is unreachable, whatever the reason. The ledger will honor a transaction signed by your master key directly, so your money is never held hostage to Tidal staying online.

This is why Tidal asks you, during setup, to make and verify an offline backup of your recovery secret before you put any real money in. Genuine self-custody means Tidal cannot recover a lost key for you — so the app makes sure you can, before anything is at stake.

What settles, and what's final

When a payment goes through, it settles on the XRP Ledger as a direct XRP or RLUSD payment — often as the settlement step of an "x402" request, which is just a standard way for a service to ask an agent to pay before it hands over a resource. Settlement is fast and, once it happens, final. That finality is a feature — it is what makes the payment as good as done — but it also means a settled payment cannot be clawed back by Tidal. Your protection is before the fact (the limits, the two-signature rule, the small balance), which is exactly where protection belongs.

Read next