Keys, backup and withdrawals
An agent's funds are one 32-byte seed. This page is where that seed lives, how its owner backs it up and restores it, in the MCP server or in the web app, and how funds leave each kind of vault. Nobody, Ostra included, can restore a seed whose every backup is lost.
12.1One seed, and the records beside it#
On first use the MCP server creates a 32-byte seed, the file master.key in the agent's directory: ~/.ostra, or the directory OSTRA_HOME names. The directory is readable by its owner only, and nothing in it is ever printed or sent anywhere keys.ts:1-12. Every key that controls funds derives from that seed keys.ts:1-13:
- the USDG vault, the seller vault, and the vault of each other token the agent holds (WETH, $OSTRA, stock tokens, launched tokens);
- its creator vaults, its private vaults and its private notes;
- every payment channel, shield deposit and one-time key.
The one key that does not is fee-payer.key, which pays gas in ETH when no relayer is used and never holds tokens. Next to them the directory keeps the record of every one-time signature (wots/) and the agent's other records keys.ts:1-12. Another agent, in another directory, has a seed of its own. The seed is not a word list, and an Ethereum wallet such as MetaMask cannot use it to reach the vaults: a vault is a contract spent only by one-time post-quantum signatures derived from the seed (post-quantum keys). Whoever holds master.key holds every vault of the agent.
12.2Backing up the seed#
The owner runs this in a terminal, not through the agent, so the passphrase never passes through the MCP server backup-cli.ts:1-15:
OSTRA_HOME=~/.ostra npx -y @ostraagent/mcp backup export ~/ostra-seed-backup.json- It asks for a passphrase of at least 12 characters, twice, without showing it.
- It writes the encrypted seed to the file, readable by its owner only, and never over a file that exists backup-cli.ts:90-100.
- Until a backup has been exported,
open_vaultandbalanceremind the agent's owner to make one vault.ts:501 vault.ts:654.
Both backup commands act on the directory OSTRA_HOME names, ~/.ostra when it is not set: give them the same directory the MCP server runs with. The file is JSON: the seed under AES-256-GCM, with a key derived from the passphrase by scrypt (N 217, r 8, p 1) seed-backup.ts:1-12. It is useless without the passphrase, and the passphrase is useless without the file. Keep both off the machine, and apart: the file in a password manager, on a USB drive or in cloud storage, the passphrase somewhere else.
12.3Restoring in the MCP server#
On the new machine, before the server first starts there:
OSTRA_HOME=~/.ostra npx -y @ostraagent/mcp backup import ~/ostra-seed-backup.json- It asks for the passphrase and writes the seed to
master.key. It refuses a directory that already holds a seed: a restore always goes into a new one backup-cli.ts:101-112. - The server then finds the vaults the seed alone finds again (above) and, with the Ostra relayer, its signature escrow sends any signature that was still in flight backup-cli.ts:1-15.
- Private notes are found on first use, or with
private_recovertools.ts:387; the seller vault withaccept_payments.
12.4In the web app#
The vault in the web app at app.ostraagent.xyz/vault uses the same seed and the same backup file. Its seed is made in the browser and kept there only encrypted under the owner's passphrase, in that same file format, which the MCP package's tests open in both directions seed-backup.ts:1-12 disk.test.ts:78-81. The web app keeps its other records in the browser, so what the seed alone does not find (above) stays in the browser that made it.
| MCP server | Web app | |
|---|---|---|
| Seed made | on first use, in ~/.ostra | in the browser, on Create a vault |
| Backup | backup export <file> | downloaded before the vault first opens; again from Settings, Download the backup file again |
| Restore | backup import <file> | Restore from a backup file: a file from either side, and its passphrase |
| Without the file | guardian recovery of the USDG vault, if set up beforehand | Restore with a passkey, if a passkey backup was saved |
Creating and backing up#
Creating a vault asks for a passphrase of at least 12 characters, twice, and for the owner to confirm that without the passphrase and the file the vault cannot be opened elsewhere. The vault opens only after its backup file is downloaded and the owner confirms it is saved off the device. Settings downloads the same file again at any time.
Restoring#
A browser keeps one seed. Restore from a backup file is offered only in a browser that keeps none; in one that does, the vault opens with its passphrase instead. To restore another seed there, remove the vault first (Settings, Remove from this browser; or, on the locked screen, Forgot the passphrase?, Remove from this browser), which only its backup file or a passkey backup can undo.
A restored vault starts working at once: as soon as it is open, the app closes finished channels and carries on shield and unshield operations, signing as it goes. A backup file can be checked in a private browser window, but only with the seed stopped everywhere else first (the MCP server, other browsers, other windows), comparing the vault address and closing the window at once.
The passkey backup#
Settings can also save the seed to a passkey of the site. The browser encrypts the seed with a secret only that passkey gives (WebAuthn PRF), and the Ostra relayer keeps only the ciphertext, which it cannot open passkey.ts:1-21. With a passkey synced by Apple Passwords or Google Password Manager, a new device restores the vault by signing in, with no file and no old passphrase; it then asks for a new passphrase and for the new backup file to be saved. Such a passkey is a full key to every vault of the agent: protect the account that syncs it as the backup file is protected. Not every passkey provider supports this, so the file stays the backup to keep.
12.5Taking funds out#
Each kind of vault has its own tool. With the Ostra relayer, the default, every withdrawal is sent by the relayer and paid in USDG, so no ETH is needed. Withdrawals from token and creator vaults are paid through the USDG vault, which must hold a little USDG (keep some USDG in the vault). None can be undone.
| Where the funds are | Tool | Notes |
|---|---|---|
| The USDG vault | withdraw tools.ts:252 | To any address. Nothing refuses an Ostra vault of another token as destination, and USDG sent there stays for good. In the web app: Vault, Withdraw. |
| A vault of another token: WETH, $OSTRA, a stock token, a launched token | transfer_token tools.ts:772 | Any token vault of the agent, not only launched tokens; WETH moves as the token, not as ETH; an Ostra vault of another token is refused as destination launchpad.ts:613-628 launchpad.ts:341-346. Or swap to USDG first with ostra_swap. |
| A creator vault | creator_withdraw tools.ts:796 | By default to the agent's own vault of that token; a WETH creator vault names the destination. |
| Private notes | private_unshield tools.ts:400 | The relayer's fee comes out of the note. The default destination, the agent's own vault, can be linked to the vault that shielded: pay a fresh address, or, for USDG, a new private vault of the agent (toPrivateVault). |
| A private vault | private_withdraw tools.ts:405-413 | The vaults private unshields paid (private_balance lists them), created on their first withdrawal through the relayer, which keeps back 1 USDG for the vault's relayer channel (what that channel does not use returns to the vault); and the vaults unshield made before 0.1.6. |
| The seller vault (x402 payments received) | seller_withdraw tools.ts:333 | By default to the agent's vault. |
Two balances come back on their own and are not withdrawn:
- What a payment channel did not spend goes back to the vault when the channel closes: the relayer's channel when the relayer closes it, Ostra AI's when it has been idle, a channel to another seller when its life ends, or earlier with
close_channel, after its grace period tools.ts:262. - Credit with Ostra AI is not a token and cannot be withdrawn: it pays part of the vault's next tasks (what a task costs).