别改了主配置却不生效——OpenClaw 多模型路由机制深度解析
别改了主配置却不生效——OpenClaw 多模型路由机制深度解析
摘要
你有没有遇到这种情况:明明在 openclaw.json 里把默认模型改成了新的,飞书消息回复的却还是旧模型?或者换了模型发现"没反应",日志里却是另一个模型在跑?
这篇文章从一次真实的排查过程出发,拆解 OpenClaw 的模型选择完整链路:主配置 → Hook 路由 → Fallback 兜底,讲清楚每一层的优先级、运作时机,以及最容易踩的坑。
背景:一次"改了但没生效"的完整排查
某天把 OpenClaw 的默认模型从 openai-codex/gpt-5.4 切换到 openai/gpt-5.3-codex,重启后发了条消息,飞书侧依然沉默或者很慢。打开日志一看,gpt-5.3-codex 大量报 API rate limit reached 和 LLM request timed out,有些请求卡到 timeoutMs=600000(整整 10 分钟)才失败,看起来就像"没反应"。
但更诡异的是:明明有些请求最后成功了,用的却是 Bailian 的模型——说明系统没死,只是走了 fallback。
这就引出了一个问题:OpenClaw 的模型到底是怎么选的?哪一层的配置优先级最高?
OpenClaw 模型选择的三层结构
第一层:agents.defaults.model——默认主模型
这是大多数人第一个想到的配置点,位于 ~/.openclaw/openclaw.json:
{
"agents": {
"defaults": {
"model": {
"primary": "openai/gpt-5.3-codex",
"fallbacks": [
"bailian/qwen3.5-plus",
"bailian/MiniMax-M2.5"
]
}
}
}
}
primary:系统在没有任何覆盖时优先选择的模型。fallbacks:当primary报错(限流、超时、余额不足)时,按数组顺序依次尝试。
坑点一:fallbacks 是静默接管的。如果 primary 失败,系统会自动换到下一个 fallback,日志里也只是多一条切换记录,飞书侧看到的是最终成功的那个模型。这会让你误以为"主模型生效了但很卡",实际上是"主模型一直在失败,fallback 在接活"。
坑点二:改完 primary 后必须重启 openclaw gateway 才能生效,修改配置文件本身不会热加载。
openclaw gateway restart
# 或者
openclaw models status --plain # 验证当前实际使用的模型
第二层:model-router Hook——内容感知的路由覆盖
这是最容易被忽视、也最容易踩坑的一层。
OpenClaw 支持自定义 Hook,其中 model-router Hook 可以在每次请求到来时,根据消息内容动态决定使用哪个模型——它的优先级高于 agents.defaults.model.primary。
Hook 文件默认在 ~/.openclaw/hooks/model-router/handler.js,以下是一个典型实现:
const CODE_PATTERNS = [
/```/,
/\b(code|coding|script|bash|shell|terminal|command|cli|sql)\b/i,
/\b(debug|traceback|报错|调试|修复|排查)\b/i,
/\b(config|配置|api key|token|gateway|hook|plugin)\b/i,
/\b(function|class|import|python|javascript|json|yaml|docker)\b/i,
/\b(openclaw|cron|workflow|自动化|脚本|代码)\b/i,
];
const GENERAL_PATTERNS = [
/\b(总结|摘要|日报|翻译|润色|改写|整理|头脑风暴)\b/i,
/\b(summary|summarize|rewrite|translate|brainstorm)\b/i,
];
export default async function modelRouter(event) {
const text = extractLatestUserText(event?.messages);
if (shouldUseCodex(text)) {
return { modelOverride: 'openai/gpt-5.3-codex' }; // ← 覆盖 primary
}
if (shouldPreferGeneral(text)) {
return { modelOverride: 'openai/gpt-4o' };
}
return { modelOverride: 'openai/gpt-4o' }; // ← 默认也是覆盖 primary
}
这就是为什么"改了 primary 却不生效":只要 model-router Hook 存在且命中了规则,它返回的 modelOverride 就会覆盖 primary。
举个具体例子:你把 primary 改成 zai/glm-4.5-air,但发送的消息里包含"帮我调试这个配置"——CODE_PATTERNS 命中,Hook 直接把请求路由到 gpt-5.3-codex,glm-4.5-air 根本没有机会。
第三层:fallbacks——失败兜底链
当上面某一层选出的模型请求失败(429 限流、504 超时、余额耗尽),fallback 链才启动:
primary 失败 → fallbacks[0] → fallbacks[1] → ... → 全部失败才算真正失败
常见的失败触发条件:
API rate limit reached(超过 RPM/TPM 限制)LLM request timed out(timeoutMs设置过长导致假死)You exceeded your current quota(账单余额不足,会被 OpenClaw 包装成 rate limit 提示)
坑点三:You exceeded your current quota 这个错误会被 OpenClaw gateway 统一包装成"⚠️ API rate limit reached"推送到飞书。如果你看到对话忽然变得很慢、偶尔恢复,大概率是 fallback 在接管,而不是 primary 本身在工作。
排查方式是直接看 gateway 错误日志:
tail -f ~/.openclaw/logs/gateway.err.log | grep -E "rawErrorPreview|modelOverride|fallback"
完整的排查 SOP
遇到"改了模型没生效"或"模型行为和预期不一致"时,按这个顺序排查:
Step 1:确认 primary 是否真的改对了
# 查看当前运行时实际使用的模型
openclaw models status --plain
# 直接用 jq 确认配置文件里的值
cat ~/.openclaw/openclaw.json | python3 -m json.tool | grep -A5 '"primary"'
注意:agents.defaults.model.primary 是生效字段,不是 models.providers.xxx.defaultModel 这类字段(后者仅用于 UI 展示)。
Step 2:检查 model-router Hook 是否存在且覆盖了你的期望
# 查看 hook 文件
cat ~/.openclaw/hooks/model-router/handler.js
# 如果 hook 里的返回值硬编码了某个模型,你改 primary 是不会生效的
# 需要同步修改 hook 里所有的 modelOverride 返回值
如果你不需要内容感知路由,最简单的做法是直接删除或禁用这个 hook:
// openclaw.json 里
{
"hooks": {
"model-router": {
"enabled": false
}
}
}
Step 3:从日志里确认实际发出请求的模型
# 找最近几条请求用了哪个模型
grep "modelOverride\|primary\|fallback" ~/.openclaw/logs/gateway.err.log | tail -30
Step 4:验证 fallback 是否在静默接管
如果 primary 一直 timeout 但 fallback 能正常返回,你看到的现象就是"有时能用、有时卡死"。此时需要:
- 确认 primary 的实际可用性(直接用 curl 测一下接口是否通)
- 临时把 primary 换成稳定的模型,把原来的放进 fallback
配置最佳实践
方案一:不需要内容感知路由
直接配好 primary 和 fallbacks,禁用 model-router hook。简单、可预期。
{
"agents": {
"defaults": {
"model": {
"primary": "custom-127-0-0-1-8317/xianyu-qwen3.6-plus",
"fallbacks": [
"custom-127-0-0-1-8317/xianyu-MiniMax-M2.7-highspeed"
]
}
}
}
}
方案二:内容感知路由 + 主配置一致
如果你需要不同类型的消息用不同模型,那 hook 和 primary 必须同步维护——改了一个另一个也要跟着改,否则会出现预期外的路由结果。
建议在 hook 里加注释:
// 同步修改:agents.defaults.model.primary 应该与此保持一致
return { modelOverride: 'openai/gpt-5.3-codex' };
方案三:配置热改后记得重启
openclaw gateway restart
# 验证新配置
openclaw models status
小结
OpenClaw 的模型选择链路按优先级从高到低是:
model-router Hook (modelOverride)
↓ 如果 hook 未命中或 hook 被禁用
agents.defaults.model.primary
↓ 如果 primary 请求失败
agents.defaults.model.fallbacks[0, 1, ...]
最核心的一条经验:改了 primary 之后,先检查有没有 model-router hook,再检查日志里实际发出请求用的是什么模型。这两步能解决 90% 的"改了没生效"问题。

浙公网安备 33010602011771号