Tools
Complexity Router
OpenClaw plugin — classify input complexity and route to the best-fit model. Supports multi-provider cross-vendor switching.
Configuration Example
{
"plugins": {
"allow": ["complexity-router"],
"entries": {
"complexity-router": {
"enabled": true,
"config": {
"classifier": {
"provider": "your-provider",
"model": "lightweight-model",
"timeoutMs": 5000
},
"routes": {
"simple": { "provider": "...", "model": "..." },
"medium": { "provider": "...", "model": "..." },
"complex": { "provider": "...", "model": "..." },
"code": { "provider": "...", "model": "..." }
}
}
}
}
}
}
README
# Complexity Router
[中文文档](./README.zh-CN.md)
An OpenClaw plugin that uses a lightweight LLM to pre-classify input complexity and automatically route requests to the most suitable model. Supports multi-provider cross-vendor switching with built-in routing stats and token usage tracking.
## How It Works
On every user message, the plugin hooks into `before_model_resolve`:
1. Sends the user input to a lightweight classifier model (e.g. `gpt-5-nano`)
2. The classifier returns a complexity level: `simple` / `medium` / `complex` / `code`
3. Looks up the routing table and forwards the request to the corresponding model
Falls back to OpenClaw's default model on classification failure.
## Complexity Levels
| Level | Meaning | Typical Scenarios |
|-------|---------|-------------------|
| `simple` | Simple chat | Greetings, small talk, short Q&A |
| `medium` | General questions | Knowledge Q&A, everyday topics |
| `complex` | Complex analysis | Technical discussion, multi-step reasoning, deep analysis |
| `code` | Programming | Code generation, debugging, SQL, algorithms |
## Installation
Copy the `complexity-router` directory to OpenClaw's extensions directory:
```bash
cp -r complexity-router ~/.openclaw/extensions/
```
## Configuration
Add to `openclaw.json`:
```json
{
"plugins": {
"allow": ["complexity-router"],
"entries": {
"complexity-router": {
"enabled": true,
"config": {
"classifier": {
"provider": "your-provider",
"model": "lightweight-model",
"timeoutMs": 5000
},
"routes": {
"simple": { "provider": "...", "model": "..." },
"medium": { "provider": "...", "model": "..." },
"complex": { "provider": "...", "model": "..." },
"code": { "provider": "...", "model": "..." }
}
}
}
}
}
}
```
### Configuration Fields
**classifier** — Classifier settings
| Field | Required | Description |
|-------|----------|-------------|
| `provider` | Yes | Provider for the classifier (must be configured in `models.providers`) |
| `model` | Yes | Classifier model ID (lightweight model recommended to reduce latency) |
| `timeoutMs` | No | Classification request timeout (default: 5000ms) |
**routes** — Routing table
Each of the 4 levels maps to a `{ provider, model }` target. Providers must be configured in `models.providers`.
### Example: Single Provider
All models from the same provider:
```json
{
"classifier": { "provider": "openai", "model": "gpt-4o-mini" },
"routes": {
"simple": { "provider": "openai", "model": "gpt-4o-mini" },
"medium": { "provider": "openai", "model": "gpt-4o" },
"complex": { "provider": "openai", "model": "o3" },
"code": { "provider": "openai", "model": "codex" }
}
}
```
### Example: Multi-Provider Cross-Vendor
Use a cheap model for classification, high-end models for complex tasks, mixing vendors:
```json
{
"classifier": { "provider": "dashscope", "model": "qwen-turbo" },
"routes": {
"simple": { "provider": "dashscope", "model": "qwen-turbo" },
"medium": { "provider": "crs", "model": "gpt-5" },
"complex": { "provider": "crs", "model": "gpt-5.1" },
"code": { "provider": "crs", "model": "gpt-5.2-codex" }
}
}
```
Requires both `dashscope` and `crs` configured in `models.providers`.
## Supported API Formats
The plugin automatically selects the request/response format based on the provider's `api` field:
| API Type | Description | Auth Method |
|----------|-------------|-------------|
| `openai-completions` | OpenAI-compatible API (default) | `Authorization: Bearer` |
| `anthropic-messages` | Anthropic Claude Messages API | `x-api-key` |
| `google-generative-ai` | Google Gemini API | `x-goog-api-key` |
The `api` field is configured in `models.providers` and read automatically by the plugin.
### Example: Claude as Classifier
```json
{
"models": {
"providers": {
"anthropic": {
"baseUrl": "https://api.anthropic.com/v1",
"apiKey": "sk-ant-...",
"api": "anthropic-messages"
}
}
},
"plugins": {
"entries": {
"complexity-router": {
"config": {
"classifier": { "provider": "anthropic", "model": "claude-haiku-4-5-20251001" },
"routes": { "..." : "..." }
}
}
}
}
}
```
### Example: Gemini as Classifier
```json
{
"models": {
"providers": {
"google": {
"baseUrl": "https://generativelanguage.googleapis.com/v1beta",
"apiKey": "AIza...",
"api": "google-generative-ai"
}
}
},
"plugins": {
"entries": {
"complexity-router": {
"config": {
"classifier": { "provider": "google", "model": "gemini-2.0-flash" },
"routes": { "..." : "..." }
}
}
}
}
}
```
## Prerequisites
The plugin reads provider credentials (baseUrl, apiKey, api) from `models.providers` in `openclaw.json`. Ensure:
1. `classifier.provider` is configured in `models.providers`
2. All providers referenced in `routes` are configured in `models.providers`
## Logs
The plugin outputs to the gateway log:
```
[complexity-router] registered — classifier: crs/gpt-5-nano
[complexity-router] classified as "code" in 1528ms
[complexity-router] routing to crs/gpt-5.2-codex
```
On classification failure:
```
[complexity-router] classifier timed out after 5001ms
[complexity-router] fallback to default model
```
## Stats & Observability
### Chat Command `/router-stats`
Type `/router-stats` in chat to view live statistics:
```
📊 Complexity Router Stats
Uptime: 2h 35m | Total: 42 | Fallback: 1
Routing:
simple 12 ( 28.6%) → gpt-5-nano | In: 3.2k Out: 8.1k tokens
medium 15 ( 35.7%) → gpt-5.1 | In: 12.5k Out: 45.2k tokens
complex 8 ( 19.0%) → gpt-5.2 | In: 8.7k Out: 32.1k tokens
code 7 ( 16.7%) → gpt-5.3-codex | In: 15.3k Out: 52.8k tokens
Classifier (gpt-5-nano): 42 calls | Avg 2,341ms | In: 1.8k Out: 0.2k tokens
```
### HTTP Endpoint `GET /complexity-router/stats`
Returns full statistics in JSON format, suitable for monitoring systems:
```bash
curl http://localhost:18789/complexity-router/stats
```
```json
{
"startedAt": 1772288992234,
"uptimeMs": 9300000,
"total": 42,
"fallback": 1,
"classifier": {
"requests": 42,
"totalMs": 98322,
"inputTokens": 1823,
"outputTokens": 210
},
"levels": {
"simple": { "count": 12, "inputTokens": 3200, "outputTokens": 8100 },
"medium": { "count": 15, "inputTokens": 12500, "outputTokens": 45200 },
"complex": { "count": 8, "inputTokens": 8700, "outputTokens": 32100 },
"code": { "count": 7, "inputTokens": 15300, "outputTokens": 52800 }
}
}
```
### Stats Fields
| Field | Description |
|-------|-------------|
| `classifier.inputTokens/outputTokens` | Tokens consumed by the classifier itself (extracted from classification API response) |
| `levels.*.inputTokens/outputTokens` | Tokens consumed by routed models (collected via `llm_output` hook) |
| `fallback` | Number of times classification failed and fell back to the default model |
## Compatibility
- Supports OpenAI, Anthropic, and Google Gemini API formats
- Auto-adapts to streaming/non-streaming APIs (auto-downgrades when provider forces streaming)
- Classification timeout triggers automatic fallback without affecting replies
- Token stats auto-adapt to each API's usage field format
tools
Comments
Sign in to leave a comment