Welcome to Agents Academy

Module 09 · Building · ~10 min

agents-starter.

By the end of this module, you’ll have a real, runnable trading agent on your laptop, not a tutorial snippet, but the same starter every Limitless agent in production was forked from.

To get there, you’ll work with the bootstrap repo for Limitless agents. Clone it, dry-run certainty-closer (the SDK-only strategy SKILL.md recommends as your first run, no extra feeds or setup), graduate to the flagship cross-market-mm, and read SKILL.md as a coding-agent operating manual. Module 10 then teaches the parallel paradigm, custom write-side skills your runtime LLM agent calls as tools.

Building tier · Reference card
Quick answer

What is the agents-starter repo for Limitless trading agents?

agents-starter (github.com/limitless-labs-group/agents-starter) is the Node.js/TypeScript bootstrap repo Limitless production agents are forked from: three runnable strategies (cross-market-mm, oracle-arb, certainty-closer), a redeem utility, and SKILL.md, an operating manual a coding agent like Claude Code or OpenClaw can follow end to end. The paradigm differs from a runtime tool-use loop: strategies are plain TypeScript built on the official @limitless-exchange/sdk, and the LLM sits outside the repo as a coding agent that reads SKILL.md (~3,300 lines, the source of truth over the README) and drives the npm scripts. Credentials live in .env: PRIVATE_KEY for a dedicated trading wallet plus the primary scoped HMAC token (LMTS_TOKEN_ID, LMTS_TOKEN_SECRET), with DRY_RUN=true as the default so decisions print without orders hitting the chain. SKILL.md recommends certainty-closer, the SDK-only strategy with no external feeds, as the first dry run; the exact install, init, funding, and deploy steps are canonical in the repo’s AGENTS.md, QUICKSTART, and SKILL.md, not in any lesson.

Verified against source, 2026-06-09.

The repo is the source of truth for setup and run commands.

This module teaches the why; the exact, current how (install, the guided init, funding via the deposit-wallet bridge and the deposit command, deploy, the operator-panel data contract) lives in the repo and changes with the code. Read it there, do not rely on commands copied into a lesson: AGENTS.md (the operating contract), QUICKSTART, and SKILL.md.

Section 01

Repo tour.

github.com/limitless-labs-group/agents-starter is a Node.js/TypeScript bootstrap repo built as an OpenClaw skill. It ships three concrete strategies (cross-market-mm [the flagship cross-venue market maker], oracle-arb, certainty-closer) plus a redeem utility and per-strategy analyze. Install via the one-line installer (curl -fsSL … | sh) or git clone + npm install + npm run cross-market-mm:init. Your first dry-run is certainty-closer, the SDK-only starting point SKILL.md recommends.

Paradigm shift from Modules 04–06

Modules 04–06 covered runtime tool-use agents: an LLM loop that calls browse_markets, place_limit_order, etc. as tools. The agents-starter repo uses a different paradigm: you write trading strategies in plain TypeScript, and a coding agent (Claude Code, OpenClaw, or any agent with file + shell access) reads SKILL.md and runs the strategies via npm run …. Both paradigms are valid; this module teaches the second one. You can mix, the trading strategies here can be called as tools from a Module 04–06-style runtime agent too.

Top-level layout:

src/core/

Built on official SDKs (not a hand-rolled client): limitless/sdk-trading.ts (SDKTradingClient wrapping @limitless-exchange/sdk), limitless/markets.ts, limitless/redeem.ts, limitless/portfolio.ts, limitless/websocket.ts, limitless/approve.ts, limitless/derive-token.ts, limitless/types.ts (trading.ts/sign.ts are LEGACY); polymarket/{client,ws}; price-feeds/hermes.ts; telegram/client.ts; kelly.ts; and a wallet.ts wrapper around viem.

src/strategies/

A base-strategy.ts abstract class plus three concrete strategies in their own folders: cross-market-mm/ (the flagship, with its own runtime loop and subcommands, not BaseStrategy), oracle-arb/, and certainty-closer/ (both extend BaseStrategy). Each contains an index.ts (the strategy class) and a run.ts (the CLI runner). There is also a tests/ suite (vitest) and .github/workflows/ci.yml. The canonical pattern for adding your own strategy is shown in Section 04.

SKILL.md

The operating manual for a coding agent. When Claude Code or OpenClaw opens the repo, it reads SKILL.md to learn the setup wizard, the scoped HMAC token auth (LMTS_TOKEN_ID + LMTS_TOKEN_SECRET are the PRIMARY credentials; the SDK auto-signs requests), the safety env vars, and the iteration loop. It’s ~3,300 lines, treat it as the source of truth for the repo, not the README. Each strategy folder also has its own SKILL.md/QUICKSTART.md.

