milo-solana-portfolio

SkillFiles & storage

--- name: milo version: 1.0.0 description: Autonomous Solana portfolio management. Non-custodial wallets, auto-trading, market analysis, orders, transfers, and AI conversations. ---

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the milo-solana-portfolio skill

About this capability

A curated guide to convention files AI agents read, write, and act on: AGENTS.md, CLAUDE.md, SKILL.md, llms.txt, MCP configs, rules, and examples.

What this skill tells your AI

The instructions your AI receives, as published by itamarzand88/awesome-agent-conventions in conventions/skill-md/examples/domain-specific-niche/milo-solana-portfolio/SKILL.md and read by ahel’s review.


name: milo version: 1.0.0 description: Autonomous Solana portfolio management. Non-custodial wallets, auto-trading, market analysis, orders, transfers, and AI conversations.

Milo Partner API Skill

Milo is an autonomous Solana portfolio manager. Through this API you can register users, create non-custodial wallets, send tokens, place buy/sell orders, manage positions, configure auto-trading strategies, and converse with Milo's AI agents.

Getting Started — First-Time Onboarding

Follow these 4 steps to go from zero to a fully active Milo account.

Step 1: Sign up

Request a SIWX message, sign it with your Solana wallet, and register.

# 1a. Get the message to sign
curl -X POST {{BASE_URL}}/api/v1/users/siwx/message \
  -H "Content-Type: application/json" \
  -d '{
    "accountAddress": "<your-wallet-address>",
    "chainId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
  }'

# 1b. Sign the returned "message" (UTF-8 bytes) with your ed25519 key, base58-encode the signature

# 1c. Register
curl -X POST {{BASE_URL}}/api/v1/users \
  -H "Content-Type: application/json" \
  -d '{
    "signupWallet": "<your-wallet-address>",
    "siwx": {
      "data": <data-object-from-1a>,
      "message": "<message-string-from-1a>",
      "signature": "<base58-signature-from-1b>"
    }
  }'
# → returns apiKey, user.id, wallets[] (save these to ~/.milo/config.json)

Step 2: Ask Milo what's trending

Start a conversation with the market analyst to explore current opportunities.

# 2a. Create a conversation
curl -X POST {{BASE_URL}}/api/v1/users/{userId}/conversations \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "What tokens are trending right now on Solana?",
    "agentType": "market-analyst"
  }'
# → returns conversationId

# 2b. Poll for the response (wait 2-3s between polls)
curl "{{BASE_URL}}/api/v1/users/{userId}/conversations/{conversationId}/messages" \
  -H "X-API-Key: $API_KEY"
# → when processing: false, the agent has responded

Step 3: Transfer funds to your Milo wallet

Deposit SOL to your Milo wallet so it has capital to trade. The Milo wallet address is wallets[1].address from signup (the type: "milo" wallet).

Send SOL from your external wallet to that address. Once funded, verify:

curl {{BASE_URL}}/api/v1/wallets/{walletId}/holdings \
  -H "X-API-Key: $API_KEY"

Step 4: Activate auto-trading

Turn on Milo's autonomous trading agent. It will start scanning for opportunities within ~30 minutes.

curl -X PATCH {{BASE_URL}}/api/v1/users/{userId}/auto-trade-settings \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "isActive": true,
    "riskTolerance": "balanced",
    "strategy": "SWING TRADER"
  }'

That's it — Milo is now managing your portfolio. Read on for the full feature guide and API reference.


Feature Overview

Note: You do NOT need to read this entire document. Use the guide below to jump to the relevant section for your task.

If you need to...Read section
Look up your user ID and wallet IDs"Me" (under Complete API Reference)
Register a new user / get an API key"First Boot Protocol" and "Signup" (under Complete API Reference)
Activate or configure auto-trading"Recipe 2: Activate the auto-trader" and "Auto-Trade Settings" (under Complete API Reference)
Create, link, or manage strategies"Strategies" (under Complete API Reference)
Deploy and manage arena strategies"Arena" (under Complete API Reference)
View quests and claim bones"Quests & Bones" (under Complete API Reference)
Place, list, or manage orders"Orders" (under Complete API Reference)
Send tokens to another wallet"Wallet Actions" (under Complete API Reference)
Check positions, holdings, or PnL"Recipe 4: Fetch your positions" and "Portfolio" (under Complete API Reference)
Chat with Milo's AI agents"Recipe 3: Talk with Milo" / "Recipe 6: Ask about a token" and "Conversations" (under Complete API Reference)
Understand the full onboarding flow"Quick Start" and "First Boot Protocol"
Set up a recurring portfolio check-in"Heartbeat Protocol"

