@ncdlabs/openclaw-difficulty-router
v1.0.4
Published
OpenClaw plugin that selects the model per turn based on prompt difficulty (simple / default / complex)
Maintainers
Readme
OpenClaw Difficulty Router
OpenClaw plugin that selects the provider/model per turn based on prompt difficulty. It implements the before_model_resolve hook and returns providerOverride / modelOverride so simple prompts can use a small model and complex prompts a larger one.
- Automatic mode: No config (or empty config). No overrides; OpenClaw uses its default model. Behavior is predictable.
- Single config: Configure tiers (and optional heuristic tuning) in one place: either the plugin config block in OpenClaw config or one optional JSON file.
No changes to the OpenClaw core repo are required. Install into an existing OpenClaw installation and enable the plugin.
Requirements: Node.js >= 18, OpenClaw >= 2026.2.0.
Installation
From the OpenClaw project or environment where the openclaw CLI is available:
openclaw plugin install @ncdlabs/openclaw-difficulty-routerOpenClaw may also support installing from GitHub; see OpenClaw plugin docs for current options.
After install, enable the plugin (if not auto-enabled) and optionally add config:
openclaw plugins enable difficulty-routerConfiguration
All user-facing configuration is either:
- Automatic: No file, no plugin config. The plugin does not override; OpenClaw’s default model is used every turn.
- Plugin config block: In your main OpenClaw config (
openclaw.yamloropenclaw.json), underplugins.entries.difficulty-router.config. - Single JSON file (optional): Set
configFilein the plugin config to a path (e.g.~/.openclaw/difficulty-router.json). That file can definetiersandheuristic; values there override the plugin config block.
Tier keys
Tiers are: simple, default, complex. Each value is a model ref in the same format OpenClaw uses: provider/model-id (e.g. ollama/qwen2.5-coder:3b, openai/gpt-4o-mini).
- simple: Very short prompts and no sign of multi-step work (see heuristic below).
- default: Everything that is neither simple nor complex.
- complex: Long prompts or clearly multi-part / step-by-step prompts.
You can set only the tiers you care about. If a tier is missing, that turn is not overridden and OpenClaw’s default applies.
Heuristic (tunable)
When tiers are configured, difficulty is computed as follows (thresholds are configurable):
- simple: Prompt length ≤
simpleMaxChars(default 50) and no multi-step indicators (e.g. “step 1”, “first, then”, bullet lists). - complex: Prompt length ≥
complexMinChars(default 500) or contains multi-step indicators. - default: Everything else.
Prefer default when in doubt. Thresholds can be set under heuristic in the plugin config or in the optional JSON file.
Example: plugin config only
In openclaw.yaml (or equivalent):
plugins:
entries:
difficulty-router:
enabled: true
config:
tiers:
simple: "ollama/qwen2.5-coder:3b"
default: "ollama/qwen2.5-coder:7b"
complex: "ollama/qwen2.5-coder:32b"
heuristic:
simpleMaxChars: 80
complexMinChars: 400Example: single JSON file
In OpenClaw config, point to one file:
plugins:
entries:
difficulty-router:
enabled: true
config:
configFile: "~/.openclaw/difficulty-router.json"Then create ~/.openclaw/difficulty-router.json:
{
"tiers": {
"simple": "ollama/qwen2.5-coder:3b",
"default": "ollama/qwen2.5-coder:7b",
"complex": "ollama/qwen2.5-coder:32b"
},
"heuristic": {
"simpleMaxChars": 50,
"complexMinChars": 500
}
}Behavior
- When no tiers are set (automatic or empty config): the plugin never overrides; OpenClaw’s default provider/model is used.
- When tiers are set: on each turn the plugin computes difficulty, picks the tier’s model ref, and returns
providerOverrideandmodelOverride. OpenClaw then uses that model for that run. If the overridden model fails, OpenClaw’s existing fallback behavior applies.
Heuristic validation
If simpleMaxChars is set greater than or equal to complexMinChars, the plugin automatically sets complexMinChars to simpleMaxChars + 1 so the default band is never empty.
Troubleshooting
- Plugin does not override: Ensure at least one tier is set under
tiers(simple, default, or complex) and the plugin is enabled (plugins.entries.difficulty-router.enabled: true). Check gateway logs for[difficulty-router] loaded with tiersat startup. - configFile not found or invalid: If you set
configFile, the path is resolved via OpenClaw’sresolvePath(e.g.~expands to your home directory). The file must be valid JSON. You’ll see[difficulty-router] configFile not foundorconfigFile parse errorin logs if the file is missing or invalid. - Invalid tier model ref: Each tier value must be
provider/model(e.g.ollama/qwen2.5-coder:3b). If a ref is malformed, that tier is skipped for the run and no override is returned. - Hook errors: If the hook throws (e.g. bug), the plugin catches, logs
[difficulty-router] before_model_resolve error: ..., and returns no override so the run continues with the default model.
Security / Scanning
This plugin has zero runtime dependencies (only a peer dependency on OpenClaw). That keeps the supply-chain surface small: no transitive packages from this plugin.
After installing (e.g. into ~/.openclaw/extensions/difficulty-router/), you can run:
- npm audit – From the plugin directory:
npm audit. Any reported vulnerabilities will be from OpenClaw’s dependency tree (installed as a peer), not from this package’s own dependencies. - Socket – For a deeper scan, use Socket CLI:
socket login(once, with your API token), thensocket scan createfrom the plugin directory orsocket package score npm @ncdlabs/openclaw-difficulty-router.
See SECURITY.md for how to report vulnerabilities.
Development
npm install
npm run buildBuild output is dist/. The OpenClaw plugin entry is ./dist/index.js (see openclaw.extensions in package.json). Run npm pkg fix to normalize package.json if needed.
License
MIT.
