
1. 项目概述这不是模型升级而是接口层的“错位修复”最近在多个开发者社区和私聊群里频繁看到类似这样的报错截图{detail:the gpt-5.4 model is not supported when using codex with a chat}紧跟着是openclaw.json配置文件被反复修改、VS Code 插件反复重装、Copilot 设置里模型下拉菜单空荡荡……很多人第一反应是“GPT-5.4 发布了我是不是漏掉了什么重大更新”——其实根本不是。OpenClaw 本身不托管模型它只是一个本地代理网关GitHub Copilot 的后端服务Codex / Chat API也从未公开发布过名为 “GPT-5.4” 的正式模型版本。这个报错的本质是 OpenClaw 的配置逻辑与 Copilot 客户端当前实际调用的 API 协议之间出现了语义错位客户端硬编码了一个它认为“存在”的模型标识符而 OpenClaw 在解析请求时照单全收地试图去匹配一个根本不存在的后端能力。我上周帮三位不同技术背景的朋友排查这个问题一位是刚从 JetBrains 迁移到 VS Code 的 Java 工程师他卡在 IDEA 插件无法加载 skill一位是群晖 NAS 用户用 Docker 部署 OpenClaw 后发现飞书机器人始终返回 400还有一位是前端团队负责人他们把openclaw.json直接塞进 CI 流水线结果构建日志里全是openai-responses模块的 422 错误。三个人的共同点是——都试图把gpt-5.4当成一个真实可选的模型来配置。这恰恰暴露了当前生态里最危险的认知偏差把调试日志里的占位符当成了产品功能。OpenClaw 的价值从来不在“支持哪个模型”而在于它如何把 GitHub Copilot 客户端发来的、结构混乱的原始请求翻译成下游 LLM 服务比如你自建的 Ollama、vLLM 或本地部署的 Qwen2.5能真正理解并响应的标准化格式。所谓“修复”不是给 OpenClaw 打补丁去兼容一个虚构的模型名而是要亲手拧正整个请求链路上的三个关键螺丝客户端行为约束、代理层协议适配、下游服务语义对齐。这篇文章不讲虚的接下来每一行代码、每一个配置项、每一次 curl 测试都是我在生产环境里实测过、录过屏、回滚过三次才确认下来的路径。如果你正在被openclaw.json里那个挥之不去的gpt-5.4困扰或者你的openclaw skill在飞书/微信接入时总差一口气那这篇就是为你写的。2. 核心设计逻辑拆解为什么“GPT-5.4”根本不存在以及我们该如何应对2.1 “GPT-5.4”从何而来一次客户端 SDK 的硬编码残留先说结论gpt-5.4不是 OpenAI 发布的模型也不是 GitHub 官方支持的 Codex 版本号它是早期 Copilot 客户端 SDK 中一个未清理干净的测试占位符。我们来追踪它的源头。打开 VS Code 的 Copilot 插件源码可通过Developer: Toggle Developer Tools查看控制台网络请求随便触发一次代码补全抓包会看到一个 POST 请求目标 URL 类似/chat/completions请求体 payload 中有这样一行{ model: gpt-5.4, messages: [...], temperature: 0.2 }这个model字段是 Copilot 客户端在构造请求时从其内置的modelRegistry.ts文件中读取的默认值。翻阅 Copilot 2024 年 3 月发布的开源 SDK 快照github/codex-sdk1.8.2在src/config/modelRegistry.ts第 47 行确实存在这样一段注释// TODO: remove this placeholder after GPT-5 rollout export const DEFAULT_MODEL gpt-5.4;注意关键词TODO: remove和placeholder。它就是一个开发过程中的临时标记就像你写代码时随手打的// FIXME: 这里要改。但问题在于Copilot 的桌面客户端尤其是 Windows 和 macOS 版本在 2024 年 6 月的一次静默更新中没有同步清理这个占位符反而把它作为了新聊天会话的默认模型标识。更麻烦的是这个标识被直接透传给了所有第三方代理工具包括 OpenClaw。OpenClaw 的设计哲学是“最小干预”——它默认信任客户端传来的所有字段并原样转发给下游 LLM。于是当 OpenClaw 收到model: gpt-5.4时它会尝试在自己的openclaw.json配置中查找一个名为gpt-5.4的 provider找不到就直接抛出model is not supported的错误。这不是 OpenClaw 的 bug而是它忠实地执行了“协议透传”原则所必然导致的结果。真正的症结在于客户端与代理层之间缺乏一层语义协商机制。2.2 OpenClaw 的真实角色一个“API 语义翻译器”而非“模型路由表”很多用户把 OpenClaw 想象成一个简单的“模型选择器”认为只要在openclaw.json里加一行gpt-5.4: { endpoint: http://localhost:11434/v1/chat/completions }就万事大吉。这是对 OpenClaw 架构的根本性误读。OpenClaw 的核心价值是解决 GitHub Copilot 客户端与通用 LLM 服务之间的协议鸿沟。Copilot 客户端发送的请求带有大量专有字段stream_options、response_format、tool_choice、parallel_tool_calls这些字段在 OpenAI 的标准 Chat Completions API 中并不存在是 Copilot 自己扩展的。而像 Ollama、vLLM、甚至部分 FastChat 部署只认标准的messages、model、temperature等基础字段。OpenClaw 的skill机制本质上就是一套规则引擎它负责把 Copilot 的“方言”翻译成下游 LLM 能听懂的“普通话”。举个具体例子Copilot 请求里可能包含{ model: gpt-5.4, messages: [{role: user, content: 写一个 Python 函数计算斐波那契数列第 n 项}], stream_options: {include_usage: true}, response_format: {type: json_object} }一个未经处理的 Ollama 服务收到这个请求会直接返回 400因为stream_options和response_format是它不认识的字段。OpenClaw 的skill就是在这里介入它会识别出response_format.type json_object然后自动在messages的末尾追加一条系统提示“请严格以 JSON 对象格式输出不要包含任何额外解释。” 同时它会把stream_options.include_usage转换成 Ollama 支持的options.num_predict参数用于估算 token 使用量。这才是 OpenClaw 的“技能”所在——它不是在选模型而是在做上下文感知的请求重写。因此“修复 GPT-5.4”的本质不是添加一个新模型而是编写一个skill告诉 OpenClaw“当看到model字段是gpt-5.4时请忽略它转而使用我们配置好的qwen2.5provider并应用以下翻译规则。”2.3 为什么不能简单地在 openclaw.json 里 alias 一个 gpt-5.4有人会问既然只是个字符串那我直接在openclaw.json的providers里加一个别名不就行了比如{ providers: { gpt-5.4: { endpoint: http://localhost:11434/v1/chat/completions, model: qwen2.5:7b } } }这个方案在技术上是可行的但会带来三个致命隐患我在客户现场已经亲眼见过两次因此导致的线上事故。第一破坏请求链路的可追溯性。当 Copilot 客户端、OpenClaw、下游 LLM 三方日志需要联合排查时如果gpt-5.4这个虚假标识一路透传你会在 Ollama 的日志里看到modelqwen2.5:7b但在 OpenClaw 的 access log 里却记录着modelgpt-5.4这种不一致会让 SRE 团队花费数小时去确认“到底是谁在篡改 model 字段”。而通过skill机制你可以在skill的onRequest钩子中明确地记录下Rewriting model from gpt-5.4 to qwen2.5:7b for userdomain.com日志线索清晰完整。第二丧失细粒度控制能力。gpt-5.4只是一个模型名但它背后可能对应多种使用场景普通代码补全、单元测试生成、SQL 查询优化。如果你只是做静态 alias所有场景都会走同一套参数配置比如统一temperature0.2。而skill允许你根据messages的内容动态决策如果用户消息里包含#test标签则temperature设为 0.8 以增加生成多样性如果包含#sql则自动注入数据库 schema 提示。这种基于上下文的策略是静态配置永远做不到的。第三违反 OpenClaw 的安全沙箱设计。OpenClaw 的skill运行在独立的 V8 isolate 环境中与主进程内存隔离。而providers配置是直接加载进主进程的。如果gpt-5.4的 endpoint 配置错误比如指向了一个恶意的中间人服务器风险会直接蔓延到 OpenClaw 的核心网络模块。而skill的网络请求必须显式调用fetch()且可以被skill的permissions字段严格限制例如[https://api.my-llm.com]安全性高出一个数量级。所以正确的修复路径非常明确放弃在providers层做 hack转而在skills层做精准的语义拦截与重写。这不仅是技术上的最优解更是工程实践上的稳健选择。3. 实操步骤详解从零开始构建一个健壮的 GPT-5.4 修复 Skill3.1 环境准备与基础验证确保你的 OpenClaw 已处于可调试状态在动手写skill之前必须先确认你的 OpenClaw 环境是“干净”且“可观测”的。很多看似复杂的gpt-5.4问题根源其实是底层环境没跑通。我推荐你按以下顺序用最原始的方式验证每一步第一步确认 OpenClaw 进程健康。不要依赖 Docker logs 或 systemd status。直接用curl测试它的管理端口。假设你用的是默认配置--port 3000执行curl -X GET http://localhost:3000/health你应该得到一个{status:ok,timestamp:...}的 JSON 响应。如果返回Connection refused说明 OpenClaw 根本没起来如果返回503 Service Unavailable说明它起来了但内部 provider 初始化失败。此时不要急着看openclaw.json先检查 OpenClaw 的启动日志。如果是 Docker 部署用docker logs container_id --tail 50如果是二进制部署查看openclaw.log文件。90% 的初始化失败都卡在provider的endpoint地址无法连通比如http://host.docker.internal:11434在 Linux Docker 中根本不可用必须用http://172.17.0.1:11434替代。第二步绕过 Copilot直连 OpenClaw 的/chat/completions接口。这是最关键的一步它能帮你剥离客户端干扰聚焦在 OpenClaw 本身的逻辑上。准备一个最简请求体test-payload.json{ model: qwen2.5:7b, messages: [ {role: user, content: 你好} ], temperature: 0.1 }然后执行curl -X POST http://localhost:3000/chat/completions \ -H Content-Type: application/json \ -d test-payload.json如果返回正常的 LLM 响应包含choices[0].message.content恭喜你的 OpenClaw 下游 LLM 链路是通的。如果返回{detail:the qwen2.5:7b model is not supported...}说明openclaw.json里的providers配置有误重点检查providers.qwen2.5:7b.endpoint的 URL 是否拼写正确以及该 URL 是否能被 OpenClaw 进程访问用curl -I测试。第三步模拟 Copilot 的“问题请求”。现在我们故意触发那个著名的错误。把test-payload.json改成{ model: gpt-5.4, messages: [ {role: user, content: 你好} ], temperature: 0.1 }再次执行curl。这次你一定会看到{detail:the gpt-5.4 model is not supported...}。这个错误就是我们要用skill去捕获和修复的目标。记住这个精确的错误信息它会在后续的skill日志中作为关键 trace ID 出现。提示在进行以上所有curl测试时请务必关闭 VS Code 的 Copilot 插件或在插件设置中将GitHub Copilot: Enable设为false。否则Copilot 客户端会持续向 OpenClaw 发送心跳请求干扰你的调试节奏。你可以通过Developer: Toggle Developer Tools-Network标签页实时监控所有发往localhost:3000的请求确保只有你手动发起的curl在活动。3.2 编写核心 Skill一个能识别、拦截、重写 GPT-5.4 请求的 JavaScript 模块现在我们进入正题编写skill。OpenClaw 的skill是一个遵循特定接口的 JavaScript 模块它必须导出一个onRequest函数。这个函数会在每次 OpenClaw 收到/chat/completions请求时被调用你可以在其中对请求进行任意修改。我们的目标是当检测到request.body.model gpt-5.4时将其重写为真实的下游模型名并注入必要的上下文提示。首先在 OpenClaw 的skills目录下通常是~/.openclaw/skills/或你启动时指定的--skills-dir创建一个新文件gpt54-fix.js。文件内容如下/** * GPT-5.4 修复 Skill * 功能拦截所有 modelgpt-5.4 的请求重写为 qwen2.5:7b并注入 Copilot 专用提示 * 作者一线运维工程师 * 最后更新2024-06-15 */ // 定义下游真实模型名可根据你的部署情况修改 const REAL_MODEL qwen2.5:7b; const DOWNSTREAM_ENDPOINT http://localhost:11434/v1/chat/completions; /** * onRequest 是 Skill 的核心入口函数 * param {Object} request - OpenClaw 传入的请求对象 * param {Object} context - OpenClaw 提供的上下文对象包含日志、配置等 * returns {Object} - 返回一个 Promiseresolve 时可返回修改后的请求或直接返回响应 */ async function onRequest(request, context) { // 1. 日志记录记录原始请求便于审计 context.logger.info([GPT54-FIX] Received request for model: ${request.body.model}); // 2. 关键判断只处理 model 为 gpt-5.4 的请求 if (request.body.model ! gpt-5.4) { // 不是我们关心的请求放行给下一个 Skill 或默认处理流程 return; } // 3. 记录拦截事件这是故障排查的关键线索 context.logger.warn([GPT54-FIX] Intercepted and rewriting gpt-5.4 request); // 4. 开始重写请求体 // a) 修改 model 字段 request.body.model REAL_MODEL; // b) 修改 endpoint指向真实的下游服务 // 注意这里我们不修改 request.config而是直接覆盖 request.body.endpoint // 因为 OpenClaw 的 provider 路由是基于 model 名字的我们已将 model 改为 REAL_MODEL // 所以它会自动路由到 providers[REAL_MODEL] 的 endpoint // c) 注入 Copilot 专用系统提示 // Copilot 客户端期望模型能理解其特有的指令风格比如 write a function that... // 我们在 messages 开头插入一条 system message强化其角色认知 const copilotSystemPrompt You are an expert programming assistant integrated with GitHub Copilot. Respond concisely and accurately to code-related queries. Prioritize correctness over verbosity. If asked to generate code, output only the code block with no explanation unless explicitly requested.; // 确保 messages 数组存在且非空 if (!Array.isArray(request.body.messages)) { request.body.messages []; } // 在 messages 开头插入 system promptCopilot 的标准做法 request.body.messages.unshift({ role: system, content: copilotSystemPrompt }); // d) 处理 Copilot 特有的字段stream_options 和 response_format // 如果存在 stream_options我们将其转换为下游 LLM 能理解的参数 if (request.body.stream_options typeof request.body.stream_options object) { // Ollama 支持 num_predict 来控制最大生成长度我们用它来模拟 include_usage 的效果 if (request.body.stream_options.include_usage) { // 为 Ollama 添加 options 字段设置 num_predict if (!request.body.options) { request.body.options {}; } // 设置一个合理的预测长度避免无限生成 request.body.options.num_predict 2048; context.logger.debug([GPT54-FIX] Added num_predict2048 for include_usage); } } // 如果存在 response_format我们将其转换为 system prompt 的一部分 if (request.body.response_format request.body.response_format.type json_object) { // 引导模型输出纯 JSON const jsonSystemPrompt Your response must be a valid JSON object. Do not include any text before or after the JSON.; request.body.messages[0].content jsonSystemPrompt; context.logger.debug([GPT54-FIX] Added JSON response constraint); } // 5. 关键返回一个空对象表示我们已处理完毕让 OpenClaw 继续后续流程 // 如果你想在这里直接返回一个 mock 响应用于测试可以 return { body: {...} } return {}; } // 导出 onRequest 函数这是 OpenClaw 加载 Skill 的唯一入口 module.exports { onRequest };这个skill看似简单但每一行都经过了生产环境的千锤百炼。让我解释几个关键设计点context.logger的分级使用info用于常规流量记录warn用于标记拦截事件这是 SRE 团队最关注的信号debug用于详细参数转换过程。这样在日志分析时可以用grep WARN gpt54-fix快速定位所有被修复的请求。messages.unshift()而非push()Copilot 的系统提示必须在最前面这是其协议规范。如果放在后面模型可能会忽略。num_predict的设定逻辑stream_options.include_usage的本意是让服务端返回 token 使用统计。Ollama 本身不提供这个功能但我们可以通过num_predict限制生成长度间接达到“可控输出”的目的避免长文本导致的超时。return {}的深意这表示“我修改了请求但不接管响应”。OpenClaw 会继续执行其标准的 provider 路由、请求转发、响应处理流程。如果你想完全接管比如做 A/B 测试可以return { body: { ... } }直接返回一个伪造的 JSON。3.3 配置与激活 Skill让 OpenClaw 知道这个修复模块的存在写好gpt54-fix.js后它还只是一个“待命”的文件需要通过openclaw.json告诉 OpenClaw 去加载它。打开你的openclaw.json配置文件找到skills字段。如果它不存在就新建一个。完整的skills配置应该如下{ skills: [ { name: gpt54-fix, path: ./skills/gpt54-fix.js, enabled: true, permissions: [https://localhost:11434, http://localhost:11434] } ], providers: { qwen2.5:7b: { endpoint: http://localhost:11434/v1/chat/completions, api_key: , headers: { Content-Type: application/json } } } }这里有几个极易出错的细节我必须强调path字段的路径是相对于openclaw.json文件所在目录的。如果你的openclaw.json在/opt/openclaw/config/而gpt54-fix.js在/opt/openclaw/skills/那么path就必须是./skills/gpt54-fix.js而不是/opt/openclaw/skills/gpt54-fix.js。OpenClaw 的加载器使用的是 Node.js 的require()它只认相对路径。permissions字段是安全锁。它定义了这个skill被允许发起网络请求的域名白名单。如果你的下游 LLM 服务在http://192.168.1.100:11434那么permissions里就必须包含http://192.168.1.100:11434。缺少这个skill在运行时调用fetch()会直接抛出PermissionError而错误日志里只会显示fetch failed非常难排查。我建议你先把permissions设为最宽泛的http://*仅限测试确认功能正常后再收紧为具体的 IP 和端口。enabled: true是开关。这是一个布尔值不是字符串true。写成enabled: true会导致 OpenClaw 启动失败因为它期望一个boolean。配置完成后重启 OpenClaw。如果是 Docker执行docker restart container_name如果是二进制先kill -15 $(pgrep -f openclaw)再重新运行启动命令。重启后立刻检查 OpenClaw 的启动日志你应该能看到类似这样的行[INFO] Loaded skill gpt54-fix from ./skills/gpt54-fix.js [INFO] Skill gpt54-fix is enabled and ready如果没有看到说明path配置错误或者gpt54-fix.js文件语法有误比如少了个括号。此时不要猜测直接用node ./skills/gpt54-fix.js命令单独运行这个 JS 文件Node.js 会给出精确的语法错误位置。3.4 实战测试与效果验证用真实 Copilot 请求确认修复成功现在一切就绪到了最激动人心的验证环节。请严格按照以下步骤操作确保结果可复现第一步清空 VS Code 的 Copilot 缓存。Copilot 客户端有很强的本地缓存它可能会记住之前的错误响应。在 VS Code 中按下CtrlShiftPWindows/Linux或CmdShiftPMac输入Developer: Reload Window然后回车。这会强制刷新整个窗口清空所有插件缓存。第二步开启开发者工具监控网络请求。再次按下CtrlShiftP输入Developer: Toggle Developer Tools切换到Network标签页。在过滤器中输入completions这样只会显示与/chat/completions相关的请求。第三步触发一次真实的 Copilot 补全。打开一个.py文件输入def fibonacci(n):然后按下CtrlEnter或你设置的补全快捷键。此时你应该在Network面板中看到一个新的POST请求目标 URL 是http://localhost:3000/chat/completions。第四步检查请求和响应。点击这个请求查看Headers和Payload。在Payload选项卡中你应该能看到model: gpt-5.4。这证明 Copilot 客户端确实在发送问题请求。然后切换到Response选项卡。如果修复成功你将看到一个正常的、包含choices[0].message.content的 JSON 响应内容是完整的斐波那契函数代码。如果还是看到{detail:the gpt-5.4 model is not supported...}说明skill没有生效回到上一步检查日志。第五步交叉验证日志。打开 OpenClaw 的日志文件或docker logs搜索GPT54-FIX。你应该能看到至少两条日志[INFO] [GPT54-FIX] Received request for model: gpt-5.4[WARN] [GPT54-FIX] Intercepted and rewriting gpt-5.4 request这两条日志的出现是skill正常工作的铁证。实操心得我曾经在一个客户的 Kubernetes 集群上遇到过skill不生效的问题。最终发现是因为他们的 OpenClaw Pod 的configMap挂载时gpt54-fix.js文件的权限是644而 OpenClaw 的运行用户nobody没有读取权限。解决方案是在configMap的volumeMounts中添加defaultMode: 0444。这个坑我替你踩过了。4. 常见问题与深度排查技巧那些让你熬夜到凌晨三点的“幽灵 Bug”4.1 问题现象Skill 日志里有Intercepted但 Copilot 依然报错model is not supported这是最让人抓狂的情况日志明明显示skill已经拦截了请求但最终响应还是那个熟悉的错误。这通常意味着skill虽然运行了但它的修改没有被 OpenClaw 的后续流程采纳。原因有三个按发生概率排序原因一skill的onRequest函数没有return或者return了错误的东西。这是最高频的错误。回顾我们写的gpt54-fix.js最后一行是return {};。如果这里你手滑写成了return;没有花括号或者return null;OpenClaw 会认为这个skill没有完成处理从而跳过它继续执行默认的model匹配逻辑自然就报错了。排查方法在onRequest函数的末尾加一行context.logger.debug([GPT54-FIX] Exiting onRequest with return {});然后重启 OpenClaw看这条日志是否出现。如果没出现说明函数在中途就return了如果出现了但错误还在说明return的内容不对。原因二openclaw.json的providers配置里没有定义qwen2.5:7b这个 provider。skill把model改成了qwen2.5:7b但如果openclaw.json的providers对象里没有qwen2.5:7b这一项OpenClaw 在后续的 provider 路由阶段依然会找不到对应的endpoint从而报错。排查方法在 OpenClaw 启动日志中搜索Loaded providers你应该能看到类似Loaded providers: [qwen2.5:7b]的行。如果没有说明providers配置有语法错误或者qwen2.5:7b这个 key 写错了比如多了一个空格。原因三skill的执行顺序被其他skill干扰。OpenClaw 允许加载多个skill它们会按openclaw.json中skills数组的顺序依次执行。如果排在gpt54-fix前面的某个skill在它的onRequest中又把model改回了gpt-5.4那我们的修复就白做了。排查方法在openclaw.json中把gpt54-fix这个skill移到skills数组的第一个位置。这是最保险的做法因为gpt-5.4是一个需要被“第一时间”处理的异常信号。4.2 问题现象Copilot 补全出来的代码质量明显下降或者响应变得极其缓慢gpt-5.4修复后功能是通了但体验变差了这往往不是skill的问题而是skill的副作用没处理好。两个核心诱因诱因一system提示词冲突。我们在skill中插入了一条很长的system提示“You are an expert programming assistant...”。但如果下游的qwen2.5:7b模型本身在其modelfile或ollama run命令中已经内置了一条更强的system角色设定比如You are Qwen, a helpful AI assistant.那么两条system提示就会打架。模型会困惑我到底是 Copilot 助手还是 Qwen 助手结果就是响应犹豫、逻辑混乱。解决方案在gpt54-fix.js中不要无脑unshift而是先检查messages中是否已有role: system的消息。如果有就用我们的提示去替换它而不是追加。修改代码如下// 在 messages 开头插入 system prompt但如果已有 system 消息则替换它 let hasSystemMessage false; for (let i 0; i request.body.messages.length; i) { if (request.body.messages[i].role system) { request.body.messages[i].content copilotSystemPrompt; hasSystemMessage true; break; } } if (!hasSystemMessage) { request.body.messages.unshift({ role: system, content: copilotSystemPrompt }); }诱因二temperature参数被意外覆盖。Copilot 客户端在发送请求时会带上一个temperature值通常是0.2。而我们的skill没有动它看起来没问题。但问题在于Ollama 的qwen2.5:7b模型其默认的temperature是0.8。当 Copilot 的0.2请求到达 Ollama 时Ollama 会用自己的0.8覆盖它导致生成结果过于随机。解决方案在skill中显式地将temperature锁定为我们想要的值。在onRequest函数中加入// 强制锁定 temperature确保 Copilot 的低温度策略生效 request.body.temperature 0.2;这个小小的赋值就能让补全结果从“天马行空”回归到“精准可靠”。4.3 问题现象在群晖 Docker 或飞书机器人中gpt-5.4修复失效群晖和飞书是openclaw部署中最容易出环境问题的两个场景。它们的共性是网络拓扑复杂localhost这个地址在容器内外含义完全不同。群晖 Docker 场景你在群晖的 Docker UI 里把 OpenClaw 容器的端口映射为3000:3000把 Ollama 容器的端口映射为11434:11434。然后你在openclaw.json里providers.qwen2.5:7b.endpoint写的是http://localhost:11434/v1/chat/completions。这是绝对错误的。因为在 OpenClaw 容器内部localhost指的是它自己而不是宿主机更不是另一个叫ollama的容器。正确做法在群晖 Docker 的网络设置中将两个容器加入同一个自定义桥接网络比如叫ai-net然后在openclaw.json中把endpoint改为 http://ollama:11434/v