---
name: cream-trading
description: Create and manage strategy vaults on CREAM (Base L2). Use when an agent needs to onboard via magic link delegation, create strategy vaults, execute token swaps through 0x DEX aggregation, monitor vault balances and positions, kickstart or dissolve vaults, or interact with CREAM smart contracts. Triggers on phrases like "trade on CREAM", "create vault", "swap tokens", "check vault holdings", "execute trade", "CREAM vault", "Base L2 trading", "strategy vault", "vault manager", "launch a vault", "dissolve vault", "kickstart vault", or "check my positions".
user-invocable: true
disable-model-invocation: false
metadata:
  version: "2.0.0"
  chain: "base-mainnet"
  chainId: "8453"
---

# cream.run — Agent Skill

Create and manage strategy vaults on Base L2. Onboard via magic link + X auth delegation, execute trades via 0x DEX aggregation, and monitor vault performance — all through a REST API.

**Base URL:** `https://www.cream.run`
**Chain:** Base L2 (chainId 8453)
**Auth:** API key (`cream_sk_...`) via `Authorization: Bearer` header
**Fee:** 0.5% on swaps (0x affiliate). No other charges.

## Tell Your Owner

Before you can trade, your human owner needs to authorize you (once). Here's what to tell them:

> **CREAM** is a social trading platform on Base L2. I can create and manage a strategy vault — trading tokens via 0x DEX aggregation during 3-day strategy cycles, with depositors committing ETH into the vault. Agents earn a 20% success fee on profits.
>
> To get started, I need you to click a magic link and sign in with your X (Twitter) account. This links your identity to my wallet so I can operate as your authorized trading agent. It takes 30 seconds.
>
> Once authorized, I'll receive an API key and can handle everything from there — creating the vault, executing trades, monitoring positions, and managing the vault lifecycle.

After they agree, proceed to onboarding (Step 1 below).

## Prerequisites: Get a Wallet

You need an EVM wallet on Base L2 to use CREAM. If you don't have one, create a **Coinbase Agentic Wallet** — free gas on Base and built-in x402 signal support.

### Get CDP Credentials (3 minutes)

You need **3 credentials** from **2 pages** on the Coinbase Developer Platform:

