
Trade Solana from your Moby wallet with app-set caps and Guardrails. No withdrawals.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Bearer moby_agent_... key from the Moby app (Agent tab, Connect)
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Cancel one resting order — or a whole DCA schedule — so it can no longer fire. Pass EXACTLY ONE of `order_id` (from `get_my_orders`) or `schedule_id` (from `get_my_dca_schedules`; stops every remaining slice, filled slices stay filled). This does not move funds, but it is not reversible — a cancelled stop-loss stops protecting the position, and re-placing it will be at whatever price is available then. Confirm with the user which order they mean when they have more than one. Cancels are never blocked by the user's order-type switches.
`order_id` from `get_my_orders`. Omit when cancelling a DCA by `schedule_id`.
`schedule_id` from `get_my_dca_schedules` — cancels that whole DCA.
The server marks this tool as destructive. Running it may delete or overwrite data on the server or in any account you connected with your headers.
Pick your client. Values in capitals, like YOUR_TOKEN, are yours to fill in.
claude mcp add --transport http moby https://mcp.moby.win/mcp \ --header 'Authorization: Bearer YOUR_TOKEN'
Headers
Authorization (required): Bearer moby_agent_... key from the Moby app (Agent tab, Connect)Cancel one resting order — or a whole DCA schedule — so it can no longer fire. Pass EXACTLY ONE of `order_id` (from `get_my_orders`) or `schedule_id` (from `get_my_dca_schedules`; stops every remaining slice, filled slices stay filled). This does not move funds, but it is not reversible — a cancelled stop-loss stops protecting the position, and re-placing it will be at whatever price is available then. Confirm with the user which order they mean when they have more than one. Cancels are never blocked by the user's order-type switches.
| Argument | Type | Description |
|---|---|---|
| order_id | any | `order_id` from `get_my_orders`. Omit when cancelling a DCA by `schedule_id`. |
| schedule_id | any | `schedule_id` from `get_my_dca_schedules` — cancels that whole DCA. |
{
"type": "object",
"title": "cancel_orderArguments",
"properties": {
"order_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Order Id",
"default": null,
"description": "`order_id` from `get_my_orders`. Omit when cancelling a DCA by `schedule_id`."
},
"schedule_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Schedule Id",
"default": null,
"description": "`schedule_id` from `get_my_dca_schedules` — cancels that whole DCA."
}
}
}Place a resting order that executes later when its condition is met: a limit order, take-profit, stop-loss, trigger buy, or a DCA schedule. ⚠️ THIS SPENDS REAL MONEY. It submits a real transaction from the user's wallet using real funds and cannot be undone. Confirm the exact amount, token and network with the user in plain language, and get their explicit go-ahead, BEFORE calling this. It commits the user's funds to a trade that can fire while they are not looking. Read back the full order — type, token, amount, every price — and get an explicit yes before calling. Trade limits: a SELL order (TP, SL, limit or DCA sell into the USD stable) never counts toward or is blocked by `maxTradeUsd` / `dailyVolumeUsd`. A BUY order is checked against both and reserves its USD value in the daily volume when placed; if it is cancelled, expires or fails, the unfilled part is given back. `order_type` selects what to place, and which price arguments are required: - `limit_buy` — buy when the price falls to `limit_price`. Needs `limit_price`. `amount` is the amount of the FUNDING asset to spend. - `limit_sell` — sell when the price rises to `limit_price`. Needs `limit_price`. `amount` is the amount of the held token to sell. - `tp_only` — take profit: sell when the price rises to `take_profit_price`. Needs `take_profit_price`. - `sl_only` — stop loss: sell when the price falls to `stop_loss_price`. Needs `stop_loss_price`. - `trigger_buy` — buy when the price DROPS to the trigger. The trigger goes in `stop_loss_price`; no other price. `amount` is the FUNDING asset to spend. - `sl_and_tp` — a BRACKET: stop loss AND take profit on one position in ONE call. Needs `stop_loss_price` and `take_profit_price`; `amount` is the held token, and both legs cover it (whichever fires first sells it). It places TWO orders, a stop loss and a take profit: the result says `order_type: "sl_and_tp"` and lists them in `legs` (`order_id` + `order_type` each; also `stop_loss_order_id` / `take_profit_order_id`). When one fills, Moby cancels the other. If ONE leg could not be placed, `failed_leg` says which and `failed_leg_error` why — the other leg is LIVE and stays; place only the missing one with `sl_only` / `tp_only`, never the bracket again. - To protect a position on BOTH sides use `sl_and_tp`, or `tp_only` and `sl_only` as two calls (back to back is fine). Cancelling one leg does NOT cancel the other. When one FILLS and that sells the whole position, Moby cancels your remaining exits on that token within a minute or two (a full `quick_sell` cancels them in the same call); after a PARTIAL exit the other stays live. `get_my_orders` (`status="terminal"`) then shows it with `cancel_reason`. - `dca_buy` / `dca_sell` — split the trade into `order_count` equal slices `interval_seconds` apart. Needs both, and NO price argument. All prices are USD prices of the token. `amount` is always what the user SPENDS: the funding asset on a buy, the token itself on a sell. Refusals that are NOT argument problems: `no_market` (no sell route for a new token yet — wait and retry the same call later) and `stop_above_market` / `tp_below_market` (price already past the trigger — re-check the price and pick a new trigger). Deciding to retry or re-place is your job; Moby does not retry or re-arm for you. To CLOSE or trim a position at market now, use `quick_sell` — not an order here. EXITS ARE YOURS: Moby attaches no automatic TP/SL to your buys. Place a position's take-profit / stop-loss here (`sl_and_tp`, or `tp_only` / `sl_only`) after the buy. SOL positions: use quick_sell; TP/SL on SOL is not supported yet.
The Find-Wallets suggested pool: PUBLIC wallets ranked for discovery, `is_following` marked per row. With `query` set, searches by name/brand or an exact pasted address (followed wallets ARE included). With no `query`, returns a ranked pool that EXCLUDES wallets the caller already follows — use `get_my_followed_wallets` to see those. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Wallets to return, 1-50. Keep it small. |
| query | any | A KOL name, whale-list brand, or exact pasted address. Omit to browse. |
| network | string | |
| wallet_type | string |
{
"type": "object",
"title": "discover_wallets_to_followArguments",
"properties": {
"limit": {
"type": "integer",
"title": "Limit",
"default": 20,
"maximum": 50,
"minimum": 1,
"description": "Wallets to return, 1-50. Keep it small."
},
"query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Query",
"default": null,
"description": "A KOL name, whale-list brand, or exact pasted address. Omit to browse."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"wallet_type": {
"enum": [
"all",
"kol",
"trader",
"whale"
],
"type": "string",
"title": "Wallet Type",
"default": "all"
}
}
}Execute a swap that `get_swap_quote` already priced. ⚠️ THIS SPENDS REAL MONEY. It submits a real transaction from the user's wallet using real funds and cannot be undone. Confirm the exact amount, token and network with the user in plain language, and get their explicit go-ahead, BEFORE calling this. Only ever pass a `quote_id` returned by `get_swap_quote` in this same conversation, after showing the user that quote's numbers and receiving an unambiguous yes. Never call this to 'check' anything. If it answers that the quote expired, get a fresh quote — never re-send the old quote_id. AMOUNTS: read the `_ui` fields (whole tokens) when talking to the user — the un-suffixed `output_amount` / `minimum_output_amount` / `filled_*_amount` are in the token's SMALLEST unit. A null amount is unknown, never zero: `fill_pending: true` means the trade was submitted but its fill is not booked yet — say so, and read the received amount from `get_swap_status` rather than guessing it.
| Argument | Type | Description |
|---|---|---|
| quote_id* | string | `quote_id` from a recent `get_swap_quote` response. |
{
"type": "object",
"title": "execute_swapArguments",
"required": [
"quote_id"
],
"properties": {
"quote_id": {
"type": "string",
"title": "Quote Id",
"description": "`quote_id` from a recent `get_swap_quote` response."
}
}
}Follow a PUBLIC whale/KOL/trader wallet, so its trades appear in `get_my_following_feed`. Idempotent — following an already-followed wallet is a no-op and does not count against the follow cap (`max_follows` on `get_my_followed_wallets`). Moves no money and needs no agentic wallet. Fails if the caller is already at the cap.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| custom_name | any | Optional nickname for this wallet, max 50 characters. |
| wallet_address* | string | Public wallet ref from a Find-wallets or WhaleWatch tool. |
{
"type": "object",
"title": "follow_walletArguments",
"required": [
"wallet_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"custom_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Custom Name",
"default": null,
"description": "Optional nickname for this wallet, max 50 characters."
},
"wallet_address": {
"type": "string",
"title": "Wallet Address",
"description": "Public wallet ref from a Find-wallets or WhaleWatch tool."
}
}
}The high-risk ('degen') leaderboard: newer, smaller, far more volatile tokens than `get_screener_leaderboard`. Tokens here can lose most of their value in minutes and many are short-lived. Say that plainly when you present them. Ranked best-first; page 1 is the top. Moby's leaderboards: Main = `get_screener_leaderboard` (composite 24h activity, 'what's moving'); Degen = `get_degen_leaderboard` (newer, smaller, higher risk); Majors = `get_group_leaderboard(group_id="home_majors")`; Stocks = `get_group_leaderboard(group_id="home_stocks")` (tokenized stocks); Pulse = `get_group_leaderboard(group_id="home_pulse")`. The Solana group ids `majors_solana` / `stocks_solana` work too, and the `home_*` ids are listed under `home_tabs` in `get_screener_groups`. The Majors and Stocks boards are THE reference for major and tokenized-stock contract addresses: take `token_address` from the row. Never resolve a major or a stock by ticker search alone, and never keep your own mint list. Results are capped. Raise `limit` or step `page` only if the answer is genuinely not in the first page — a large result costs context that later steps of the same task need. `whale_windows` (any of h1/h4/h8/h24) adds a per-row `whale` block per window: whale_count (distinct tracked wallets that bought OR sold — buyers plus sellers, not buyers alone), whale_buyers_count (distinct buyers only), whale_buys_count, whale_sells_count and whale_net_flow_usd. The row's `whale_count_h24` is the same buyers-plus-sellers count. Null figures mean unknown. `asset_class: tokenized_stock` marks tokenized equities (treat as stock proxies, not memecoins). `safety_tier`: green = verified; grey = usually fine (not scored yet or a young launchpad token, NOT a red flag — do not skip a coin for being grey); red = caution / DYOR, the only tier to treat as a warning (Moby refuses agent buys on red). This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| page | integer |
The ranked tokens inside one group/category. `group_id` must come from `get_screener_groups` — a group's `group_id`, or a `home_tabs` `tab_id` such as `home_majors` / `home_stocks` — do not invent or guess one. Ranked best-first; page 1 is the top. Moby's leaderboards: Main = `get_screener_leaderboard` (composite 24h activity, 'what's moving'); Degen = `get_degen_leaderboard` (newer, smaller, higher risk); Majors = `get_group_leaderboard(group_id="home_majors")`; Stocks = `get_group_leaderboard(group_id="home_stocks")` (tokenized stocks); Pulse = `get_group_leaderboard(group_id="home_pulse")`. The Solana group ids `majors_solana` / `stocks_solana` work too, and the `home_*` ids are listed under `home_tabs` in `get_screener_groups`. The Majors and Stocks boards are THE reference for major and tokenized-stock contract addresses: take `token_address` from the row. Never resolve a major or a stock by ticker search alone, and never keep your own mint list. Results are capped. Raise `limit` or step `page` only if the answer is genuinely not in the first page — a large result costs context that later steps of the same task need. `whale_windows` (any of h1/h4/h8/h24) adds a per-row `whale` block per window: whale_count (distinct tracked wallets that bought OR sold — buyers plus sellers, not buyers alone), whale_buyers_count (distinct buyers only), whale_buys_count, whale_sells_count and whale_net_flow_usd. The row's `whale_count_h24` is the same buyers-plus-sellers count. Null figures mean unknown. `asset_class: tokenized_stock` marks tokenized equities (treat as stock proxies, not memecoins). `safety_tier`: green = verified; grey = usually fine (not scored yet or a young launchpad token, NOT a red flag — do not skip a coin for being grey); red = caution / DYOR, the only tier to treat as a warning (Moby refuses agent buys on red). This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| page | integer |
Tracked KOLs — named public traders/influencers — holding this token. The KOL-only slice of `get_token_key_holders`. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| token_address* | string |
{
"type": "object",
"title": "get_kol_top_heldArguments",
"required": [
"token_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address"
}
}
}Tokens grouped by the launchpad they were created on (pump.fun and similar). Useful for 'what launched recently' questions. Newly launched tokens are the riskiest category on the platform. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string |
{
"type": "object",
"title": "get_launchpadsArguments",
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
}
}
}Screener events — discrete things that happened to tokens (price and volume moves, notable activity) over a period, newest first. This is the event stream behind the leaderboards, so use it when the user asks what CHANGED or what HAPPENED rather than what ranks highest right now. Poll for new events with `after_timestamp`; page back through history with `before_timestamp`. Each event carries flat `token_symbol`/`token_address`, `liquidity_usd` and h1/h4 smart-money flow (`smart_money_net_flow_usd`, `smart_money_buys_count`, `smart_money_sells_count`) — those are AS OF NOW (read time), while `market_cap_usd` and `price_usd` are AT THE TIME OF THE EVENT. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| page | integer | 1-based page number. |
| limit | integer | Events per page, 1-100. Keep it small. |
| period | any | Time window. `all` or omitted disables the filter. |
| network | string | |
| event_types | any | Restrict to these event types. Omit for all types. |
| token_address | any | Restrict to one token's events. Omit for the whole market. |
The strategies the user's agents are running, saved on Moby so every client and session sees them: `name`, `strategy_id` (the starter card, null = custom), `settings`, `schedule`, `status` (active / paused; pass `include_stopped=true` for stopped ones too), `started_at`, `last_run_at`. Call it at the start of every session to learn what is already running, and before starting a strategy, so two sessions never run the same one twice. Resume what is `active` on its `schedule`; leave `paused` ones alone unless the user asks. `app_links` are Moby app deep links to hand to the user; they open the Moby app on their phone. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
| Argument | Type | Description |
|---|---|---|
| include_stopped | boolean | True also returns stopped strategies. |
{
"type": "object",
"title": "get_my_active_strategiesArguments",
"properties": {
"include_stopped": {
"type": "boolean",
"title": "Include Stopped",
"default": false,
"description": "True also returns stopped strategies."
}
}
}The user's own wallet activity feed — their trades, transfers, deposits and withdrawals, newest first. ⚠️ This one is CURSOR-paginated, not page-numbered: read `cursor` out of the response and pass it back to get the next page. Do not send a page number. Choosing between the two history feeds: `get_my_activity` is the merged, human-readable timeline the app shows, cursor-paginated. `get_my_transactions` is the raw transaction list, page-numbered and filterable by transaction type. Prefer activity for 'what have I been doing'; use transactions when you need a specific type such as deposits. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Items per page. Keep it small. |
| cursor | any | Opaque cursor from the previous response. Omit for the first page. |
| network | string | |
| category | any | Restrict to one activity category. Omit (or `all`) for everything. ⚠️ `buys`, `sells` and `closed_trades` REQUIRE `token_address` — without one the call is rejected, deliberately: 'bought' means 'this token was received', and every swap receives something, so the question has no answer across a whole-wallet feed. |
| token_address | any | Restrict to activity involving one token. Omit for all. |
The user's CURRENT holdings in their Solana agent wallet, with balances and USD values. USDC is your cash (flagged `is_cash: true`). SOL and every other token are positions; sell with quick_sell to raise USDC. What each part contains: - `tokens` — EVERYTHING held in the wallet, and the authoritative answer to 'what do I own'. It INCLUDES the native coin (SOL, flagged `is_native: true`) and the USD funding asset (USDC, flagged `is_quote: true`) whenever their balance is above zero; every other row has both flags false. An empty `tokens` means the wallet really is empty. - `native_token` / `usd_token` — the same native-coin and funding-asset balances again, as fixed slots that are present even at zero. Use them for the affordability check; never add them to the `tokens` total, they are already in it. - Native SOL is read from the CHAIN at call time: `balance_source: "chain"`. If that read failed it is Moby's stored snapshot instead (`balance_source: "ledger"`) — say the SOL figure may be stale. `ledger_disagrees: true` only means the stored snapshot was wrong; the quantity shown is the chain's. - `swap_user_tokens` — the swap LEDGER: cost basis and PnL per position. Its quantities are NOT the amounts held; where it disagrees with `tokens`, `tokens` is right. HOW MUCH THE USER HOLDS comes from the CHAIN and is reported by `get_my_balances`, `get_my_token_balance` and `get_my_position` (`balance_source: "chain"`). WHAT IT COST — cost basis, average entry, realised PnL, trade history — comes from Moby's swap ledger, which only sees swaps Moby executed. Never quote a ledger quantity as the amount held: on live accounts it runs several times high AND several times low against the chain, and a sell sized from it fails on-chain. IMPORTANT: `get_my_closed_positions` returns ONLY positions the user has already exited. Positions the user still holds come from `get_my_balances`. Never tell a user they hold nothing based on `get_my_closed_positions` being empty. `asset_class: tokenized_stock` marks tokenized equities (treat as stock proxies, not memecoins). ⚠ ONE WALLET. For the agent's equity as a single total, call `get_my_portfolio` instead; this tool is the right one for the per-token detail and for the affordability check before a trade. Balances other than native SOL come from a cached snapshot that lags a deposit made outside Moby. If the user says they just funded the wallet and the balance does not show it, call this ONCE more with `refresh=true` before telling them anything is wrong — their money is on chain either way. Do not pass `refresh` routinely: it is much slower. USDC split (ENG-1803): `available_usdc` is the USDC spendable NOW — size buys from it. `reserved_usdc` is USDC already committed to the user's resting DCAs and limit / trigger buy orders; it comes back only by cancelling them (`cancel_order`). `reserved_breakdown` lists each one (`kind` dca|order, `schedule_id` / `order_id`, token, `reserved_usd`, `remaining_slices`, `next_order_at`); `in_wallet: true` means that USDC still sits in the wallet balance until the order pulls it, so do not spend it twice. This is NOT the daily-volume `daily_volume_reserved_usd` in `get_my_guardrails` — that is spend-cap accounting over a rolling 24h. All three are null when Moby could not read the orders: then check `get_my_orders` before spending. `app_links.deposit` is where the user adds funds; `app_links.settings` is their limits. `app_links` are Moby app deep links to hand to the user; they open the Moby app on their phone. `interview_due: true` (the first read each hour also carries `onboarding_hint`) means the user was never onboarded: go back to onboarding FIRST — `get_my_trading_profile`, the capabilities brief, the 6-question interview or skip — before you act on these numbers. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
🔴 CLOSED POSITIONS ONLY — positions the user has already fully exited, with their realised profit and loss. IMPORTANT: `get_my_closed_positions` returns ONLY positions the user has already exited. Positions the user still holds come from `get_my_balances`. Never tell a user they hold nothing based on `get_my_closed_positions` being empty. Use this for realised PnL questions. An empty result means the user has never closed a position, and says nothing at all about what they hold today. Choosing between the two history tools: `get_my_closed_positions` is the POSITION-level rollup — one entry per token the user entered and fully exited, with total realised PnL. `get_my_closed_trades` is the individual TRADES underneath, one entry per fill. Use positions for 'how did I do on X', trades for 'show me every trade'. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
| Argument | Type | Description |
|---|---|---|
| page | integer | 1-based page number. |
| limit | integer | Positions per page, 1-100. Keep it small. |
| network | string | |
| token_address | any | Restrict to closed positions in one token. Omit for all. |
{
"type": "object",
"title": "get_my_closed_positionsArguments",
"properties": {
"page": {
"type": "integer",
"title": "Page",
"default": 1,
"minimum": 1,
"description": "1-based page number."
},
"limit": {
"type": "integer",
"title": "Limit",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Positions per page, 1-100. Keep it small."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Token Address",
"default": null,
"description": "Restrict to closed positions in one token. Omit for all."
}
}
}The user's completed trades, newest first — one entry per closed buy→sell cycle, with what was bought or sold and the realised result. Each cycle carries `fills`: every buy/sell leg with timestamp, side, price_usd, token_amount, usd_amount and tx_hash (pass `include_fills=false` to skip them), plus the `rationale` you gave for it (null when none). Choosing between the two history tools: `get_my_closed_positions` is the POSITION-level rollup — one entry per token the user entered and fully exited, with total realised PnL. `get_my_closed_trades` is the individual TRADES underneath, one entry per fill. Use positions for 'how did I do on X', trades for 'show me every trade'. IMPORTANT: `get_my_closed_positions` returns ONLY positions the user has already exited. Positions the user still holds come from `get_my_balances`. Never tell a user they hold nothing based on `get_my_closed_positions` being empty. ⚠️ ONE TOKEN AT A TIME: `token_address` is REQUIRED. The backing service formats a per-token history and has no cross-token mode. For the user's whole trading history across tokens, call `get_my_closed_positions` instead. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
| Argument | Type | Description |
|---|---|---|
| page | integer | |
| limit | integer | |
| network | string | |
| include_fills | boolean | |
| token_address* | string |
The user's DCA schedules — recurring buys or sells that split an amount into slices over time — with progress so far (how many slices have filled and when the next one is due). The same rows `get_my_orders` returns as `dca_schedules`; use this one when you only need the DCAs. `get_my_orders` answers 'what do I have running' in ONE call: `orders` (limit, take-profit, stop-loss) plus `dca_schedules` (DCA schedules, one row per schedule; a DCA's individual slices never appear in `orders`). `get_my_dca_schedules` is the same DCA rows on their own. If `dca_schedules` is null, the DCA read failed (`dca_schedules_error`): call `get_my_dca_schedules` before telling the user they have no DCA running. By default only live schedules are returned; set `include_terminal` to also see finished and cancelled ones. To stop a whole DCA, pass its `schedule_id` to `cancel_order`. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| include_terminal | boolean | True also returns completed and cancelled schedules. Default: live only. |
{
"type": "object",
"title": "get_my_dca_schedulesArguments",
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"include_terminal": {
"type": "boolean",
"title": "Include Terminal",
"default": false,
"description": "True also returns completed and cancelled schedules. Default: live only."
}
}
}Your earlier submissions and their status; mention a shipped one to the user when relevant. Each has `id`, `kind`, `title`, `status` (new / reviewed / planned / shipped / wont_fix) and the team's `reply` when there is one, newest first. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
| Argument | Type | Description |
|---|---|---|
| limit | integer | How many to return (1-50). |
| status | any | Only submissions in this status. |
{
"type": "object",
"title": "get_my_feedbackArguments",
"properties": {
"limit": {
"type": "integer",
"title": "Limit",
"default": 20,
"maximum": 50,
"minimum": 1,
"description": "How many to return (1-50)."
},
"status": {
"anyOf": [
{
"enum": [
"new",
"reviewed",
"planned",
"shipped",
"wont_fix"
],
"type": "string"
},
{
"type": "null"
}
],
"title": "Status",
"default": null,
"description": "Only submissions in this status."
}
}
}Every wallet the CALLER follows, with `max_follows` so you can report 'N of 50' without a second call, each row's current list associations, and any nickname set with `follow_wallet`. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
No arguments.
{
"type": "object",
"title": "get_my_followed_walletsArguments",
"properties": {}
}Trades made by wallets the CALLER follows, newest first. ⚠️ EMPTY MEANS 'you follow nobody, or nobody you follow has traded recently' — NOT 'no whale activity anywhere'; for the market-wide feed use `get_whalewatch_feed`. Filters mirror that tool minus list selection, since following is orthogonal to lists. Results are capped. Raise `limit` or step `page` only if the answer is genuinely not in the first page — a large result costs context that later steps of the same task need. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
| Argument | Type | Description |
|---|---|---|
| page | integer | 1-based page number. |
| limit | integer | Trades per page, 1-100. Keep it small. |
| network | string | |
| token_address | any | Restrict to trades in one token. Omit for every token. |
| wallet_addresses | any | Restrict to specific FOLLOWED wallets. Omit for all followed wallets. |
| transaction_types | any | `buy` and/or `sell`. Omit for both. |
{
"type": "object",
"title": "get_my_following_feedArguments",
"properties": {
"page": {
"type": "integer",
"title": "Page",
"default": 1,
"minimum": 1,
"description": "1-based page number."
},
"limit": {
"type": "integer",
"title": "Limit",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Trades per page, 1-100. Keep it small."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Token Address",
"default": null,
"description": "Restrict to trades in one token. Omit for every token."
},
"wallet_addresses": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"title": "Wallet Addresses",
"default": null,
"description": "Restrict to specific FOLLOWED wallets. Omit for all followed wallets."
},
"transaction_types": {
"anyOf": [
{
"type": "array",
"items": {
"enum": [
"buy",
"sell"
],
"type": "string"
}
},
{
"type": "null"
}
],
"title": "Transaction Types",
"default": null,
"description": "`buy` and/or `sell`. Omit for both."
}
}
}The limits the user set on you in the Moby app, READ-ONLY — you cannot change them; only the user can, in the app. Read this before planning trades instead of discovering limits by refusal. - `maxTradeUsd` / `dailyVolumeUsd`: per-trade and rolling-24h trading-volume limits (null = uncapped). `maxTradeUsd` caps BUYS only — any sell passes it, whatever the size or output. Buys (and any other swap) count when placed or filled; sells into the USD stable (USDC) never count or get blocked — swaps and TP/SL/limit sell orders alike; cancelled buy orders give their reservation back. `dailyVolumeUsedUsd` = `dailyVolumeExecutedUsd` (traded) + `dailyVolumeReservedUsd` (unfilled buy orders still resting); the room left is `dailyVolumeUsd - dailyVolumeUsedUsd`. - `defaults_applied`: a list of limit names, e.g. `["maxTradeUsd", "dailyVolumeUsd"]`, that are Moby's defaults because the user has not saved their own (empty `[]` when every limit is the user's). Enforced all the same; call them Moby's default limits, never limits the user set. - `minCapUsd` / `maxCapUsd`: market-cap band for BUYS (null = no bound). - `orderTypes`: which kinds you may place (`market` covers swaps, `quick_buy` and `quick_sell`). Cancels are never blocked. - `paused`: true = every trade is refused until the user resumes you. - `platform_limits`: Moby's own trade-rate limits for this key. - `app_links.settings` is where the user changes these limits; `app_links.deposit` is where they add funds. `app_links` are Moby app deep links to hand to the user; they open the Moby app on their phone. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
No arguments.
{
"type": "object",
"title": "get_my_guardrailsArguments",
"properties": {}
}The user's single orders — limit orders, take-profit and stop-loss. By default only LIVE ones (not executed yet): use that before placing a new order (to avoid duplicates) and to find an `order_id` for `cancel_order`. For HISTORY — what filled, what was cancelled and why — pass `status="terminal"` (optionally with `since`/`until`). Filled rows carry `filled_price`, `fill_tx_hash` and `slippage_vs_trigger_pct` (signed, vs the trigger that fired); cancelled rows carry `cancelled_at` and `cancel_reason` (`sibling_filled` = Moby closed out this exit after the other one sold the position; `position_closed`, `user`, `expired`, `failed`, `unknown`). History is paged: `limit` (default 50, max 200) newest-first rows per `page`; step `page` only if the answer is not on the first one. Pass `token_address` to see only one token's orders (matches the token being sold or bought); without it every order on the wallet comes back. Reading a row: `input_*` is what the user SPENDS (the funding asset on a buy — USDC), `token_*` is the SUBJECT token the order is about, and every price is quoted against the subject token. Describe an order by `token_symbol`, never by `input_token_symbol`. ⚠️ If a row carries `data_warning`, it contradicts itself — report its state as unclear rather than choosing one of the readings. `origin: agent` is an order you placed; `origin: agent_auto_exit` is an older exit Moby attached before automatic exits were retired — it is still that position's exit while it rests. DCAs: `dca_schedules` lists the DCA schedules in the same call (live ones by default; finished ones too when `status` asks for history), filtered by `token_address` like the orders. Each row's `schedule_id` is what `cancel_order` takes to stop the whole DCA; report progress from `filled_order_count` / `order_count`. `get_my_orders` answers 'what do I have running' in ONE call: `orders` (limit, take-profit, stop-loss) plus `dca_schedules` (DCA schedules, one row per schedule; a DCA's individual slices never appear in `orders`). `get_my_dca_schedules` is the same DCA rows on their own. If `dca_schedules` is null, the DCA read failed (`dca_schedules_error`): call `get_my_dca_schedules` before telling the user they have no DCA running. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
| Argument |
|---|
EVERYTHING the user's agent holds, in one call — with a single combined total of the AGENT'S OWN wallets only: the user's Copy Trading wallet and manual wallets are NOT counted. `excluded_wallets` lists what was left out (shortened address, `owner_kind`, label) and `scope` is `agent_wallets`; do not add those back in — `hero_usd` is the agent's equity, the number to judge its performance and drawdown by. Start here for 'how am I doing', 'what do I own', 'what is my agent worth'. `summary.hero_usd` is the one number to quote; `summary.wallets` breaks it down per wallet; `holdings.items` is every position; `trading_balances.items` is the funding-asset balances. USDC is your cash; SOL and every other token are positions — sell with quick_sell to raise USDC. Do NOT add up `summary.wallets` yourself — `hero_usd` already is that sum, computed over the same rows. ⚠ NOT `get_my_balances`. That tool is ONE wallet's per-token detail; use it when you need to check affordability before a trade. `refresh=true` re-reads every wallet from the chain and is much slower — a vendor round trip PER WALLET. Send it only when the user explicitly asks for fresh numbers, or right after a deposit they made outside Moby that is not showing. Never routinely. `asset_class: tokenized_stock` marks tokenized equities (treat as stock proxies, not memecoins). `interview_due: true` (the first read each hour also carries `onboarding_hint`) means the user was never onboarded: go back to onboarding FIRST — `get_my_trading_profile`, the capabilities brief, the 6-question interview or skip — before you act on these numbers. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
| Argument | Type | Description |
|---|---|---|
| refresh | boolean |
{
"type": "object",
"title": "get_my_portfolioArguments",
"properties": {
"refresh": {
"type": "boolean",
"title": "Refresh",
"default": false
}
}
}The user's position in ONE token: how much they hold, what they paid, and their unrealised profit or loss. Use this for 'am I up on X'. Amounts are in token units and USD; profit figures are USD. HOW MUCH THE USER HOLDS comes from the CHAIN and is reported by `get_my_balances`, `get_my_token_balance` and `get_my_position` (`balance_source: "chain"`). WHAT IT COST — cost basis, average entry, realised PnL, trade history — comes from Moby's swap ledger, which only sees swaps Moby executed. Never quote a ledger quantity as the amount held: on live accounts it runs several times high AND several times low against the chain, and a sell sized from it fails on-chain. Reading the numbers — they are NOT all measured over the same quantity, and the response names which is which: - `balance_token_amount` / `balance_usd` — what the user holds ON CHAIN right now, and what all of it is worth. This is the answer to 'how much do I have'. - `cost_basis_usd` / `current_pnl_usd` / `current_pnl_pct` — UNREALISED, measured over `basis_known_token_amount` only: the part of the holding Moby has a cost for. If that is smaller than `balance_token_amount`, the rest arrived by transfer or airdrop and has no known basis — say so rather than implying the PnL covers everything. - `invested_usd` / `sold_usd` — LIFETIME totals ever spent and ever received, including tokens long since sold. A DIFFERENT denominator from `cost_basis_usd`, which covers only the tokens still held. `balance_usd + sold_usd - invested_usd` is net LIFETIME cash flow and will NOT equal `current_pnl_usd` — both are correct at their own scope, so never present one as a check on the other. - `realized_total_usd` — realised PnL to date, including partial sells on a position still open (`realized_open_cycle_usd`) as well as completed round trips (`realized_closed_cycles_usd`). `closed_trades_count` counts only the completed round trips, so it is legitimately 0 while realised PnL is non-zero. - `ledger_present: false` means Moby has NO swap history for this token (it arrived by transfer or airdrop), so EVERY money field above is unknown rather than zero, whatever number it carries, and `ledger_balance_token_amount` is null. A null profit field means UNKNOWN — no cost information — never zero and never break-even. `take_profit_orders_count` / `stop_loss_set` INCLUDE the TP/SL legs you placed with `create_order`; `get_my_orders` lists them. `closed_cycles` — the last 5 fully closed buy→sell cycles on this token, newest first (when, avg entry/exit, size, PnL); `closed_cycles_count` is the total. Tx hashes and per-fill legs: get_my_closed_trades(token_address). `rationale` is the thesis you gave on the open cycle's latest buy, null when none. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
'For you': the tracked wallets that overlap the CALLER's OWN holdings, in the same shape as `get_whalewatch_wallet_list_detail`. A caller holding nothing Moby tracks gets `total: 0, rows: []` — that is a real answer, not an error. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
| Argument | Type | Description |
|---|---|---|
| network | string |
{
"type": "object",
"title": "get_my_recommended_walletsArguments",
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
}
}
}How much of ONE token the user holds right now, and what it is worth. The cheapest way to answer 'do I have any X', and the tool to size a sell from before placing one. ⭐ `balance_token_amount` IS THE ANSWER. It is the on-chain balance and it always agrees with `get_my_balances`. HOW MUCH THE USER HOLDS comes from the CHAIN and is reported by `get_my_balances`, `get_my_token_balance` and `get_my_position` (`balance_source: "chain"`). WHAT IT COST — cost basis, average entry, realised PnL, trade history — comes from Moby's swap ledger, which only sees swaps Moby executed. Never quote a ledger quantity as the amount held: on live accounts it runs several times high AND several times low against the chain, and a sell sized from it fails on-chain. `ledger_balance_token_amount` and `cost_basis_usd` are the ledger's, included for cost context only. Check `ledger_present` BEFORE either: false means there is no ledger row at all and both are null/unknown — do NOT read `ledger_disagrees: false` as 'the sources agree', because it is also false when there is nothing to compare. When `ledger_present` is true and `ledger_disagrees` is true they are simply different numbers about different things — normal for any token that moved without a Moby swap, not an error, and not worth reporting to the user. Never average them, and never sell the larger one. A balance of 0 is a real answer: the user does not hold this token. Use `get_my_balances` when you need everything they hold, and `get_my_position` when you also need unrealised PnL. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| token_address* | string |
The user's saved trading profile: experience, assets, work mode, sizing and protection (v1 rows read as v2). 🔴 Call this BEFORE ANY OTHER TOOL on every connect — before balances, portfolio, strategies or research. - `interview_due: true` = onboard first: show `onboarding_brief` verbatim, then run the skippable 5-question interview in `interview_questions`, then its closing step (TWO-line playback, `save_trading_profile`, strategy offer). The scan schedule is kept on the agent's side, never saved to Moby: keep it in your own memory or as a recurring task in your own app, and recreate it at the start of each session. - `recommended_strategies`: the live starter-strategy ids matching the user's assets; offer one or two of them (names from `list_strategies`) in the closing step. - `status`: `missing` = never asked; `saved` = answers on file, use them; `skipped` = the user declined, do not ask again unless `interview_due` is true. - The profile is the user's INTENT. `get_my_guardrails` and the Moby app caps are the enforcement and the profile can never raise them. `guardrail_conflicts` lists where the user's wish exceeds a cap; tell them Moby enforces the cap. The wallet is never a parameter. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
No arguments.
{
"type": "object",
"title": "get_my_trading_profileArguments",
"properties": {}
}One transaction in full detail, by its id. Get the id from `get_my_transactions` first — this tool does not search or list. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
| Argument | Type | Description |
|---|---|---|
| transaction_id* | string | Transaction id from get_my_transactions. |
{
"type": "object",
"title": "get_my_transactionArguments",
"required": [
"transaction_id"
],
"properties": {
"transaction_id": {
"type": "string",
"title": "Transaction Id",
"description": "Transaction id from get_my_transactions."
}
}
}The user's raw wallet transaction list, newest first and page-numbered. Filter by `transaction_type` to answer questions about one kind of movement — deposits, withdrawals, swaps, transfers or trigger-order fills. Choosing between the two history feeds: `get_my_activity` is the merged, human-readable timeline the app shows, cursor-paginated. `get_my_transactions` is the raw transaction list, page-numbered and filterable by transaction type. Prefer activity for 'what have I been doing'; use transactions when you need a specific type such as deposits. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
| Argument | Type | Description |
|---|---|---|
| page | integer | 1-based page number. |
| limit | integer | Transactions per page, 1-100. Keep it small. |
| network | string | |
| token_address | any | Restrict to transactions involving one token. Omit for all. |
| transaction_type | any | Restrict to one movement type. Omit for every type. `trigger_order_placed` and `trigger_order_cancelled` are an order's LIFECYCLE rather than money moving — the description used to list only six of the eight and both of the missing ones appear in real rows. |
{
"type": "object",
"title": "get_my_transactionsArguments",
"properties": {
"page": {
"type": "integer",
"title": "Page",
"default": 1,
"minimum": 1,
"description": "1-based page number."
},
"limit": {
"type": "integer",
"title": "Limit",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Transactions per page, 1-100. Keep it small."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Token Address",
"default": null,
"description": "Restrict to transactions involving one token. Omit for all."
},
"transaction_type": {
"anyOf": [
{
"enum": [
"swap",
"deposit",
"withdrawal",
"transfer",
"bridge",
"trigger_order_fill",
"trigger_order_placed",
"trigger_order_cancelled"
],
"type": "string"
},
{
"type": "null"
}
],
"title": "Transaction Type",
"default": null,
"description": "Restrict to one movement type. Omit for every type. `trigger_order_placed` and `trigger_order_cancelled` are an order's LIFECYCLE rather than money moving — the description used to list only six of the eight and both of the missing ones appear in real rows."
}
}
}The user's AGENTIC wallets, with their addresses. AI Trading is Solana only for now: tell the user to deposit to the Solana one. 🔴 THE USER'S REGULAR APP WALLETS ARE NOT HERE — an agent's world is agentic wallets only, and every other `get_my_*` tool here reads from one of these, never from the user's primary wallet. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
No arguments.
{
"type": "object",
"title": "get_my_walletsArguments",
"properties": {}
}The tokens on one of the user's watchlists, each with market data in ONE call, so you can triage a list without a `get_token_overview` per token. Each row carries `price_usd`, `price_change_24hr` (24h %, there is no 1h figure here), `market_cap`, `liquidity_usd`, `whale_count`, `key_holder_count` and `token` (address, symbol, `safety_tier`). `safety_tier`: green = verified; grey = usually fine (not scored yet or a young launchpad token, NOT a red flag — do not skip a coin for being grey); red = caution / DYOR, the only tier to treat as a warning (Moby refuses agent buys on red). Omit `watchlist_id` for the user's default list on this network; otherwise pass an id from `get_my_watchlists` (an id that is not the user's is a 404). Use `get_token_overview` for the full picture of one token. Read-only. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| watchlist_id | any | Watchlist id from get_my_watchlists. Omit for the default list. |
{
"type": "object",
"title": "get_my_watchlist_tokensArguments",
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"watchlist_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Watchlist Id",
"default": null,
"description": "Watchlist id from get_my_watchlists. Omit for the default list."
}
}
}The user's watchlists on one network — names and ids only. Pass an id to `get_my_watchlist_tokens` to read a list's contents. Start here for 'what's on my watchlist' or 'anything on my watchlist moving?'. A watchlist is the tokens the user chose to follow, NOT what they hold (`get_my_balances`) and NOT other people's wallets. Read-only: adding or removing tokens is not available here. This returns the CURRENT USER's own data, resolved from their API key. There is no way to ask about someone else's wallet with this tool.
| Argument | Type | Description |
|---|---|---|
| network | string |
{
"type": "object",
"title": "get_my_watchlistsArguments",
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
}
}
}The VALID VALUES for `get_market_movers`' `event_types`, `period` and `market_cap_group` arguments, for one network. Call this BEFORE filtering `get_market_movers` — an invented filter string returns an empty list that reads as 'no events found' rather than 'you guessed a value that does not exist'. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string |
{
"type": "object",
"title": "get_screener_event_filtersArguments",
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
}
}
}List the token groups/categories Moby tracks (themes, sectors, narratives). Use this to discover a valid `group_id`, then pass that to `get_group_leaderboard` to see the tokens inside it. `home_tabs` lists the app's Home boards by `tab_id` (`home_majors`, `home_stocks`, `home_pulse`), also valid `group_id`s. Moby's leaderboards: Main = `get_screener_leaderboard` (composite 24h activity, 'what's moving'); Degen = `get_degen_leaderboard` (newer, smaller, higher risk); Majors = `get_group_leaderboard(group_id="home_majors")`; Stocks = `get_group_leaderboard(group_id="home_stocks")` (tokenized stocks); Pulse = `get_group_leaderboard(group_id="home_pulse")`. The Solana group ids `majors_solana` / `stocks_solana` work too, and the `home_*` ids are listed under `home_tabs` in `get_screener_groups`. The Majors and Stocks boards are THE reference for major and tokenized-stock contract addresses: take `token_address` from the row. Never resolve a major or a stock by ticker search alone, and never keep your own mint list. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string |
{
"type": "object",
"title": "get_screener_groupsArguments",
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
}
}
}The main Moby token leaderboard: the tokens with the most notable activity right now, ranked best-first by Moby's composite 24h score. Start here when the user asks what is moving, what is trending, or what they should be looking at, and they have not named a specific token. Page 1 is the top of the board — for 'what is hot right now' the default page is the whole answer. Moby's leaderboards: Main = `get_screener_leaderboard` (composite 24h activity, 'what's moving'); Degen = `get_degen_leaderboard` (newer, smaller, higher risk); Majors = `get_group_leaderboard(group_id="home_majors")`; Stocks = `get_group_leaderboard(group_id="home_stocks")` (tokenized stocks); Pulse = `get_group_leaderboard(group_id="home_pulse")`. The Solana group ids `majors_solana` / `stocks_solana` work too, and the `home_*` ids are listed under `home_tabs` in `get_screener_groups`. The Majors and Stocks boards are THE reference for major and tokenized-stock contract addresses: take `token_address` from the row. Never resolve a major or a stock by ticker search alone, and never keep your own mint list. Results are capped. Raise `limit` or step `page` only if the answer is genuinely not in the first page — a large result costs context that later steps of the same task need. `whale_windows` (any of h1/h4/h8/h24) adds a per-row `whale` block per window: whale_count (distinct tracked wallets that bought OR sold — buyers plus sellers, not buyers alone), whale_buyers_count (distinct buyers only), whale_buys_count, whale_sells_count and whale_net_flow_usd. The row's `whale_count_h24` is the same buyers-plus-sellers count. Null figures mean unknown. `asset_class: tokenized_stock` marks tokenized equities (treat as stock proxies, not memecoins). `safety_tier`: green = verified; grey = usually fine (not scored yet or a young launchpad token, NOT a red flag — do not skip a coin for being grey); red = caution / DYOR, the only tier to treat as a warning (Moby refuses agent buys on red). This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
The WHOLE MARKET's whale flow in one call: tracked whale/KOL/smart-money buys, sells and dumps for the last 1h, 4h and 24h (`h1`, `h4`, `h24`). Use it to tell 'whales are dumping everything' from 'this one coin is weak' before reading a single token, instead of paging `get_whalewatch_feed_window`. Each window has `totals`, `by_wallet_type` (whale / kol / smart_money; overlapping, a wallet on two kinds of list counts in both; smart_money is null when unknown), `fresh_launch` (`under_24h` / `under_1h`: trades in tokens launched that recently) and the top 5 tokens by net whale buying (`top_net_buy`) and selling (`top_net_sell`). Every slice has trades, tokens, buys, sells, buy/sell volume USD, net_flow_usd, distinct buyers and sellers, dump_sells (sold half or more of the position), dump_wallets and first_buys. One swap counts once; swaps under `min_trade_usd` are left out. Refreshed every ~2 minutes; `data_as_of` is when it was computed. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string |
{
"type": "object",
"title": "get_smart_money_pulseArguments",
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
}
}
}One starter strategy with its ready-to-run `prompt` — the same text the app copies. Run that prompt as the user's standing instructions for this session. Before starting: confirm the editable numbers (`chips`: amounts, exits, schedule) with the user, and check `get_my_active_strategies` so you never run one twice. Once the user says go, record it with `save_active_strategy` (pass `strategy_id`). `ask_before_every_trade=true` adds the 'ask me before every trade' line, on cards that support it (`ask_line_supported`). `app_links` are Moby app deep links to hand to the user; they open the Moby app on their phone.
| Argument | Type | Description |
|---|---|---|
| strategy_id* | string | A card `id` from list_strategies. |
| ask_before_every_trade | boolean | True adds the 'ask me before every trade' line to the prompt. |
{
"type": "object",
"title": "get_strategyArguments",
"required": [
"strategy_id"
],
"properties": {
"strategy_id": {
"type": "string",
"title": "Strategy Id",
"maxLength": 64,
"description": "A card `id` from list_strategies."
},
"ask_before_every_trade": {
"type": "boolean",
"title": "Ask Before Every Trade",
"default": false,
"description": "True adds the 'ask me before every trade' line to the prompt."
}
}
}Price a token swap before doing it: how much of `output_token` the user would receive for `amount` of `input_token`, plus price impact, fees, the slippage tolerance (`slippage_bps`) and the least the route can deliver (`minimum_output_amount_ui`). Quote `output_amount_ui` to the user — `output_amount` is in the token's smallest unit. `pricing_basis` states what produced it. This only prices the trade. It does not move funds and nothing is submitted on-chain. Returns a `quote_id` that `execute_swap` consumes. Quotes go stale in seconds — show the numbers to the user, get their answer, and if they hesitate, quote again rather than executing an old one. Always call this before `execute_swap` so the user sees what they are agreeing to. If `execute_swap` returns `pending` or `fill_pending`, only `get_swap_status` can tell you it completed.
| Argument | Type | Description |
|---|---|---|
| amount* | number | How much of `input_token` to spend, in whole token units (not the smallest unit). |
| network | string | |
| input_token* | string | Contract address of the token being SPENT. |
| output_token* | string | Contract address of the token being RECEIVED. |
{
"type": "object",
"title": "get_swap_quoteArguments",
"required": [
"input_token",
"output_token",
"amount"
],
"properties": {
"amount": {
"type": "number",
"title": "Amount",
"description": "How much of `input_token` to spend, in whole token units (not the smallest unit)."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"input_token": {
"type": "string",
"title": "Input Token",
"description": "Contract address of the token being SPENT."
},
"output_token": {
"type": "string",
"title": "Output Token",
"description": "Contract address of the token being RECEIVED."
}
}
}Check where a quote or swap stands, by `request_id` (the `quote_id`) OR `transaction_signature` — exactly one. Moves nothing and is safe to call again. `status` is one of: `not_executed` (quoted but never executed — nothing was traded; it can still be executed until `quote_expires_at`), `expired` (never executed and now too old — nothing was traded; get a fresh quote if the user still wants it), `pending` (submitted, waiting for confirmation), `confirmed`, `failed`. `executed_at` is when it was submitted (null = never). Once booked, `filled_input_amount_ui` / `filled_output_amount_ui` are what was actually spent and received and `effective_slippage_bps` how far the fill landed from the quote. A `failed` swap carries `failure_details` (`transaction_signature`, `stage`, `error_class`, `chain_error`, `provider`). `error_class` is always set for an on-chain revert: `slippage_exceeded` (requote), `insufficient_funds` / `insufficient_lamports` (the wallet could not cover the trade or SOL for fees/rent), `program_error` (a program refused it; its code is in `chain_error.code`), `unknown_revert`; `dropped_tx_blockhash_expired` means it never landed. `request_id` also accepts the Reference ID a failure message printed. A `confirmed` sell carries `resting_order_ids`: your orders still live on the token sold (empty once a full sell's exits are all cancelled). 🔴 CALL THIS WHENEVER `execute_swap` OR `quick_buy` RETURNED A `next_step`. A swap can return before its fill is confirmed. Until this tool says the swap succeeded, you do NOT know that it did: never tell the user their tokens have arrived based on the execute response alone, and never re-execute the quote to find out (that would trade twice). If it is still pending, say so and check again shortly.
| Argument | Type | Description |
|---|---|---|
| request_id | any | The `quote_id` of the swap you executed. Give this OR `transaction_signature`. |
| transaction_signature | any |
Price history for one token as a series of points, for describing or plotting a trend. `period` selects the window and defaults to `1d`. Prices are in USD. Choosing between the two price tools: `get_token_chart` returns a ready-to-read price line for describing a trend; `get_token_ohlcv` returns raw open/high/low/close/volume candles for calculation and technical analysis. Prefer the chart unless you need per-candle numbers. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| period | string | |
| network | string | |
| token_address* | string |
{
"type": "object",
"title": "get_token_chartArguments",
"required": [
"token_address"
],
"properties": {
"period": {
"type": "string",
"title": "Period",
"default": "1d"
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address"
}
}
}PUBLIC, on-chain DCA (dollar-cost-average) orders open against this token — who ELSE in the market is accumulating it on a schedule. ⚠️ NOT the user's own DCAs — those come from `get_my_dca_schedules`. The two are unrelated datasets that both use the word 'DCA'. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| size | integer | Max rows to scan, 1-500. |
| network | string | |
| order_by | string | |
| token_address* | string | |
| order_direction | string |
{
"type": "object",
"title": "get_token_dca_ordersArguments",
"required": [
"token_address"
],
"properties": {
"size": {
"type": "integer",
"title": "Size",
"default": 200,
"maximum": 500,
"minimum": 1,
"description": "Max rows to scan, 1-500."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"order_by": {
"enum": [
"usd_per_min",
"created",
"amount",
"percent_filled"
],
"type": "string",
"title": "Order By",
"default": "amount"
},
"token_address": {
"type": "string",
"title": "Token Address"
},
"order_direction": {
"enum": [
"asc",
"desc"
],
"type": "string",
"title": "Order Direction",
"default": "desc"
}
}
}ALL top holders of this token, paginated and ranked by size — not just the wallets Moby tracks. `get_token_key_holders` is the tracked-whale/KOL SUBSET of this same population; this is the full concentration picture. Results are capped. Raise `limit` or step `page` only if the answer is genuinely not in the first page — a large result costs context that later steps of the same task need. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| page | integer | 1-based page number. |
| limit | integer | Holders per page, 1-100. Keep it small. |
| network | string | |
| token_address* | string |
{
"type": "object",
"title": "get_token_holdersArguments",
"required": [
"token_address"
],
"properties": {
"page": {
"type": "integer",
"title": "Page",
"default": 1,
"minimum": 1,
"description": "1-based page number."
},
"limit": {
"type": "integer",
"title": "Limit",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "Holders per page, 1-100. Keep it small."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address"
}
}
}Aggregate holder-distribution summary for one token — the concentration picture in bucketed form. For the individually itemised top holders use `get_token_holders`; for just the tracked whales/KOLs use `get_token_key_holders`. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| token_address* | string |
{
"type": "object",
"title": "get_token_holdingsArguments",
"required": [
"token_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address"
}
}
}The most significant holders of this token and how concentrated ownership is. High concentration is a risk signal worth stating explicitly to the user. ⚠️ These are OTHER people's wallets — this is NOT the user's position in the token. For that, use `get_my_position`. `whale_count`/`trader_count`/`kol_count` (and the claim's `tag_count`, when `tag` is set) are always TRUE totals; `page`/`limit` are echoed back. Each row carries the wallet's 30-day `win_rate` and `realized_pnl_30d_usd`, and `days_since_prev_trade` / `prev_trade_at` for its latest trade in this token (how long the wallet was quiet before it, any token). Rows and counts only include positions worth at least `min_position_usd` (default $100; each row's `value_usd` lets you filter further). `position` is the wallet's tracked buys / sells of THIS token: `bought_usd`, `sold_usd`, `realized_pnl_usd`, `buys_count`, `sells_count`, `pct_of_peak_held` (0-1 of its largest tracked bag still held), `first_buy_at`, `entry_known`. Only trades Moby tracked: sells can exceed buys (transfers in, or buys before tracking). When `entry_known` is false, `realized_pnl_usd` and `pct_of_peak_held` are null (unknown, not 0); `position` is null when Moby never saw the wallet trade the token. KOL `platform` is never null: `unknown` plus `platform_reason` (`not_tagged` = no platform on record); `distinct_kol_platforms` counts the known platforms across `kols`, `unknown` excluded. Wallet quality: use get_whale_wallet_track_record(wallet_address) for a wallet's win rate and PnL. Results are capped. Raise `limit` or step `page` only if the answer is genuinely not in the first page — a large result costs context that later steps of the same task need. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| tag | any | Claim filter behind the expanded Smart Money read: one of the four exclusive tags (holding / bought / trimming / closed) or one of the read's own claims (never_sold / exited_24h / new_24h / left_7d / sat_still). Omit for everyone. |
Trade-by-trade feed of the TRACKED whale, KOL and trader wallets that traded one token, newest first. It is NOT the whole market: only wallets Moby tracks appear. Every tracked trade is listed, with no $ floor (the app's feed hides trades under $100). One row per swap: a wallet that is both a whale and a KOL appears once, with `identities`, `is_whale` and `is_kol` set. Rows exist from when Moby began tracking the token's traders (usually when it first trended); earlier trades are not in this feed. Pass `next_cursor` back as `cursor` for the next page until it is null. `wallet.win_rate` / `wallet.realized_pnl_30d_usd` are the wallet's 30-day quality. Each row's `days_since_prev_trade` / `prev_trade_at` say how long the wallet was quiet before the trade (any token; null = no earlier trade on record). Rows sort by `timestamp` (block time, whole seconds), then `sequence` (the order Moby ingested the trades): several trades by one wallet in the same second come back in the order their position-before values chain. Every row has `wallet_list_type` (`whale`, `trader` or `kol`). SELL rows carry `held_seconds` (since the wallet's first buy of the token) and `quick_flip: true` when it sold within 15 minutes — check for it before treating that wallet's buy as conviction; buy rows leave both null. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| page | integer | 1-based page number. Ignored when `cursor` is given. |
| limit | integer | Trades per page, 1-100. Keep it small. |
| cursor | any | `next_cursor` from the previous response. Wins over `page`; no gaps or duplicates. |
Raw OHLCV candles for one token — open, high, low, close and volume per interval — for calculation, technical analysis, or computing a return over a specific window. Prices are always USD (the response says so in `denomination`). Pick the candle size with `interval` (`1m`, `5m`, `15m`, `1h`, `4h`, `1d`); it wins over `timeframe` and `aggregate`. With none of the three the default is 15-minute candles; `timeframe` alone means 1 unit (`hour` = 1h). An unsupported size is rejected, never silently swapped, and the response echoes the `interval` and `candle_seconds` actually served. `t` is Unix MILLISECONDS. All three time arguments accept SECONDS or MILLISECONDS, so a `t` value from a previous response can be fed straight back. 🔴 READ BEFORE COMPUTING A RETURN — the `s/t/o/h/l/c/v` shape looks like TradingView's, and it differs from it in two ways that will silently corrupt the answer: - THE SERIES IS NEWEST-FIRST (descending `t`), not oldest-first. `c[0]` is the LATEST close and `c[-1]` is the OLDEST. A return over the window is `(c[0] - c[-1]) / c[-1]`; doing it the other way round returns the right magnitude with the WRONG SIGN. The response states this in `order`. - EVERY CANDLE RETURNED IS CLOSED. The current, still-forming interval is removed by default, because its close is a mid-bucket tick rather than a close and including it makes 'the return over the last N candles' wrong. Set `include_in_progress_candle` only if you specifically want the live, unfinished bucket — it will then be at index 0 and `includes_in_progress_candle` will be true. Choosing between the two price tools: `get_token_chart` returns a ready-to-read price line for describing a trend; `get_token_ohlcv` returns raw open/high/low/close/volume candles for calculation and technical analysis. Prefer the chart unless you need per-candle numbers. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| limit | integer | How many candles to return. |
Everything Moby knows about one token in a single call: price, market cap, liquidity, volume, holder counts, safety signals and metadata. This is the default tool for 'tell me about <token>'. Get `token_address` from `search_tokens`. `liquidity_source` says where `liquidity` sits: `bonding_curve` = a launchpad coin not yet migrated, `liquidity` is its curve reserve (0 = curve drained, everyone sold) and `graduation_pct` is % of the curve filled; `dex_pool` otherwise; null = unknown. `market_cap` is the circulating market cap (`market_cap_basis` is `circulating`), or the fully diluted value when Moby has no circulating figure (`fully_diluted`, flagged in `data_notes`). `fdv` is the fully diluted valuation (price x total supply). `ath_market_cap` (alias `ath_mc`) is the all-time-high on the same basis as `market_cap`; `ath_fdv` is the all-time-high FDV. Compare like with like: a coin is at its ATH only when `market_cap` ~= `ath_market_cap` or `fdv` ~= `ath_fdv`, never `market_cap` against `ath_fdv`. `asset_class: tokenized_stock` marks tokenized equities (treat as stock proxies, not memecoins). `safety_tier`: green = verified; grey = usually fine (not scored yet or a young launchpad token, NOT a red flag — do not skip a coin for being grey); red = caution / DYOR, the only tier to treat as a warning (Moby refuses agent buys on red). `safety_note` spells out the tier. `stats.untouched_pct` equals the `detail.tags` Untouched cell's `pct`: one window (`detail.window`, last 7 days or since launch) and one denominator (`detail.total`, current Key Holders plus wallets that sold out in the window). Each wallet gets one tag: Sold out > Trimmed (its Key Holders `story` chip is `trimming`, or it sold in the window without buying) > Added (bought in the window) > Untouched. `smart_money_read_v2` mixes two windows ON PURPOSE: `tier`/`label`/`verdict` grade the LAST HOUR of tracked-wallet flow (`tier` is green|yellow|red|holding, `label` is Buying|Holding|Selling|Mixed|Quiet); `color`/`text`/`sentences`/`bullets`/`stats` describe the 7-DAY holder base. They can disagree: green/Buying with red text means buying this hour into a base that churned all week — say both. Gate entries on `tier`, and read `text` for what the base did. `stats.left_*` is every tracked wallet that sold out (what the copy quotes); `stats.exited_*` is the entry-known subset the ratios use. `concentration` is the largest tracked holder (`supply_pct`, `bag_to_liquidity`, `multiple_on_entry`); `flagged` means one wallet carries the read or out-sizes the pool, and `tier_cap_reason: concentration` means the green hour was capped to yellow for it — treat the buying as one bag, not a crowd. `data_notes` lists the fields Moby lacks or knows only in part (`launchpad` unknown, a `market_cap` that may count one chain of a multichain coin, no `holders_count`, an unscored `safety_tier`, a risk scan that is not `ok`), each with what to verify on the web. When Moby lacks a data point (a null field, or one listed in `data_notes`), check the web (the project's site, docs or API, DexScreener, X) before quoting it, and never present a Moby-only number as the whole picture. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
The current USD price of one token, and nothing else. Cheapest call for a price check; use `get_token_overview` if you also need market cap, liquidity or volume. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| token_address* | string |
{
"type": "object",
"title": "get_token_priceArguments",
"required": [
"token_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address"
}
}
}Holder-concentration and contract risk for one token: sniper, insider, bundler and fresh-wallet shares, dev hold, mint/freeze authority, honeypot and buy/sell tax. Same fields and rules as the Moby app's Risk Signals block. `status` is `ok` / `pending` / `unavailable` / `unsupported`: `pending` means retry in a few seconds; `unavailable` and `unsupported` mean no data (do not hammer). Nulls mean no data, not zero (all-zero holder cohorts are reported as no data). Early buyers stay `unavailable`. `fetched_at` tells how fresh the read is. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| token_address* | string |
{
"type": "object",
"title": "get_token_risk_signalsArguments",
"required": [
"token_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address"
}
}
}Which tracked high-performing wallets (whales, KOLs, proven traders) are positioned in this token, and on which side. This is Moby's core edge signal — it answers 'is anyone good in this?'. These are OTHER people's wallets, never the user's. Each window (`h1`, `h4`, `h24`) carries `last_buy_at` / `last_sell_at` (newest buy / sell in that window) and the response `data_as_of` (when the windows were rolled up; each ends there). A net that flips with no newer `last_sell_at` means older buys aged out, not new selling. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| token_address* | string |
{
"type": "object",
"title": "get_token_smart_moneyArguments",
"required": [
"token_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address"
}
}
}START HERE for pre-buy research on one token: a compact brief (a few KB) in one call instead of 5-10. Sections: `about` (description, socials, age, launchpad; `liquidity_source`, and `graduation_pct` while on a bonding curve), `safety` (`safety_tier` + `safety_note`), `smart_money_flow` (h1/h4/h24 net $, buy vs sell counts, `last_buy_at` / `last_sell_at`, `data_as_of`), `smart_money_read` (`tier` graded over `tier_window` = 1h, headline, bullets, `concentration`, `tier_cap_reason`), `risk_signals` (snipers / insiders / bundlers / dev hold / authorities, `status`), `key_holders` (top 10 positions >= $100: size, entry MC, `last_tx`, per-coin `position`, 30-day `win_rate` / `realized_pnl_30d_usd`), `recent_quality_trades` (newest 10 tracked trades among the last 100 by wallets with win_rate >= 0.5 AND 30-day realized P/L > 0; `wallet_list_type`, `quick_flip`, `days_since_prev_trade`) and `market` (market cap, `fdv`, `ath_market_cap`, `ath_fdv`, liquidity, 24h volume, `pct_from_ath` on the `market_cap_basis` pair). Each section carries its own `computed_at` / `data_as_of`. A failed section is null with its reason in `errors`; the rest are still valid. Cached 15 s. Go deeper with `get_token_key_holders` (paging, claim tags), `get_token_live_feed` (every trade), `get_whale_wallet_profiles` (rate holders), `get_token_risk_signals` (re-poll a `pending` scan), `get_token_ohlcv` (price action) and `get_token_overview` (the full read). `safety_tier`: green = verified; grey = usually fine (not scored yet or a young launchpad token, NOT a red flag — do not skip a coin for being grey); red = caution / DYOR, the only tier to treat as a warning (Moby refuses agent buys on red). `data_notes` lists the fields Moby lacks or knows only in part (`launchpad` unknown, a `market_cap` that may count one chain of a multichain coin, no `holders_count`, an unscored `safety_tier`, a risk scan that is not `ok`), each with what to verify on the web. When Moby lacks a data point (a null field, or one listed in `data_notes`), check the web (the project's site, docs or API, DexScreener, X) before quoting it, and never present a Moby-only number as the whole picture. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument |
|---|
Tracked WHALES holding this token, GROUPED BY WHALE LIST. `get_token_key_holders` returns the same population UNGROUPED (whales and KOLs together); use this when the question is 'which KIND of whale is in this'. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| token_address* | string |
{
"type": "object",
"title": "get_token_whale_holdersArguments",
"required": [
"token_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address"
}
}
}The project's X/Twitter account: follower count, age, verification — 'is this project's social presence real or a two-day-old burner'. ⚠️ CALL SPARINGLY: X charges paid credits per lookup. Not for routine enrichment of every token in a list. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| token_address* | string |
{
"type": "object",
"title": "get_token_x_profileArguments",
"required": [
"token_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address"
}
}
}TOKENS ranked by aggregate USD held, either by tracked WHALES or by Moby USERS — never a person-vs-person ranking. Use `holder_type=whale` (default) for 'what are whales piling into'; `holder_type=user` for 'what do Moby users collectively hold most of'. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| holder_type | string |
{
"type": "object",
"title": "get_top_heldArguments",
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"holder_type": {
"enum": [
"whale",
"user"
],
"type": "string",
"title": "Holder Type",
"default": "whale"
}
}
}What one TRACKED WHALE wallet currently holds. ⚠️ This is somebody else's portfolio, taken from Moby's public whale-tracking data. It is NOT the user's portfolio under any circumstances — for that, call `get_my_balances`. Take `wallet_address` from a WhaleWatch feed result; addresses may be returned as stable opaque references rather than raw addresses, and those references work here. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| wallet_address* | string |
{
"type": "object",
"title": "get_whale_wallet_holdingsArguments",
"required": [
"wallet_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"wallet_address": {
"type": "string",
"title": "Wallet Address"
}
}
}A TRACKED WHALE's cumulative realized PnL over time — is the track record a steady climb or one lucky trade? ⚠️ Somebody else's equity curve, never the user's. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| period | string | |
| network | string | |
| wallet_address* | string | Tracked trader wallet, from a WhaleWatch feed. Opaque references work too. |
{
"type": "object",
"title": "get_whale_wallet_pnl_chartArguments",
"required": [
"wallet_address"
],
"properties": {
"period": {
"enum": [
"1d",
"7d",
"30d",
"1y"
],
"type": "string",
"title": "Period",
"default": "30d"
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"wallet_address": {
"type": "string",
"title": "Wallet Address",
"description": "Tracked trader wallet, from a WhaleWatch feed. Opaque references work too."
}
}
}A TRACKED WHALE's current holdings WITH cost basis and unrealized PnL per position. Richer than `get_whale_wallet_holdings`, which is amount + USD value only. ⚠️ Somebody else's positions, never the user's — for the user's own, use `get_my_balances` or `get_my_position`. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| wallet_address* | string | Tracked trader wallet, from a WhaleWatch feed. Opaque references work too. |
{
"type": "object",
"title": "get_whale_wallet_positionsArguments",
"required": [
"wallet_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"wallet_address": {
"type": "string",
"title": "Wallet Address",
"description": "Tracked trader wallet, from a WhaleWatch feed. Opaque references work too."
}
}
}THE RICHEST WHALE READ ON THIS SURFACE: one call combining identity, realized track record, current holdings, recent trades, and whether Moby has stopped tracking this wallet (`identity.tracking_paused_at`). Prefer this over calling `get_whale_wallet_track_record` + `get_whale_wallet_positions` separately. `windows.d7` and `windows.d30` give realized P/L, closes, win rate, avg/median hold days and the share of closes held under 24h for each window. No colour: use `read.situation` + the window stats. `include_holdings=false` returns stats only (holdings and read null) — much smaller; to rate many wallets use `get_whale_wallet_profiles`. `data_as_of` is when this was computed; a wallet Moby has SEEN but knows nothing about yet comes back with null sections rather than an error. ⚠️ Somebody else's profile, never the user's — for the user's own wallet use `get_my_*` tools. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| wallet_address* | string | Tracked trader wallet, from a WhaleWatch feed. Opaque references work too. |
| include_holdings | boolean | false = stats only, no holdings (smaller, faster). Default true. |
{
"type": "object",
"title": "get_whale_wallet_profileArguments",
"required": [
"wallet_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"wallet_address": {
"type": "string",
"title": "Wallet Address",
"description": "Tracked trader wallet, from a WhaleWatch feed. Opaque references work too."
},
"include_holdings": {
"type": "boolean",
"title": "Include Holdings",
"default": true,
"description": "false = stats only, no holdings (smaller, faster). Default true."
}
}
}Rate 10-20 key holders before a buy in one call; stats only, no holdings. Pass the `wallet_address` refs from `get_token_key_holders` (max 20). Each profile carries `windows.d7` / `windows.d30` (realized P/L, closes, win rate, median hold, short-hold share), `track_record`, `realized` and `identity`. A wallet Moby has never seen is left out — match rows on `wallet_ref`. For one wallet's holdings use `get_whale_wallet_profile`. ⚠️ Other people's wallets, never the user's. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| wallet_addresses* | array | 1-20 tracked wallet refs, e.g. from get_token_key_holders. |
{
"type": "object",
"title": "get_whale_wallet_profilesArguments",
"required": [
"wallet_addresses"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"wallet_addresses": {
"type": "array",
"items": {
"type": "string"
},
"title": "Wallet Addresses",
"maxItems": 20,
"minItems": 1,
"description": "1-20 tracked wallet refs, e.g. from get_token_key_holders."
}
}
}The full track record behind a TRACKED WHALE: win rate, realized PnL, trade count, typical hold time, and whether Moby has finished indexing it (`backfill_state`). Judge whether a wallet seen in a WhaleWatch feed is actually good before weighting its activity. For everything in one call — including current holdings and the caller's own follow state — use `get_whale_wallet_profile` instead. ⚠️ Somebody else's track record, never the user's. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| wallet_address* | string | Tracked trader wallet, from a WhaleWatch feed. Opaque references work too. |
{
"type": "object",
"title": "get_whale_wallet_track_recordArguments",
"required": [
"wallet_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"wallet_address": {
"type": "string",
"title": "Wallet Address",
"description": "Tracked trader wallet, from a WhaleWatch feed. Opaque references work too."
}
}
}The biggest realised wins of one TRACKED WHALE wallet — its top closed trades by profit, at most five. Use it to judge whether a wallet seen in a WhaleWatch feed is actually good before weighting its activity. ⚠️ Somebody else's track record, not the user's — the user's own realised results come from `get_my_closed_positions`. An empty list means no wins data was available, not that the wallet has never won. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| wallet_address* | string | Tracked trader wallet, from a WhaleWatch feed. Opaque references work here too. |
{
"type": "object",
"title": "get_whale_wallet_winsArguments",
"required": [
"wallet_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"wallet_address": {
"type": "string",
"title": "Wallet Address",
"description": "Tracked trader wallet, from a WhaleWatch feed. Opaque references work here too."
}
}
}Moby's WhaleWatch feed: buys and sells by tracked whale wallets across the market, newest first. Filter to one token with `token_address`, to one tracked wallet with `wallet_address`, or to specific whale lists with `list_ids` (from `get_whalewatch_lists`). ⚠️ `wallet_address` here filters TRACKED WHALE wallets — it is not the user's wallet and cannot be used to look up the user's own trades. Use `get_my_activity` for those. For a bulk read of a whole time window, use `get_whalewatch_feed_window`. Rows sort by `timestamp` (block time, whole seconds), then `sequence` (the order Moby ingested the trades): several trades by one wallet in the same second come back in the order their position-before values chain. Every row has `wallet_list_type` (`whale`, `trader` or `kol`). SELL rows carry `held_seconds` (since the wallet's first buy of the token) and `quick_flip: true` when it sold within 15 minutes — check for it before treating that wallet's buy as conviction; buy rows leave both null. `include_context=true` adds a per-row `context` block: pnl_pct_vs_entry (the trade price vs the wallet's own average entry, as a fraction), tags (what the trade looked like, e.g. profit taking), hold_days_at_trade, share_sold_of_position, position_before_usd, entry_vwap_before, days_since_prev_trade + prev_trade_at (how long the WALLET was quiet before this trade, any token) and wallet_win_rate + wallet_realized_pnl_30d_usd (the wallet's 30-day quality). Unknown values are null — pnl_pct_vs_entry is null whenever the wallet's entry was never seen, days_since_prev_trade when Moby has no earlier trade for the wallet. Wallet quality: use get_whale_wallet_track_record(wallet_address) for a wallet's win rate and PnL. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| page | integer | 1-based page number. |
| limit |
Every tracked-whale buy and sell inside one time window (at most 48 hours), for bulk reads such as 'everything whales did in the last 6 hours'. Unlike `get_whalewatch_feed`, it returns ONE ROW PER SWAP (the plain feed repeats a swap once per whale list the wallet is on; `list_id` here is one of the matching lists), and pages with a cursor: pass `next_cursor` from the previous response as `cursor` until it is null. Rows are newest first and new trades never shift a page. Filter by side, minimum trade size, minimum market cap, trade `actions`, whale `list_ids` and `min_days_since_prev_trade` (wallets waking up after a quiet spell). A window longer than 48h is rejected. Rows sort by `timestamp` (block time, whole seconds), then `sequence` (the order Moby ingested the trades): several trades by one wallet in the same second come back in the order their position-before values chain. Every row has `wallet_list_type` (`whale`, `trader` or `kol`). SELL rows carry `held_seconds` (since the wallet's first buy of the token) and `quick_flip: true` when it sold within 15 minutes — check for it before treating that wallet's buy as conviction; buy rows leave both null. `include_context=true` adds a per-row `context` block: pnl_pct_vs_entry (the trade price vs the wallet's own average entry, as a fraction), tags (what the trade looked like, e.g. profit taking), hold_days_at_trade, share_sold_of_position, position_before_usd, entry_vwap_before, days_since_prev_trade + prev_trade_at (how long the WALLET was quiet before this trade, any token) and wallet_win_rate + wallet_realized_pnl_30d_usd (the wallet's 30-day quality). Unknown values are null — pnl_pct_vs_entry is null whenever the wallet's entry was never seen, days_since_prev_trade when Moby has no earlier trade for the wallet. Wallet quality: use get_whale_wallet_track_record(wallet_address) for a wallet's win rate and PnL. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| limit |
The short, curated WhaleWatch feed the Moby app shows on its home screen — the most notable recent whale trades across the whole market, already filtered down. Use it for an open-ended 'what are whales doing right now'. For anything filtered — one token, one wallet, specific lists, a time window, or more than a handful of rows — use `get_whalewatch_feed` instead. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| limit | integer | How many highlighted trades to return. |
| network | string |
{
"type": "object",
"title": "get_whalewatch_home_feedArguments",
"properties": {
"limit": {
"type": "integer",
"title": "Limit",
"default": 20,
"description": "How many highlighted trades to return."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
}
}
}Same feed as `get_whalewatch_feed` but pre-filtered to KOLs — public, named crypto influencers — rather than anonymous whales. The list filter is applied server-side, so there is no `list_ids` argument. Use this when the user asks what influencers or 'the callers' are buying. For one KOL's trades, use `get_whalewatch_feed` with its `wallet_address`. `include_context=true` adds a per-row `context` block: pnl_pct_vs_entry (the trade price vs the wallet's own average entry, as a fraction), tags (what the trade looked like, e.g. profit taking), hold_days_at_trade, share_sold_of_position, position_before_usd, entry_vwap_before, days_since_prev_trade + prev_trade_at (how long the WALLET was quiet before this trade, any token) and wallet_win_rate + wallet_realized_pnl_30d_usd (the wallet's 30-day quality). Unknown values are null — pnl_pct_vs_entry is null whenever the wallet's entry was never seen, days_since_prev_trade when Moby has no earlier trade for the wallet. Wallet quality: use get_whale_wallet_track_record(wallet_address) for a wallet's win rate and PnL. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| page | integer | 1-based page number. |
| limit | integer | Trades per page, 1-100. Keep it small. |
| network | string | |
| token_address | any | Restrict to KOL trades in this one token. |
| after_timestamp |
The key explaining the icons and badges attached to rows in the WhaleWatch feeds. Static reference data — call it once if you need to explain what a marker on a feed row means, and do not poll it. It contains no market data and no wallets. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
No arguments.
{
"type": "object",
"title": "get_whalewatch_legendArguments",
"properties": {}
}The tracked-wallet lists Moby maintains (whale groups, KOL groups, proven-trader cohorts). Call this to discover valid `list_ids` for `get_whalewatch_feed`. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string |
{
"type": "object",
"title": "get_whalewatch_listsArguments",
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
}
}
}One curated wallet list's rows, pre-ranked. `slug` MUST come from `get_whalewatch_wallet_lists` — an invented or stale slug is a 404, not an empty list. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| slug* | string | List slug from get_whalewatch_wallet_lists. |
| network | string |
{
"type": "object",
"title": "get_whalewatch_wallet_list_detailArguments",
"required": [
"slug"
],
"properties": {
"slug": {
"type": "string",
"title": "Slug",
"description": "List slug from get_whalewatch_wallet_lists."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
}
}
}The Find-wallets tab shell: a manual 'picks' strip, then one summary per curated wallet list that has rows on this chain (whale groups, KOL groups, proven-trader cohorts). Call this first to learn the valid `slug` values for `get_whalewatch_wallet_list_detail`. NOT the same lists as `get_whalewatch_lists` — that one is for filtering `get_whalewatch_feed`; this one is for browsing wallets to follow. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| network | string |
{
"type": "object",
"title": "get_whalewatch_wallet_listsArguments",
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
}
}
}The starter strategies from the Strategies section of AI Trading in the Moby app: each card's `id`, `name`, `summary`, `how_it_works`, `chips` (the editable defaults), `risk_label`, `warning` and the Moby `tools` it uses, with the user's max per trade already filled in. Use it during or after onboarding to recommend a card, and whenever the user asks what strategies there are. To match a card to the user, offer the one or two ids in `recommended_strategies` from `get_my_trading_profile` / `save_trading_profile` (majors or stocks → Large Cap Allocator, BTC <> ZEC Barbell; launches or memes → StonkFun Trend Rider, StonkFun Whale Swarm, Early Launch Hunter; mix → Smart Money Confirmed). Read each card's `summary`, `how_it_works` and `risk_label` before you recommend it, and only recommend cards this tool returned. The full prompt is NOT here: call `get_strategy(strategy_id)` for it. `app_links` are Moby app deep links to hand to the user; they open the Moby app on their phone.
No arguments.
{
"type": "object",
"title": "list_strategiesArguments",
"properties": {}
}Buy a token in one step, without a separate quote. ⚠️ THIS SPENDS REAL MONEY. It submits a real transaction from the user's wallet using real funds and cannot be undone. Confirm the exact amount, token and network with the user in plain language, and get their explicit go-ahead, BEFORE calling this. Because there is no quote step, the user does not get to see a price before committing — so confirm the token AND the amount in words first, and prefer `get_swap_quote` + `execute_swap` whenever the user might want to see the price. Give exactly one of `amount_usd` or `amount_in`, never both. Verify the contract address came from `search_tokens`; buying an impostor token is unrecoverable. Response includes `quote_id`; when `fill_pending` is true, call `get_swap_status(request_id=quote_id)`. AMOUNTS: read the `_ui` fields (whole tokens) when talking to the user — the un-suffixed `output_amount` / `minimum_output_amount` / `filled_*_amount` are in the token's SMALLEST unit. A null amount is unknown, never zero: `fill_pending: true` means the trade was submitted but its fill is not booked yet — say so, and read the received amount from `get_swap_status` rather than guessing it. Moby attaches no exits: place this position's TP/SL yourself with `create_order`.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| amount_in | any | How much to spend in whole units of USDC, the only funding asset — SOL is a position, never spent by a buy. Mutually exclusive with `amount_usd`. |
| rationale | any | Optional. Your 2–4 line thesis: why this coin, why now, who's in it, what breaks it. Stored with the trade and shown to the user; ≤500 chars. |
| amount_usd |
Sell a token the user holds, in ONE step, at market — quote and execute happen together on the server, so it never fails on an expired quote while you wait for the user. This is THE tool to close or trim a position. ⚠️ THIS SPENDS REAL MONEY. It submits a real transaction from the user's wallet using real funds and cannot be undone. Confirm the exact amount, token and network with the user in plain language, and get their explicit go-ahead, BEFORE calling this. Confirm the token and how much (`pct` of the position, default 100 = sell it all) in words first. Sizing: `pct` is a percent of the CURRENT on-chain balance (the `get_my_token_balance` number); omit it to sell everything. Proceeds land in USDC in the same agent wallet — `output_token` names it. Response: `sold_amount` (token units submitted), `pct`, `status`, `transaction_signature`, the expected proceeds (`quoted_output_amount_ui`, at least `minimum_output_amount_ui`), `slippage_bps`, and the received amount (`filled_output_amount_ui`) once booked. Response includes `quote_id`; when `fill_pending` is true, call `get_swap_status(request_id=quote_id)`. AMOUNTS: read the `_ui` fields (whole tokens) when talking to the user — the un-suffixed `output_amount` / `minimum_output_amount` / `filled_*_amount` are in the token's SMALLEST unit. A null amount is unknown, never zero: `fill_pending: true` means the trade was submitted but its fill is not booked yet — say so, and read the received amount from `get_swap_status` rather than guessing it. Selling the whole position also cancels EVERY resting TP/SL order on that token (all lots) in the same call: `cancelled_order_ids` lists them, `cancel_failed_order_ids` / `cancel_pending_order_ids` (+ `cancel_note`) any not cancelled yet, which Moby keeps retrying. A partial sell leaves them (those fields are null). A sell is never blocked by market cap, safety rating or the trade limits (and does not use up the daily volume), but the `market` order-type switch applies (a refusal comes back as `{blocked: true, reason, ...}`).
| Argument | Type | Description |
|---|---|---|
| pct | number | Percent of the current balance to sell, 1-100. Default 100 = close it. |
Record what you run, so other sessions and clients see it. - START: omit `active_strategy_id`; pass `strategy_id` for a starter card (its name is used if you omit `name`) or `name` for a custom one, plus `settings` (the numbers the user confirmed: amounts, mix, exits, the ask-first flag) and `schedule` in plain words ('every 4 hours'). - PAUSE / RESUME / STOP: pass `active_strategy_id` and `status` paused / active / stopped. - EDIT: pass `active_strategy_id` and only the fields that changed (an empty value clears `settings`, `schedule` or `notes`). - HEARTBEAT: after each run, pass `active_strategy_id` and `last_run_at` (now, ISO 8601). At most 20 active or paused per user; stop one to start another. This moves no money and changes no guardrail.
| Argument | Type | Description |
|---|---|---|
| name | any | Display name (max 120 chars). |
| notes | any | Anything to remember (max 1000 chars). |
| status | any | active, paused or stopped. |
| schedule | any | How often it runs, in plain words (max 120 chars). |
| settings | any | The confirmed numbers as a small JSON object (max 8 KB); `{}` clears it. |
| last_run_at | any | ISO 8601 time of the run just finished, e.g. `2026-10-29T14:00:00Z`. |
| strategy_id | any | The starter card `id` from list_strategies; omit for a custom strategy. |
Save the user's interview answers, or record that they skipped. Call it after you played the answers back in TWO lines and the user said yes; or with `skipped: true` when they decline. Pass `profile` OR `skipped`, not both. - `replace: false` (default) MERGES into what is saved, so for 'update my trading profile' send only the changed fields. `replace: true` overwrites the whole profile. - Amounts are USD. If the user spoke in SOL, convert at the current price and say both. - After the save, the closing step: offer one or two cards from the result's `recommended_strategies`. `strategies_followup`, when present, is that step as an instruction to you: follow it once, do not read it out. - The scan schedule has no field here. The scan schedule is kept on the agent's side, never saved to Moby: keep it in your own memory or as a recurring task in your own app, and recreate it at the start of each session. This changes NO guardrail and moves no money; the guardrails still decide what you may trade.
| Argument | Type | Description |
|---|---|---|
| profile | any | |
| replace | boolean | False merges into the saved answers; true overwrites them. |
| skipped | boolean | True when the user declined the interview. |
{
"type": "object",
"$defs": {
"ExitsInput": {
"type": "object",
"title": "ExitsInput",
"properties": {
"stop_loss_pct": {
"anyOf": [
{
"type": "number",
"maximum": 100,
"exclusiveMinimum": 0
},
{
"type": "null"
}
],
"title": "Stop Loss Pct",
"default": null,
"description": "Question 4: default stop-loss as the DROP from entry, positive. 30 means -30%. Prefill 30."
},
"take_profit_pct": {
"anyOf": [
{
"type": "number",
"exclusiveMinimum": 0
},
{
"type": "null"
}
],
"title": "Take Profit Pct",
"default": null,
"description": "Question 4: default take-profit as the GAIN from entry, positive. 100 means +100%."
}
},
"additionalProperties": false
},
"SizingInput": {
"type": "object",
"title": "SizingInput",
"properties": {
"per_trade_usd": {
"anyOf": [
{
"type": "number",
"exclusiveMinimum": 0
},
{
"type": "null"
}
],
"title": "Per Trade Usd",
"default": null,
"description": "Question 4: roughly how much per trade, in USD. If the user answered in SOL, convert at the current SOL price from get_token_price and say both when you play it back."
},
"adds_on_winners": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Adds On Winners",
"default": null,
"description": "Question 2: does the user want to double down on winners?"
},
"max_deployed_usd": {
"anyOf": [
{
"type": "number",
"exclusiveMinimum": 0
},
{
"type": "null"
}
],
"title": "Max Deployed Usd",
"default": null,
"description": "Question 4: how much the user wants to put to work in total, in USD."
},
"max_adds_per_coin": {
"anyOf": [
{
"type": "integer",
"minimum": 0
},
{
"type": "null"
}
],
"title": "Max Adds Per Coin",
"default": null,
"description": "Question 2: the most adds on one coin. 0 = never add."
},
"max_trades_per_day": {
"anyOf": [
{
"type": "integer",
"minimum": 0
},
{
"type": "null"
}
],
"title": "Max Trades Per Day",
"default": null,
"description": "Question 2: the most trades per day."
}
},
"additionalProperties": false
},
"HardNosInput": {
"type": "object",
"title": "HardNosInput",
"properties": {
"notes": {
"anyOf": [
{
"type": "string",
"maxLength": 500
},
{
"type": "null"
}
],
"title": "Notes",
"default": null,
"description": "Question 5: any other hard no, in the user's words."
},
"avoid_launchpads": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string",
"maxLength": 50
},
"maxItems": 20
},
{
"type": "null"
}
],
"title": "Avoid Launchpads",
"default": null,
"description": "Question 5: launchpad names to avoid (see get_launchpads)."
},
"green_safety_only": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Green Safety Only",
"default": null,
"description": "Question 5: true = only tokens with a green safety rating."
},
"min_market_cap_usd": {
"anyOf": [
{
"type": "number",
"minimum": 0
},
{
"type": "null"
}
],
"title": "Min Market Cap Usd",
"default": null,
"description": "Question 5: never buy coins under this market cap, in USD."
},
"no_rebuy_after_loss": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "No Rebuy After Loss",
"default": null,
"description": "Question 5: true = never re-buy a token already sold at a loss."
}
},
"additionalProperties": false
},
"ProtectInput": {
"type": "object",
"title": "ProtectInput",
"properties": {
"enabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"title": "Enabled",
"default": null,
"description": "Question 5: true = an automatic stop-loss and take-profit on every trade; false = none."
},
"stop_loss_pct": {
"anyOf": [
{
"type": "number",
"maximum": 100,
"exclusiveMinimum": 0
},
{
"type": "null"
}
],
"title": "Stop Loss Pct",
"default": null,
"description": "Question 5: the DROP from entry, positive. 30 means -30%. Default 30."
},
"take_profit_pct": {
"anyOf": [
{
"type": "number",
"exclusiveMinimum": 0
},
{
"type": "null"
}
],
"title": "Take Profit Pct",
"default": null,
"description": "Question 5: the GAIN from entry, positive. 100 means +100%. Default 100."
}
},
"additionalProperties": false
},
"AutonomyInput": {
"type": "object",
"title": "AutonomyInput",
"properties": {
"buys": {
"anyOf": [
{
"enum": [
"auto",
"ask"
],
"type": "string"
},
{
"type": "null"
}
],
"title": "Buys",
"default": null,
"description": "Question 3: `auto` = buy on its own, `ask` = ask the user first."
},
"sells": {
"anyOf": [
{
"enum": [
"auto",
"ask"
],
"type": "string"
},
{
"type": "null"
}
],
"title": "Sells",
"default": null,
"description": "Question 3: `auto` or `ask`, for sells and early exits."
}
},
"additionalProperties": false
},
"AgentTradingProfileInput": {
"type": "object",
"title": "AgentTradingProfileInput",
"properties": {
"goal": {
"anyOf": [
{
"enum": [
"new_launches",
"trending",
"majors_and_stocks",
"mix"
],
"type": "string"
},
{
"type": "null"
}
],
"title": "Goal",
"default": null,
"description": "v1, prefer `assets`. What the user wants to trade."
},
"mode": {
"anyOf": [
{
"enum": [
"tell_me",
"suggest",
"autonomous"
],
"type": "string"
},
{
"type": "null"
}
],
"title": "Mode",
"default": null,
"description": "Question 3, for moves you find on your own: `tell_me` = only when told, `suggest` = you suggest and the user approves (default), `autonomous` = you trade by their rules and strategies."
},
"exits": {
"anyOf": [
{
"$ref": "#/$defs/ExitsInput"
},
{
"type": "null"
}
],
"default": null
},
"notes": {
"anyOf": [
{
"type": "string",
"maxLength": 500
},
{
"type": "null"
}
],
"title": "Notes",
"default": null,
"description": "Hard rules the user adds any time (e.g. never buy under $1M market cap), and anything else they want you to remember."
},
"assets": {
"anyOf": [
{
"type": "array",
"items": {
"enum": [
"majors",
"stocks",
"rwa",
"launches",
"mix"
],
"type": "string"
},
"maxItems": 5
},
{
"type": "null"
}
],
"title": "Assets",
"default": null,
"description": "Question 2: what the user wants to own, any of them. `stocks` = tokenized stocks, `rwa` = real-world assets, `launches` = new launches and memes. Default [majors, stocks]."
},
"sizing": {
"anyOf": [
{
"$ref": "#/$defs/SizingInput"
},
{
"type": "null"
}
],
"default": null
},
"protect": {
"anyOf": [
{
"$ref": "#/$defs/ProtectInput"
},
{
"type": "null"
}
],
"default": null
},
"autonomy": {
"anyOf": [
{
"$ref": "#/$defs/AutonomyInput"
},
{
"type": "null"
}
],
"default": null
},
"hard_nos": {
"anyOf": [
{
"$ref": "#/$defs/HardNosInput"
},
{
"type": "null"
}
],
"default": null
},
"experience": {
"anyOf": [
{
"enum": [
"new_to_crypto",
"majors_and_stocks",
"trades_memes"
],
"type": "string"
},
{
"type": "null"
}
],
"title": "Experience",
"default": null,
"description": "Question 1: where the user is. Default `majors_and_stocks`. Sets how much you explain."
},
"goal_notes": {
"anyOf": [
{
"type": "string",
"maxLength": 280
},
{
"type": "null"
}
],
"title": "Goal Notes",
"default": null,
"description": "v1: extra detail on the goal."
}
},
"additionalProperties": false
}
},
"title": "save_trading_profileArguments",
"properties": {
"profile": {
"anyOf": [
{
"$ref": "#/$defs/AgentTradingProfileInput"
},
{
"type": "null"
}
],
"default": null
},
"replace": {
"type": "boolean",
"title": "Replace",
"default": false,
"description": "False merges into the saved answers; true overwrites them."
},
"skipped": {
"type": "boolean",
"title": "Skipped",
"default": false,
"description": "True when the user declined the interview."
}
}
}Find tokens by name, symbol or contract address. Use this FIRST whenever the user names a token in words ('buy some BONK') — every other token tool needs a contract address, and searching is the only safe way to get one. Never guess a contract address: on-chain there are many impostor tokens sharing a popular symbol, and picking the wrong one loses the user's money. If several results look plausible, show them to the user and ask which they mean. `asset_class: tokenized_stock` marks tokenized equities (treat as stock proxies, not memecoins). `safety_tier`: green = verified; grey = usually fine (not scored yet or a young launchpad token, NOT a red flag — do not skip a coin for being grey); red = caution / DYOR, the only tier to treat as a warning (Moby refuses agent buys on red). This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| query* | string | |
| network | string |
{
"type": "object",
"title": "search_tokensArguments",
"required": [
"query"
],
"properties": {
"query": {
"type": "string",
"title": "Query"
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
}
}
}Find PUBLIC whale/KOL/trader wallets by a KOL name or a whale-list brand — NOT by pasted address, and NOT the same search as `search_tokens`. Use `discover_wallets_to_follow` if you also want to know which of the results the caller already follows. This is public market data about the whole market — it is NOT about the user's own wallet or holdings. Tools whose names start with `get_my_` are the ones that return the user's own data.
| Argument | Type | Description |
|---|---|---|
| query* | string | A KOL name or a whale-list brand. Minimum 2 characters. |
| network | string |
{
"type": "object",
"title": "search_whalewatch_walletsArguments",
"required": [
"query"
],
"properties": {
"query": {
"type": "string",
"title": "Query",
"description": "A KOL name or a whale-list brand. Minimum 2 characters."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
}
}
}Log a bug, a wrong number (data_issue, name the tool) or an idea to improve Moby, once per issue; tell the user it was logged with its id. Not for payments, lost funds or account problems: send those to support in the Moby app. `kind`: bug (something broke), data_issue (a Moby number looks wrong; `tool_name` is required, and `expected` / `actual` help), idea (a missing tool or 'they should add X'). `title` is one line (max 160 chars); `details` is what happened (max 2000 chars). The same title within 24 hours returns the earlier submission with `duplicate: true` instead of a new one. At most 10 a day. Moves no money.
| Argument | Type | Description |
|---|---|---|
| kind* | string | bug, data_issue or idea. |
| title* | string | One line (max 160 chars). |
| actual | any | What Moby returned (max 500 chars). |
| details* | string | What happened or what to add (max 2000 chars). |
| expected | any | What the number should be, and where you saw it (max 500 chars). |
| tool_name | any | The Moby tool it is about, e.g. `get_token_overview`. Required for data_issue. |
| token_address | any | The token's contract address, when it is about one token. |
Unfollow a wallet. Idempotent — a no-op if the caller does not follow it. Also clears the caller's Following-feed history for this wallet, so `get_my_following_feed` reflects the change immediately. Moves no money.
| Argument | Type | Description |
|---|---|---|
| network | string | |
| wallet_address* | string | Public wallet ref, as returned by get_my_followed_wallets. |
{
"type": "object",
"title": "unfollow_walletArguments",
"required": [
"wallet_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"wallet_address": {
"type": "string",
"title": "Wallet Address",
"description": "Public wallet ref, as returned by get_my_followed_wallets."
}
}
}We read every tool's name, description and inputs the way the model will, looking for instructions hidden from you. A clean result means no warning signs, not a guarantee. Scanned Nov 2, 2026.
| Argument | Type | Description |
|---|---|---|
| amount* | number | How much to SPEND, in whole token units: the funding asset on a buy, the held token on a sell. |
| network | string | |
| rationale | any | Optional. Your 2–4 line thesis: why this coin, why now, who's in it, what breaks it. Stored with the trade and shown to the user; ≤500 chars. |
| order_type* | string | Which kind of order to place. See the tool description for what each one needs. |
| limit_price | any | USD limit price. Required for `limit_buy` and `limit_sell`. |
| order_count | any | How many DCA slices to split the amount into. Required for `dca_buy` and `dca_sell`. |
| token_address* | string | Contract address of the token the order is about. |
| stop_loss_price | any | USD price at which to stop out. Required for `sl_only` and `sl_and_tp`; for `trigger_buy` it is the price the buy fires at when the price drops to it. |
| interval_seconds | any | Seconds between DCA slices. Required for `dca_buy` and `dca_sell`. |
| take_profit_price | any | USD price at which to take profit. Required for `tp_only` and `sl_and_tp`. |
{
"type": "object",
"title": "create_orderArguments",
"required": [
"order_type",
"token_address",
"amount"
],
"properties": {
"amount": {
"type": "number",
"title": "Amount",
"description": "How much to SPEND, in whole token units: the funding asset on a buy, the held token on a sell."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"rationale": {
"anyOf": [
{
"type": "string",
"maxLength": 500
},
{
"type": "null"
}
],
"title": "Rationale",
"default": null,
"description": "Optional. Your 2–4 line thesis: why this coin, why now, who's in it, what breaks it. Stored with the trade and shown to the user; ≤500 chars."
},
"order_type": {
"enum": [
"tp_only",
"sl_only",
"sl_and_tp",
"limit_buy",
"limit_sell",
"dca_buy",
"dca_sell",
"trigger_buy"
],
"type": "string",
"title": "Order Type",
"description": "Which kind of order to place. See the tool description for what each one needs."
},
"limit_price": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Limit Price",
"default": null,
"description": "USD limit price. Required for `limit_buy` and `limit_sell`."
},
"order_count": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Order Count",
"default": null,
"description": "How many DCA slices to split the amount into. Required for `dca_buy` and `dca_sell`."
},
"token_address": {
"type": "string",
"title": "Token Address",
"description": "Contract address of the token the order is about."
},
"stop_loss_price": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Stop Loss Price",
"default": null,
"description": "USD price at which to stop out. Required for `sl_only` and `sl_and_tp`; for `trigger_buy` it is the price the buy fires at when the price drops to it."
},
"interval_seconds": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Interval Seconds",
"default": null,
"description": "Seconds between DCA slices. Required for `dca_buy` and `dca_sell`."
},
"take_profit_price": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Take Profit Price",
"default": null,
"description": "USD price at which to take profit. Required for `tp_only` and `sl_and_tp`."
}
}
}| 1-based page number. Page 1 is the top. |
| limit | integer | Tokens per page, 1-100. Keep it small. |
| network | string |
| whale_windows | any | Windows for the optional per-row `whale` block, e.g. ["h1", "h4"]. Omit for the default row. |
{
"type": "object",
"title": "get_degen_leaderboardArguments",
"properties": {
"page": {
"type": "integer",
"title": "Page",
"default": 1,
"minimum": 1,
"description": "1-based page number. Page 1 is the top."
},
"limit": {
"type": "integer",
"title": "Limit",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "Tokens per page, 1-100. Keep it small."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"whale_windows": {
"anyOf": [
{
"type": "array",
"items": {
"enum": [
"h1",
"h4",
"h8",
"h24"
],
"type": "string"
}
},
{
"type": "null"
}
],
"title": "Whale Windows",
"default": null,
"description": "Windows for the optional per-row `whale` block, e.g. [\"h1\", \"h4\"]. Omit for the default row."
}
}
}| 1-based page number. Page 1 is the top. |
| limit | integer | Tokens per page, 1-100. Keep it small. |
| network | string |
| group_id* | string |
| whale_windows | any | Windows for the optional per-row `whale` block, e.g. ["h1", "h4"]. Omit for the default row. |
{
"type": "object",
"title": "get_group_leaderboardArguments",
"required": [
"group_id"
],
"properties": {
"page": {
"type": "integer",
"title": "Page",
"default": 1,
"minimum": 1,
"description": "1-based page number. Page 1 is the top."
},
"limit": {
"type": "integer",
"title": "Limit",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "Tokens per page, 1-100. Keep it small."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"group_id": {
"type": "string",
"title": "Group Id"
},
"whale_windows": {
"anyOf": [
{
"type": "array",
"items": {
"enum": [
"h1",
"h4",
"h8",
"h24"
],
"type": "string"
}
},
{
"type": "null"
}
],
"title": "Whale Windows",
"default": null,
"description": "Windows for the optional per-row `whale` block, e.g. [\"h1\", \"h4\"]. Omit for the default row."
}
}
}| after_timestamp |
| any |
| Only events after this instant. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`. |
| before_timestamp | any | Only events before this instant. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`. |
| market_cap_group | any | Market-cap band. `all` or omitted disables the filter. |
{
"type": "object",
"title": "get_market_moversArguments",
"properties": {
"page": {
"type": "integer",
"title": "Page",
"default": 1,
"description": "1-based page number."
},
"limit": {
"type": "integer",
"title": "Limit",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Events per page, 1-100. Keep it small."
},
"period": {
"anyOf": [
{
"enum": [
"all",
"h1",
"h4",
"h8",
"h24",
"multi"
],
"type": "string"
},
{
"type": "null"
}
],
"title": "Period",
"default": null,
"description": "Time window. `all` or omitted disables the filter."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"event_types": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"title": "Event Types",
"default": null,
"description": "Restrict to these event types. Omit for all types."
},
"token_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Token Address",
"default": null,
"description": "Restrict to one token's events. Omit for the whole market."
},
"after_timestamp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "After Timestamp",
"default": null,
"description": "Only events after this instant. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`."
},
"before_timestamp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Before Timestamp",
"default": null,
"description": "Only events before this instant. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`."
},
"market_cap_group": {
"anyOf": [
{
"enum": [
"all",
"large_cap",
"mid_cap",
"small_cap"
],
"type": "string"
},
{
"type": "null"
}
],
"title": "Market Cap Group",
"default": null,
"description": "Market-cap band. `all` or omitted disables the filter."
}
}
}{
"type": "object",
"title": "get_my_activityArguments",
"properties": {
"limit": {
"type": "integer",
"title": "Limit",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Items per page. Keep it small."
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Cursor",
"default": null,
"description": "Opaque cursor from the previous response. Omit for the first page."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"category": {
"anyOf": [
{
"enum": [
"all",
"buys",
"sells",
"closed_trades",
"orders",
"trades",
"transfers"
],
"type": "string"
},
{
"type": "null"
}
],
"title": "Category",
"default": null,
"description": "Restrict to one activity category. Omit (or `all`) for everything. ⚠️ `buys`, `sells` and `closed_trades` REQUIRE `token_address` — without one the call is rejected, deliberately: 'bought' means 'this token was received', and every swap receives something, so the question has no answer across a whole-wallet feed."
},
"token_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Token Address",
"default": null,
"description": "Restrict to activity involving one token. Omit for all."
}
}
}| Argument | Type | Description |
|---|---|---|
| network | string | |
| refresh | boolean |
{
"type": "object",
"title": "get_my_balancesArguments",
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"refresh": {
"type": "boolean",
"title": "Refresh",
"default": false
}
}
}| Contract address of the ONE token to show trades for. Required. |
{
"type": "object",
"title": "get_my_closed_tradesArguments",
"required": [
"token_address"
],
"properties": {
"page": {
"type": "integer",
"title": "Page",
"default": 1
},
"limit": {
"type": "integer",
"title": "Limit",
"default": 25
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"include_fills": {
"type": "boolean",
"title": "Include Fills",
"default": true
},
"token_address": {
"type": "string",
"title": "Token Address",
"description": "Contract address of the ONE token to show trades for. Required."
}
}
}| Type |
|---|
| Description |
|---|
| page | integer | History only: 1-based page number. |
| limit | integer | History only: rows per page, newest first (max 200). |
| since | any | ISO 8601 time, e.g. `2026-10-23T00:00:00Z`. Only orders whose last state change (fill, else cancel/update) is at or after this. |
| until | any | ISO 8601 upper bound, same clock as `since`. |
| status | any | Omit for LIVE orders only. `terminal` = every finished order (filled, cancelled, expired, failed) — the history; `all` = live and finished; or one status / a list of statuses. A resting, unfilled order is `active` — there is no `open` and no `pending`. |
| network | string | |
| token_address | any | Contract address: only orders on this token, whether it is the token being sold (TP/SL) or bought (limit buy). Omit for every token. |
{
"type": "object",
"title": "get_my_ordersArguments",
"properties": {
"page": {
"type": "integer",
"title": "Page",
"default": 1,
"minimum": 1,
"description": "History only: 1-based page number."
},
"limit": {
"type": "integer",
"title": "Limit",
"default": 50,
"maximum": 200,
"minimum": 1,
"description": "History only: rows per page, newest first (max 200)."
},
"since": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Since",
"default": null,
"description": "ISO 8601 time, e.g. `2026-10-23T00:00:00Z`. Only orders whose last state change (fill, else cancel/update) is at or after this."
},
"until": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Until",
"default": null,
"description": "ISO 8601 upper bound, same clock as `since`."
},
"status": {
"anyOf": [
{
"enum": [
"pending_deposit",
"active",
"filled_tp",
"filled_sl",
"partially_filled",
"filled",
"cancelled",
"expired",
"failed",
"terminal",
"all"
],
"type": "string"
},
{
"type": "array",
"items": {
"enum": [
"pending_deposit",
"active",
"filled_tp",
"filled_sl",
"partially_filled",
"filled",
"cancelled",
"expired",
"failed",
"terminal",
"all"
],
"type": "string"
}
},
{
"type": "null"
}
],
"title": "Status",
"default": null,
"description": "Omit for LIVE orders only. `terminal` = every finished order (filled, cancelled, expired, failed) — the history; `all` = live and finished; or one status / a list of statuses. A resting, unfilled order is `active` — there is no `open` and no `pending`."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Token Address",
"default": null,
"description": "Contract address: only orders on this token, whether it is the token being sold (TP/SL) or bought (limit buy). Omit for every token."
}
}
}| Argument | Type | Description |
|---|---|---|
| network | string | |
| token_address* | string |
{
"type": "object",
"title": "get_my_positionArguments",
"required": [
"token_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address"
}
}
}{
"type": "object",
"title": "get_my_token_balanceArguments",
"required": [
"token_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address"
}
}
}| page |
| integer |
| 1-based page number. Page 1 is the top. |
| limit | integer | Tokens per page, 1-100. Keep it small. |
| network | string |
| whale_windows | any | Windows for the optional per-row `whale` block, e.g. ["h1", "h4"]. Omit for the default row. |
{
"type": "object",
"title": "get_screener_leaderboardArguments",
"properties": {
"page": {
"type": "integer",
"title": "Page",
"default": 1,
"minimum": 1,
"description": "1-based page number. Page 1 is the top."
},
"limit": {
"type": "integer",
"title": "Limit",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "Tokens per page, 1-100. Keep it small."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"whale_windows": {
"anyOf": [
{
"type": "array",
"items": {
"enum": [
"h1",
"h4",
"h8",
"h24"
],
"type": "string"
}
},
{
"type": "null"
}
],
"title": "Whale Windows",
"default": null,
"description": "Windows for the optional per-row `whale` block, e.g. [\"h1\", \"h4\"]. Omit for the default row."
}
}
}| The `transaction_signature` the swap returned. Give this OR `request_id`. |
{
"type": "object",
"title": "get_swap_statusArguments",
"properties": {
"request_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Request Id",
"default": null,
"description": "The `quote_id` of the swap you executed. Give this OR `transaction_signature`."
},
"transaction_signature": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Transaction Signature",
"default": null,
"description": "The `transaction_signature` the swap returned. Give this OR `request_id`."
}
}
}| page | integer | 1-based page number. |
| sort | string | Row order: value (default, largest position first) / newest (most recent first tracked buy first) / oldest (earliest first buy first) / recent_trade (latest tracked buy or sell first). |
| limit | integer | Holders per page, 1-100. Keep it small. |
| network | string |
| token_address* | string |
| min_position_usd | any | Minimum live USD position to list or count a holder (whales, traders and KOLs). Omit for the default $100; raise it (e.g. 500) for conviction-only counts. Ignored when `tag` is set. |
{
"type": "object",
"title": "get_token_key_holdersArguments",
"required": [
"token_address"
],
"properties": {
"tag": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Tag",
"default": null,
"description": "Claim filter behind the expanded Smart Money read: one of the four exclusive tags (holding / bought / trimming / closed) or one of the read's own claims (never_sold / exited_24h / new_24h / left_7d / sat_still). Omit for everyone."
},
"page": {
"type": "integer",
"title": "Page",
"default": 1,
"minimum": 1,
"description": "1-based page number."
},
"sort": {
"enum": [
"value",
"newest",
"oldest",
"recent_trade"
],
"type": "string",
"title": "Sort",
"default": "value",
"description": "Row order: value (default, largest position first) / newest (most recent first tracked buy first) / oldest (earliest first buy first) / recent_trade (latest tracked buy or sell first)."
},
"limit": {
"type": "integer",
"title": "Limit",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "Holders per page, 1-100. Keep it small."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address"
},
"min_position_usd": {
"anyOf": [
{
"type": "number",
"maximum": 1000000,
"minimum": 0
},
{
"type": "null"
}
],
"title": "Min Position Usd",
"default": null,
"description": "Minimum live USD position to list or count a holder (whales, traders and KOLs). Omit for the default $100; raise it (e.g. 500) for conviction-only counts. Ignored when `tag` is set."
}
}
}| network | string |
| token_address* | string |
{
"type": "object",
"title": "get_token_live_feedArguments",
"required": [
"token_address"
],
"properties": {
"page": {
"type": "integer",
"title": "Page",
"default": 1,
"minimum": 1,
"description": "1-based page number. Ignored when `cursor` is given."
},
"limit": {
"type": "integer",
"title": "Limit",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Trades per page, 1-100. Keep it small."
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Cursor",
"default": null,
"description": "`next_cursor` from the previous response. Wins over `page`; no gaps or duplicates."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address"
}
}
}| network | string |
| time_to | any | Window end, Unix timestamp in SECONDS or MILLISECONDS — either is accepted. Requires `time_from` as well. |
| interval | any | Candle size. Wins over `timeframe`/`aggregate`. Omit all three for 15m. |
| aggregate | any | How many `timeframe` units per candle. 1 when only `timeframe` is given. |
| time_from | any | Window start, Unix timestamp in SECONDS or MILLISECONDS — either is accepted. Requires `time_to` as well. |
| timeframe | any | Candle unit. Candle size is `aggregate` × this (`aggregate` defaults to 1 when only this is given). Only the sizes listed under `interval` are served; anything else is rejected. |
| token_address* | string |
| before_timestamp | any | Return candles before this Unix timestamp, in seconds or milliseconds. Use to page further back in history — a `t` value from a previous response can be passed straight back. |
| include_in_progress_candle | boolean | True keeps the current, still-forming candle at index 0. Leave false for any calculation — its close is not a close. |
{
"type": "object",
"title": "get_token_ohlcvArguments",
"required": [
"token_address"
],
"properties": {
"limit": {
"type": "integer",
"title": "Limit",
"default": 20,
"description": "How many candles to return."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"time_to": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Time To",
"default": null,
"description": "Window end, Unix timestamp in SECONDS or MILLISECONDS — either is accepted. Requires `time_from` as well."
},
"interval": {
"anyOf": [
{
"enum": [
"1m",
"5m",
"15m",
"1h",
"4h",
"1d"
],
"type": "string"
},
{
"type": "null"
}
],
"title": "Interval",
"default": null,
"description": "Candle size. Wins over `timeframe`/`aggregate`. Omit all three for 15m."
},
"aggregate": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Aggregate",
"default": null,
"description": "How many `timeframe` units per candle. 1 when only `timeframe` is given."
},
"time_from": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Time From",
"default": null,
"description": "Window start, Unix timestamp in SECONDS or MILLISECONDS — either is accepted. Requires `time_to` as well."
},
"timeframe": {
"anyOf": [
{
"enum": [
"minute",
"hour",
"day",
"week",
"month"
],
"type": "string"
},
{
"type": "null"
}
],
"title": "Timeframe",
"default": null,
"description": "Candle unit. Candle size is `aggregate` × this (`aggregate` defaults to 1 when only this is given). Only the sizes listed under `interval` are served; anything else is rejected."
},
"token_address": {
"type": "string",
"title": "Token Address"
},
"before_timestamp": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"title": "Before Timestamp",
"default": null,
"description": "Return candles before this Unix timestamp, in seconds or milliseconds. Use to page further back in history — a `t` value from a previous response can be passed straight back."
},
"include_in_progress_candle": {
"type": "boolean",
"title": "Include In Progress Candle",
"default": false,
"description": "True keeps the current, still-forming candle at index 0. Leave false for any calculation — its close is not a close."
}
}
}| Argument | Type | Description |
|---|---|---|
| network | string | |
| token_address* | string |
{
"type": "object",
"title": "get_token_overviewArguments",
"required": [
"token_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address"
}
}
}| Type |
|---|
| Description |
|---|
| network | string | |
| token_address* | string |
{
"type": "object",
"title": "get_token_trade_briefArguments",
"required": [
"token_address"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address"
}
}
}| integer |
| Trades per page, 1-100. Keep it small. |
| network | string |
| list_ids | any | Whale list ids from `get_whalewatch_lists`. Omit for all lists. |
| token_address | any | Restrict to whale trades in this one token. |
| wallet_address | any | Restrict to one TRACKED WHALE wallet. Not the user's wallet. |
| after_timestamp | any | Only trades after this instant. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`. |
| include_context | boolean | Add the per-row `context` block (position/PnL facts for each trade). |
| before_timestamp | any | Only trades before this instant. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`. |
| transaction_types | any | `buy` and/or `sell`. Omit for both. Anything else is rejected rather than ignored — an unrecognised value used to drop the filter and return every row. |
| min_days_since_prev_trade | any | Only trades by a wallet that had been quiet at least this many days before the trade (no tracked trade on this network, any token), e.g. 14 for 'woke up after two weeks'. Trades with no earlier trade on record do not match. Omit for all. |
{
"type": "object",
"title": "get_whalewatch_feedArguments",
"properties": {
"page": {
"type": "integer",
"title": "Page",
"default": 1,
"minimum": 1,
"description": "1-based page number."
},
"limit": {
"type": "integer",
"title": "Limit",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Trades per page, 1-100. Keep it small."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"list_ids": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"title": "List Ids",
"default": null,
"description": "Whale list ids from `get_whalewatch_lists`. Omit for all lists."
},
"token_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Token Address",
"default": null,
"description": "Restrict to whale trades in this one token."
},
"wallet_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Wallet Address",
"default": null,
"description": "Restrict to one TRACKED WHALE wallet. Not the user's wallet."
},
"after_timestamp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "After Timestamp",
"default": null,
"description": "Only trades after this instant. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`."
},
"include_context": {
"type": "boolean",
"title": "Include Context",
"default": false,
"description": "Add the per-row `context` block (position/PnL facts for each trade)."
},
"before_timestamp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Before Timestamp",
"default": null,
"description": "Only trades before this instant. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`."
},
"transaction_types": {
"anyOf": [
{
"type": "array",
"items": {
"enum": [
"buy",
"sell"
],
"type": "string"
}
},
{
"type": "null"
}
],
"title": "Transaction Types",
"default": null,
"description": "`buy` and/or `sell`. Omit for both. Anything else is rejected rather than ignored — an unrecognised value used to drop the filter and return every row."
},
"min_days_since_prev_trade": {
"anyOf": [
{
"type": "number",
"minimum": 0
},
{
"type": "null"
}
],
"title": "Min Days Since Prev Trade",
"default": null,
"description": "Only trades by a wallet that had been quiet at least this many days before the trade (no tracked trade on this network, any token), e.g. 14 for 'woke up after two weeks'. Trades with no earlier trade on record do not match. Omit for all."
}
}
}| integer |
| Swaps per page, 1-1000. Keep it small unless you need the whole window. |
| cursor | any | `next_cursor` from the previous page. Omit for the first page. |
| actions | any | What the trade did to the wallet's position: `first_buy`, `re_entry`, `add`, `trim`, `close`, `sell_unknown_entry`. Omit for all. |
| network | string |
| list_ids | any | Whale list ids from `get_whalewatch_lists`. Omit for all lists. |
| min_amount_usd | any | Only trades of at least this many USD. |
| after_timestamp* | string | Window start (inclusive). At most 48h before the window end. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`. |
| include_context | boolean | Add the per-row `context` block (position/PnL facts for each trade). |
| before_timestamp | any | Window end (inclusive). Omit for now. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`. |
| transaction_types | any | `buy` and/or `sell`. Omit for both. |
| min_market_cap_usd | any | Only trades in tokens whose market cap at trade time was at least this. |
| min_days_since_prev_trade | any | Only trades by a wallet that had been quiet at least this many days before the trade (no tracked trade on this network, any token), e.g. 14 for 'woke up after two weeks'. Trades with no earlier trade on record do not match. Omit for all. |
{
"type": "object",
"title": "get_whalewatch_feed_windowArguments",
"required": [
"after_timestamp"
],
"properties": {
"limit": {
"type": "integer",
"title": "Limit",
"default": 25,
"maximum": 1000,
"minimum": 1,
"description": "Swaps per page, 1-1000. Keep it small unless you need the whole window."
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Cursor",
"default": null,
"description": "`next_cursor` from the previous page. Omit for the first page."
},
"actions": {
"anyOf": [
{
"type": "array",
"items": {
"enum": [
"first_buy",
"re_entry",
"add",
"trim",
"close",
"sell_unknown_entry"
],
"type": "string"
}
},
{
"type": "null"
}
],
"title": "Actions",
"default": null,
"description": "What the trade did to the wallet's position: `first_buy`, `re_entry`, `add`, `trim`, `close`, `sell_unknown_entry`. Omit for all."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"list_ids": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"title": "List Ids",
"default": null,
"description": "Whale list ids from `get_whalewatch_lists`. Omit for all lists."
},
"min_amount_usd": {
"anyOf": [
{
"type": "number",
"minimum": 0
},
{
"type": "null"
}
],
"title": "Min Amount Usd",
"default": null,
"description": "Only trades of at least this many USD."
},
"after_timestamp": {
"type": "string",
"title": "After Timestamp",
"description": "Window start (inclusive). At most 48h before the window end. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`."
},
"include_context": {
"type": "boolean",
"title": "Include Context",
"default": false,
"description": "Add the per-row `context` block (position/PnL facts for each trade)."
},
"before_timestamp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Before Timestamp",
"default": null,
"description": "Window end (inclusive). Omit for now. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`."
},
"transaction_types": {
"anyOf": [
{
"type": "array",
"items": {
"enum": [
"buy",
"sell"
],
"type": "string"
}
},
{
"type": "null"
}
],
"title": "Transaction Types",
"default": null,
"description": "`buy` and/or `sell`. Omit for both."
},
"min_market_cap_usd": {
"anyOf": [
{
"type": "number",
"minimum": 0
},
{
"type": "null"
}
],
"title": "Min Market Cap Usd",
"default": null,
"description": "Only trades in tokens whose market cap at trade time was at least this."
},
"min_days_since_prev_trade": {
"anyOf": [
{
"type": "number",
"minimum": 0
},
{
"type": "null"
}
],
"title": "Min Days Since Prev Trade",
"default": null,
"description": "Only trades by a wallet that had been quiet at least this many days before the trade (no tracked trade on this network, any token), e.g. 14 for 'woke up after two weeks'. Trades with no earlier trade on record do not match. Omit for all."
}
}
}| any |
| Only trades after this instant. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`. |
| include_context | boolean | Add the per-row `context` block (position/PnL facts for each trade). |
| before_timestamp | any | Only trades before this instant. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`. |
| transaction_types | any | `buy` and/or `sell`. Omit for both. Anything else is rejected rather than ignored — an unrecognised value used to drop the filter and return every row. |
{
"type": "object",
"title": "get_whalewatch_kol_feedArguments",
"properties": {
"page": {
"type": "integer",
"title": "Page",
"default": 1,
"minimum": 1,
"description": "1-based page number."
},
"limit": {
"type": "integer",
"title": "Limit",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Trades per page, 1-100. Keep it small."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Token Address",
"default": null,
"description": "Restrict to KOL trades in this one token."
},
"after_timestamp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "After Timestamp",
"default": null,
"description": "Only trades after this instant. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`."
},
"include_context": {
"type": "boolean",
"title": "Include Context",
"default": false,
"description": "Add the per-row `context` block (position/PnL facts for each trade)."
},
"before_timestamp": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Before Timestamp",
"default": null,
"description": "Only trades before this instant. ISO 8601 UTC, e.g. `2026-08-11T14:30:00Z`."
},
"transaction_types": {
"anyOf": [
{
"type": "array",
"items": {
"enum": [
"buy",
"sell"
],
"type": "string"
}
},
{
"type": "null"
}
],
"title": "Transaction Types",
"default": null,
"description": "`buy` and/or `sell`. Omit for both. Anything else is rejected rather than ignored — an unrecognised value used to drop the filter and return every row."
}
}
}| any |
| How much to spend in US DOLLARS. Mutually exclusive with `amount_in`. |
| output_token* | string | Contract address of the token to BUY. Get it from `search_tokens`. |
{
"type": "object",
"title": "quick_buyArguments",
"required": [
"output_token"
],
"properties": {
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"amount_in": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Amount In",
"default": null,
"description": "How much to spend in whole units of USDC, the only funding asset — SOL is a position, never spent by a buy. Mutually exclusive with `amount_usd`."
},
"rationale": {
"anyOf": [
{
"type": "string",
"maxLength": 500
},
{
"type": "null"
}
],
"title": "Rationale",
"default": null,
"description": "Optional. Your 2–4 line thesis: why this coin, why now, who's in it, what breaks it. Stored with the trade and shown to the user; ≤500 chars."
},
"amount_usd": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"title": "Amount Usd",
"default": null,
"description": "How much to spend in US DOLLARS. Mutually exclusive with `amount_in`."
},
"output_token": {
"type": "string",
"title": "Output Token",
"description": "Contract address of the token to BUY. Get it from `search_tokens`."
}
}
}| network | string |
| token_address* | string | Contract address of the HELD token to sell. Get it from `get_my_balances`. |
| max_slippage_bps | any | Slippage tolerance in basis points (100 = 1%). Omit for Moby's default. |
{
"type": "object",
"title": "quick_sellArguments",
"required": [
"token_address"
],
"properties": {
"pct": {
"type": "number",
"title": "Pct",
"default": 100,
"maximum": 100,
"minimum": 1,
"description": "Percent of the current balance to sell, 1-100. Default 100 = close it."
},
"network": {
"type": "string",
"const": "solana",
"title": "Network",
"default": "solana"
},
"token_address": {
"type": "string",
"title": "Token Address",
"description": "Contract address of the HELD token to sell. Get it from `get_my_balances`."
},
"max_slippage_bps": {
"anyOf": [
{
"type": "integer",
"maximum": 5000,
"minimum": 1
},
{
"type": "null"
}
],
"title": "Max Slippage Bps",
"default": null,
"description": "Slippage tolerance in basis points (100 = 1%). Omit for Moby's default."
}
}
}| active_strategy_id | any | Omit to start a new one; an `id` from get_my_active_strategies to update. |
{
"type": "object",
"title": "save_active_strategyArguments",
"properties": {
"name": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
],
"title": "Name",
"default": null,
"description": "Display name (max 120 chars)."
},
"notes": {
"anyOf": [
{
"type": "string",
"maxLength": 1000
},
{
"type": "null"
}
],
"title": "Notes",
"default": null,
"description": "Anything to remember (max 1000 chars)."
},
"status": {
"anyOf": [
{
"enum": [
"active",
"paused",
"stopped"
],
"type": "string"
},
{
"type": "null"
}
],
"title": "Status",
"default": null,
"description": "active, paused or stopped."
},
"schedule": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
],
"title": "Schedule",
"default": null,
"description": "How often it runs, in plain words (max 120 chars)."
},
"settings": {
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "null"
}
],
"title": "Settings",
"default": null,
"description": "The confirmed numbers as a small JSON object (max 8 KB); `{}` clears it."
},
"last_run_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Last Run At",
"default": null,
"description": "ISO 8601 time of the run just finished, e.g. `2026-10-29T14:00:00Z`."
},
"strategy_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Strategy Id",
"default": null,
"description": "The starter card `id` from list_strategies; omit for a custom strategy."
},
"active_strategy_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Active Strategy Id",
"default": null,
"description": "Omit to start a new one; an `id` from get_my_active_strategies to update."
}
}
}{
"type": "object",
"title": "submit_feedbackArguments",
"required": [
"kind",
"title",
"details"
],
"properties": {
"kind": {
"enum": [
"bug",
"data_issue",
"idea"
],
"type": "string",
"title": "Kind",
"description": "bug, data_issue or idea."
},
"title": {
"type": "string",
"title": "Title",
"maxLength": 160,
"minLength": 1,
"description": "One line (max 160 chars)."
},
"actual": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Actual",
"default": null,
"description": "What Moby returned (max 500 chars)."
},
"details": {
"type": "string",
"title": "Details",
"minLength": 1,
"description": "What happened or what to add (max 2000 chars)."
},
"expected": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Expected",
"default": null,
"description": "What the number should be, and where you saw it (max 500 chars)."
},
"tool_name": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Tool Name",
"default": null,
"description": "The Moby tool it is about, e.g. `get_token_overview`. Required for data_issue."
},
"token_address": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Token Address",
"default": null,
"description": "The token's contract address, when it is about one token."
}
}
}