前段时间我把工作流里的模型接入层整理了一遍顺手给 OpenClaw 配上了 DeepSeek 和百炼大模型两个入口。原本以为就是填两个 Base URL、粘两串 API Key 的事结果从密钥验证到网络连通前后折腾了小半天踩了不少隐蔽的坑。这篇文章就把整个排查过程、验证思路和最终可复用的配置模板写出来给同样在 OpenClaw 这类网关工具里对接国内模型服务的读者一些参考。不管是把 OpenClaw 当作统一的模型入口还是想在自己的脚本里同时调用 DeepSeek 和百炼核心要解决的就两件事密钥是否正确被服务端接受网络链路是否真的能到达目标 API。这两件事看似基础实际排查起来却最容易绕弯子。1. 为什么要在 OpenClaw 里同时对接两套模型以及两者的 API 风格差异OpenClaw 这类工具本质上是一个模型网关它不关心你背后接的是哪家服务商只要求你给它一个 Base URL、一组密钥、若干模型名称它就能把统一请求转发到不同后端。这样做的好处很明显上层应用只需要面对 OpenClaw 一个入口切换模型时不用改业务代码。我在实际配置时选择的两个目标分别是 DeepSeek 开放平台和百炼大模型服务平台。两者都提供 OpenAI 兼容的接口意思是说如果你用过 OpenAI 的 Chat Completions 接口那么迁移过去几乎没有学习成本。但注意“兼容”不等于“完全相同”它们在自己的 API 形态和鉴权方式上有一个关键差异。1.1 OpenClaw 对接模型服务的最简模型OpenClaw 的配置页通常只有三个核心项Base URLAPI 的根地址所有请求都基于这个地址拼接路径API Key服务商给你的密钥字符串Model Name你想要调用的模型标识比如deepseek-chat、qwen-plus一个标准的聊天补全请求路径大致是{Base URL}/chat/completions。请求时 OpenClaw 会在 HTTP 头里带上Authorization: Bearer API Key。后端通过这个头来识别调用者身份和配额。1.2 DeepSeek 与百炼的鉴权差异我把两家的关键差异整理成了表格第一次配置的人最好先看这个对比项DeepSeek 开放平台百炼大模型服务平台Base URL 示例https://api.deepseek.comhttps://dashscope.aliyuncs.com/compatible-mode/v1鉴权方式Authorization: Bearer API KeyAuthorization: Bearer API Key密钥前缀通常以sk-开头也是sk-开头的长字符串模型名示例deepseek-chat、deepseek-reasonerqwen-plus、qwen-turbo、qwen-max兼容 OpenAI 接口是是走 compatible-mode这里第一眼看上去两家的鉴权方式完全一致都是 Bearer Token。但实际踩坑往往不在“鉴权方式长什么样”而在“你给出去的那串字符串到底是不是服务端预期的那串”。密钥验证失败的九成原因都出在字符串本身而不是鉴权协议。百炼平台还有一点需要注意它有两种调用模式一种是原生 DashScope 格式走https://dashscope.aliyuncs.com/api/v1另一种是 OpenAI 兼容模式走https://dashscope.aliyuncs.com/compatible-mode/v1。如果你在 OpenClaw 里填的是原生 DashScope 地址OpenClaw 按 OpenAI 协议拼接/chat/completions返回的很可能是一堆看不懂的 XML 风格错误而不是标准的 JSON 错误体。这是很多人在百炼上首次配置失败的典型原因地址抄错了模式。2. 密钥验证的第一次翻车不可见字符与复制粘贴陷阱我第一次配置时把 DeepSeek 的密钥复制进 OpenClaw点击测试立刻得到 401 Unauthorized。当时第一反应是“密钥错了”于是重新复制一遍、删掉末尾的空格、再试还是 401。后来才发现问题根本不在密钥本身而在很多隐蔽的细节上。2.1 密钥形态检查清单我把自己后来总结的密钥检查顺序列在这里确认复制的是 API Key而不是账号密码或 AccessKey ID确认没有复制到前导或尾随空格确认密钥没有因为换行被拆成两段确认密钥中的所有字符都是英文字符没有混入中文标点确认密钥被完整复制没有漏掉最后几位这些看似蠢的问题在真实场景里出现的频率非常高。尤其是网页控制台的密钥展示区域有的支持一键复制有的并不支持只能用鼠标手动选择。手动选择时很容易因为鼠标拖动不到位少选了末尾的几个字符或者多选中了一个换行符。我还遇到过一种情况密钥中间某个字符看起来像数字0实际是英文字母O。这类视觉混淆字符肉眼很难发现只能通过逐字符比对或者直接重新生成密钥来解决。2.2 配置文件里埋下的“隐形炸弹”OpenClaw 的配置一般支持 YAML 或 JSON 格式。YAML 格式下如果你写的是api_key: sk-xxxxxxxxxxxxxxxx这个写法本身没问题但如果你在编辑时不小心在sk-xxxxxxxx后面留下了一个空格YAML 解析器会把空格当作值的一部分最终发送出去的 Authorization 头就变成了Bearer sk-xxxxxxxx末尾带空格。服务端比对密钥时是逐字节的多一个空格立刻 401。另一个高频问题是引号。如果你在 JSON 里写{ api_key: sk-xxxxxxxx }没问题。但如果某个编辑器自动帮你转义了字符或者你粘贴时引号变成了中文全角引号“sk-xxxx”JSON 解析就会失败OpenClaw 可能直接报配置格式错误也可能静默读取到一个空值。最稳妥的做法是把密钥放在.env环境变量文件里配置项里只写变量名引用。比如DEEPSEEK_API_KEYsk-xxxxxxxx DASHSCOPE_API_KEYsk-yyyyyyyy配置里这样引用api_key: ${DEEPSEEK_API_KEY}这样做的好处是密钥不会因为编辑器的编码问题或手误被污染而且方便多个环境之间切换。2.3 环境变量优先级问题OpenClaw 读取密钥通常有三种来源配置文件里直接写、环境变量、系统密钥管理服务。如果你同时配置了多个来源一定要弄清楚优先级。我实测下来有些版本里环境变量的优先级高于配置文件也就是说你明明在配置文件里写了新密钥但环境变量里还残留着旧密钥程序依然会使用旧值。排查方法是直接打开终端打印环境变量确认echo $DEEPSEEK_API_KEY如果你发现打印出来的值和你在控制台复制的不一致问题就在环境变量层面而不是配置文件。这种情况在我切换密钥后尤其常见旧密钥已经在 shell 的 session 里被 export 过新开的 OpenClaw 进程继承了旧值。3. 401/403 逐步排查从 curl 出发逆向确认请求身份解决了不可见字符问题后DeepSeek 很快通了但百炼依然不稳定。有时返回 401有时返回 403还有一次返回了奇怪的 404。这时候我意识到不能再靠“复制粘贴再试”的笨办法必须用 curl 把最原始的请求行为复现出来逐层确认问题出在哪一层。3.1 用 curl 复现最简请求所有客户端工具包括 OpenClaw本质上都在做同样一件事向 Base URL 发 POST 请求带 Authorization 头。所以可以直接用 curl 测试先绕开 OpenClaw把问题缩小到“密钥和地址”这个层面。测试 DeepSeek 的完整命令如下curl -v https://api.deepseek.com/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-xxxxxxxx \ -d { model: deepseek-chat, messages: [{role: user, content: 你好}], stream: false }-v参数会打印完整的请求头和响应头。如果密钥正确你会看到 HTTP/1.1 200 OK并跟着一段 JSON 文本。如果密钥错误服务端返回 401响应体里通常写着Authentication Fails或类似提示。测试百炼的 OpenAI 兼容模式命令如下curl -v https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-yyyyyyyy \ -d { model: qwen-plus, messages: [{role: user, content: 你好}], stream: false }这里有个关键细节百炼的 OpenAI 兼容模式路径是/compatible-mode/v1后面再接/chat/completions。如果你是第一次用百炼很容易把地址抄成https://dashscope.aliyuncs.com/api/v1/chat/completions这是原生模式路径返回的报错风格完全不同。3.2 根据状态码快速定位问题层我把实测中遇到的状态码和对应可能原因整理成了下表状态码可能原因建议动作401密钥错误、密钥过期、Authorization 头格式不对重点检查密钥字符串本身403密钥正确但无权限调用该模型检查账号是否开通对应模型服务404路径错误、模型名不存在检查 Base URL 路径和 model 参数429请求频率超限或账户欠费检查配额和余额500/502服务端异常或网关错误多为服务端问题稍后重试一个非常常见的坑是401 和 403 被混为一谈。实际上401 代表“你是谁我都不知道”多半是密钥问题403 代表“我知道你是谁但你不许调用这个模型”。表现到 OpenClaw 里可能都是红字报错但处理方向完全不同。我遇到过百炼返回 403 的情况原因是账号没有开通qwen-max的调用权限换了qwen-plus立刻就好了。如果你在百炼控制台看到了某个模型但实际账号权限没有生效就会出现这种“密钥没问题但请求被拒”的假象。3.3 确认 OpenClaw 实际发送的 Headercurl 能通不代表 OpenClaw 一定通。因为 OpenClaw 有可能在转发请求时对 Header 做了二次封装或者错误地拼接了路径。我排查时在 OpenClaw 里开启了 debug 级别的日志查看它实际打出的请求地址和 Authorization 头。如果你用的版本不支持直接看请求日志可以在服务端日志或网卡抓包里确认。最简单的方法是临时把 Base URL 指向自己本地起的一个 echo 服务比如nc -l 8080然后用 OpenClaw 发一次请求看收到的是什么。这个方法可以完整看到 OpenClaw 发出的路径和 Header 是否和 curl 一致。实测中我发现某些 OpenClaw 版本会把 Base URL 末尾的/v1自动拼接成/v1/v1导致 404。解决办法很简单Base URL 填到https://api.deepseek.com这一层不要自己补/v1让工具自动处理。4. 网络调试超时、DNS、握手异常的真实排查顺序密钥问题解决后我以为万事大吉结果又出现新症状有时请求卡住十几秒后超时有时报 DNS 解析失败有时报 TLS 握手超时。这些都是网络层问题排查思路和密钥验证完全不同。4.1 先把网络错误分门别类我习惯把网络错误分成四类DNS 解析失败报错里通常有Could not resolve hostTCP 连接超时报错里有connect timed outTLS 握手失败报错里有tls handshake timeout或证书相关错误HTTP 请求超时服务端迟迟不返回响应最终客户端主动断开它们的排查方向不一样。DNS 问题看的是本机解析配置TCP 超时看的是路由和防火墙TLS 问题看的是证书链路和系统时间HTTP 超时看的是服务端负载和请求参数。4.2 用 curl 的 verbose 模式看握手全过程如果你遇到网络层问题不要直接去改 OpenClaw 的配置先用 curl 看链路。命令是curl -v https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \ -H Authorization: Bearer sk-yyyyyyyy \ -d {model: qwen-plus, messages: [{role: user, content: hi}]} \ -m 10 --connect-timeout 5-v会输出以下关键信息Trying 1.2.3.4:443...说明已经开始 TCP 连接Connected to ...说明 TCP 已建立SSL connection using TLSv1.3说明 TLS 握手成功HTTP/2 200说明 HTTP 请求成功如果卡在Trying很久不进下一步说明 TCP 出不去如果 TCP 已连接但 SSL 一直不成功说明 TLS 链路有问题可能是防火墙干扰也可能是系统时间不正确。我自己的经验是当服务端偶尔通偶尔超时的时候优先怀疑网络链路中的中间设备而不是服务端。某些办公网络或云服务器的安全组策略会对长时间空闲的连接做静默丢弃表现为第一次请求正常第二次就卡死。4.3 环境变量里的代理设置这是最容易被忽略的一个点。很多人的机器上设置了HTTP_PROXY或HTTPS_PROXY环境变量这些变量对 curl 和 OpenClaw 都生效。如果你本机代理地址失效或者代理本身无法访问公网所有请求都会失败。排查方法很简单env | grep -i proxy如果输出里有代理地址可以先临时取消代理测试unset HTTP_PROXY HTTPS_PROXY ALL_PROXY然后再跑一遍 curl。如果取消代理后立刻通了说明问题出在代理链路上。OpenClaw 的配置文件里往往也有独立的代理设置项它可能覆盖环境变量也可能被环境变量覆盖要看具体版本最可靠的办法还是看日志。4.4 超时参数不是越大越好OpenClaw 里一般有请求超时和连接超时两个参数。我最初为了保证大模型响应完整把超时时间调到了 300 秒结果反而更难排查问题请求挂起半小时日志里什么都看不到。后来我把连接超时调到 5 秒把请求超时保留 60 秒。这样区分了“连不上”和“响应慢”两种场景连接超时失败说明网络链路有问题请求超时则多半是模型推理太慢或参数不合理。4.5 IPv4/IPv6 双栈问题还有一类情况某些新机器默认优先 IPv6 解析但本地 IPv6 网络其实不通。curl 会先尝试 IPv6等 IPv6 超时后才回退到 IPv4表现为“每次请求都要卡几秒”。解决办法是在 OpenClaw 所在机器的 hosts 文件里强制指定 API 域名的 IPv4 地址或者在系统层面禁用优先 IPv6。你可以用下面的命令测试当前网络对目标域名的解析结果dig short api.deepseek.com A dig short api.deepseek.com AAAA如果 AAAA 记录存在但本机 ping 不通 IPv6 地址大概率就是双栈切换导致的延迟。5. 可复现的完整调试流程与 OpenClaw 最终配置模板把以上所有排查经验归纳起来我形成了一套固定的调试顺序。现在每次接新的模型服务商我都按这个顺序走一遍十分钟内基本能确定问题在哪一层。调试顺序如下用 curl 直接测试先绕开 OpenClaw确定密钥和地址是否可用若 curl 成功开启 OpenClaw 调试日志看它发出的请求和 curl 是否一致若 OpenClaw 发出的请求路径或 Header 不对检查 Base URL 是否填多了或填少了路径若请求一致但仍失败检查环境变量和代理设置是否有干扰若网络卡顿用 curl -v 观察卡在哪一步再对症处理最终跑通后把成功配置保存成模板备查我最终的 OpenClaw 配置片段长这样models: deepseek: base_url: https://api.deepseek.com api_key: ${DEEPSEEK_API_KEY} model: deepseek-chat timeout: 60 connect_timeout: 5 bailian: base_url: https://dashscope.aliyuncs.com/compatible-mode/v1 api_key: ${DASHSCOPE_API_KEY} model: qwen-plus timeout: 60 connect_timeout: 5 proxy: enabled: false这段配置里百炼的 Base URL 用到了/compatible-mode/v1这是我一直强调的关键点。如果你接的是百炼上其他区域的模型实例可能需要换成对应区域的 comatible-mode 地址通常以dashscope.aliyuncs.com开头的主域名最通用。密钥我用${DEEPSEEK_API_KEY}这样的占位符引用.env里的变量避免把真实密钥写进版本控制。如果你没有使用环境变量加载工具也可以直接把密钥写在api_key字段但要注意 YAML 的引号和末尾空格。最后做端到端验证时我通常会发一个最简单的请求比如curl -X POST https://api.deepseek.com/chat/completions \ -H Authorization: Bearer $DEEPSEEK_API_KEY \ -H Content-Type: application/json \ -d {model: deepseek-chat, messages: [{role: user, content: ping}], max_tokens: 10}看到返回内容里有正常的文本字段再切回 OpenClaw 做图形界面测试。这样能保证如果 OpenClaw 侧依然失败问题一定出在工具本身的封装逻辑上而不是后端服务。最后说点排查的体会几次踩坑下来最大的感受是模型服务的 API 对接失败时第一反应不要是“服务商有问题”而是先确认自己发出的请求到底长什么样。密钥验证的重点不在协议有多复杂而在字符串传递过程中有没有被污染网络调试的重点也不在于配置多少参数而在于能否精确地定位请求卡在哪一层。OpenClaw 这类网关工具把多模型统一到了一个入口但它不会帮你修复错误填写的地址也不会替你检查环境变量里的残留值。把这些底层问题按顺序排查清楚后续接再多的模型服务商都不会再手忙脚乱。