jgeiser's picture
Wicklee fleet demo (static build from main)
01560d7
|
Raw History Blame Contribute Delete
11 kB

Wicklee API Reference

Localhost Agent API

Base URL: http://localhost:7700 Auth: None required.

Method Endpoint Description
GET /api/metrics SSE stream β€” 1 Hz telemetry with full MetricsPayload
GET /ws WebSocket β€” 1 Hz live telemetry (same payload as SSE, fallback transport)
GET /api/observations 18 agent-evaluated patterns with routing_hint per observation + node-level routing_hint/routing_hint_source. (2 additional cloud-evaluated patterns are queryable via the cloud Observations endpoint.)
GET /api/history?node_id=WK-XXXX Metric history β€” 1h raw samples
GET /api/profile?minutes=60 Inference Profiler β€” correlated TTFT/KV/queue/thermal/power timeline
GET /api/sla?window_min=60&target_ttft_ms=500 Inference SLA Monitor β€” p50/p95/p99 for TTFT, E2E latency, TPOT plus compliance vs target
GET /api/v1/thermal-budget?node_id=X Thermal Budget Calculator (Pro+, cloud) β€” sustainable rate, push threshold, time-to-Fair, penalized rate, plain-English advice
POST/GET/DELETE /api/v1/webhooks[/:id[/test]] Threshold Webhooks (Pro+) β€” push notifications on thermal/inference state changes and WES threshold crossings. HMAC-SHA256 signed
GET /api/health (localhost) Agent diagnostic β€” agent version, build target, DuckDB store health, list of routes available/unavailable when store init failed. One-curl debug for "why are my routes missing?"
GET /api/cost-by-model?hours=24 Cost attribution per model β€” daily power cost breakdown
GET /api/explain-slowdown?ts_ms=N Slowdown explainer β€” root cause analysis for a slow request
GET /api/model-comparison?hours=168 Model comparison β€” side-by-side efficiency for every model that has run
GET /api/model-switches?hours=24 Model switching cost β€” swap frequency, idle gap per transition
GET /api/model-candidates?search=llama&limit=20 Model discovery β€” GGUF models from HuggingFace scored against local hardware
GET /api/runtime-config?model=X Runtime Config Surface (v0.9.0) β€” cached launch-time config for a named model (Ollama, vLLM, llama.cpp). 200 with JSON, 400 if ?model= missing, 404 if not yet cached. Templates and system prompts stay local β€” never pushed to the fleet.
GET /api/traces Proxy inference traces
GET /api/events/history Node event log
GET /api/events/recent Recent in-memory events
GET /api/export?format=json|csv Data export
GET /api/tags Ollama model tags
GET /api/pair/status Pairing status
POST /api/insights/dismiss Permanently dismiss a pattern
GET /api/insights/dismissed List dismissed patterns
POST /mcp MCP (Model Context Protocol) JSON-RPC 2.0 endpoint
GET /.well-known/mcp.json MCP server manifest

MCP (Model Context Protocol)

The agent exposes a local MCP server for AI agents (Cursor, Claude Desktop, custom agents).

Endpoint: POST http://localhost:7700/mcp Protocol: JSON-RPC 2.0 Auth: None (localhost only)

Tools

Tool Description
get_node_status Full hardware + inference metrics snapshot
get_inference_state Live/idle/busy state with sensor context
get_active_models Running models across Ollama, vLLM, llama.cpp
get_observations Server-side pattern evaluation β€” 17 agent-evaluated observations (live data)
get_metrics_history 1-hour rolling telemetry buffer

Resources

URI Description
wicklee://node/metrics Live MetricsPayload JSON
wicklee://node/thermal Thermal state + WES penalty values

Connect to Claude Desktop

Open the config file in your terminal:

# macOS
nano "$HOME/Library/Application Support/Claude/claude_desktop_config.json"

# Linux
nano ~/.config/Claude/claude_desktop_config.json

# Windows (PowerShell)
notepad "$env:APPDATA\Claude\claude_desktop_config.json"

