# Configuration Reference Complete reference for ClawRouter configuration options. ## Table of Contents - [Environment Variables](#environment-variables) - [Wallet Configuration](#wallet-configuration) - [Wallet Backup & Recovery](#wallet-backup--recovery) - [Proxy Settings](#proxy-settings) - [Programmatic Usage](#programmatic-usage) - [Routing Configuration](#routing-configuration) - [Tier Overrides](#tier-overrides) - [Scoring Weights](#scoring-weights) - [Testing Configuration](#testing-configuration) --- ## Environment Variables | Variable | Default | Description | | --------------------------- | ------------------------------------- | --------------------------------------------------------------------------------- | | `BLOCKRUN_WALLET_KEY` | - | Ethereum private key (hex, 0x-prefixed). Used if no saved wallet exists. | | `BLOCKRUN_PROXY_PORT` | `8402` | Port for the local x402 proxy server. | | `CLAWROUTER_SOLANA_RPC_URL` | `https://api.mainnet-beta.solana.com` | Solana RPC endpoint for USDC balance checks. | | `CLAWROUTER_DISABLED` | `false` | Set to `true` to disable smart routing (pass requests through as-is). | | `CLAWROUTER_WORKER` | - | Set to `1` to enable Worker Mode (earn USDC by running health checks). | | `CLAWROUTER_DEBUG_HEADERS` | (on) | Set to `off`/`false`/`0` to suppress the `x-clawrouter-*` debug response headers. | | `BLOCKRUN_WEB_SEARCH` | (auto-enabled) | Set to `off` to disable BlockRun's Exa web search provider registration. | ### BLOCKRUN_WALLET_KEY The wallet private key for signing x402 micropayments. ```bash export BLOCKRUN_WALLET_KEY=0x...your_private_key... ``` **Resolution order:** 1. Saved file (`~/.openclaw/blockrun/wallet.key`) — checked first 2. `BLOCKRUN_WALLET_KEY` environment variable — used if no saved file 3. Auto-generate — creates new wallet and saves to file > **Security Note:** The saved file takes priority to prevent accidentally switching wallets and losing access to funded balances. ### BLOCKRUN_PROXY_PORT Configure the proxy to listen on a different port: ```bash export BLOCKRUN_PROXY_PORT=8403 openclaw gateway restart ``` **Behavior:** - If a proxy is already running on the configured port, ClawRouter will **reuse it** instead of failing with `EADDRINUSE` - The proxy returns the wallet address of the existing instance, not the configured wallet - A warning is logged if the existing proxy uses a different wallet **Valid values:** 1-65535 (integers only). Invalid values fall back to 8402. ### BLOCKRUN_WEB_SEARCH Disable BlockRun's bundled Exa web search provider. By default ClawRouter calls `registerWebSearchProvider(blockrun-exa)` and lets OpenClaw auto-detect it as the active search provider; if you'd rather use a different provider (or no web search at all), turn it off. **Two equivalent opt-out paths:** ```bash # Path 1: env var (CI / one-off runs) export BLOCKRUN_WEB_SEARCH=off openclaw gateway restart ``` ```jsonc // Path 2: persistent — edit ~/.openclaw/openclaw.json { "tools": { "web": { "search": { "enabled": false, }, }, }, } ``` When disabled: - ClawRouter skips `registerWebSearchProvider()` so blockrun-exa never gets wired up. - `injectModelsConfig` leaves your `tools.web.search.enabled = false` alone instead of flipping it back to `true` on every plugin load. - The legacy `tools.web.search.provider = "blockrun-exa"` migration still runs (that's correctness — it's an invalid value rejected by OpenClaw 2026.5.2+ validators, regardless of whether you want search enabled). ### CLAWROUTER_DEBUG_HEADERS Non-streaming responses carry routing debug headers by default (`x-clawrouter-profile`, `x-clawrouter-tier`, `x-clawrouter-model`, `x-clawrouter-confidence`, `x-clawrouter-reasoning`). To turn them off globally: ```bash export CLAWROUTER_DEBUG_HEADERS=off # also accepts false / 0 openclaw gateway restart ``` Per-request alternative: send `x-clawrouter-debug: false` on the request. > Since v0.12.208 the reasoning value is percent-encoded, so non-ASCII routing > signals (Cyrillic/CJK keyword matches) can no longer produce an invalid > header. On v0.12.207 and earlier, non-English prompts could crash response > delivery with `Invalid character in header content ["x-clawrouter-reasoning"]` > — upgrade rather than relying on this switch. ### CLAWROUTER_SOLANA_RPC_URL Override the Solana RPC endpoint used for USDC balance checks (Solana chain only): ```bash export CLAWROUTER_SOLANA_RPC_URL=https://your-rpc-provider.com openclaw gateway restart ``` Public RPC may rate-limit on heavy usage. Use a dedicated RPC for production. --- ## Wallet Configuration ClawRouter supports **two payment chains**: Base (EVM) and Solana. Both are USDC only — no SOL or ETH accepted for payments. ### Check Active Wallet ```bash # View wallet address + balance (both chains shown) /wallet # Or via HTTP curl http://localhost:8402/health | jq .wallet curl "http://localhost:8402/health?full=true" | jq ``` Response (dual-chain): ```json { "status": "ok", "wallet": "0x1234...abcd", "solanaWallet": "7Xkr...xyz", "paymentChain": "base", "balance": "$2.50", "isLow": false, "isEmpty": false } ``` ### Switch Payment Chain ```bash /wallet solana # Switch to Solana USDC payments /wallet base # Switch back to Base (EVM) USDC payments ``` Or use the `/chain` command: ```bash /chain solana /chain base ``` The selected chain is persisted across gateway restarts. ### Switch Wallets To use a different wallet: ```bash # 1. Remove saved wallet rm ~/.openclaw/blockrun/wallet.key # 2. Set new wallet key export BLOCKRUN_WALLET_KEY=0x... # 3. Restart openclaw gateway restart ``` ### Backup Wallet ```bash # Backup wallet key cp ~/.openclaw/blockrun/wallet.key ~/backup/ # View wallet address from key file cat ~/.openclaw/blockrun/wallet.key ``` ### Wallet Backup & Recovery ClawRouter generates a **BIP-39 mnemonic** on first install — stored at `~/.openclaw/blockrun/wallet.key`. This single mnemonic derives both your EVM (Base) and Solana addresses. **Back up this file before terminating any VPS or machine!** #### Using the `/wallet` Command ```bash # Check wallet status (address, balance, chain, file location) /wallet # Export mnemonic + private keys for backup /wallet export ``` The `/wallet export` command displays your mnemonic and keys so you can copy them before terminating a machine. #### Manual Backup ```bash # Option 1: Copy the key file cp ~/.openclaw/blockrun/wallet.key ~/backup-wallet.key # Option 2: View mnemonic cat ~/.openclaw/blockrun/wallet.key ``` #### Restore on a New Machine ```bash # Option 1: Recover from mnemonic npx @blockrun/clawrouter wallet recover "word1 word2 ... word12" # Option 2: Set environment variable (before installing ClawRouter) export BLOCKRUN_WALLET_KEY=0x...your_private_key... openclaw plugins install @blockrun/clawrouter # Option 3: Create the key file directly mkdir -p ~/.openclaw/blockrun echo "your twelve word mnemonic here" > ~/.openclaw/blockrun/wallet.key chmod 600 ~/.openclaw/blockrun/wallet.key openclaw plugins install @blockrun/clawrouter ``` **Important:** If a saved wallet file exists, it takes priority over the environment variable. To use a different wallet, delete the existing file first. #### Lost Key Recovery If you lose your wallet key, **there is no way to recover it**. The wallet is self-custodial, meaning only you have the private key. We do not store keys or have any way to restore access. **Prevention tips:** - Run `/wallet export` before terminating any VPS - Keep a secure backup of `~/.openclaw/blockrun/wallet.key` - For production use, consider using a hardware wallet or key management system --- ## Proxy Settings ### Proxy Reuse (v0.4.1+) ClawRouter automatically detects and reuses an existing proxy on startup: ``` Session 1: startProxy() → starts server on :8402 Session 2: startProxy() → detects existing, reuses handle ``` **Behavior:** - Health check is performed on the configured port before starting - If responsive, returns a handle that uses the existing proxy - `close()` on reused handles is a no-op (doesn't stop the original server) - Warning logged if existing proxy uses a different wallet ### Programmatic Usage Use ClawRouter without OpenClaw: ```typescript import { startProxy } from "@blockrun/clawrouter"; const proxy = await startProxy({ walletKey: process.env.BLOCKRUN_WALLET_KEY!, onReady: (port) => console.log(`Proxy on port ${port}`), onRouted: (d) => console.log(`${d.model} saved ${(d.savings * 100).toFixed(0)}%`), }); // Any OpenAI-compatible client works const res = await fetch(`${proxy.baseUrl}/v1/chat/completions`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ model: "blockrun/auto", messages: [{ role: "user", content: "What is 2+2?" }], }), }); await proxy.close(); ``` Or use the router directly (no proxy, no payments): ```typescript import { route, DEFAULT_ROUTING_CONFIG, BLOCKRUN_MODELS } from "@blockrun/clawrouter"; // Build pricing map const modelPricing = new Map(); for (const m of BLOCKRUN_MODELS) { modelPricing.set(m.id, { inputPrice: m.inputPrice, outputPrice: m.outputPrice }); } const decision = route("Prove sqrt(2) is irrational", undefined, 4096, { config: DEFAULT_ROUTING_CONFIG, modelPricing, }); console.log(decision); // { // model: "deepseek/deepseek-reasoner", // tier: "REASONING", // confidence: 0.97, // method: "rules", // savings: 0.994, // costEstimate: 0.002, // } ``` ### Programmatic Options All options for `startProxy()`: ```typescript import { startProxy } from "@blockrun/clawrouter"; const proxy = await startProxy({ walletKey: "0x...", // Port configuration port: 8402, // Default: 8402 or BLOCKRUN_PROXY_PORT // Timeouts requestTimeoutMs: 180000, // 3 minutes (covers on-chain tx + LLM response) // API base (for testing) apiBase: "https://blockrun.ai/api", // Callbacks onReady: (port) => console.log(`Proxy ready on ${port}`), onError: (error) => console.error(error), onRouted: (decision) => console.log(decision.model, decision.tier), onLowBalance: (info) => console.warn(`Low balance: ${info.balanceUSD}`), onInsufficientFunds: (info) => console.error(`Need ${info.requiredUSD}`), onPayment: (info) => console.log(`Paid ${info.amount} for ${info.model}`), // Routing config overrides routingConfig: { // See Routing Configuration below }, }); ``` --- ## Routing Configuration ### Via openclaw.yaml ```yaml plugins: - id: "@blockrun/clawrouter" config: # Maximum spend per session/run in USD. # Default: disabled (no limit) maxCostPerRun: 0.50 # $0.50 per session # How to enforce the budget cap. Default: graceful # # graceful (default): when budget runs low, ClawRouter automatically downgrades # to cheaper models (premium → auto → eco → free). Tasks keep running. # Only returns an error if no model can serve the request at all. # # strict: immediately returns 429 (X-ClawRouter-Cost-Cap-Exceeded: 1) once # the session spend reaches the cap. Use when you need a hard budget ceiling. maxCostPerRunMode: graceful # or: strict # Note: image generation endpoints (/v1/images/generations) bypass maxCostPerRun. # Their cost is charged via x402 micropayment directly and is not tracked per-session. routing: # Override tier assignments tiers: SIMPLE: primary: "google/gemini-2.5-flash" fallback: ["deepseek/deepseek-chat"] MEDIUM: primary: "deepseek/deepseek-chat" fallback: ["openai/gpt-4o-mini"] COMPLEX: primary: "anthropic/claude-sonnet-4.6" fallback: ["openai/gpt-4o"] REASONING: primary: "deepseek/deepseek-reasoner" fallback: ["openai/o3-mini"] # Override scoring parameters scoring: reasoningKeywords: ["prove", "theorem", "formal", "derive"] codeKeywords: ["function", "class", "async", "import"] simpleKeywords: ["what is", "define", "hello"] # Override thresholds classifier: confidenceThreshold: 0.7 reasoningConfidence: 0.97 # Context-based overrides overrides: largeContextTokens: 100000 # Force COMPLEX above this structuredOutput: true # Bump to min MEDIUM for JSON/YAML ``` --- ## Tier Overrides ### Default Tier Mappings | Tier | Primary Model | Fallback Chain | | --------- | ----------------------------- | ----------------------------------------------- | | SIMPLE | `google/gemini-2.5-flash` | `deepseek/deepseek-chat` | | MEDIUM | `deepseek/deepseek-chat` | `openai/gpt-4o-mini`, `google/gemini-2.5-flash` | | COMPLEX | `anthropic/claude-sonnet-4.6` | `openai/gpt-4o`, `google/gemini-2.5-pro` | | REASONING | `deepseek/deepseek-reasoner` | `openai/o3-mini`, `anthropic/claude-sonnet-4.6` | ### Fallback Chain When the primary model fails (rate limits, billing errors, provider outages), ClawRouter tries the next model in the fallback chain: ``` Request → gemini-2.5-flash (rate limited) → deepseek-chat (billing error) → gpt-4o-mini (success) ``` Max fallback attempts: 3 models per request. ### Custom Tier Configuration ```yaml routing: tiers: COMPLEX: primary: "openai/gpt-4o" # Use GPT-4o instead of Claude fallback: - "anthropic/claude-sonnet-4.6" - "google/gemini-2.5-pro" ``` --- ## Scoring Weights The 15-dimension weighted scorer determines query complexity: | Dimension | Weight | Detection | | --------------------- | ------ | ---------------------------------------- | | `reasoningMarkers` | 0.18 | "prove", "theorem", "step by step" | | `codePresence` | 0.15 | "function", "async", "import", "```" | | `multiStepPatterns` | 0.12 | "first...then", "step 1", numbered lists | | `agenticTask` | 0.10 | "run", "test", "fix", "deploy", "edit" | | `technicalTerms` | 0.10 | "algorithm", "kubernetes", "distributed" | | `tokenCount` | 0.08 | short (<50) vs long (>500) | | `creativeMarkers` | 0.05 | "story", "poem", "brainstorm" | | `questionComplexity` | 0.05 | Multiple question marks | | `constraintCount` | 0.04 | "at most", "O(n)", "maximum" | | `imperativeVerbs` | 0.03 | "build", "create", "implement" | | `outputFormat` | 0.03 | "json", "yaml", "schema" | | `simpleIndicators` | 0.02 | "what is", "define", "translate" | | `domainSpecificity` | 0.02 | "quantum", "fpga", "genomics" | | `referenceComplexity` | 0.02 | "the docs", "the api", "above" | | `negationComplexity` | 0.01 | "don't", "avoid", "without" | ### Custom Keywords ```yaml routing: scoring: # Add domain-specific reasoning triggers reasoningKeywords: - "prove" - "theorem" - "formal verification" - "type theory" # Custom # Add framework-specific code triggers codeKeywords: - "function" - "useEffect" # React-specific - "prisma" # ORM-specific ``` --- ## Advanced: Confidence Calibration The classifier uses sigmoid calibration to convert raw scores to confidence values: ``` confidence = 1 / (1 + exp(-k * (score - midpoint))) ``` Parameters: - `k = 8` — steepness of the sigmoid curve - `midpoint = 0.5` — score at which confidence = 50% ### Override Thresholds ```yaml routing: classifier: # Require higher confidence for tier assignment confidenceThreshold: 0.8 # Default: 0.7 # Force REASONING tier at lower confidence reasoningConfidence: 0.90 # Default: 0.97 ``` --- ## Testing Configuration ### Dry Run (No Payments) For testing routing without spending USDC: ```typescript import { route, DEFAULT_ROUTING_CONFIG, BLOCKRUN_MODELS } from "@blockrun/clawrouter"; // Build pricing map const modelPricing = new Map(); for (const m of BLOCKRUN_MODELS) { modelPricing.set(m.id, { inputPrice: m.inputPrice, outputPrice: m.outputPrice }); } // Test routing decisions locally const decision = route("Prove sqrt(2) is irrational", undefined, 4096, { config: DEFAULT_ROUTING_CONFIG, modelPricing, }); console.log(decision); // { model: "deepseek/deepseek-reasoner", tier: "REASONING", ... } ``` ### Run Tests ```bash # Router tests (no wallet needed) npx tsx test/e2e.ts # Proxy end-to-end smoke (mock upstream, no wallet needed) npm run test:e2e # Proxy reuse tests npx tsx test/proxy-reuse.ts # Live e2e with payments (requires funded wallet) BLOCKRUN_WALLET_KEY=0x... npm run test:e2e # Optional slower/costlier live coverage CLAWROUTER_E2E_FULL=1 BLOCKRUN_WALLET_KEY=0x... npm run test:e2e RUN_IMAGE_TEST=1 BLOCKRUN_WALLET_KEY=0x... npm run test:e2e RUN_MUSIC_TEST=1 BLOCKRUN_WALLET_KEY=0x... npm run test:e2e ```