作者:金木鼬
链接:https://www.zhihu.com/question/2002419946173510919/answer/2007858910695014830
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

从一脸懵到跑通 thinking 模式,全程记录。


Part 1:最终方案(直接抄作业)

如果你不想看踩坑过程,直接用这个配置就行:

1. 订阅火山方舟 Coding Plan

volcengine.com/activity 买个 Lite 套餐(首月 8.9 元),然后在开通管理页面选 Kimi-K2.5

2. 拿 API Key

console.volcengine.com/

3. 配置 OpenClaw

openclaw config set 'models.providers.doubao' --json '{
  "baseUrl": "https://ark.cn-beijing.volces.com/api/coding/v3",
  "apiKey": "你的真实API Key",
  "api": "openai-completions",
  "models": [
    {
      "id": "ark-code-latest",
      "name": "ark-code-latest",
      "reasoning": true,
      "input": ["text"],
      "contextWindow": 131072,
      "maxTokens": 32768,
      "compat": {
        "supportsDeveloperRole": false
      }
    }
  ]
}'

openclaw config set 'agents.defaults.model' --json '{"primary": "doubao/ark-code-latest"}'
openclaw config set 'agents.defaults.models' --json '{"doubao/ark-code-latest": {"alias": "doubao"}}'
openclaw config set 'agents.defaults.thinkingDefault' '"high"'

4. 清 session + 重启