Capabilities:

  • Non-custodial Solana wallet — Each user gets a Milo wallet (created via Turnkey). The user's signing key owns the wallet; Milo receives delegated permission to execute trades.
  • Auto-trading — Configure risk tolerance, strategy, and asset allocation. Milo's auto-trader agent monitors markets and executes trades autonomously.
  • Orders — Create limit, market, stop-loss, and take-profit orders on any Solana token.
  • Token transfers — Send any SPL token or SOL from your Milo wallet to any Solana address.
  • Positions — Track open positions with PnL data, close positions.
  • Arena — Deploy public strategies to a competitive leaderboard. Milo funds an arena wallet and trades autonomously using the strategy. Withdraw to reclaim holdings.
  • Quests & Bones — Complete quests (event-driven tasks like trades, signups) to earn bones (reward points). Check quests regularly and claim bones for completed quests.
  • AI conversations — Chat with Milo's market analyst, auto-trader, or game agent. Async processing with polling.
  • Portfolio data — Holdings, transactions, executed transactions, diary logs.

Quick Start

  1. Get SIWX message - Call POST /api/v1/users/siwx/message with your wallet address to get a message to sign.
  2. Register - Sign the message with your wallet's ed25519 key, then call POST /api/v1/users with the signed SIWX proof to create a user and receive an API key + Milo wallet.
  3. Save credentials - Store the API key, user ID, wallet ID, and wallet address in ~/.milo/config.json.
  4. Deposit SOL - Send SOL to your Milo wallet address (the type: "milo" wallet from signup).
  5. Activate auto-trader - Call PATCH /api/v1/users/{userId}/auto-trade-settings with { "isActive": true }.
  6. Fetch open quests - Call GET /api/v1/users/{userId}/quests to see available quests. Claim bones for any completed quests.
  7. Start trading - Create orders, chat with agents, or let the auto-trader manage your portfolio.

Credential Storage

After signup, persist credentials locally so they survive across sessions:

// ~/.milo/config.json
{
  "api_key": "mk_live_...",
  "user_id": "uuid",
  "wallet_id": "uuid",
  "wallet_address": "7xKXtg...",
  "base_url": "{{BASE_URL}}"
}

Warning: In ephemeral environments (containers, serverless), this file may not persist. Use environment variables or a secrets manager instead.

All authenticated requests require the header:

X-API-Key: <api_key>

(NOT Authorization: Bearer — the API uses the X-API-Key header.)

MCP Access

The partner API server exposes MCP on the same host at /mcp using Streamable HTTP:

  • POST /mcp for initialize and JSON-RPC requests
  • GET /mcp for SSE stream
  • DELETE /mcp for session termination

POST /mcp initialize accepts optional X-API-Key. If omitted, the MCP session starts unauthenticated and only signup/public tools are usable until signup returns an API key. Request throttling and session-capacity protections are enforced, so initialize may return 429. On 429, respect Retry-After and retry after the indicated delay. Sessions can also expire, so re-initialize after invalid-session errors.

For sessioned requests after initialize, send Mcp-Session-Id.

Wallet & Deposits

Milo creates a non-custodial Solana wallet for each user via Turnkey. The wallet-creating account is the owner; Milo receives delegated permission for trading.

On signup you receive two wallets:

  • type: "signup" - Your external signing wallet (used for SIWX verification).
  • type: "milo" - Your Milo trading wallet. Deposit SOL here for trading.

To check your wallet balance, use the holdings endpoint:

curl {{BASE_URL}}/api/v1/wallets/{walletId}/holdings \
  -H "X-API-Key: $API_KEY"

First Boot Protocol

When starting fresh with no saved credentials:

  1. Generate a Solana keypair for SIWX signing.
  2. Request a SIWX message from the server:
    curl -X POST {{BASE_URL}}/api/v1/users/siwx/message \
      -H "Content-Type: application/json" \
      -d '{
        "accountAddress": "<your-wallet-address>",
        "chainId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
      }'
    
    This returns { "data": { ... }, "message": "<message-string>" }. The data object contains all SIWX fields (domain, uri, nonce, etc.) and the message is the human-readable string to sign.
  3. Sign the message — Sign the message string (UTF-8 encoded bytes) with your Solana keypair's ed25519 private key. Base58-encode the resulting signature.
  4. Register:
    curl -X POST {{BASE_URL}}/api/v1/users \
      -H "Content-Type: application/json" \
      -d '{
        "signupWallet": "<your-wallet-address>",
        "siwx": {
          "data": <data-object-from-step-2>,
          "message": "<message-string-from-step-2>",
          "signature": "<base58-signature-from-step-3>"
        }
      }'
    
    Important: Pass the data and message exactly as returned by the server. Do not construct them manually.
  5. Save the returned apiKey, user.id, and wallets[1] (the Milo wallet) to ~/.milo/config.json.
  6. Deposit SOL to the Milo wallet address.
  7. Configure auto-trade:
    curl -X PATCH {{BASE_URL}}/api/v1/users/{userId}/auto-trade-settings \
      -H "X-API-Key: $API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "isActive": true,
        "riskTolerance": "balanced",
        "strategy": "SWING TRADER"
      }'
    

