self-custody · MCP · three trust levels

Give your agent
a wallet of its own.

Self-custody Ethereum wallet for AI agents. One local Docker image, keys never leave your machine — and you choose how much control the agent gets.

rustoktrust_ladder

One wallet. Three trust levels.

Same self-custody core, same MCP tools — the difference is who holds the key and who presses approve. Start hot, upgrade as the stakes grow.

full autonomy

rung 1 · Agent edition

key: lives with the agent

The agent signs and sends on its own. For agents you talk to remotely — Telegram and the like — where pressing a button isn't an option.

⚠ Hot by design: no spending limits, no approval step. Fund it like a hot wallet.
Install →
human-approved

rung 2 · Console edition

key: local container — approval: yours

Every transaction that moves funds waits for your y/N in a separate console on your machine — PIN for high-risk approvals.

Install →
keys on your phone

rung 3 · Mobile

key: your phone — agent: keyless

The agent proposes, your phone re-derives and signs. Approve from anywhere. The endgame: an agent that never touches a key.

In development — follows the same core.
Read the thesis →

Moving up a rung means a new wallet: spin up the next edition, then move your funds on-chain. Recovery phrases import into any standard wallet — nothing is locked in.

rustokinstall

Pick a rung, set up in two steps.

i Prerequisites — Docker running + an Ethereum RPC URL (an Alchemy key URL is best; a public RPC works for testing).
Agent edition rung 1 · full autonomy
01
Create your wallet
Prints an address + 24 words — visible only in your terminal.
docker run -it --rm -v rustok-wallet:/data \
  -e RUSTOK_KEYRING_PASSWORD="choose-a-strong-password" \
  ghcr.io/rustok-org/rustok-wallet:latest create-wallet
Recovery = the 24 words (importable into any standard wallet, e.g. MetaMask) or the Docker volume + password.
02
Add the MCP server config
Drop this into your MCP client.
{
"mcpServers": {
"rustok-wallet": {
"command": "docker",
"args": ["run","-i","--rm","--init",
"-v","rustok-wallet:/data",
"-e","RUSTOK_KEYRING_PASSWORD",
"-e","RUSTOK_ALLOWED_CHAINS=1,8453",
"-e","RUSTOK_RPC_URLS_1",
"ghcr.io/rustok-org/rustok-wallet:latest"],
"env": {
"RUSTOK_KEYRING_PASSWORD": "...",
"RUSTOK_RPC_URLS_1": "https://your-rpc"
}
    }
  }
}
Read-only agent? Set RUSTOK_MCP_CAPABILITIES=read_wallet.
Console edition rung 2 · human-approved
01
Create your wallet
Run this in a terminal the agent cannot see. Prints the 12-word recovery phrase + a 6-digit approval PIN — once.
docker run -it --rm --name rustok-wallet-tui \
  -v rustok-wallet-tui:/data \
  -e RUSTOK_KEYRING_PASSWORD="choose-a-strong-password" \
  ghcr.io/rustok-org/rustok-wallet-tui:v0.6.0 create-wallet
Back up the 12 words and the PIN offline, then fund the address. Lost the PIN? docker exec -it rustok-wallet-tui core-server set-pin.
02
Add the MCP server config
Drop this into your MCP client.
{
"mcpServers": {
"rustok-wallet-tui": {
"command": "docker",
"args": ["run","-i","--rm","--init",
"--name","rustok-wallet-tui",
"-v","rustok-wallet-tui:/data",
"-e","RUSTOK_KEYRING_PASSWORD",
"-e","RUSTOK_ALLOWED_CHAINS=1,8453",
"-e","RUSTOK_RPC_URLS_1",
"ghcr.io/rustok-org/rustok-wallet-tui:v0.6.0"],
"env": {
"RUSTOK_KEYRING_PASSWORD": "...",
"RUSTOK_RPC_URLS_1": "https://your-rpc"
}
    }
  }
}
Then: approvals happen in a second terminal
When a transaction is pending, open a window the agent can't see — y/N per transaction, PIN for high-risk approvals.
docker exec -it rustok-wallet-tui rustok-console
rustoktools --list

Every tool, both editions. Nothing hidden.

Capability gating is fail-closed — scope a session to read only, prepare only, or execute. And on the console edition, execute waits for a human.

tool
capability
agent
console
what it does
get_wallet_context
read_wallet
active address, per-chain balances, allowed chains
get_balances
read_wallet
token balances for the active wallet
get_positions
read_wallet
DeFi positions — Aave v3 + ERC-4626 vaults
preview_send
preview_tx
preview an ETH send → preview_id, gas, risk level
preview_transaction
preview_tx
preview a transaction → decoded call, simulation, gas, risk level
execute_send
execute_tx
broadcast a previewed send → tx_hash
execute_transaction
execute_tx
queue a previewed transaction — waits for your console approval
get_execution_status
execute_tx
poll a queued transaction — executed / denied / expired
sign_message
execute_tx
sign a message (EIP-191)
rustoksafety

The agent proposes. You decide.

On the console and mobile rungs, nothing moves without you. On the agent rung, you trade that for full autonomy — knowingly.

Self-custody
Keys live only in the local core and never leave it. Encrypted at rest with Argon2id + AES-256-GCM.
Capability gating
read / preview / execute — fail-closed, nothing more than you grant.
txguard
Every transaction is parsed and risk-flagged before you sign — scam-address and risky-approval checks.
Your approval channel
Nobody on rung 1, your console on rung 2, your phone on rung 3. The rung is the choice.
Self-custody means your risk: the agent edition has no spending limits and no approval step — txguard flags risky transactions, it does not block them. That's what the ladder is for.
txguard.log
rustokchains

Mainnet, first-class L2s, and your own RPC.

Ethereum mainnet, plus first-class L2s — Arbitrum One, Base, and Optimism. Sepolia testnet for development. Any other EVM chain works with your own RPC URL.

RUSTOK_ALLOWED_CHAINS  ·  default ships 1,8453
Ethereum1 Arbitrum42161 Base8453 Optimism10 Sepolia11155111
// why rustok
Rustok gives an AI agent a wallet of its own — self-custody, no middleman — so agents can take part in the economy directly: paying for the compute, data, and tools they rely on.

The endgame is an agent with no keys at all — proposing transactions your phone signs.

Give your agent a wallet.

support  0xA713e7145F0060A35E92a928e997B42481c0FfEE