.env.example

Template covering PRIVATE_KEY plus the primary scoped HMAC token (LMTS_TOKEN_ID, LMTS_TOKEN_SECRET; legacy LIMITLESS_API_KEY is only a fallback), the DRY_RUN=true default, and per-strategy sizing (ORACLE_BET_SIZE; CC_BANKROLL/CC_MAX_RISK/CC_KELLY_FRACTION; cross-market-mm uses order_size + a max_loss_usd circuit-breaker in its YAML config). Defaults to dry-run.

docs.limitless.exchange/mcp

A live MCP endpoint over JSON-RPC + SSE that exposes two tools: search_limitless_exchange (semantic search across docs) and query_docs_filesystem_limitless_exchange (read-only shell into a virtualised docs filesystem, rg, cat, tree, etc). SKILL.md instructs coding agents to query the MCP before writing any new API call, treat it as the source of truth for endpoint shapes and error codes.

Section 02

The starter strategies.

The repo ships with three ready-to-run strategies plus a redeem utility and per-strategy analyze. Each strategy lives under src/strategies/<name>/ as index.ts plus run.ts (the runner). oracle-arb and certainty-closer extend BaseStrategy, whose base class drives the loop, initialize()tick() → execute decisions → wait → repeat, while the flagship cross-market-mm runs its own runtime loop. Module 10 walks the parallel paradigm (skills for runtime LLM agents); the canonical pattern for writing your own BaseStrategy is shown in Section 04 below.

certainty-closer

SKILL.md first run

Certainty closer (recommended first run, SDK-only)

Buys near-resolution favourites, sized with fractional Kelly (core/kelly.ts). No external feeds, the simplest template, which is why SKILL.md uses it for the first dry run.

npm run certainty-closer

oracle-arb

Oracle arbitrage

Connects to Pyth Hermes SSE for sub-second oracle prices and fires FOK orders against the actual orderbook ask when the market hasn’t priced in the move. Includes orderbook validation, position tracking, and auto-approval. The most complete reference example.

npm run oracle-arb

cross-market-mm

Flagship

Cross-market market maker

Quotes on Limitless and hedges fills on Polymarket for a delta-neutral book; earns cross-venue spread + Limitless maker rebates + LP rewards. Runs its own runtime loop with subcommands (init/find-pairs/setup-poly/preflight/flatten/close/status/analyze) and a YAML config.

npm run cross-market-mm

ops utilities

Redeem, analyze, observability

A redeem CLI with check <slug>, claim <slug>, claim-many, and claim-all subcommands; per-strategy analyze that reads your trade log for win rate by asset, edge distribution, and parameter suggestions; and observability via per-strategy :status JSON (e.g. data/cross-market-mm-status.json) plus optional Telegram alerts.

npm run redeem claim-all · npm run cross-market-mm:analyze · npm run cross-market-mm:status

Section 03

Running the starter.

Clone the repo, npm install, copy .env.example to .env, and run one of the strategies. It starts in dry-run mode by default (DRY_RUN=true), every decision is printed, but no orders hit the chain. Leave it in dry-run for at least one full day before flipping DRY_RUN=false. SKILL.md’s setup wizard recommends certainty-closer as the first strategy to dry-run because it is SDK-only and needs no external feeds or extra configuration. The repo is Node.js/TypeScript; there is no Python flavour.

How to run this

  1. Install Node 18+ (node --version) and make sure git and npm are on your PATH.
  2. After cp .env.example .env, fill in PRIVATE_KEY and the primary scoped HMAC token (LMTS_TOKEN_ID, LMTS_TOKEN_SECRET), keep DRY_RUN=true, and set per-strategy sizing. Bridge a few USDC on Base plus a small amount of ETH for gas to the wallet before flipping DRY_RUN=false.
  3. Run the shell block above line-by-line, clone, npm install, npm run cross-market-mm:init to bootstrap, then npm run certainty-closer from the agents-starter directory. Confirm zero orders are placed before moving to live trading.
  4. Watch the per-strategy status file in another terminal via npm run cross-market-mm:status (or wire up optional Telegram alerts) to track live positions and PnL. Once positions resolve, run npm run redeem claim-all to convert winning tokens to USDC.
# Module 09: Clone and run the starter
# Real README: https://github.com/limitless-labs-group/agents-starter
# Source of truth: SKILL.md at the repo root

# One-line installer (clone + install in one step):
#   curl -fsSL https://raw.githubusercontent.com/limitless-labs-group/agents-starter/main/install.sh | sh
# ...or do it by hand:
git clone https://github.com/limitless-labs-group/agents-starter.git
cd agents-starter

# 1. Install dependencies (Node 18+ required)
npm install

