The AI trading agent with account API and wallet support.
Researches, debates, and paper-trades against real prices with account API or x402 billing. Risk limits live in code, not in the prompt. Every fill has a receipt. Set a budget. Connect a transaction wallet for live trades. Walk away — and come back to a book.
Franklin Trading is a fork of Franklin — the general-purpose Autonomous Economic Agent — specialized as a wallet-native trading agent. It inherits Franklin's economic substrate (account API access, x402 micropayments, the shared Router Core engine across
76 models, removable-by-design harness components)and adds a deterministic fee-aware risk engine, a wallet-bound trade journal, a multi-role persona debate, and a Backtest → Paper → Live strategy lifecycle.
This section is the honest one. Everything in it ships in @blockrun/franklin-trading 0.3.0
and is covered by the local test suite (392 tests, no network).
| Capability | Status | Where |
|---|---|---|
| Account API key or USDC wallet on Solana / Base for every model and paid API | ✅ shipped | src/payments/, src/wallet/, @blockrun/llm |
| Auto model routing on the shared Router Core engine, 76 models, dead-model kill-switch | ✅ shipped | src/router/ |
| Paper trading against live CoinGecko marks (real P&L, simulated fills) | ✅ shipped | src/trading/live-exchange.ts |
| Deterministic risk engine: cash including exchange fee, per-position cap, total exposure cap, sell integrity | ✅ shipped | src/trading/risk.ts |
| Record-then-flag execution: a fill the venue executed is always booked; deviations are warnings, never silent drops | ✅ shipped | src/trading/engine.ts |
Persistent trade journal with rationale scoring, cross-session TradingHistory |
✅ shipped | src/trading/trade-log.ts |
| Market data, Exa research, prediction markets, DeFiLlama, Jupiter / 0x quotes, multi-chain RPC (paid per call) | ✅ shipped | src/tools/ |
| Base MCP (onchain balances / swaps / x402 via your Base Account) | ✅ shipped | docs/base-mcp.md |
Strategy DSL (defineStrategy) |
🟡 author-facing helper only | src/strategies/ |
Unified backtest / paper / live runner (franklin-trading run) |
🚧 M1 | roadmap |
| Role personas, regime detector, prompt-cache optimizer, slippage model, fact-checker | 🚧 M2–M3 | roadmap |
| Real venue adapters (Hyperliquid, Jupiter, 0x, Polymarket, Binance) | 🚧 M4–M5 | roadmap |
The open-source trading-agent landscape splits into halves nobody has joined:
| Project | Strength | What it can't do |
|---|---|---|
| TradingAgents (78.8k★) | Multi-role agent debate, academic rigor | No live execution; 0% prompt-cache hit rate (#750); ticker hallucination (#814); risk limits silently drop out of context (#479) |
| AI-Trader (18.5k★) | Federated agents, Polymarket live data, copy-trading | Stale price data (#188); position-averaging bug (#186); no published backtests (#207) |
| Vibe-Trading (8.4k★) | LLM-driven research, persistent memory, Alpha Zoo (452 factors), Shadow Account | Zero exchange connectors (#100) |
| Hummingbot (18.6k★, $34B+ volume) | 50+ CEX/DEX connectors, V2 framework, institutional-grade risk controls | No LLM brain; no narrative awareness |
Franklin Trading is the synthesis: Vibe-Trading-style natural-language research and persistent memory, TradingAgents-style hierarchical persona debate, Hummingbot-style execution rigor — wrapped in Franklin's wallet-native economic substrate, with the one thing none of them do: the money is real from day one, so the guardrails had to be too.
Register at user.blockrun.ai, create an API key, and add credits.
export BLOCKRUN_API_KEY="brk_live_..."
franklin-tradingThe account endpoint defaults to https://api.blockrun.ai; set
BLOCKRUN_API_BASE_URL only when using another trusted BlockRun deployment.
API mode covers the agent, subagents, local proxy, model catalog, Exa,
prediction markets, DeFiLlama, RPC and BlockRun market data. A 401 points to
the key dashboard; a 402 points to account credit top-up. Franklin Trading
does not fall back to a wallet payment after either response.
The API key pays for BlockRun services. It cannot sign an exchange order or
an on-chain transaction. Paper trading needs no transaction wallet; live
trading still requires a separate Solana or Base wallet. setup, balance
and the Wallet tool continue to manage and report that transaction wallet.
Never put either credential in source control.
Conviction #5: the LLM is never the last line of defense. Every
order — buys and sells — goes through RiskEngine.check in code before it reaches a
venue, and the delivered fill is checked again after.
openPosition(BTC, 0.001 @ $100,000)
1. local pass qty / price / notional finite and > 0; caps → blocked? kind=risk
2. estimateFee() venue quotes a fee CEILING ($0.10) → blocked? kind=fee-quote
3. fee-aware pass $100.00 + $0.10 must fit cash + caps → blocked? kind=risk
4. placeOrder() a throw here means "not executed" → blocked? kind=venue
5. record-then-flag the fill is ALWAYS booked; anything the venue changed
(fee above ceiling, qty/price drift, cap breached,
cash negative) → warnings[] on the outcome + journal
Step 5 is the part most agents get wrong. A post-execution rejection leaves real money at the venue that the local book does not know about, and the resulting tool error tells the model to try again — a double buy. Franklin books the fill and shouts about it instead.
Same shape for closePosition: an oversell, a non-positive quantity, a zero mark, or a
dust close the fee would consume is refused before the venue is asked. Orders are
serialised per engine; cash is compared at sub-cent precision; the persisted portfolio is
validated on load (an Infinity balance would otherwise disarm every cap).
Requires Node.js 20.19+ (Node 22 LTS recommended). Check with
node -v.
npm install -g @blockrun/franklin-trading
# Option A: use account credits for models, research and market data
export BLOCKRUN_API_KEY="brk_live_..."
franklin-trading
# Add a separate transaction wallet only when you are ready for live trades.
# Solana is the default; Base remains available explicitly.
franklin-trading setup solana
# franklin-trading setup base
# Option B: unset the key and use x402 wallet billing for BlockRun calls
unset BLOCKRUN_API_KEY
franklin-trading setup solana
# Print the active transaction wallet and its USDC balance
franklin-trading balance
# Franklin Trading stops when the local session estimate reaches the cap
franklin-trading --max-spend 5Account API usage is recorded in the
account dashboard. In API mode, local
cost totals and --max-spend are estimates; the dashboard ledger is
authoritative. Unset BLOCKRUN_API_KEY to return to x402 wallet billing.
> open a 0.001 BTC position at the current price
Auto → deepseek/deepseek-v4-pro
## Order filled
- Bought 0.001 BTC @ $100,000.00 (fee $0.10)
- Position now: 0.001 BTC @ avg $100,000.00
- Cash remaining: $899.90
> what's my P&L this week?
## Trade history (7d)
- 7d P&L (realized): +$12.40
- Trades: 6 (3 opens, 3 closes)
...
> sell 0.002 BTC
## Close blocked
- Symbol: BTC
- Attempted: sell 0.002
- Reason: Cannot sell 0.002 BTC: only 0.001 held
Try a smaller qty, or close other positions first to free up exposure headroom.
Every model call, every paid tool call, every fill is written to
~/.blockrun/sessions/<uuid>.jsonl; the trade journal lives in ~/.blockrun/trades.jsonl
and the portfolio in ~/.blockrun/portfolio.json. Resume any session, search across all
of them, audit every trade.
You don't pick models. Auto (the default) runs the shared
Router Core engine locally — the same decision
Franklin, ClawRouter and @blockrun/llm make — classifying the request across 15 dimensions,
dropping every model that cannot satisfy it (tools, vision, context, output length), and
ranking the survivors on fit, cost, speed and reliability. Sub-millisecond, no network on the
hot path, 84% cheaper than pinning Claude Opus 5 for everything.
A model the gateway stops serving is removed from every chain on the next request (the dead-rung kill-switch), so a retired id never strands a turn.
Pin one with /model <shortcut> when you want to:
| Tier | Shortcut | Model | Price (in / out per 1M) |
|---|---|---|---|
| Frontier | opus |
Claude Opus 5 | $5 / $25 |
fable |
Claude Fable 5 | $10 / $50 | |
sonnet |
Claude Sonnet 5 | $3 / $15 | |
gpt |
GPT-5.6 Sol | $5 / $30 | |
qwen-max |
Qwen3.7 Max | $1.475 / $4.425 | |
gemini |
Gemini 3.1 Pro | $2 / $12 | |
grok |
Grok 4.5 | $2.5 / $9 | |
kimi |
Kimi K3 | $3 / $15 | |
| Reasoning | o3 |
O3 | $2 / $8 |
codex |
GPT-5.3 Codex | $1.75 / $14 | |
deepseek-v4-pro |
DeepSeek V4 Pro | $0.435 / $0.87 | |
terra-pro |
GPT-5.6 Terra Pro | $1 / $6 | |
glm-5.3 |
GLM-5.3 | $1.4 / $4.4 | |
| Budget | haiku |
Claude Haiku 4.5 | $1 / $5 |
mini |
GPT-5 Mini | $0.25 / $2 | |
glm-flash |
GLM-5.3 Flash (1M ctx, vision) | $0.15 / $0.5 | |
deepseek |
DeepSeek V4 Flash | $0.14 / $0.28 | |
qwen-flash |
Qwen3.7 Flash (1M ctx) | $0.03 / $0.13 | |
| Free | free |
Nemotron Nano 9B | $0 |
omni |
Nemotron 3 Nano Omni (text + image + audio) | $0 | |
nano-vl |
Nemotron Nano VL | $0 |
The full catalog — 100 visible models including image, video, music and speech — is at blockrun.ai/models. Pricing is provider cost + 5%, settled per call in USDC. No free alias ever falls back to a paid model.
Franklin Trading CLI / TUI / Telegram
│
Agent loop (inherited from Franklin)
plan · execute · compact · evaluate · verify · polish
(each removable via FRANKLIN_NO_*)
│
┌─────────────┬───┴──────┬──────────────┐
Router Core Brain + Session + Trading harness
(shared, Learnings + Cost + layers (M3: 4 moats)
72 models) Shadow Acct JSONL
│
TradingEngine: local risk → fee quote → fee-aware risk → place → record-then-flag
│
Role personas (M2): Analyst → Bull / Bear → Trader → Risk → Compliance
│
Strategy surface (M1): defineStrategy now; unified runner roadmap
│
Execution: LiveExchange (paper, live marks) today · Hyperliquid · Jupiter · 0x · Polymarket (M4–M5)
│
Economic substrate: account API · x402 USDC on Solana + Base · separate trade signing
See PHILOSOPHY.md for the design principles,
docs/CONVICTIONS.md for the 12 design stances
formed from analyzing 60+ open issues across the four reference projects,
and docs/adr/ for individual architecture decisions.
Real execution plugs in at one seam: src/trading/exchange.ts.
import type { ExchangeClient, ExchangeOrder } from '@blockrun/franklin-trading/trading/exchange';
export class MyVenue implements ExchangeClient {
// A CEILING, not an expectation: round up, include your margin. The engine
// approves the order against notional + this number.
async estimateFee(order: ExchangeOrder): Promise<number> { /* fee-tier endpoint */ }
// Forward order.clientOrderId as the venue's client order id — a retried
// submission after a timeout must not fill twice. Throw ONLY if the venue
// rejected the order before executing; resolve the order state first otherwise.
async placeOrder(order: ExchangeOrder) { /* ... returns Fill with feeUsd actually charged */ }
// A usable quote is a finite number > 0. Return null, never 0, for a stale market.
async getPrice(symbol: string): Promise<number | null> { /* ticker */ }
}MockExchange and LiveExchange are the reference implementations; the contract's invariants
are pinned by the tests in test/local.mjs (search for ExchangeClient).
Franklin connects to the official Base MCP server
(https://mcp.base.org) for onchain Base actions — balances, transactions, swaps, and
x402 payments — authorized via your Base Account (OAuth, per-write approval). One command:
franklin-trading mcp add base # browser login, then start — tools appear as mcp__base__*The HTTP+OAuth transport is generic: franklin-trading mcp add <name> --url <url> connects any
hosted MCP server that supports Dynamic Client Registration + PKCE. See
docs/base-mcp.md.
Each is a removable harness component per ADR 0003: toggle off with an env flag when the model catches up.
| Layer | What it does | Env opt-out |
|---|---|---|
| Regime detector | Lightweight HMM on rolling vol + correlation; tags every decision; swaps Trader persona prompt between trend / chop / risk-off | FRANKLIN_NO_REGIME=1 |
| Prompt-cache optimizer | Separates static persona prompts from volatile context; targets ≥40% cache hit rate from turn 2 | FRANKLIN_NO_PROMPTCACHE=1 |
| Slippage model | Per-venue impact (linear+sqrt) calibrated from observed fills; applied consistently in backtest, paper, live | FRANKLIN_NO_SLIPPAGE=1 |
| Fact-checker | Deterministic ticker → entity resolver via on-chain registries + CoinGecko; blocks TOTDY-style hallucinations | FRANKLIN_NO_FACTCHECK=1 |
The author-facing strategy helper is available for early artifacts, while the
franklin-trading run <strategy> command and unified backtest/paper/live runtime
are still M1 roadmap work.
// src/strategies/btc-funding-basis.strategy.ts
import { defineStrategy } from '@blockrun/franklin-trading/strategy';
export default defineStrategy({
name: 'btc-funding-basis',
universe: ['BTC-PERP@hyperliquid', 'BTC@jupiter'],
signal: async (ctx) => {
const fr = await ctx.market.fundingRate('BTC-PERP@hyperliquid');
return fr > 0.0001
? { action: 'arb-long-spot-short-perp', size: 0.2 }
: null;
},
risk: { maxNotionalUsd: 1000, maxDrawdownPct: 5, killSwitch: true },
schedule: { every: '1m' },
});Once the M1 runner lands, one artifact will run three modes:
franklin-trading run btc-funding-basis --mode backtest --from 2024-01-01
franklin-trading run btc-funding-basis --mode paper # live data, simulated fills
franklin-trading run btc-funding-basis --mode live # real on-chain orders| Status | Milestone |
|---|---|
| ✅ | M0 — Fork from Franklin, prune non-trading verticals, rebrand |
| ✅ | M0.5 — Fee-aware risk engine with record-then-flag execution; Router Core + 2026-08 catalog sync (0.3.0) |
| 🚧 | M1 — Strategy DSL + walk-forward backtest engine |
| 🚧 | M2 — Role personas (Analyst, Bull, Bear, Trader, Risk, Compliance) wired via Task dispatch |
| 🚧 | M3 — Four moats (regime.ts, prompt-cache.ts, slippage.ts, fact-check.ts) |
| 🚧 | M4 — Connectors (read): Hyperliquid, Jupiter, 0x, Polymarket, Binance |
| 🚧 | M5 — Connectors (write) + 24h-clean paper trade |
| 🚧 | M6 — Alpha Zoo (40 factors v1) + Shadow Account (broker CSV import) |
| 🚧 | M7 — Polish, docs, demo GIF, benchmark page, v1.0.0 launch |
- Equities (IB / Alpaca / retail brokers) — v2; crypto-first proves the loop
- Options Greeks / vol-surface fitting — v2
- Hosted SaaS — never; Franklin Trading's whole point is non-custodial
- Token model / liquidity-mining rewards — v2 at earliest; institutional approach in v1
- LangGraph or any other agent-graph runtime — we use Franklin's
Tasktool dispatch - Web dashboard — v2; CLI + TUI + Telegram is sufficient for v1
- Full-orderbook market-making — Hummingbot already excels here; we differentiate on LLM-driven research + execution
npm install
npm run build # tsc + copy bundled skills
npm test # local tests, no network or funded wallet
npm run test:e2e # real models — needs BLOCKRUN_API_KEY or a funded x402 walletUpstream sync: model catalog, router and pricing changes land in
Franklin first and are ported here; the Router
Core dependency is pinned to a commit SHA in package.json so a routing change can never
arrive unnoticed. Marketing numbers regenerate from brand-numbers.json
(node scripts/sync-brand-numbers.mjs --refresh) and CI fails when they drift.
See CONTRIBUTING.md. The Franklin rule applies: every fix
needs a receipt (session id, log line, gateway response) showing the bug
actually happened. We don't accept "looks broken" fixes.
Apache-2.0 — see LICENSE. Inherits the upstream Franklin
license. Strategy contributions in strategies/community/ follow the same
license unless explicitly marked otherwise.
Franklin Trading stands on the shoulders of these open-source projects:
- Franklin — wallet, x402, Router Core, harness, plugin SDK
- TradingAgents — multi-role debate architecture
- AI-Trader — federated-agent + Polymarket integration ideas
- Vibe-Trading — Alpha Zoo, persistent research memory, Shadow Account
- Hummingbot — Executor/Controller framework, multi-venue connector abstraction, governance model
If we did our job right, this is the agent each of them wanted to be.