Heartbeat Protocol

See heartbeat.md for the recurring check-in protocol. Run every 4+ hours to stay informed about your portfolio.


Cookbook — Working with Milo

This cookbook walks through the most common workflows end-to-end. Follow these recipes to get up and running quickly.

Recipe 1: Get your API key

Before anything else you need credentials. Generate a Solana keypair, request a SIWX message from the server, sign it, and register.

# 1. Request a SIWX message to sign
curl -X POST {{BASE_URL}}/api/v1/users/siwx/message \
  -H "Content-Type: application/json" \
  -d '{
    "accountAddress": "<your-wallet-address>",
    "chainId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
  }'
# → returns { "data": { "data": { ... }, "message": "<message-to-sign>" } }

# 2. Sign the "message" string (UTF-8 bytes) with your ed25519 private key
#    Base58-encode the signature

# 3. Register with the signed proof
curl -X POST {{BASE_URL}}/api/v1/users \
  -H "Content-Type: application/json" \
  -d '{
    "signupWallet": "<your-wallet-address>",
    "siwx": {
      "data": <data-object-from-step-1>,
      "message": "<message-string-from-step-1>",
      "signature": "<base58-signature-from-step-2>"
    }
  }'

# 4. Save the response — you need these for every subsequent call
#    api_key  → Authorization header
#    user.id  → {userId} in routes
#    wallets[1].id      → {walletId} (the "milo" wallet)
#    wallets[1].address → deposit SOL here

Store credentials in ~/.milo/config.json so they persist across sessions.


Recipe 2: Activate the auto-trader

Once registered, turn on Milo's autonomous trading agent.

curl -X PATCH {{BASE_URL}}/api/v1/users/{userId}/auto-trade-settings \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "isActive": true,
    "riskTolerance": "balanced",
    "strategy": "SWING TRADER",
    "instructions": "Focus on SOL ecosystem tokens. Avoid meme coins.",
    "customTickers": ["SOL", "JUP", "BONK"]
  }'

That's it — Milo will start monitoring markets and placing trades according to your configuration. You can verify it's active:

curl {{BASE_URL}}/api/v1/users/{userId}/auto-trade-settings \
  -H "X-API-Key: $API_KEY"

Recipe 3: Talk with Milo about your investment strategy

Use the auto-trader agent to discuss, refine, or brainstorm your trading strategy. This is a conversation — Milo understands your portfolio context.

# 1. Start a conversation with the auto-trader
curl -X POST {{BASE_URL}}/api/v1/users/{userId}/conversations \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "I want to shift my strategy toward DeFi blue-chips. What allocation do you recommend for a balanced risk profile?",
    "agentType": "auto-trader"
  }'
# → returns { conversationId, processing: true }

# 2. Poll for the response (wait 2-3s between polls)
curl "{{BASE_URL}}/api/v1/users/{userId}/conversations/{conversationId}/messages" \
  -H "X-API-Key: $API_KEY"
# → when processing: false, the agent has responded

# 3. Continue the conversation
curl -X POST {{BASE_URL}}/api/v1/users/{userId}/conversations/{conversationId}/messages \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "message": "Good plan. Apply those changes to my auto-trade settings." }'

Tip: The auto-trader agent can directly update your settings when you ask it to — it has tool access to modify your allocation, risk tolerance, and instructions.


Recipe 4: Fetch your positions

Check what Milo is holding and how each position is performing.

# List all active positions with PnL
curl "{{BASE_URL}}/api/v1/users/{userId}/positions?status=active&page=1&pageSize=50" \
  -H "X-API-Key: $API_KEY"

Each position includes the token, entry price, current PnL, and thesis. Use status=pending for positions still being built, or omit the filter to get everything.

For a deeper look at your wallet's token balances:

curl {{BASE_URL}}/api/v1/wallets/{walletId}/holdings \
  -H "X-API-Key: $API_KEY"

Recipe 5: Revalidate a position with Milo

Have Milo re-analyze an existing position to decide whether to hold, add, or exit.