# 2. Set env vars (copy .env.example to .env, then edit)
cp .env.example .env
# REQUIRED:
#   PRIVATE_KEY=0x...                  (dedicated trading wallet, NOT your main)
#   LMTS_TOKEN_ID=...                  (primary scoped HMAC token; SDK auto-signs)
#   LMTS_TOKEN_SECRET=...              (legacy LIMITLESS_API_KEY is only a fallback)
# SAFETY (default):
#   DRY_RUN=true
# PER-STRATEGY SIZING (tune before going live):
#   ORACLE_BET_SIZE=...                (oracle-arb)
#   CC_BANKROLL=... CC_MAX_RISK=... CC_KELLY_FRACTION=...   (certainty-closer)
#   cross-market-mm: order_size + max_loss_usd circuit-breaker in its YAML config

# Fund the wallet with USDC + a few cents of ETH for gas on Base.

# 3. Bootstrap, then dry-run the recommended starter strategy
npm run cross-market-mm:init   # guided bootstrap (config + checks)
npm run certainty-closer       # SDK-only first dry-run (per SKILL.md)

# Expected output (illustrative):
#   Certainty Closer
#     Mode: DRY RUN (no trades)
#     Buying near-resolution favourites, fractional Kelly sizing
#   [info] Wallet initialized {"address":"0xabc..."}
#   [info] Scanning 9 near-resolution markets (favourite ≥ 0.90)
#   [info] DRY → would BUY YES @ 0.94, kelly-size $0.42, edge=0.04

# 4. Other strategies
npm run oracle-arb           # Pyth Hermes SSE oracle arb (FOK orders)
npm run cross-market-mm      # flagship cross-venue market maker (delta-neutral)

# 5. Ops utilities
npm run redeem claim-all     # claim every resolved position via the SDK
                             # (npm 7+; on npm 6 use: npm run redeem -- claim-all)
npm run cross-market-mm:status   # read data/cross-market-mm-status.json
npm run cross-market-mm:analyze  # win rate by asset, edge distribution from your trade log

# 6. Install PM2 once for long-running supervision (used in step 8 for go-live)
npm i -g pm2

# 7. Pre-approve a market before going live (recommended for clean demos)
#    Without this, the first BUY order fails with "Insufficient collateral allowance".
#    The approval covers every market sharing the same exchange venue.
npx tsx src/index.ts approve <any-active-market-slug>

# 8. Go live when you're ready: set DRY_RUN=false in .env, restart.

Section 04

SKILL.md & strategy customisation.

The starter doesn’t have a “system prompt” file because the runtime isn’t an LLM loop, the LLM sits outside the repo as a coding agent. Instead, SKILL.md at the repo root is the operating manual: it walks the agent through clone → install → configure → dry-run → approve → go live, with a Quick Start prompt at the top that hands the wizard off in one paste. To specialise behaviour, you either (a) tune the per-strategy env vars in .env, (b) edit a strategy class under src/strategies/<name>/index.ts, or (c) write your own strategy by extending BaseStrategy, the canonical pattern is shown below.

// Module 09: src/strategies/my-strategy/index.ts
// Extend BaseStrategy, implement initialize / tick / shutdown / getStats.
// The base class drives the loop: it calls tick() on a timer and executes
// each TradeDecision via SDKTradingClient. DRY_RUN is honoured automatically.
//
// Note: imports use the .js extension because the repo is ESM ("type":"module").

import {
  BaseStrategy,
  StrategyConfig,
  TradeDecision,
  StrategyStats,
} from '../base-strategy.js';
import { LimitlessClient } from '../../core/limitless/markets.js';
import { SDKTradingClient } from '../../core/limitless/sdk-trading.js';

export class MyStrategy extends BaseStrategy {
  constructor(
    config: StrategyConfig,
    deps: { limitless: LimitlessClient; trading: SDKTradingClient },
  ) {
    super(config, deps);
    this.tickIntervalMs = 30_000; // how often tick() runs; default is 60_000
  }

  async initialize(): Promise<void> {
    // One-time setup: warm caches, load state, check approvals.
    this.logger.info('MyStrategy initialised');
  }

  async tick(): Promise<TradeDecision[]> {
    // 1. Discover candidate markets (CLOB venue only).
    const markets = await this.limitless.getActiveMarkets({ tradeType: 'clob' });

    // 2. Decide. TradeDecision shape is the contract: see base-strategy.ts.
    const decisions: TradeDecision[] = [];
    for (const market of markets) {
      const yesPrice = market.prices[0] / 100; // prices are 0–100
      if (yesPrice < 0.45) {
        decisions.push({
          action:     'BUY',
          marketSlug: market.slug,
          side:       'YES',
          amountUsd:  1.0,
          priceLimit: Math.floor((yesPrice + 0.02) * 100), // cents
          reason:     `YES at ${yesPrice.toFixed(2)} below 0.45 floor`,
        });
      }
    }
    return decisions; // the base class submits these via this.trading.createOrder()
  }

