API Reference

API Reference — Pulling Data from Nunchi Agents

This guide covers every method for pulling data from a running Nunchi agent. There are three access paths depending on your deployment and use case:

Path
Protocol
Use Case

HTTP REST API

HTTP/JSON

Dashboards, monitoring, external integrations

SSE Feed

Server-Sent Events

Live streaming to frontends

MCP Server

Model Context Protocol

AI agent orchestration (Claude, OpenClaw)

All endpoints are unauthenticated. If your agent is publicly accessible, anyone with the URL can read its state. Plan your network security accordingly.


Prerequisites

Agent Deployment

Your agent must be running in one of two deployment modes:

Self-hosted (Python entrypoint):

# The entrypoint starts a health server on $PORT and the trading process
python scripts/entrypoint.py

The HTTP server binds to 0.0.0.0:$PORT (default 8080).

Railway / OpenClaw (Node.js entrypoint):

# Express server with reverse proxy to OpenClaw gateway
node src/server.js

The Express server binds to 0.0.0.0:$PORT (default 8080) and exposes the same API surface.

Base URL

Throughout this document, $AGENT_URL refers to your agent's base URL:


HTTP REST API

GET /health

Health check endpoint. Use this to verify the agent is reachable and the trading process is alive.

Request:

Response:

Field
Type
Description

status

string

Always "ok" if server is responding

mode

string

RUN_MODE env var: "wolf", "strategy", or "mcp"

uptime_s

int

Seconds since the entrypoint started

pid

int|null

PID of the child trading process

alive

bool

Whether the child process is still running

Notes:

  • This endpoint is used by Railway's health check system (healthcheckPath in railway.toml).

  • Returns 200 even if the trading process has crashed — check alive to distinguish.


GET /api/status

Primary status endpoint. Returns the agent's current state, positions, and PnL.

Request:

Response (WOLF mode):

Response (single-strategy mode):

Response (agent not running):

Field
Type
Present In
Description

status

string

Both

"running" or "stopped"

engine

string

Both

Strategy ID ("wolf", "engine_mm", etc.)

tick_count

int

Both

Number of evaluation cycles completed

daily_pnl

float

WOLF

Today's profit/loss in USD

total_pnl

float

WOLF

Cumulative profit/loss in USD

total_trades

int

WOLF

Number of executed trades

max_slots

int

WOLF

Maximum concurrent positions

active_slots

array

WOLF

Currently open position details (full slot objects)

closed_slots

array

WOLF

Last 5 closed positions

positions

array

WOLF

Simplified position array for UI consumption

instrument

string

Strategy

Trading instrument (e.g., "ETH-PERP")

position_qty

float

Strategy

Net position quantity (positive = long)

unrealized_pnl

float

Strategy

Mark-to-market PnL

realized_pnl

float

Strategy

Locked PnL from closed trades

total_orders

int

Strategy

Orders placed this session

total_fills

int

Strategy

Orders that filled

Data source: Reads from $DATA_DIR/wolf/state.json (WOLF mode) or $DATA_DIR/cli/state.db (strategy mode). These files are written by the trading engine after every tick.

Fallback behavior: If the Python status reader fails, the Node.js server reads state.json directly as a fallback. The Python entrypoint has no fallback.


GET /api/strategies

Returns the full catalog of available trading strategies and YEX markets.

Request:

Response:

Each strategy includes its description, type, and params with default values. Use this to populate strategy selection UI or validate configuration inputs.


GET /status

Human-readable plain-text status. Calls hl wolf status internally.

Request:

Response:

This is the same output you would see running hl wolf status in a terminal. Useful for quick checks but not suitable for programmatic consumption — use /api/status instead.


POST /api/skill/install

Verifies that the agent has the Nunchi trading CLI installed and returns the strategy count.

Request:

Response:

Error response:

Use this as a connectivity + capability check before wiring a UI to the agent.


POST /api/pause

Pauses the trading process by sending SIGSTOP to the child process. The agent stops executing ticks but maintains all state. Positions remain open.

Request:

Response:

Error (no process running):

Warning: Pausing stops the DSL trailing stop from updating. If the market moves significantly while paused, positions will not be protected.


POST /api/resume

Resumes a paused trading process by sending SIGCONT.

Request:

Response:


CORS

