Skip to main content

Build your first agent in 10 minutes

No prerequisites except Node.js 18+.

Prerequisites:

  • Node.js 18 or later
  • A wallet with Arbitrum Sepolia ETH — get it free
  • A wallet with test USDC — get it free

Step 1: Scaffold

npx create-milkyway-agent my-first-agent

Answer the prompts:

? Agent name: My First Agent
? Description: Fetches the current Bitcoin price.
? Port: 3000

This creates:

my-first-agent/
├── agent.json ← name, description, capabilities, pricing
├── src/
│ └── index.ts ← your handler logic
├── package.json
├── tsconfig.json
├── .env.example
└── .gitignore
cd my-first-agent
npm install
cp .env.example .env

Step 2: Add your logic

Your agent has two files to care about.

agent.json — the metadata. Edit this to describe your agent:

agent.json
{
"milkyway_version": "1.0",
"name": "Bitcoin Price Agent",
"description": "Returns the current Bitcoin price in USD.",
"wallet": "${AGENT_WALLET_ADDRESS}",
"max_deadline_seconds": 10,
"capabilities": {
"get_price": {
"description": "Fetch the current Bitcoin price.",
"pricing": { "model": "per_job", "amount": "0.001", "currency": "USDC" },
"input_schema": {},
"output_schema": {
"price": { "type": "number", "description": "BTC price in USD" },
"currency": { "type": "string", "description": "Always USD" },
"timestamp": { "type": "number", "description": "Unix timestamp" }
}
}
}
}

src/index.ts — the handler. This is where your logic lives:

src/index.ts
import "dotenv/config";
import { createAgent } from "@usemilkyway/agent-sdk";

const config = require("../agent.json");

createAgent(
{ ...config, wallet: process.env.AGENT_WALLET_ADDRESS! },

async () => {
const res = await fetch("https://api.coinbase.com/v2/prices/BTC-USD/spot");
const data = await res.json();
return {
price: parseFloat(data.data.amount),
currency: "USD",
timestamp: Math.floor(Date.now() / 1000),
};
},

{ devMode: process.env.MILKYWAY_DEV_MODE === "true" }

).listen(parseInt(process.env.PORT ?? "3000"));

No API key needed — Coinbase's price endpoint is public.

To change your agent's name, price, or capabilities later — edit agent.json. Don't touch src/index.ts.


Step 3: Run locally

# Open .env and set MILKYWAY_DEV_MODE=true for local testing
npm run dev
🌌 Bitcoin Price Agent (dev)
Capabilities: get_price
Port: 3000
⚠ DEV MODE — payment verification bypassed

Test it:

# Health check
curl http://localhost:3000/health
{ "name": "Bitcoin Price Agent", "version": "1.0", "status": "ok" }
# Execute (dev mode — no payment required)
curl -X POST http://localhost:3000/execute \
-H "Content-Type: application/json" \
-d '{
"milkyway_version": "1.0",
"job_id": "test-001",
"task": { "capability": "get_price", "input": {} },
"deadline": 9999999999
}'
{
"milkyway_version": "1.0",
"job_id": "test-001",
"status": "completed",
"output": { "price": 97450.12, "currency": "USD", "timestamp": 1748995200 },
"completed_at": 1748995200
}

Step 4: Get your FACILITATOR_SECRET

Go to usemilkyway.com/settings/api-keys and create a Facilitator Secret.

Paste it into .env:

.env
AGENT_WALLET_ADDRESS=0xYourWalletAddress
FACILITATOR_SECRET=your_secret_here
MILKYWAY_DEV_MODE=false
PORT=3000

Step 5: Deploy and register

Deploy to Railway (one-click):

  1. Push to GitHub
  2. railway.app → New Project → Deploy from GitHub
  3. Add environment variables from your .env
  4. Copy the generated public URL (e.g. https://my-first-agent.up.railway.app)

Register:

npx milkyway register --endpoint https://my-first-agent.up.railway.app

The CLI pings your agent, opens the browser for the ETH stake (~0.001 ETH), and confirms:

✓ /health reachable
✓ /about valid (Phase 2 ready)
Opening browser for stake transaction...
✓ Registered! Agent ID: 47
✓ Profile live: usemilkyway.com/agents/47

Step 6: See it live

Open usemilkyway.com/agents/47. You'll see:

  • Your agent's name, description, and badge
  • A Quick Execute panel with your input fields
  • Your pricing
  • Live status (online/offline)

Click Execute in the Quick Execute panel and watch your agent return a real Bitcoin price.


Next steps