Intelligent model routing for OpenClaw — declare model traits, let the router match automatically.
Not every message needs GPT-4 or Claude Opus. A "hello" can go to a fast, cheap model. A system-design question deserves the best. Claw Router makes this decision for you:
- Trait-based matching: Declare what each model is good at, the router does the matching
- Rule-only mode: Local computation, < 1ms, zero API calls
- LLM-assisted mode: Triggers LLM for tier boundary refinement and model conflict arbitration
- Turn-by-turn re-routing: Session model overrides are cleared after
agent_end, so each new message is routed again instead of inheriting the previous turn's model
User: "hi" → TRIVIAL → doubao-seed-code (fast, cheap)
User: "写个爬虫" → COMPLEX → gpt-5.3-codex-high (example outcome)
User: "设计分布式架构" → EXPERT → claude-opus-4 (best)
To ensure all dependencies (especially local semantic routing engines) are packaged correctly, please install directly from the source repository into your extensions directory:
# 1. Go to OpenClaw's extensions directory
mkdir -p ~/.openclaw/extensions
cd ~/.openclaw/extensions
# 2. Clone the repository directly here
git clone https://github.com/HackSing/claw-router.git
cd claw-router
# 3. Install production dependencies (creates a local node_modules)
npm install
# 4. Compile TypeScript to JavaScript
npx tsc
# Done! The plugin is now fully self-contained with its dependencies.Add to your OpenClaw config (~/.openclaw/openclaw.json):
{
"plugins": {
"enabled": true,
"allow": ["claw-router"],
"entries": {
"claw-router": {
"enabled": true
}
}
}
}Important: Plugin config must be placed under the config key. Declare each model's traits (what it's good at):
{
"plugins": {
"entries": {
"claw-router": {
"enabled": true,
"config": {
"models": [
{
"id": "anthropic/claude-sonnet",
"traits": ["coding", "analysis", "COMPLEX", "EXPERT"]
},
{
"id": "openai/gpt-4o-mini",
"traits": ["chat", "translation", "TRIVIAL", "SIMPLE"]
},
{
"id": "google/gemini-pro",
"traits": ["writing", "research", "MODERATE", "COMPLEX"]
}
],
"logging": true
}
}
}
}
}Trait vocabulary (fixed):
- Tier:
TRIVIAL,SIMPLE,MODERATE,COMPLEX,EXPERT - TaskType:
coding,writing,chat,analysis,translation,math,research,other
before_agent_startonly applies routing fortrigger === "user"- Background triggers such as memory flush are ignored for routing decisions
- The plugin writes a temporary model override before the run, then clears it in
agent_end - If OpenClaw invokes repeated user hooks for the same turn, only the first successful override emits the full routing decision log
┌──────────────────────────────────────────────────┐
│ User Message │
└──────────────────────┬───────────────────────┘
│
▼
┌────────────────┐
│ Hard Overrides │ ◄── ≤5 chars? 3+ code blocks? "system design"?
└───────┬───────┘
│ no match
▼
┌────────────────────────────────────────┐
│ Semantic Routing (if enabled, default on) │
│ bge-small-zh-v1.5 · cosine similarity │
└────────────────────┬───────────────────┘
│ tier hint (or skip)
▼
┌──────────────────────────┐ ┌────────────────────┐
│ 8-Dimension Heuristic │ │ Context-Awareness │
│ Scorer (<1ms) → Tier │ │ history boost │
└────────────┬─────────────┘ └────────┬───────────┘
└───────────────────────────────┘
▼ │ LLM refine if near boundary
│
┌──────────────────────────┐ ┌────────────────────┐
│ Task Classifier │ │ Trait Matcher │
│ keywords → TaskType │ │ score + select model │
└────────────┬─────────────┘ └────────┬───────────┘
└───────────────────────────────┘
│ (tied → LLM Arbitration)
▼
┌────────────┐
│ Final Model │
└────────────┘
The agent can call this tool to get routing recommendations:
Tool: claw_route
Input: { "message": "Design a distributed caching system with sharding" }
Output: {
"tier": "EXPERT",
"taskType": "coding",
"model": "anthropic/claude-sonnet",
"matchSource": "trait",
"score": 0.8234,
"candidates": [...]
}
Type /route in chat to see current router status and statistics.
# Check router status
openclaw route status
# Test a message
openclaw route test "Help me write a sorting algorithm"// Programmatic access
await rpc('route.decide', { message: '...' });
await rpc('route.stats');| Key | Type | Default | Description |
|---|---|---|---|
models |
ModelProfile[] |
[{id:'default', traits:[...all]}] |
Model trait declarations |
thresholds |
[n, n, n, n] |
[0.20, 0.42, 0.58, 0.78] |
Score boundaries between tiers |
scoring.weights |
Record<Dimension, number> |
See below | Override dimension weights |
logging |
boolean |
false |
Enable verbose decision logs |
enableSemanticRouting |
boolean |
true |
启用本地 embedding 语义路由(bge-small-zh-v1.5)。首次启动自动下载模型,后续冷启动读磁盘 anchor 缓存。设为 false 可禁用 |
llmScoring.enabled |
boolean |
false |
Enable LLM-assisted scoring & arbitration |
llmScoring.model |
string |
— | LLM model for scoring/arbitration |
llmScoring.apiKey |
string |
— | LLM API key |
llmScoring.baseUrl |
string |
— | LLM API base URL |
llmScoring.apiPath |
string |
/v1/chat/completions |
API endpoint path |
{
"llmScoring": {
"enabled": true,
"model": "deepseek-ai/DeepSeek-V3-Chat",
"apiKey": "sk-xxx",
"baseUrl": "https://api.siliconflow.cn"
}
}LLM is invoked in two scenarios:
- Tier boundary: Rule score near threshold (±0.08) — LLM refines complexity, so most messages skip LLM calls
- Model arbitration: Multiple models tie on trait match — LLM picks best one
Includes 3-second timeout with automatic fallback.
| Dimension | Key | Weight |
|---|---|---|
| Reasoning Depth | reasoning |
0.20 |
| Code / Tech | codeTech |
0.18 |
| Task Steps | taskSteps |
0.15 |
| Domain Expertise | domainExpert |
0.12 |
| Output Complexity | outputComplex |
0.10 |
| Creativity | creativity |
0.10 |
| Context Dependency | contextDepend |
0.08 |
| Message Length | messageLength |
0.07 |
These take priority over scoring:
| Condition | Result |
|---|---|
| Message ≤ 5 chars, no tech words | → TRIVIAL |
| Multiple code fences with sufficient code volume | → COMPLEX |
| Contains "system design", "from scratch", etc. | → EXPERT |
-
Keyword matching — Each dimension has a bilingual (CN + EN) keyword library. Matches accumulate via soft-max:
score = 1 - ∏(1 - wᵢ), naturally saturating toward 1.0. -
Length scoring — Piecewise linear mapping from character count to 0–1.
-
Weighted sum —
rawSum = Σ(dimensionScore × weight) -
Sigmoid calibration —
calibrated = 1 / (1 + exp(-k·(rawSum - midpoint)))with grid-search optimized parameters:k=8, midpoint=0.18. The S-curve provides better tier discrimination in the mid-range. -
Tier mapping — Calibrated score mapped to tier via thresholds
[0.20, 0.42, 0.58, 0.78].
git clone https://github.com/HackSing/claw-router.git
cd claw-router
npm install
npm testclaw-router/
├── index.ts # 插件入口
├── openclaw.plugin.json # 插件清单 & 配置 Schema
├── src/
│ ├── router/
│ │ ├── engine.ts # 路由主流程
│ │ ├── semantic.ts # 语义路由(本地嵌入 + anchor 缓存)
│ │ ├── context.ts # 历史上下文感知
│ │ ├── math-utils.ts # 共享数学工具(calibrate/scoreToTier/clamp)
│ │ ├── semantic-signals.ts # 语义信号提取
│ │ ├── model-matcher.ts # Trait 匹配引擎
│ │ ├── task-classifier.ts # 任务类型分类器
│ │ ├── scorer.ts # 8 维度评分
│ │ ├── llm-scorer.ts # LLM 评分 & 仲裁
│ │ ├── keywords.ts # 中英文关键词库
│ │ ├── overrides.ts # 硬规则覆盖
│ │ └── types.ts # 全局类型(含 ResolvedConfig)
│ ├── config.ts # 配置解析 & 验证
│ └── logger.ts # 决策日志
├── test/
│ ├── engine.test.ts # 端到端集成测试
│ ├── extended-data.test.ts # 真实业务极端用例
│ ├── model-matcher.test.ts # Trait 匹配测试
│ ├── scorer.test.ts # 维度评分测试
│ ├── task-classifier.test.ts # 任务分类测试
│ └── fixtures.ts # 35+ 测试固件
└── skills/
└── claw-router/SKILL.md
See ROADMAP.md for detailed development plans.
v2.0.1 (Released)
- ✅ 打破循环依赖:新增
math-utils.ts统一存放共享算法 - ✅ LRU 缓存修复、跨平台路径修复、类型安全提升
- ✅ Anchor 向量磁盘缓存(
~/.claw-router/anchor-cache.json) - ✅ 162 测试用例 / 24 个套件
v2.0.0 (Released)
- ✅ Trait-based model routing: declare model capabilities, router matches automatically
- ✅ 历史上下文感知 (Context-Awareness)
- ✅ 本地语义路由 (Semantic Routing): bge-small-zh-v1.5 + 余弦相似度
- ✅ LLM arbitration for tied model candidates
- ✅ Task types expanded: +math, +research
- Learning & Feedback — Record routing decisions and adapt based on user corrections
- Route Decision Visualization — Web UI with radar charts and historical trends
We welcome contributions! Please see ROADMAP.md for details.
# Fork and clone
git clone https://github.com/your-username/claw-router.git
cd claw-router
npm install
npm test- Use GitHub Issues with provided templates
- Include environment info and reproduction steps
- Check existing issues first
- GitHub Discussions: https://github.com/HackSing/claw-router/discussions
- Twitter/X: @WareAi996
AIWare Community License © aiwaretop