rm -rf ~/.openclaw/sessions/*
openclaw gateway restart

搞定。接下来是踩坑故事。


Part 2:踩坑全记录

🕳️ 坑 1:Message Ordering Conflict

配好 provider、设好 reasoning: true 准备开心地聊天,结果第一句话就炸了:

Message ordering conflict – please try again. If this persists, use /new to start a fresh session.

/new 也没用,换 session 也没用,彻底没法对话。

第一反应:是 thinking 惹的祸

因为加了 reasoning: true 才出问题,所以先怀疑是 thinking 相关。搜 GitHub issue 找到了这个:

openclaw/openclaw#7693 — Role ordering conflict for third-party OpenAI-compatible providers (Kimi, Qwen, etc.)

Issue 里说的很清楚:

翻译一下:火山方舟的 provider 名叫 `”doubao”`,OpenClaw 不认为它是 OpenAI,也不认为它是 Anthropic,所以**消息顺序验证直接被跳过了**。 Issue 作者建议的修复:

于是我去改了 OpenClaw 的编译后源码(`transcript-policy.js`),把

!isOpenAi && isAnthropic

改成

!isOpenAi

改了之后——还是报错。🤦

拨开迷雾:真正的元凶是 `developer` role

继续翻 issue,找到了另外两个关键线索:

openclaw/openclaw#3566— DeepSeek: Message ordering conflict due to unsupported `developer` role

openclaw/openclaw#3022 — MiniMax provider rejects “developer” role

原来如此!OpenClaw 开了 reasoning: true 之后,会用 developer role 发系统提示词。火山方舟根本不认识这个 role,直接 400,然后 OpenClaw 把这个 API 错误包装成了 “Message ordering conflict”——真实原因藏在日志里,用户看到的是个误导性的提示。

第一次尝试修复:放错位置

知道要加 supportsDeveloperRole: false 了,凭直觉放在了 provider 级别:

"providers": {
  "doubao": {
    "supportsDeveloperRole": false,  // ← 放这里
    ...
  }
}

结果 OpenClaw 启动直接报错:

Invalid config at /root/.openclaw/openclaw.json:
- models.providers.doubao: Unrecognized key: "supportsDeveloperRole"

还贴心地告诉你去 doctor --fix 删掉这个 key。好家伙。

找到正确位置

继续搜,找到了一个关于 Ollama 遇到相同问题的 Gist 讨论:

GitHub Gist: OpenClaw + Ollama

When openclaw has “reasoning” enabled it sends the prompt (all the md files) as developer, which ollama doesn’t support. Setting models.providers.models.compat.supportsDeveloperRole to false might fix for some people.

然后在另一个 Discussion 里看到了 schema 定义:

openclaw/openclaw Discussion #6922

export const ModelCompatSchema = z.object({
  supportsStore: z.boolean().optional(),
  supportsDeveloperRole: z.boolean().optional(),
  supportsReasoningEffort: z.boolean().optional(),
  maxTokensField: z.union([...]).optional(),
}).strict().optional();

supportsDeveloperRoleModelCompatSchema 的字段,也就是说它属于单个模型的 compat 对象,不是 provider 级别的配置。

正确写法:

"models": [{
  "id": "ark-code-latest",
  "compat": {
    "supportsDeveloperRole": false   // ✅ 在 model 的 compat 里
  }
}]

改完重启,终于能正常对话了。🎉


🕳️ 坑 2:Thinking 到底开了没有

对话通了,但怎么确认 thinking 模式真的在工作?

看日志:

openclaw logs --follow

发一条消息,日志里出现了:

embedded run start: ... provider=doubao model=ark-code-latest thinking=low ...

thinking=low ✅ 说明 thinking 已经生效了!

因为在模型上设了 reasoning: true,根据 OpenClaw Thinking 文档 的 fallback 规则:

Fallback: low for reasoning-capable models; off otherwise.

没有手动设 thinkingDefault 的话,默认就是 low。想要更深的思考,设成 high

openclaw config set 'agents.defaults.thinkingDefault' '"high"'
openclaw gateway restart

也可以在对话中随时切换:

/think:high    # 当前会话用 high
/think:off     # 关掉
/think         # 看当前级别
/reasoning on  # 让思维链内容可见

🕳️ 坑 3:中文 API Key 占位符炸了

这个纯属手滑。复制命令时忘了把 AI给的"你的API_KEY" 换成真实 key,结果:

cannot convert argument to a bytestring because the character
at index 7 has a value of 20320 which is greater than 255

20320 是汉字 "你" 的 Unicode 码位。换成真实 key 就好了,不提了(尴尬 😅


Part 3:为什么会这样?

developer role 是个什么东西

OpenAI 在 2024 年底搞了个新 role 叫 developer,用来跟 system 区分:

  • system:平台级指令
  • developer:开发者写的应用指令(比如 SOUL.md、TOOLS.md 的内容)
  • user:用户说的话

OpenClaw 在 reasoning: true 时会用 developer role 发系统提示词。这对 OpenAI 原生 API 没问题,但大多数第三方 API 都不认这个 role

supportsDeveloperRole: false 后,OpenClaw 自动把 developer 降级为 system——对火山方舟来说效果完全一样,tool calling 也不受影响。

为什么表面报错那么误导

OpenClaw 把所有 API 返回的错误都包装成了 “Message ordering conflict”。不管是 role 不对、token 超限还是别的什么,用户看到的都是同一句话。真正的错误信息只在 openclaw logs 里,这也是为什么遇到问题第一件事一定要看日志


附录:完整配置文件片段

{
  "models": {
    "providers": {
      "doubao": {
        "baseUrl": "https://ark.cn-beijing.volces.com/api/coding/v3",
        "apiKey": "ark-xxxxxxxxxxxxxxxx",
        "api": "openai-completions",
        "models": [
          {
            "id": "ark-code-latest",
            "name": "ark-code-latest",
            "reasoning": true,
            "input": ["text"],
            "contextWindow": 131072,
            "maxTokens": 32768,
            "compat": {
              "supportsDeveloperRole": false
            }
          }
        ]
      }
    }
  },
  "agents": {
    "defaults": {
      "thinkingDefault": "high",
      "model": {
        "primary": "doubao/ark-code-latest"
      },
      "models": {
        "doubao/ark-code-latest": {
          "alias": "doubao"
        }
      }
    }
  }
}

附录:踩坑涉及的 Issue / Discussion

问题 链接 关键信息
第三方 provider role ordering #7693 validateAnthropicTurns 只对 Anthropic 生效,第三方 provider 被跳过
DeepSeek developer role 400 #3566 API 不认 developer role,报错被包装成 “ordering conflict”
MiniMax developer role 400 #3022 提到 supportsDeveloperRole: false 的解决方案
compat schema 定义 Discussion #6922 supportsDeveloperRole 在 ModelCompatSchema 里,是 model 级别
Ollama developer role Gist “reasoning enabled → sends prompt as developer → ollama doesn’t support”
Session 状态污染 #998 ordering conflict 会污染 session,必须 rm -rf sessions/*
DeepSeek R1 切模型 ordering #6655 切模型后 session history 包含连续同 role 消息