ACP 运行时模型覆盖 Bug 的排查与修复
配置文件里的 agent.model.primary 没有生效,所有 ACP agent 都回到了默认模型。我从 sessions_spawn 往下追调用链,最后发现代码传参、配置污染和启动模型三个问题叠在了一起。
现象
我用 OpenClaw 管理多个 AI agent。claude3 配置的是 mimo-v2.5,支持多模态和 262K 上下文;claude1、claude2 配置的是纯文本模型 mimo-v2.5-pro,上下文为 1M。配置写在 openclaw.json:
{
"id": "claude3",
"model": { "primary": "xiaomi/mimo-v2.5" },
"runtime": { "type": "acp", "acp": { "agent": "claude", "backend": "acpx" } }
}
从微信触发 claude3 的任务时,实际使用的始终是默认模型 mimo-v2.5-pro。配置本身能被读取,但模型覆盖没有落到 ACP 会话里。
沿 ACP spawn 调用链往下查
当时能看到的是 dist/ 目录里的 minified JS,没有 source map。我从 sessions_spawn 的入口开始,按 model 参数的传递路径逐层追:
sessions_spawn → spawnAcpDirect → initializeAcpSpawnRuntime
→ ACP Session Manager → AcpxRuntime.ensureSession → AcpxManager
这条链上有两个独立问题。
1. ACP spawn 没有读取 agent 配置
sessions_spawn 只从工具调用参数里取 model,没有回退到 agent 配置。对比另一条 subagent 路径,那里已经有 resolveSubagentSpawnModelSelection,可以解析 agent.model.primary;ACP 路径少了对应处理。
2. AcpxRuntime 收到了 model,又在下一层丢掉了
AcpxRuntime.ensureSession 能拿到 input.model,但传给内层 manager 的只有 input.sessionOptions。在这条路径里,后者一直是 undefined,所以 model 没有进入 session options。
// 修复前
sessionOptions: input.sessionOptions
// 修复后
sessionOptions: input.sessionOptions ?? (input.model ? { model: input.model } : undefined)
补上 agent 配置解析和这层映射以后,openclaw agent --agent claude3 已经能返回正确的模型名。但从微信发起真实委托时,又出现了新的报错。
模型名里混进了 ANSI 转义码
真实委托返回的错误是:
model (mimo-v2.5-pro[1m]) may not exist or you may not have access
[1m 是 ANSI 加粗序列的一部分。配置和打包代码里都没有这段字符,最后在 ~/.claude/settings.json 找到了来源:
"ANTHROPIC_MODEL": "mimo-v2.5-pro[1m"
清掉这段污染以后,报错里的模型名恢复正常,但请求仍然没有切到 mimo-v2.5:
model (mimo-v2.5-pro) may not exist or you may not have access
ANTHROPIC_MODEL 还决定了启动模型
ANTHROPIC_MODEL 不只是普通默认值,它会影响 Claude Code 进程启动时使用的模型。ACP runtime 后续虽然调用 setSessionModel 尝试切换到 mimo-v2.5,但进程已经按 mimo-v2.5-pro 启动,切换可能失败或被忽略。
最后把 ANTHROPIC_MODEL 改成 mimo-v2.5,让 claude3 从启动时就使用它需要的模型。claude1、claude2 需要 mimo-v2.5-pro 时,再由 ACP runtime 切换。
最后对照
| 问题 | 原因 | 处理 |
|---|---|---|
| ACP spawn 不读 agent 配置 | sessions_spawn 只读取工具参数里的 model |
通过 resolveAgentConfig 解析 agent 配置 |
AcpxRuntime 丢弃 model |
input.sessionOptions 为 undefined |
把 input.model 映射到 sessionOptions |
| 启动模型仍被锁定 | ANTHROPIC_MODEL 带有 ANSI 污染,且指向另一个默认模型 |
清理变量并把启动模型改为 mimo-v2.5 |
难点主要有两个:一是只能在压缩后的变量名和控制流里找参数去了哪里;二是三个问题单独看都不像完整原因,只有依次修掉以后,下一层现象才会露出来。