  async shutdown(): Promise<void> {
    this.logger.info('MyStrategy shutting down');
  }

  getStats(): StrategyStats {
    return { activePositions: 0, totalVolumeUsd: 0, pnlUsd: 0, lastTickDurationMs: 0 };
  }
}

// Add a runner at src/strategies/my-strategy/run.ts that wires LimitlessClient
// and SDKTradingClient together (mirror src/strategies/oracle-arb/run.ts).
// Then a package.json script:
//   "my-strategy": "npx tsx src/strategies/my-strategy/run.ts"
//
// Then: npm run my-strategy
Common questions

The agents-starter repo: what people ask

Each answer also ships invisibly as schema.org FAQ data for search engines and AI assistants. Tap a question to expand.

  1. What strategies ship with agents-starter?
    Three, each under src/strategies/<name>/: certainty-closer buys near-resolution favourites sized with fractional Kelly, no external feeds; oracle-arb connects to Pyth Hermes SSE for sub-second oracle prices and fires FOK orders against the actual orderbook ask; and cross-market-mm, the flagship, quotes on Limitless and hedges fills on Polymarket for a delta-neutral book. A redeem CLI (check, claim, claim-many, claim-all) and per-strategy analyze round out the ops surface.
  2. Which agents-starter strategy should you dry-run first?
    certainty-closer: it is the SDK-only starting point SKILL.md recommends because it needs no external feeds or extra configuration. The repo defaults to DRY_RUN=true, so every trade decision is printed but no orders hit the chain. Leave it in dry-run for at least one full day, and confirm zero orders were placed, before flipping DRY_RUN=false.
  3. What is SKILL.md and why does it matter?
    SKILL.md at the repo root is the operating manual a coding agent reads when it opens agents-starter: a setup wizard from clone to go-live, the scoped HMAC token auth, the safety env vars, and the iteration loop. At ~3,300 lines, treat it as the source of truth for the repo, not the README. It also points agents at the live docs MCP endpoint, docs.limitless.exchange/mcp, to query before writing any new API call.
  4. What credentials and funding does agents-starter need?
    PRIVATE_KEY for a dedicated trading wallet (never your main) plus the primary scoped HMAC token, LMTS_TOKEN_ID and LMTS_TOKEN_SECRET; the SDK auto-signs requests, and the legacy LIMITLESS_API_KEY is only a fallback. Before going live, bridge a few USDC on Base plus a small amount of ETH for gas. Secrets stay in environment variables: a tool schema that accepts an API key as an argument makes the model the source of secrets, and the leak is silent.
  5. How is the coding-agent paradigm different from runtime tool use?
    Runtime tool-use agents are an LLM loop calling functions like browse_markets as tools. agents-starter inverts that: strategies are plain TypeScript (your own extends BaseStrategy and implements initialize, tick, shutdown, getStats), and a coding agent with file and shell access reads SKILL.md and runs them. Both paradigms are valid and they compose: the starter strategies can be called as tools from a runtime agent too.

Module checklist

Five quick confirmations.

Tick each item once you’ve actually done it. The Continue button unlocks at 5/5.

Module 09 complete

Bootstrap ready.

Your agent has gone from notebook to repo. It’s a proper project now, with the structure, dry-run discipline, and operating manual that turn an experiment into something you’d actually deploy.

Concretely, you have a working starter agent running in dry-run mode. A real repo, three reference strategies (cross-market-mm, oracle-arb, certainty-closer) and a coding-agent operating manual, the scaffold every Production-tier module builds on.

01

A cloned agents-starter repo with .env configured for PRIVATE_KEY, the scoped HMAC token (LMTS_TOKEN_ID/LMTS_TOKEN_SECRET), DRY_RUN=true, and per-strategy sizing, the same layout every Production-tier module assumes.

02

Three runnable reference strategies (cross-market-mm, oracle-arb, certainty-closer), per-strategy status files + analyze, and a redeem CLI with claim-all, all behind npm run <name>.

03

A working mental model of the coding-agent paradigm: SKILL.md as runbook, the docs.limitless.exchange/mcp live-docs endpoint as the source of truth, BaseStrategy.tick() as the extension point, and the composability story that lets Module 04–06 tool-use agents orchestrate these same strategies.

Next up: the parallel paradigm, writing custom write-side skills a runtime LLM agent calls as tools, so it can compose CLI reads with native SDK orders.

Complete the checklist above to unlock