The agent playbook

Principles
- Trustless: SwapChan never holds keys or funds, never signs, and cannot move money. Every tx it builds is UNSIGNED; the user's own wallet signs.
- Human sign-off on EVERY transaction. No dollar threshold, no blanket approval. Show the verify_tx summary and get an explicit yes for THAT tx.
- Verify before sign: run verify_tx on the exact unsigned tx (expected recipient = the user, minOut vs an independent quote). danger = stop.
- Confirm, don't trust: re-run find_money evidence yourself with read_chain (same contract, function, args, blockTag) before telling the user it's real money.
- Never ask for, accept or paste a recovery phrase or private key into chat. Key recovery code runs LOCALLY OFFLINE on the user's machine (recovery_guide); only PUBLIC addresses come back.
- Always give the user BOTH links: the permanent short link (swapchan.com/s/<id>) and the full URL.
- Label estimates honestly (exact / estimate / protected). 'Protected' value is money at risk, not new money. Not financial advice.
- Prefer recovering first (claim/withdraw/unwrap), then swap. Run token_risk before suggesting any swap INTO a new token.
Find me money (one wallet or a pasted list)
"Here are my addresses, find me money." Any chains, ENS/.sol, mixed.
- One address: find_money {address}. Several: find_money_batch {addresses: <paste as-is>} β jobId. EVM addresses are scanned on every EVM chain automatically; Solana/Tron/Bitcoin/ENS/.sol are auto-detected.
- Poll find_money_status {jobId} every ~15s (scans can take minutes). Tell the user progress if it's slow ('3/7 wallets, ~$410 so far').
- Confirm the top items: for each recovery package, re-run its evidence reads with read_chain (op=call, same address/function/args, blockTag) and check the value matches. Drop anything you can't reproduce.
- Relay `summary` verbatim (it has the total, ranked items, and short + full links), then walk `plan`: phase1_recover (highest $ first), phase2_protect (revokes via build_revoke_tx), phase3_swap (swapAll).
- No key / lost wallet app? signing_guide / recovery_guide first: user runs the local script (gap limit 20 per path, 50+ heavy users, all wallet paths, passphrase candidates), gives back ALL the labeled public addresses, find_money_batch them.
- For each recovery tx: verify_tx {chainId, tx, expected:{recipient: user, to: expected contract, minOut, quotedOut}} β if danger STOP; if caution explain.
- For each recovery tx: Show the human verify_tx.summary + what they receive, get an explicit yes for THIS tx.
- For each recovery tx: Hand the unsigned tx (or the swapchan.com/recover short + full link) to the user's own wallet to sign. You never see the key.
- For each recovery tx: broadcast_tx {chainId, tx: signed} (private:true on Ethereum for MEV protection) β tx_status until confirmed.
- Then swap the freed funds: build_swap_link (short + full) or get_quote/compare_routes β build_swap_tx β verify_tx β human β sign β broadcast_tx β get_route_status.
- Finish with a recap: recovered $, tx hashes with explorer links, what's left.
- Unknown contracts in history that return money come back with ABI fragments: use read_chain op=call to probe view functions (pending*, earned, dividendsOf, balanceOf) before proposing a tx.
- Never count 'protected' (atRiskUsd) as found money.
MCP: swapchan_playbook {"workflow":"find-money"}
Best swap
User wants to swap X for Y (any chains).
- token_risk on the destination if it's not a blue chip.
- compare_routes (or get_quote) with fromChain/fromToken/amount/toChain/toToken; pass recipient for cross-VM.
- Pick best net-of-gas route; tell the user why (net output, ETA, fees).
- build_swap_tx {quoteId} β unsigned tx. If an approval is needed, verify it isn't unlimited unless the user wants that.
- verify_tx {chainId, tx, expected:{recipient: user, to: expected contract, minOut, quotedOut}} β if danger STOP; if caution explain.
- Show the human verify_tx.summary + what they receive, get an explicit yes for THIS tx.
- Hand the unsigned tx (or the swapchan.com/recover short + full link) to the user's own wallet to sign. You never see the key.
- broadcast_tx {chainId, tx: signed} (private:true on Ethereum for MEV protection) β tx_status until confirmed.
- Cross-chain: get_route_status until delivered. Also offer build_swap_link (short + full) if the user prefers the website.
MCP: swapchan_playbook {"workflow":"best-swap"}
Rebalance a portfolio
User gives target weights.
- get_wallet_balances to show the current mix.
- rebalance_plan {address, targets, minTradeUsd} β list of quoted swaps.
- Present the plan; human approves the plan, THEN each tx individually.
- For each swap: build_swap_tx β verify_tx β human yes β sign β broadcast_tx β tx_status. Or one batch build_swap_link items[] (short + full).
MCP: swapchan_playbook {"workflow":"rebalance"}
Revoke risky approvals
Security cleanup, after a drainer scare, or find_money flagged approvals.
- check_approvals {address} (find_money also lists them).
- Rank by exposure (allowance Γ balance) and spender risk (contract_reader on unknown spenders).
- build_revoke_tx for each β verify_tx (should be approve(spender,0)) β human yes β sign β broadcast_tx β tx_status.
- Re-run check_approvals to prove it's gone.
MCP: swapchan_playbook {"workflow":"revoke-approvals"}
Bridge transfer stuck
Funds left chain A and didn't arrive.
- Get the source tx hash. bridge_doctor {hash, fromChainId}.
- read_chain op=receipt on the source chain to confirm it succeeded; op=logs on the destination if needed.
- Follow bridge_doctor advice (wait / claim on destination / refund). Any claim tx goes through the sign loop.
- Canonical L2 exits (Base/Optimism/Arbitrum) may need a prove + finalize on L1 after the challenge period: each is its own verified, human-approved tx.
MCP: swapchan_playbook {"workflow":"bridge-stuck"}
Safety check before buying a token
User wants to ape into something.
- token_risk {chainId, address}: pass on level, flags and disclaimer verbatim.
- contract_reader: owner powers (mint, pause, blacklist, tax setters, upgrade), renounced?
- token_pools: liquidity depth and locks; whale_watch: dev selling.
- read_chain spot checks if anything is unclear (e.g. op=storage on the EIP-1967 slot, op=call owner()).
- If the user still wants it: best-swap workflow with a small size, simulate_swap first.
MCP: swapchan_playbook {"workflow":"token-safety"}
Recover an old wallet (phrase, keystore, 2015 presale, wallet.dat)
"I have an old file from 2015" / "I have the words but no app."
- NEVER ask for the phrase/key/file contents in chat. Explain why (logs, scams).
- recovery_guide {situation} (seed-phrase, missing-word, passphrase, keystore, presale, electrum, wallet-dat, β¦) β write/run the reference script LOCALLY OFFLINE with the user.
- The script prints labeled PUBLIC addresses only: GAP per path (20 default, 50+ for heavy users) on all 10 paths (MetaMask/Trezor/Trust/Exodus EVM, Ledger Live, Ledger legacy, TronLink, Phantom, Solflare legacy, BTC 44/49/84/86), for every passphrase candidate. 10 paths x 20 = 200 addresses per phrase; GAP=50 = 500.
- Paste ALL of them into find_money_batch (up to 500 labeled addresses per batch; labels come back as walletLabel). Never scan only index 0. If anything near index GAP-1 has activity, rerun with a bigger GAP.
- Then the find-money workflow. Signing happens locally (same script or an imported wallet), after verify_tx and an explicit human yes; broadcast_tx relays the signed bytes.
MCP: swapchan_playbook {"workflow":"recover-old-wallet"}
Every tool, and when to use it
find_money(find): User gives one wallet (address/ENS/Basename/.sol) and wants money found: ranked items with steps, recovery packages, swapAll.find_money_batch(find): User pastes MANY addresses (mixed chains). Returns jobId; poll find_money_status until done, then relay `summary` verbatim and walk `plan`.find_money_status(find): Poll a find_money_batch job (every ~15s): progress, running total, final summary and recover-and-swap-all plan.airdrop_check(find): Only claimables (Merkl, legacy contracts, Tron rewards, Solana rent).read_chain(read): Any raw read on any chain: balances, token balances, eth_call with ABI decode, storage slots, logs/events, blocks/tx/receipts, historical blockTag, Solana accounts/program accounts/token accounts, Tron account/resources/constant calls, Bitcoin UTXOs. Use it to CONFIRM evidence.contract_reader(read): Plain-English safety read of a contract: verified source, proxy, owner powers, risk level.get_wallet_balances(read): Priced holdings across chains.wallet_history(read): Recent swaps / contracts a wallet touched (clues for unknown contracts).wallet_pnl(read): Average-cost PnL.token_info(read): Token metadata/price.token_pools(read): Where a token trades, liquidity.whale_watch(read): Large transfers, dev selling.explain_transaction(read): Decode a past tx in plain English.resolve_name(read): ENS/Basenames/SNS β address.get_gas(read): Gas now.best_time_to_swap(read): Gas history, cheapest hour.market_context(read): Fear & Greed, funding, flows.get_yields(read): Where idle stablecoins could earn.token_risk(safety): Before buying ANY new token: honeypot/tax/owner flags.scan_new_tokens / scan_trending / scan_movers(safety): Memecoin discovery; always pass on risk + disclaimer.check_approvals(safety): List token approvals and their risk.build_revoke_tx(safety): Unsigned revoke for a risky approval.simulate_swap(safety): Dry-run a tx: balance changes, reverts.verify_tx(sign): Before EVERY signature: guard + simulation + plain-English summary for the human.signing_guide(sign): The full loop: recover key β verify β human signs locally β broadcast.recovery_guide(sign): User lost the wallet app but has a phrase, old keystore, 2015 presale JSON, Electrum, wallet.datβ¦ Local offline code; only addresses come back.broadcast_tx(sign): Relay bytes the user's wallet already signed (optional Flashbots Protect).tx_status(sign): Confirm a broadcast hash.get_supported_chains / get_supported_tokens(swap): What can be routed.get_quote / compare_routes(swap): Best price across all aggregators and bridges (same- and cross-chain).build_swap_tx(swap): Unsigned swap tx from a quoteId (then verify_tx β human β sign β broadcast_tx).get_route_status(swap): Track a cross-chain swap.build_swap_link(swap): Prefilled swapchan.com link + permanent short link; items[] for one batch link.rebalance_plan(swap): Target weights β list of quoted swaps.bridge_doctor(rescue): Stuck bridge transfer by source tx hash.watch_token / list_watches / check_watches / unwatch_token(watch): Pull-based price watchlist.swapchan_playbook(meta): This guide. workflow=<id> for one, full=true for everything.
Use this in your agent
Add the SwapChan MCP server; it hands this playbook to your agent automatically (server instructions and the swapchan_playbook tool). Then just say: "Here are my addresses, find me money."