一个参数毁一天:OpenClaw 接入第三方模型的血泪避坑指南

摘要:OpenClaw 是一款强大的开源 AI Agent 框架,支持接入多种 LLM 模型。但当你兴冲冲地配置第二个 OpenAI 兼容模型时,可能会遭遇一个诡异的问题——不仅新模型用不了,连原来好好的模型也一起挂了。本文记录了我花费整整一天排查这个问题的全过程,以及最终发现的那个"一个参数"的真相。


🎯 背景

我在云服务器上部署了 OpenClaw,用它作为个人 AI 助手,通过飞书、Web 等渠道与 LLM 交互。

最初只配了一个模型 provider,一切运行正常。直到有一天,我想接入第二个 OpenAI 兼容的模型端点(一个自建的 Claude 代理服务),噩梦开始了。

💥 问题现象

配置好第二个 provider 后,重启网关:

openclaw gateway restart

结果:

  • ❌ 新配的模型:无响应
  • ❌ 原来正常的模型:也挂了!
  • ✅ 网关启动正常,没有报错
  • ✅ 配置文件验证通过

最恐怖的是——没有任何错误提示。 配置看起来完全正确,网关也正常启动了,但就是所有模型都不工作了。

🔍 排查过程(走了一天弯路)

第一阶段:怀疑配置格式

我反复检查 JSON 格式、路径嵌套、字段拼写……

{
  "models": {
    "providers": {
      "my-provider": {
        "baseUrl": "http://my-api-endpoint/v1",
        "apiKey": "sk-xxxxx",
        "models": [
          {
            "id": "claude-sonnet-4-5",
            "name": "Claude Sonnet 4.5",
            "contextWindow": 200000,
            "maxTokens": 8192
          }
        ]
      }
    }
  }
}

看起来没问题啊?文档里也是这么写的。

第二阶段:怀疑网络

curl -X POST http://my-api-endpoint/v1/chat/completions \
  -H "Authorization: Bearer sk-xxxxx" \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-sonnet-4-5","messages":[{"role":"user","content":"hello"}]}'

API 端点直接 curl 测试——完全正常,返回了正确的响应。

第三阶段:怀疑人生

  • 回滚配置 → 原来的模型恢复了 ✅
  • 加上新 provider → 又全挂了 ❌
  • 删掉新 provider 的 models 数组 → 还是挂 ❌

到这里我开始意识到:问题不在模型定义上,而在 provider 级别的某个配置缺失。

第四阶段:源码阅读(终极手段)

文档翻了三遍,没找到答案。最后我决定直接读 OpenClaw 的源码:

grep -r "openai-completions" ~/.npm-global/lib/node_modules/openclaw/dist/

追踪到请求构建逻辑后,我终于发现了真相——

💡 真相:两个"隐形"必填参数

OpenClaw 在对接 OpenAI 兼容端点时,有两个参数在文档中不够醒目,但缺一不可:

参数一:api: "openai-completions"

告诉 OpenClaw 使用 OpenAI Chat Completions API 格式发送请求。

不设置会怎样? OpenClaw 不知道该用什么协议格式跟你的 API 通信,请求格式错误,API 返回 400/422。

参数二:authHeader: true

告诉 OpenClaw 在请求头中加上 Authorization: Bearer <apiKey>

不设置会怎样? 即使你配了 apiKey,OpenClaw 也不会把它放到请求头里,API 返回 401/403。

✅ 正确的完整配置

{
  "models": {
    "providers": {
      "my-provider": {
        "baseUrl": "http://my-api-endpoint/v1",
        "apiKey": "sk-xxxxx",
        "api": "openai-completions",
        "authHeader": true,
        "models": [
          {
            "id": "claude-sonnet-4-5",
            "name": "Claude Sonnet 4.5",
            "reasoning": false,
            "input": ["text"],
            "cost": {
              "input": 3,
              "output": 15,
              "cacheRead": 0,
              "cacheWrite": 0
            },
            "contextWindow": 200000,
            "maxTokens": 8192
          }
        ]
      }
    }
  }
}

就是 "api": "openai-completions""authHeader": true 这两行,少了任何一个,整个 provider 就静默失败

✅ 正确的通用配置

{
  "provider": "provider_name",
  "base_url": "baseurl",
  "api": "API协议openai-completions"/"anthropic-messages",
  "authHeader": true,
  "api_key": "your-api-key-here",
  "model": {
    "id": "model_id",
    "name": "model_name"
  }
}

🤯 为什么"原来的模型也挂了"?

这是最坑的地方。当你新增一个有问题的 provider 时,OpenClaw 的模型路由逻辑会尝试解析所有 provider。如果新 provider 的配置导致运行时异常(比如请求格式不对),可能会影响整个模型调度链路,导致连原本正常的 provider 也无法正常路由。

这就是为什么我花了一整天——因为我一直在排查"为什么原来的模型也坏了",而不是聚焦在"新加的 provider 到底缺了什么"。

📋 OpenClaw 第三方模型接入 Checklist

经过这次教训,我总结了一份接入 checklist,每次配新模型前过一遍:

# 检查项 说明
1 baseUrl 是否以 /v1 结尾 不完整会 404
2 apiKey 是否正确 直接 curl 验证
3 api 是否设为 "openai-completions" ⭐ 最容易遗漏
4 authHeader 是否设为 true ⭐ 最容易遗漏
5 models[].id 是否与 API 端点的模型 ID 一致 大小写敏感
6 配置路径是否正确:models.providers.xxx 不是顶层 providers
7 修改后用 cat ~/.openclaw/openclaw.json | jq 验证 patch 写错路径不报错
8 先备份再改 cp openclaw.json openclaw.json.backup

💭 感悟

一个参数,一天时间。

结果看起来很简单——加两行配置就好了。但找到这个答案的过程,涉及文档阅读、日志分析、网络排查、源码追踪……这就是工程的真实面貌。

真正有价值的不是答案本身,而是找到答案的方法论。

OpenClaw 是一个优秀的开源项目,迭代很快,文档难免有滞后。当文档不够用时,源码就是唯一的 truth。学会读源码,是每个工程师的必修课。

希望这篇文章能帮你少走一天弯路。


参考资料


关于作者:一个在 openclaw Agent 应用路上不断踩坑的工程师。如果这篇文章帮到了你,点个赞就是最好的鼓励 👍

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