# 1. Get the position's thesisId from the positions list (Recipe 4)
# 2. Start a conversation with the auto-trader, referencing the position
curl -X POST {{BASE_URL}}/api/v1/users/{userId}/conversations \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Re-evaluate my position on JUP (thesis {thesisId}). Given the latest market conditions, should I hold, take partial profit, or close it entirely?",
    "agentType": "auto-trader"
  }'

# 3. Poll for the response
curl "{{BASE_URL}}/api/v1/users/{userId}/conversations/{conversationId}/messages" \
  -H "X-API-Key: $API_KEY"

# 4. If Milo recommends closing, you can close it directly:
curl -X POST {{BASE_URL}}/api/v1/users/{userId}/positions/{thesisId}/close \
  -H "X-API-Key: $API_KEY"

Recipe 6: Ask Milo about a specific token

Use the market-analyst agent for token research. It can pull market data, analyze trends, and give you a thesis.

# 1. Ask the market analyst about a token
curl -X POST {{BASE_URL}}/api/v1/users/{userId}/conversations \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "What do you think about RENDER? Give me a full analysis — fundamentals, technicals, and whether it fits my current portfolio.",
    "agentType": "market-analyst"
  }'

# 2. Poll for the response
curl "{{BASE_URL}}/api/v1/users/{userId}/conversations/{conversationId}/messages" \
  -H "X-API-Key: $API_KEY"

# 3. Follow up with more questions in the same conversation
curl -X POST {{BASE_URL}}/api/v1/users/{userId}/conversations/{conversationId}/messages \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "message": "Compare it with RNDR vs HNT for a DePIN play. Which is the better entry right now?" }'

Tip: The market-analyst agent focuses on research and analysis. If you want Milo to actually execute a trade based on the analysis, either create an order manually or switch to the auto-trader agent.


Putting it all together

A typical session with Milo looks like:

  1. Check in — Fetch positions and holdings (Recipes 4)
  2. Strategize — Talk to the auto-trader about adjusting your approach (Recipe 3)
  3. Research — Ask the market analyst about tokens you're curious about (Recipe 6)
  4. Validate — Revalidate existing positions with fresh analysis (Recipe 5)
  5. Act — Let the auto-trader handle execution, or place manual orders via the Orders API

Run the heartbeat protocol every 4+ hours to keep this cycle going automatically.


Complete API Reference

Authentication

All endpoints (except signup) require:

X-API-Key: <api_key>

Me

GET /api/v1/me

Get the current user profile and wallets for the authenticated API key. Use this to discover your userId and walletId values.

curl {{BASE_URL}}/api/v1/me \
  -H "X-API-Key: $API_KEY"

Response (200):

{
  "user": {
    "id": "uuid",
    "signupWalletId": "uuid",
    "provider": "siwx",
    "createdAt": "2025-01-01T00:00:00.000Z"
  },
  "wallets": [
    { "id": "uuid", "address": "<address>", "chain": "solana", "type": "signup" },
    { "id": "uuid", "address": "<address>", "chain": "solana", "type": "milo" }
  ]
}

Signup

Signup is a two-step process: first request a SIWX message from the server, then sign it and submit the proof.

POST /api/v1/users/siwx/message

Generate a SIWX message for the wallet to sign. This is step 1 of signup.

curl -X POST {{BASE_URL}}/api/v1/users/siwx/message \
  -H "Content-Type: application/json" \
  -d '{
    "accountAddress": "<wallet-address>",
    "chainId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
  }'

Request body:

FieldTypeRequiredDescription
accountAddressstringyesSolana wallet address (32-64 chars)
chainIdstringyesCAIP-2 chain ID (e.g. solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp)
inviteCodestringnoOptional invite code

Response (200):

{
  "data": {
    "data": {
      "accountAddress": "<wallet-address>",
      "chainId": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
      "domain": "andmilo.com",
      "uri": "https://andmilo.com",
      "version": "v1",
      "nonce": "<server-generated-nonce>",
      "issuedAt": "2025-06-15T12:00:00.000Z",
      "expirationTime": "2025-06-22T12:00:00.000Z",
      "statement": "By signing, you agree to andmilo Terms of Use..."
    },
    "message": "andmilo.com wants you to sign in with your Solana account:\n<wallet-address>\n\n..."
  }
}

Sign the message string (UTF-8 encoded bytes) with the wallet's ed25519 private key. Base58-encode the signature. Then proceed to step 2.

POST /api/v1/users

Create a new user via SIWX wallet verification. This is step 2 of signup.

