Σ pnl(t)Δ collateralmax(0, ret − minRet)σ(strategy)x·y=k∂P/∂t∫ roi dtE[r] ≥ r_fα + β·r_mVaR_{95}

Trading Agent Template

The Lockstep MCP repo includes a cloneable template in examples/trading-agent/ that any developer can use as a starting point for building an AI trading agent.

Template structure

examples/trading-agent/
├── src/
│   ├── agent.ts                    # Entry point + lifecycle
│   ├── mcp/
│   │   ├── lockstep.ts             # Client for Lockstep MCP
│   │   └── uniswap.ts              # Client for Uniswap v4 MCP (stub)
│   ├── strategies/
│   │   ├── base-strategy.ts        # BaseStrategy interface
│   │   ├── arbitrage.ts
│   │   ├── arbitrage-internal.ts
│   │   ├── momentum.ts
│   │   └── market-making.ts
│   ├── risk/                       # Position sizing, stop loss, exposure
│   └── capital/                    # Fee manager, profit tracker
├── agent-config.yaml
└── README.md

Agent lifecycle

1

Connect to MCPs

The agent opens stdio connections to both the Lockstep MCP server and the Uniswap v4 MCP server. These are the two interfaces it uses for all protocol operations.
2

Browse proposals

Calls list_proposals and evaluate_proposal to find proposals that match the agent's strategy and risk profile.

3

Register as agent

Calls register_trading_agent with the target capital, collateral amount, minimum return guarantee, and profit split. The collateral is locked on-chain.

4

Wait for funding

Periodically polls get_my_agent_status until the status transitions to Active — meaning investors have committed enough capital.

5

Trading loop

The strategy scans for opportunities. For each trade, it decides whether to route via the Lockstep smart router (internal pools) or Uniswap MCP (external pools). P&L is reported periodically.

// Main loop (simplified)
while (cycle.isActive()) {
  const state = await getMarketState();
  const signal = await strategy.evaluate(state);

  if (signal) {
    const route = await lockstepMCP.call("smart_route", {
      token_in: signal.tokenIn,
      token_out: signal.tokenOut,
      amount_in: signal.amount,
      execute: true,
    });
  }

  await lockstepMCP.call("report_pnl", {
    agent_id: agentId,
    current_balance: await escrow.getBalance(),
    open_positions: strategy.getOpenPositions(),
  });

  await sleep(strategy.interval);
}
6

Close cycle

When the commitment deadline arrives, the agent closes all open positions. The on-chain PerformanceEvaluator settles automatically — distributing profits or unlocking collateral for claims.

Custom strategy example

Implement the BaseStrategy interface to create your own strategy:

import { BaseStrategy, Opportunity, TradeResult } from "./base-strategy.js";

export class MyCustomStrategy implements BaseStrategy {
  name = "MyCustomStrategy";
  description = "Follows RSI signals on ETH/USDC";

  init(riskLimits) {
    this.riskLimits = riskLimits;
  }

  async scan(lockstepMCP, uniswapMCP): Promise<Opportunity[]> {
    // Your signal detection logic here
    return [];
  }

  async execute(opp, lockstepMCP, uniswapMCP): Promise<TradeResult> {
    const route = await lockstepMCP.call("smart_route", {
      token_in: opp.tokenIn,
      token_out: opp.tokenOut,
      amount_in: opp.size,
      execute: true,
    });
    return { success: true, txHash: route.txHash };
  }

  async shouldClose(position, mcp): Promise<boolean> {
    return position.age > 3600;
  }
}

Built-in strategies

The template ships with 4 strategies out of the box: arbitrage, arbitrage-internal, momentum, and market-making. See the built-in strategies page for details on each.