All /api/* endpoints return CORS headers:

OPTIONS requests to any path return 204 with these headers. Set the CORS_ORIGIN environment variable to restrict origins in production.


SSE Real-Time Feed

GET /api/feed

Server-Sent Events stream that pushes the agent's status every time the tick counter changes. The server polls the state file every 2 seconds and emits an event only when tick_count has advanced.

Connecting:

curl (for testing):

Event format:

Each data: line contains the same JSON payload as GET /api/status. Events are separated by double newlines per the SSE specification.

Headers returned:

The X-Accel-Buffering: no header prevents Nginx reverse proxies from buffering the stream.

Behavior:

  • Emits immediately on first connect (current state)

  • Then emits only when tick_count changes (de-duplicated)

  • WOLF ticks every 60 seconds by default, so events arrive roughly every 60s

  • Single-strategy ticks are configurable (default 10s), so events arrive more frequently

  • The connection stays open indefinitely until the client disconnects

  • EventSource auto-reconnects on connection loss (browser default behavior)

Python example:


Leaderboard API

The leaderboard runs as a separate microservice from the agent. It tracks registered wallet addresses and queries Hyperliquid directly for account values.

Deployment

Or deploy to Railway using the included railway.toml.

Environment variables:

Variable
Default
Description

LEADERBOARD_PORT

8090

HTTP server port

LEADERBOARD_DB

/data/leaderboard.db

SQLite database path

CORS_ORIGIN

*

Allowed CORS origin

GET /health

POST /api/register

Register a wallet address for leaderboard tracking. The service queries Hyperliquid at registration time to capture the initial_account_value baseline.

Request:

Field
Type
Required
Description

address

string

Yes

Ethereum address (0x + 40 hex chars)

network

string

No

"testnet" (default) or "mainnet"

display_name

string

No

Display name (max 32 chars)

Response (new registration):

Response (already registered):

Error (invalid address):

Error (HL query failed):

How PnL is computed: PnL = current_account_value - initial_account_value. The initial_account_value is captured once at registration and never updated. If the user deposits or withdraws funds after registration, the PnL figure will be incorrect. This is a known limitation.

GET /api/leaderboard

Returns the ranked leaderboard for a given network.

Request:

Parameter
Type
Default
Description

network

string

testnet

"testnet" or "mainnet"

Response:

Field
Type
Description

agents

array

Agents sorted by PnL (descending)

agents[].rank

int

1-indexed rank

agents[].address

string

Wallet address (lowercase)

agents[].display_name

string

User-chosen name (may be empty)

agents[].pnl

float

current_value - initial_value (rounded to 2 decimals)

agents[].account_value

float

Current HL account value

agents[].positions_count

int

Number of open positions on HL

agents[].network

string

"testnet" or "mainnet"

agents[].registered_at

int

Registration timestamp (Unix ms)

agents[].stale

bool

Present and true if the HL query failed for this agent

total_agents

int

Total registered agents on this network

last_updated

int

Cache refresh timestamp (Unix ms)

Caching: The leaderboard is cached and refreshed by a background thread every 45 seconds. The last_updated field tells you how fresh the data is. The cache refreshes both testnet and mainnet every cycle.

Polling from a frontend:

CLI Usage

The leaderboard service also works as a CLI tool:


MCP Server

The MCP server exposes 13 tools for AI agent orchestration via the Model Context Protocol. This is the access path for Claude Code, OpenClaw, or any MCP-compatible client.

Starting the Server

Or set RUN_MODE=mcp in your Railway deployment.

Connecting from Claude Code

Add to your Claude Code MCP configuration:

Available Tools

Information Tools (Fast, sub-second)

These execute directly in Python with no subprocess overhead.


strategies()

List all 14 trading strategies with descriptions and default parameters.

Returns JSON with strategy catalog and YEX markets. Same data as GET /api/strategies.


builder_status()

Get builder fee configuration.

Returns:


wallet_list()

List saved encrypted keystores.

Returns array of keystore file paths and addresses, or "No keystores found.".


wallet_auto(save_env=true)

Create a new Ethereum wallet non-interactively. Generates a random private key, encrypts it with a random password, and saves to ~/.hl-agent/keystore/.

Returns:


setup_check()

Validate that the environment is correctly configured for trading.

Returns:


account(mainnet=false)

Get Hyperliquid account state (balances, margins, positions).

Returns human-readable account summary from hl account.


status()

Show current positions, PnL, and risk state.

Returns human-readable status from hl status.


Action Tools (Subprocess, seconds to minutes)

These shell out to the CLI and may take significant time.


trade(instrument, side, size)

Place a single manual order (IOC).

Executes hl trade ETH-PERP buy 0.5. Returns fill confirmation or error.


run_strategy(strategy, instrument, tick, max_ticks, mock, dry_run, mainnet)

Start autonomous trading with a named strategy.

This is a long-running call. If max_ticks is set, it returns after completion. Without max_ticks, it runs indefinitely (set a timeout on your MCP client).


scanner_run(mock=false)

Run the opportunity scanner once — screen all HL perps for trading setups.

Returns scored opportunities with market structure, technicals, and funding analysis.


wolf_status()

Get WOLF orchestrator status (slots, positions, daily PnL).


wolf_run(mock, max_ticks, preset, mainnet)

Start the WOLF multi-slot orchestrator.

Long-running. Timeout is computed as max(120, max_ticks * 60 + 30) seconds.


howl_run(since=null)

Run HOWL performance review — analyze trades, compute metrics, generate recommendations.

Returns detailed performance report with win rate, FDR, direction analysis, and parameter adjustment recommendations.


Context Tools (Memory, Journal, Judge)

These access the agent's accumulated knowledge and trade records.


agent_memory(query_type, limit, event_type)

Read agent memory — learnings, parameter changes, market observations.

Arg
Values
Description

query_type

"recent", "playbook"

Recent events or accumulated knowledge

limit

int

Max events (default 20)

event_type

"param_change", "howl_review", "notable_trade", "judge_finding", "session_start", "session_end"

Filter by type


trade_journal(date, limit)

Read trade journal — structured position records with entry/exit reasoning.

Returns journal entries with signal source, entry reasoning, exit reasoning, close reason, and quality rating.


judge_report()

Get latest signal quality evaluation — false positive rates, accuracy by instrument, config recommendations.

Returns the most recent Judge analysis, or {"status": "no_reports"} if WOLF hasn't run long enough to generate one.


obsidian_context()

Read trading context from Obsidian vault — watchlists, market theses, risk preferences.

Requires an Obsidian vault at ~/obsidian-vault. Returns {"status": "unavailable"} if not found.


Reading State Files Directly

If you have filesystem access to the agent (SSH, mounted volume, same container), you can read the state files directly without going through the API.

WOLF State

Contains: tick_count, slots[], daily_pnl, total_pnl, total_trades, preset, config.

Trade Log

Each line is a JSON object:

Financial values are strings to preserve decimal precision.

StateDB (SQLite)

Keys: tick_count, positions, risk, start_time_ms, strategy_id, instrument, order_stats.

Scanner Results

Movers Signals

HOWL Reports

Journal Entries


Integration Patterns

Polling Dashboard (Minimal)

SSE Consumer (Real-Time)

Multi-Agent Monitor

Leaderboard + Agent Combo


Endpoint Summary

Agent Endpoints (on every deployed agent)

Method
Path
Auth
Response
Latency

GET

/health

None

JSON

<10ms

GET

/api/status

None

JSON

<100ms

GET

/api/strategies

None

JSON

<100ms

GET

/api/feed

None

SSE stream

Persistent

GET

/status

None

Plain text

<1s

POST

/api/skill/install

None

JSON

<2s

POST

/api/pause

None

JSON

<10ms

POST

/api/resume

None

JSON

<10ms

Leaderboard Endpoints (separate service)

Method
Path
Auth
Response
Latency

GET

/health

None

JSON

<10ms

GET

/api/leaderboard?network=

None

JSON

<10ms (cached)

POST

/api/register

None

JSON

1-5s (queries HL)

OPTIONS

*

None

204

<10ms

MCP Tools (via hl mcp serve)

Tool
Type
Latency
Side Effects

strategies

Fast

<100ms

None

builder_status

Fast

<100ms

None

wallet_list

Fast

<100ms

None

wallet_auto

Fast

<500ms

Creates keystore file

setup_check

Fast

<100ms

None

account

Subprocess

1-5s

None

status

Subprocess

<1s

None

trade

Subprocess

1-5s

Places order on HL

run_strategy

Subprocess

Minutes+

Runs trading loop

scanner_run

Subprocess

10-30s

None

wolf_status

Subprocess

<1s

None

wolf_run

Subprocess

Minutes+

Runs WOLF loop

howl_run

Subprocess

5-15s

None

agent_memory

Fast

<100ms

None

trade_journal

Fast

<100ms

None

judge_report

Fast

<100ms

None

obsidian_context

Fast

<100ms

None

Last updated

Was this helpful?