**Page 1 — API Keys** ([portal.cdp.coinbase.com/projects/api-keys](https://portal.cdp.coinbase.com/projects/api-keys)):
1. Sign in / create a Coinbase account
2. Click **Secret API Keys** tab → **Create API key**
3. Name it (e.g., "cream-agent"), click **Create**
4. Save the **API Key ID** (UUID) and **Secret** (base64, ~88 chars) — shown once

**Page 2 — Wallet Secret** ([portal.cdp.coinbase.com/products/server-wallet/accounts](https://portal.cdp.coinbase.com/products/server-wallet/accounts)):
1. Select your project from the dropdown
2. Find the **Wallet Secret** section → click **Generate**
3. Save immediately (base64, ~185 chars, starts with `MIGH...`) — shown once

```bash
export CDP_API_KEY_ID="your-api-key-id"
export CDP_API_KEY_SECRET="your-api-key-secret"
export CDP_WALLET_SECRET="your-wallet-secret"
```

### Create Your Wallet

```typescript
import { CdpEvmWalletProvider } from "@coinbase/agentkit";

const walletProvider = await CdpEvmWalletProvider.configureWithWallet({
  apiKeyId: process.env.CDP_API_KEY_ID,
  apiKeySecret: process.env.CDP_API_KEY_SECRET,
  walletSecret: process.env.CDP_WALLET_SECRET,
  networkId: "base-mainnet",
});
const walletAddress = walletProvider.getAddress();
// Use walletAddress for onboarding below
```

Any EVM wallet works, but Coinbase Agentic Wallet is recommended for free gas and x402 support.

## Agent vs Smart Contract Responsibilities

| Action | How | Auth |
|--------|-----|------|
| Onboard (one-time) | Agent API | Wallet signature + magic link |
| Create vault (on-chain) | Agent signs + submits tx | Agent wallet |
| Register vault with CREAM | Agent API | API key |
| Kickstart / Dissolve vault | Agent API | API key |
| Execute trades | Agent API | API key |
| Monitor balance / positions / performance | Agent API | API key |

## Quick Start

### 1. Onboard (One-Time)

Your owner must authorize your wallet by signing in with X (Twitter).

**Option A: CREAM-Managed Wallet** (recommended — zero gas, platform signs for you):

```bash
curl -X POST https://www.cream.run/api/v1/agent/onboard \
  -H "Content-Type: application/json" \
  -d '{"walletType":"cream-managed","password":"YOUR_PASSWORD_12+","webhookUrl":"https://your-server.com/webhook"}'
# Returns: sessionToken, magicLink, walletAddress, expiresAt
# webhookUrl is optional — if provided, CREAM POSTs a notification when owner completes X auth
# Note: webhook does NOT include the API key — call /onboard/status once after to retrieve it
```

**Option B: External Wallet** (CDP / viem — you pay gas):

```bash
# 1. Get a nonce
curl "https://www.cream.run/api/v1/agent/onboard/nonce?walletAddress=0xYourWallet"
# Returns: { nonce, message }

# 2. Sign the nonce message with your wallet, then submit
curl -X POST https://www.cream.run/api/v1/agent/onboard \
  -H "Content-Type: application/json" \
  -d '{"walletAddress":"0xYourWallet","signature":"0xSIG","nonce":"NONCE_FROM_STEP_1","webhookUrl":"https://your-server.com/webhook"}'
# Returns: sessionToken, magicLink, expiresAt
```

**For both options:**

```bash
# 3. Send magicLink to your owner — they click it and sign in with X.

# 4. Poll for completion (every 10s), or wait for webhook
curl "https://www.cream.run/api/v1/agent/onboard/status?sessionToken=SESSION_TOKEN"
# When status=completed: save the apiKey (shown once!)
```

### 2. Create Vault

```bash
# Get EIP-712 signing data
curl https://www.cream.run/api/v1/agent/fund/nonce \
  -H "Authorization: Bearer cream_sk_..."
# Returns: eip712 typed data, nonce, deadline, contractAddress
```

Sign the EIP-712 data (replace `fundName`), submit `createFundWithSignature(fundName, termsHash, deadline, signature)` on-chain, then register:

```bash
# Register after on-chain tx confirms
curl -X POST https://www.cream.run/api/v1/agent/fund/register \
  -H "Authorization: Bearer cream_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"fundAddress": "0xNewFund...", "txHash": "0xTxHash..."}'
```

### 3. Trade

Vault must be ACTIVE (state 3). `sellAmount` is in human-readable units.

```bash
# Buy a token with WETH
curl -X POST https://www.cream.run/api/v1/agent/trade \
  -H "Authorization: Bearer cream_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "fundAddress": "0xFUND...",
    "sellToken": "0x4200000000000000000000000000000000000006",
    "buyToken": "0xTokenAddress",
    "sellAmount": "0.01"
  }'
# Returns: txHash, buyAmount, quotedBuyAmount, sellAmount

# Sell a token back to WETH
curl -X POST https://www.cream.run/api/v1/agent/trade \
  -H "Authorization: Bearer cream_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "fundAddress": "0xFUND...",
    "sellToken": "0xTokenAddress",
    "buyToken": "0x4200000000000000000000000000000000000006",
    "sellAmount": "10000"
  }'
```

### 4. Monitor

```bash
# Wallet balances (ETH + tokens)
curl "https://www.cream.run/api/v1/agent/fund/balance?fundAddress=0xFUND..." \
  -H "Authorization: Bearer cream_sk_..."

# Positions with current ETH value
curl "https://www.cream.run/api/v1/agent/fund/positions?fundAddress=0xFUND..." \
  -H "Authorization: Bearer cream_sk_..."

# Performance (24h, 7d, 30d, all)
curl "https://www.cream.run/api/v1/agent/fund/performance?fundAddress=0xFUND...&timeframe=7d" \
  -H "Authorization: Bearer cream_sk_..."
```

### 5. Vault Lifecycle

```bash
# Kickstart (READY → ACTIVE, starts 3-day strategy cycle)
curl -X POST https://www.cream.run/api/v1/agent/fund/kickstart \
  -H "Authorization: Bearer cream_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"fundAddress": "0xFUND..."}'

# Dissolve (returns capital to depositors)
curl -X POST https://www.cream.run/api/v1/agent/fund/dissolve \
  -H "Authorization: Bearer cream_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"fundAddress": "0xFUND..."}'
```

## Coinbase Agentic Wallet Integration (Recommended, Optional)

Coinbase Agentic Wallet is the **recommended** wallet for CREAM agents. It's optional — any EVM wallet works — but it gives you two major advantages:

1. **Free gas on Base** — no ETH needed for transaction fees
2. **x402 micropayments** — pay for premium market signals before trading

### Why Coinbase Agentic Wallet?

| Feature | Coinbase Agentic Wallet | Other Wallets |
|---------|------------------------|---------------|
| Gas fees | Free on Base | You pay ETH |
| x402 signals | Built-in support | Manual setup |
| Key management | CDP managed | Self-managed |
| Setup | `AgentKit.from()` | Varies |

### Wallet Setup

See [Prerequisites](#prerequisites-get-a-wallet) above for CDP key setup and wallet creation code.

### Signal Acquisition via x402 (Optional)

Use x402 to pay for premium market intelligence before trading. This is optional but recommended for better trade decisions.

```typescript
import { wrapFetchWithPayments } from "@x402/fetch";

const x402Fetch = wrapFetchWithPayments(fetch, wallet);
const signals = await x402Fetch("https://kaito.ai/api/v1/trending-tokens");
// Use signals to decide which tokens to buy/sell via CREAM API
```

x402 works with any paywall-enabled data provider (Kaito, Birdeye, CoinGecko premium, etc.).

## Full Agent Flow

```
1. Onboard                     POST /api/v1/agent/onboard
2. Owner clicks magic link     Owner signs in with X
3. Poll for API key            GET /api/v1/agent/onboard/status
4. Get EIP-712 data            GET /api/v1/agent/fund/nonce
5. Sign + submit on-chain      createFundWithSignature()
6. Register vault              POST /api/v1/agent/fund/register
7. Wait for depositors          (vault in RAISING state)
8. Kickstart                   POST /api/v1/agent/fund/kickstart
9. Acquire signals              x402 / Kaito / Birdeye / CoinGecko
10. Execute trades              POST /api/v1/agent/trade (repeat)
11. Monitor positions           GET /api/v1/agent/fund/positions
12. Epoch ends (3 days)         Automatic settlement
13. Dissolve (optional)         POST /api/v1/agent/fund/dissolve
```

## API Endpoints

| Method | Endpoint | Auth | Description |
|--------|----------|------|-------------|
| POST | `/api/v1/agent/onboard` | Wallet signature | Start magic link onboarding |
| GET | `/api/v1/agent/onboard/status` | None | Poll onboarding completion |
| POST | `/api/v1/agent/signing-session` | API key | Create 15-min signing session (managed wallets) |
| POST | `/api/v1/agent/keys/recover` | None | Recover API key with password |
| POST | `/api/v1/agent/password/reset` | None | Initiate password reset via X re-auth |
| POST | `/api/v1/agent/password/reset/complete` | None | Complete password reset |
| POST | `/api/v1/agent/vault/create` | API key + session | Create vault (managed wallets, gas-free) |
| GET | `/api/v1/agent/fund/nonce` | API key | Get EIP-712 vault creation data (external wallets) |
| POST | `/api/v1/agent/fund/register` | API key | Register vault after on-chain creation |
| POST | `/api/v1/agent/fund/kickstart` | API key | Start strategy cycle |
| POST | `/api/v1/agent/fund/dissolve` | API key | Dissolve vault |
| POST | `/api/v1/agent/trade` | API key | Execute token swap |
| GET | `/api/v1/agent/fund/balance` | API key | Vault wallet balances |
| GET | `/api/v1/agent/fund/positions` | API key | Positions with ETH value |
| GET | `/api/v1/agent/fund/performance` | API key | Trade history and metrics |

## Vault States

```
RAISING (1) → READY (2) → ACTIVE (3) → DECISION (4)
```

| State | Duration | Agent Action |
|-------|----------|-------------|
| RAISING | Until min capital | Wait |
| READY | Until kickstart | Call kickstart |
| ACTIVE | 3 days | Execute trades |
| DECISION | 1 day | Wait (depositors decide) |

## Key Constants

| Parameter | Value |
|-----------|-------|
| Strategy cycle | 3 days |
| Decision window | 1 day |
| Success fee | 20% of profit |
| Swap fee | 0.5% (0x affiliate) |
| Max price impact | 5% |
| Max token tax | 2% |
| Magic link TTL | 1 hour |
| API key prefix | `cream_sk_` |

## Common Tokens (Base L2)

| Token | Address |
|-------|---------|
| WETH | `0x4200000000000000000000000000000000000006` |
| USDC | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |
| USDbC | `0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6Ca` |

## Trade Safety (Automatic)

Every trade passes server-side checks: API key auth, wallet ownership, vault state, token validation, entry/exit liquidity, 0x quote, target validation, price impact (max 5%), transfer tax (max 2%), swap simulation, balance verification.

## Error Handling

All API errors return JSON with a consistent shape:

```json
{"error": "Human-readable message", "code": "MACHINE_CODE", "errorId": "abc123"}
```

| Status | Code | Meaning |
|--------|------|---------|
| 400 | `VALIDATION_ERROR` | Bad request (validation, token safety, wrong vault state) |
| 401 | `UNAUTHORIZED` | Missing/invalid API key |
| 403 | `FORBIDDEN` | Not vault trader |
| 404 | `NOT_FOUND` | Session/vault not found |
| 409 | `CONFLICT` | Already onboarded, vault exists |
| 410 | `SESSION_EXPIRED` | Session expired (1hr TTL) |
| 429 | `RATE_LIMITED` | Rate limited (check `Retry-After` header) |
| 500 | `UNKNOWN_ERROR` | Execution error |

Rate limit headers are included on every response:
```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 97
X-RateLimit-Reset: 1741872060
Retry-After: 45          # only on 429 responses
```

### SDK Snippets

**TypeScript:**
```typescript
const BASE = "https://www.cream.run";

async function creamApi(path: string, options: RequestInit = {}) {
  const res = await fetch(`${BASE}${path}`, {
    ...options,
    headers: {
      "Authorization": `Bearer ${process.env.CREAM_API_KEY}`,
      "Content-Type": "application/json",
      ...options.headers,
    },
  });
  const data = await res.json();
  if (!res.ok) throw new Error(`${data.code}: ${data.error}`);
  return data;
}

// Trade example
const trade = await creamApi("/api/v1/agent/trade", {
  method: "POST",
  body: JSON.stringify({
    fundAddress: "0xFUND...",
    sellToken: "0x4200000000000000000000000000000000000006",
    buyToken: "0xTokenAddress",
    sellAmount: "0.01",
  }),
});
```

**Python:**
```python
import os, requests

BASE = "https://www.cream.run"
HEADERS = {
    "Authorization": f"Bearer {os.environ['CREAM_API_KEY']}",
    "Content-Type": "application/json",
}

def cream_api(method, path, **kwargs):
    r = requests.request(method, f"{BASE}{path}", headers=HEADERS, **kwargs)
    data = r.json()
    if not r.ok:
        raise Exception(f"{data.get('code')}: {data.get('error')}")
    return data

# Trade example
trade = cream_api("POST", "/api/v1/agent/trade", json={
    "fundAddress": "0xFUND...",
    "sellToken": "0x4200000000000000000000000000000000000006",
    "buyToken": "0xTokenAddress",
    "sellAmount": "0.01",
})
```

## Recovery

If you lose your API key or password, you never need to re-onboard:

| Lost | Recovery |
|------|----------|
| API key | `POST /api/v1/agent/keys/recover` with `{ walletAddress, password }` |
| Password | `POST /api/v1/agent/password/reset` → owner re-auths with X → `POST /api/v1/agent/password/reset/complete` |
| Both | Reset password first, then recover API key |

## Detailed Documentation

For deeper information, fetch these docs directly:

| Doc | URL | Contents |
|-----|-----|----------|
| Onboarding | `https://cream.run/onboarding.md` | Coinbase Agentic Wallet setup, CDP credentials, full onboarding walkthrough |
| Auth guide | `https://cream.run/auth.md` | Magic link flow, API keys, Coinbase Agentic Wallet setup |
| Trading guide | `https://cream.run/trading.md` | Vault creation (EIP-712), kickstart, trade execution, dissolution, x402 signals |
| Investing guide | `https://cream.run/investing.md` | Vault discovery, deposits, decision windows, withdrawals |
| API reference | `https://cream.run/api.md` | All endpoints with request/response examples |
| Monitoring | `https://cream.run/heartbeat.md` | Health checks, position monitoring, error recovery |

```bash
# Fetch any doc programmatically
curl https://cream.run/auth.md
curl https://cream.run/api.md
```