Add the wicklee entry inside mcpServers (create the file if it doesn't exist):

{
  "mcpServers": {
    "wicklee": {
      "command": "/opt/homebrew/bin/npx",
      "args": ["-y", "mcp-remote", "http://localhost:7700/mcp"],
      "env": {
        "HOME": "/Users/YOUR_USERNAME",
        "PATH": "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin"
      }
    }
  }
}

Requires Node.js. Use which npx to find the correct npx path. Fully quit Claude Desktop (Cmd+Q) and relaunch after editing.

Connect to Claude Code

claude mcp add -s user wicklee -- npx -y mcp-remote http://localhost:7700/mcp

Cursor

Edit ~/.cursor/mcp.json (global) or .cursor/mcp.json (project). Add wicklee to mcpServers:

"wicklee": {
  "command": "npx",
  "args": ["-y", "mcp-remote", "http://localhost:7700/mcp"]
}

Windsurf

Edit ~/.codeium/windsurf/mcp_config.json. Add wicklee to mcpServers:

"wicklee": {
  "command": "npx",
  "args": ["-y", "mcp-remote", "http://localhost:7700/mcp"]
}

All setups require Node.js for the mcp-remote bridge. Restart your IDE after configuration changes.

Test with curl

curl -X POST http://localhost:7700/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"get_inference_state"},"id":1}'

Fleet API v1

Base URL: https://wicklee.dev/api/v1 Auth: X-API-Key: wk_live_... header.

Method Endpoint Description Tier
GET /api/v1/fleet All nodes with full MetricsPayload All
GET /api/v1/fleet/wes WES scores ranked All
GET /api/v1/nodes/{id} Single node deep dive All
GET /api/v1/route/best Routing recommendation (latency or efficiency). Optional ?model= for per-model routing All
GET /api/v1/models/discover Model discovery β€” browse catalog, ?simulate_hw= (Pro+), ?fleet=true (Team+) Tiered
GET /api/v1/fleet/model-comparison?hours=168 Fleet-wide per-model rollup (WES, tok/s, watts, TTFT, cost). Reads metrics_5min. 1–720 hour window. All
GET /api/v1/fleet/model-switches?hours=24 Cross-node model swap events (LAG window function over metrics_raw). 1–168 hour window, capped at 200 rows. All
GET /api/v1/fleet/cost-by-model?hours=24 Fleet-wide per-model power cost using $0.16/kWh default. 1–168 hour window. All
GET /api/v1/insights/latest Fleet intelligence snapshot Team+
GET /api/v1/fleet/chargeback?days=30 Chargeback/showback (Clerk JWT auth) β€” cost + $/1M-token attribution by team tag / model / node + daily trend. &format=csv&group= for finance export (audited) Team+
GET /api/v1/fleet/capacity?target_tok_s=200 Capacity planner with procurement scenarios (Clerk JWT auth) β€” "reach 200 tok/s: 2Γ— RTX 4090 vs 1Γ— H100" priced from the fleet's own measured tok/W per hardware class; every scenario states its basis Team+
GET /api/v1/fleet/migration-advisor Cross-node model migration (Clerk JWT auth) β€” live WES vs peers' 7-day demonstrated WES + free memory; moves with β‰₯20% estimated gain and 1.2Γ— headroom Team+
GET /api/v1/fleet/idle-waste?days=30 Idle-waste & right-sizing report (Clerk JWT auth) β€” phantom-load cost + recovery actions (unload idle model, consolidate) with projected $/mo recovery Team+
GET/PUT /api/digest Weekly idle-waste email digest settings (Clerk JWT auth) β€” Resend-delivered, one per tenant, audited Team+
POST /api/v1/keys Create API key All
GET /api/v1/keys List API keys All
DELETE /api/v1/keys/{id} Revoke API key All
GET /metrics Prometheus scrape endpoint (text format) Team+
GET /api/otel/config OpenTelemetry export configuration Team+
PUT /api/otel/config Update OTel export settings Team+

Response Examples

GET /api/v1/fleet/wes

{
  "nodes": [
    { "node_id": "WK-XXXX", "online": true, "wes": 15.0 },
    { "node_id": "WK-99E9", "online": true, "wes": 3.2 }
  ]
}

GET /api/v1/route/best

{
  "latency":    { "node": "WK-99E9", "tok_s": 31.9, "wes": 3.3, "reason": "Highest throughput" },
  "efficiency": { "node": "WK-XXXX", "tok_s": 19.5, "wes": 15.0, "reason": "Highest WES" },
  "default":    "efficiency"
}

GET /api/runtime-config?model=llama3.1:8b

{
  "model": "llama3.1:8b",
  "runtime": "ollama",
  "captured_at_ms": 1774622475195,
  "context_length": 131072,
  "n_gpu_layers": 33,
  "quantization": "Q4_K_M",
  "parameter_count": 8030261312,
  "template": "{{ if .System }}<|system|>{{ .System }}{{ end }}...",
  "system_prompt": "You are a helpful assistant."
}

GET /api/v1/fleet/model-comparison?hours=168

{
  "models": [
    { "model": "llama3.1:70b", "hours_active": 18.3, "avg_tok_s": 22.5, "avg_watts": 95.0, "wes": 0.24, "avg_ttft_ms": 245, "cost_per_hour": 0.0152, "total_cost": 0.278, "sample_count": 219 },
    { "model": "phi3:mini",    "hours_active": 42.0, "avg_tok_s": 85.1, "avg_watts": 12.0, "wes": 7.09, "avg_ttft_ms":  34, "cost_per_hour": 0.0019, "total_cost": 0.081, "sample_count": 504 }
  ]
}

GET /api/v1/fleet/model-switches?hours=24

{
  "swaps": [
    { "ts_ms": 1774621630223, "node_id": "WK-XXXX", "from_model": "llama3.1:70b", "to_model": "phi3:mini", "gap_ms": 3200 }
  ],
  "total_swaps": 14,
  "total_gap_ms": 480000,
  "total_gap_minutes": 8.0
}

GET /api/v1/fleet/cost-by-model?hours=24

{
  "models": [
    { "model": "llama3.1:70b", "hours_active": 6.2, "avg_watts": 95.0, "cost_usd": 0.0942, "tok_s_avg": 22.5, "sample_count": 744 }
  ],
  "total_cost_usd": 0.221
}

GET /api/v1/insights/latest

{
  "generated_at_ms": 1774624251478,
  "fleet": { "online_count": 3, "total_count": 3, "avg_wes": 9.9, "fleet_tok_s": 79.0 },
  "findings": [{
    "node_id": "WK-99E9",
    "hostname": "spark-c559",
    "severity": "low",
    "pattern": "wes_below_baseline",
    "title": "WES below fleet average",
    "detail": "WES 3.3 vs fleet average 9.9",
    "value": 3.3,
    "unit": "WES"
  }]
}

Key Metrics

Field Type Description
inference_state string "live" | "idle-spd" | "busy" | "idle"
ollama_tokens_per_second f32 tok/s from 20-token probe (≀ every 10 min)
apple_soc_power_w f32 Combined CPU+GPU+ANE (Apple Silicon)
nvidia_power_draw_w f32 Board power (NVIDIA)
thermal_state string "Normal" | "Fair" | "Serious" | "Critical"
penalty_avg f32 Thermal penalty (1.0 = no penalty)
ollama_ttft_ms f32 TTFT from probe baseline
vllm_avg_ttft_ms f32 TTFT from production histogram
vllm_requests_waiting u32 Queue depth

WES Formula

WES = tok/s / (Watts x ThermalPenalty)

Normal thermal (penalty=1.0): WES = tok/s / Watts = tok/W.

Color scale: >10 Excellent (emerald) Β· 3-10 Good (green) Β· 1-3 Acceptable (yellow) Β· <1 Low (red)