现象 链接到标题

升级 OpenClaw 后,在飞书私聊中输入 /model 指令,返回:

⚠️ This reply completed without visible content. The turn may have been interrupted; please retry or ask me to recover from recent context.

但令人困惑的是:

  • 普通对话消息正常回复
  • /new 指令也正常(“New session started.")
  • 只有 /model/models 这类指令型命令无响应

同一个模型、同一个会话,为什么有的命令能走有的不行?

排查链路 链接到标题

疑点一:走不走 LLM? 链接到标题

查看 /model 的实现代码,发现它属于 directive handler(指令处理器),根本不调用 LLM。它的作用是读取当前模型配置并以文本形式返回。所以问题不在模型或 API key 上。

疑点二:为什么 /new 能走但 /model 不能? 链接到标题

从 gateway 日志看,两个命令都输出了 dispatching to agent,但 /model 紧接着输出了 dispatch complete (queuedFinal=false, replies=0),而 /newqueuedFinal=true, replies=1

翻阅 OpenClaw 源码后,指令的分发流程大致如下:

flowchart TD A[用户发送命令] --> B{isDirectiveOnly?} B -->|是| C{isAuthorizedSender?} C -->|否| D[返回空回复
no-visible-reply] C -->|是| E[处理指令
返回文本] B -->|否| F[走 LLM 对话] F --> G[正常回复]

关键区别:/modeldirective-only 命令(指令参数为空时,整条消息只剩指令本身,无需 LLM 参与),会进入 isDirectiveOnly 分支,再通过 isAuthorizedSender 检查。而 /new 是会话管理命令,不走这个分支。

疑点三:问题定位 链接到标题

isDirectiveOnly == true 的分支中,如果 isAuthorizedSender 返回 false,直接返回空回复——恰好是报错的现象。

那么 isAuthorizedSender 的判断依据是什么?答案是配置文件中的 commands.ownerAllowFrom 字段。

根因 链接到标题

检查配置发现:

"commands": {
  "ownerAllowFrom": ["feishu:8f78aage"]
}

这个值格式错误。Feishu 用户的正确标识格式是 feishu:ou_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxou_ 开头),而当前值 8f78aage 不是一个合法的 open_id,导致权限验证不通过。

这也是普通对话不受影响的原因——普通消息不经过 isDirectiveOnly 分支,不走这个权限检查。

解决 链接到标题

修正 ownerAllowFrom 为正确的 Feishu open_id:

"commands": {
  "ownerAllowFrom": ["feishu:ou_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
}

OpenClaw 检测到配置变化后自动热重载,无需重启进程。再次输入 /model 即正常返回当前模型信息:

Current: deepseek/deepseek-v4-flash
Switch: /model <provider/model>
...

总结 链接到标题

  • OpenClaw 中指令型命令(/model/models/think/fast 等)与 LLM 对话走的是不同的权限验证路径
  • commands.ownerAllowFrom 的值必须是正确的 feishu:ou_xxx 格式,否则指令型命令会被静默拒绝
  • 排查技巧:同配置 ≠ 同行为,遇到不一致时要逐一对比配置项的值而非仅看配置结构
  • 使用 openclaw doctor 可帮助发现部分配置问题,但不是所有配置错误都会被检测到