curl -X POST {{BASE_URL}}/api/v1/users \
  -H "Content-Type: application/json" \
  -d '{
    "signupWallet": "<wallet-address>",
    "siwx": {
      "data": <data-object-from-siwx-message-response>,
      "message": "<message-string-from-siwx-message-response>",
      "signature": "<base58-ed25519-signature>"
    }
  }'

Important: Pass the data and message fields exactly as returned by POST /api/v1/users/siwx/message. Do not construct them manually.

Response (200):

{
  "data": {
    "user": { "id": "uuid", "signupWalletId": "uuid", "provider": "siwx", "createdAt": "..." },
    "wallets": [
      { "id": "uuid", "address": "<address>", "chain": "solana", "type": "signup" },
      { "id": "uuid", "address": "<address>", "chain": "solana", "type": "milo" }
    ],
    "apiKey": "mk_live_..."
  }
}

Auto-Trade Settings

GET /api/v1/users/{userId}/auto-trade-settings

Get current auto-trade configuration.

curl {{BASE_URL}}/api/v1/users/{userId}/auto-trade-settings \
  -H "X-API-Key: $API_KEY"
PATCH /api/v1/users/{userId}/auto-trade-settings

Update auto-trade configuration.

curl -X PATCH {{BASE_URL}}/api/v1/users/{userId}/auto-trade-settings \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "isActive": true,
    "riskTolerance": "balanced",
    "strategy": "SWING TRADER",
    "instructions": "Focus on SOL ecosystem tokens",
    "customTickers": ["SOL", "JUP", "BONK"],
    "dataSources": { "fundingRates": true, "openInterest": true },
    "assetClassSettings": {
      "memes": { "dataSources": { "liquidationData": true } },
      "majors": { "dataSources": { "macroData": true } }
    }
  }'

Settings fields:

FieldTypeValues
isActivebooleanEnable/disable auto-trading
riskTolerancestringconservative, balanced, degen
strategystringVALUE INVESTOR, SWING TRADER, SCALPER, CUSTOM
strategyIduuid | nullLink a saved strategy to auto-trade settings
modelVersionstring | nullPreferred model
instructionsstringFree-text trading instructions for the agent
customTickersstring[]Specific tokens to focus on
allocationobjectAsset class allocation percentages
dataSourcesobject | nullGlobal data-source toggles: fundingRates, openInterest, liquidationData, macroData
assetClassSettingsobject | nullPer-asset-class configuration, including nested dataSources overrides

Asset classes for allocation: trenches, memes, promising-memes, staking, native, majors, stables, xStocks, custom

Data-source resolution notes:

  • Asset-class dataSources overrides win over top-level dataSources.
  • If no override exists, the top-level value applies.
  • Missing keys are treated as disabled.
  • PATCH deep-merges dataSources both globally and inside assetClassSettings, so partial updates do not wipe sibling keys.

Model entitlement notes:

  • Only canonical model ids are accepted on the partner surface.
  • Canonical OpenAI model ids are o3, gpt-5.2-high, gpt-5.2-xh, and gpt-5.4.
  • Canonical Anthropic model ids are claude-opus-4.5 and claude-opus-4.6.
  • Canonical Gemini model ids are gemini-3-pro and gemini-3.1-pro-preview.
  • Canonical Grok model ids are grok-4.1-fast-reasoning and grok-4.
  • If a model is unavailable for your account, the API returns 400 Bad Request with error.details.requiredPlan, error.details.upgradeUrl, and an error message containing the same plan-specific Stripe link.

Data-source entitlement notes:

  • Only pro and max users can create, update, apply, sync, or otherwise change dataSources.
  • Free users can still read saved dataSources in GET responses.
  • If an account downgrades, saved dataSources remain visible but are inactive in auto-trader chat, execution, and position review until the account is back on Pro or Max.
  • When blocked, the API returns 400 Bad Request with error.details.feature = "dataSources", error.details.requiredPlan = "pro", and upgrade details when available.

Strategies

Strategies are reusable autotrade configurations that live under auto-trade settings. Create a strategy, link it to your settings, and sync when the strategy evolves.

Workflow:

  1. Create a strategy with allocation, instructions, and trading approach.
  2. Link it via PATCH /auto-trade-settings with { "strategyId": "<uuid>" }. This takes a snapshot of the strategy into your settings.
  3. Use — Milo auto-trades according to the snapshot.
  4. If the strategy is updated later, the GET settings response includes strategySync.synced: false.
  5. Sync — call POST .../strategies/{strategyId}/sync to re-apply the latest version.

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
31
Forks
3
Last commit
Jul 2026
Advanced
Catalog kind
skill
Gateway key
milo-solana-portfolio
Source
github.com/itamarzand88/awesome-agent-conventions