1. 为什么 OpenClaw Gateway 的 WebSocket UI 总连不上
OpenClaw 的 Gateway 是一个把模型能力、会话路由和工具调用统一收口的本地服务,而 WebChat / Control UI 这类前端并不走浏览器静态页面,而是直接通过 WebSocket 连到 Gateway,用chat.history、chat.send、chat.inject这几个方法完成对话。也就是说,UI 能不能用,几乎完全取决于 Gateway 的 WebSocket 端点、认证和会话路由三件事有没有配对。
我见过最多的翻车场景是:Gateway 进程明明起来了,UI 却一直转圈或者提示只读。原因通常不是模型本身,而是gateway.port、gateway.bind、gateway.auth.mode和gateway.auth.token之间对不上,或者远程模式下gateway.remote.url写成了 HTTP 地址而不是 WebSocket 地址。另一个高频坑是认证:即使你在本机回环地址上跑,Gateway 默认也要求认证,token 或 password 缺一个就直接拒绝握手。
这篇就按“从配置文件骨架到跑通链路”的顺序走一遍。我会用 TaoToken 的统一 Key 作为模型通道,把 Gateway 的模型出口和 UI 的 WebSocket 入口分开讲清楚,再给出 CC Switch / Cline 侧的对接步骤,最后用几个可复制的验证动作确认链路真的通了。适合已经在折腾 OpenClaw、但卡在 Gateway 配置或 WebSocket 连接上的同学。
2. TaoToken 前置:统一 Key 与 API 通道准备
在动 Gateway 配置之前,先把模型出口准备好。OpenClaw 的 Gateway 本身不生产模型能力,它需要一个上游 API 通道。TaoToken 在这里的角色就是统一 Key 和统一 API 入口:你拿到一个 Key,配好 base URL,Gateway 里的模型调用就走这条通道,不用在多个平台之间来回切。
第一步是拿 Key。打开控制台,进入 API Keys 页面创建一个新 Key,复制出来先存好。这个 Key 后面会写进 Gateway 的模型配置里,所以别丢。
- 控制台入口:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite
- API Keys 页面:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite
第二步是确认 API 通道地址。TaoToken 的 API 端点是https://taotoken.net/api,注意这个地址不加 UTM 参数,直接作为 base URL 用。很多同学在这里踩坑:把带查询参数的官网地址当成 API 地址填进去,结果 Gateway 请求 404。官网是给人看的,API 是给程序调的,两者要分开。
注意:Key 只创建一次就够,但建议按用途分 Key。比如 Gateway 用一个、Cline 用一个,后面排查问题时能快速定位是哪条链路出的错。
如果你还想先验证模型通道本身是否可用,可以走模型对话页面发一条测试消息,确认 Key 和通道没问题,再去配 Gateway。这样能把“模型通道问题”和“Gateway 配置问题”分开,排错效率高很多。
- 模型对话:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite
3. Gateway 配置骨架:settings.json 与 config.toml 可复制片段
OpenClaw 的配置分两块:Gateway 端点与认证,以及模型通道。前者决定 UI 能不能连上 WebSocket,后者决定连上之后模型能不能回话。下面给出可复制的骨架,你按自己的路径和端口改。
先看 Gateway 端点与认证部分。WebChat 没有独立的webchat.**配置块,它复用 Gateway 的端点和认证设置,所以这几个字段是核心:
{ "gateway": { "port": 18789, "bind": "127.0.0.1", "auth": { "mode": "token", "token": "your-gateway-token-here" }, "remote": { "url": "ws://127.0.0.1:18789", "token": "your-gateway-token-here" } }, "session": { "store": "./sessions", "primaryKey": "default" } }几个字段的含义要拎清楚。gateway.port和gateway.bind决定 WebSocket 监听在哪,bind写127.0.0.1只允许本机连,写0.0.0.0才允许局域网。gateway.auth.mode支持token和password,默认必须配置,哪怕在回环地址上。gateway.remote.url是远程模式用的目标地址,注意协议头是ws://或wss://,不是http://。
如果你用 TOML 风格配置,等价写法是这样:
[gateway] port = 18789 bind = "127.0.0.1" [gateway.auth] mode = "token" token = "your-gateway-token-here" [gateway.remote] url = "ws://127.0.0.1:18789" token = "your-gateway-token-here" [session] store = "./sessions" primaryKey = "default"然后是模型通道部分,把 TaoToken 的 Key 和 API 地址接进来:
{ "models": { "provider": "openai-compatible", "baseUrl": "https://taotoken.net/api", "apiKey": "your-taotoken-key-here", "model": "claude-sonnet-4-20250514" } }这里baseUrl必须是https://taotoken.net/api,不要带任何查询参数。apiKey填你在控制台创建的那个 Key。model按你实际要用的模型名填,不同模型名对应不同能力,按需选。
提示:
gateway.auth.token和models.apiKey是两个完全不同的东西。前者是 UI 连 Gateway 的握手凭证,后者是 Gateway 调模型的凭证。混填会导致“UI 连上了但模型不回复”或者“模型能调但 UI 连不上”,排查时先确认这两个值各自对不对。
4. 启动 Gateway 并验证 WebSocket 链路
配置写好后,启动 Gateway。启动命令按你的安装方式走,常见的是在项目根目录执行:
openclaw gateway start --config ./settings.json启动后先看日志里有没有监听端口的输出,类似gateway listening on ws://127.0.0.1:18789。如果日志里出现认证相关的报错,说明auth.mode和auth.token没配对。
接着验证 WebSocket 是否真的能握手。用一个最小的 Node 脚本测一下,比直接开 UI 更快定位问题:
const WebSocket = require('ws'); const ws = new WebSocket('ws://127.0.0.1:18789', { headers: { 'Authorization': 'Bearer your-gateway-token-here' } }); ws.on('open', () => { console.log('WebSocket connected'); ws.send(JSON.stringify({ method: 'chat.history', params: {} })); }); ws.on('message', (data) => { console.log('Received:', data.toString()); ws.close(); }); ws.on('error', (err) => { console.error('Connection failed:', err.message); });跑通的话会先打印WebSocket connected,然后收到chat.history的返回。如果卡在连接阶段,基本就是端口、bind 或 token 的问题;如果连上了但chat.history报错,多半是 session 配置或 Gateway 内部路由的问题。
WebSocket 通了之后,再打开 WebChat UI 或 Control UI 的聊天标签。UI 会走同样的握手流程,连上后历史记录从 Gateway 拉取,不监视本地文件。如果 Gateway 不可达,UI 会进入只读模式,这时候你发消息是发不出去的,只能看历史。
验证模型通道是否真的通了,可以在 UI 里发一条消息,观察 Gateway 日志里有没有向上游 API 发请求。如果 UI 显示消息已发送但一直没有回复,去检查models.baseUrl和models.apiKey。这一步用模型对话页面单独测一次 TaoToken 通道,能快速区分是通道问题还是 Gateway 问题。
5. CC Switch / Cline 侧对接与常见报错排查
如果你在 CC Switch 或 Cline 里也要用同一套通道,配置逻辑和 Gateway 类似,但入口不同。Cline 侧一般填 base URL 和 API Key,base URL 同样是https://taotoken.net/api,Key 用你创建的那个。CC Switch 如果支持多配置切换,建议给 Gateway 和 Cline 各建一个 profile,避免 Key 混用。
下面按报错现象来排查,这是实测下来最高效的方式。
现象一:UI 一直转圈,日志显示auth failed。检查gateway.auth.mode和gateway.auth.token是否一致,以及 UI 侧填的 token 是否和配置文件里完全相同。token 前后有空格也会导致失败。
现象二:WebSocket 连上了,但chat.history返回空或报错。检查session.store路径是否存在且可写,session.primaryKey是否和 UI 请求的会话对得上。历史记录始终从 Gateway 获取,本地文件不参与。
现象三:消息发出去了,模型不回复。这基本是模型通道问题。确认models.baseUrl是https://taotoken.net/api,models.apiKey是有效的 TaoToken Key。可以先用模型对话页面单独验证 Key 是否可用。
现象四:远程模式下连不上。远程模式通过隧道连 Gateway WebSocket,gateway.remote.url必须是ws://或wss://开头。如果你写成了http://,握手会直接失败。另外远程模式下不需要单独跑 WebChat 服务器,UI 直连 Gateway 即可。
现象五:Control UI 的 agents tools 面板显示不全。这个面板通过tools.catalog获取运行时目录,如果该接口不可用,会回退到内置静态列表。工具会标记为core或plugin:<名称>,可选插件工具标记为optional。面板编辑的是 profile 和 override 配置,但实际运行时访问仍遵循策略优先级,allow/deny 和每 agent、provider、channel 的覆盖都会影响最终结果。
注意:
chat.inject是把助手备注直接附加到对话记录并广播到 UI,不触发 agent 运行。如果你用这个接口做测试,看到 UI 里有消息但模型没动,这是正常行为,不是 bug。
6. 把链路固定下来:长期编码与 Agent 场景的接入建议
链路跑通一次不难,难的是长期稳定。如果你打算把 OpenClaw Gateway 用在日常编码或 Agent 场景里,建议把配置和 Key 管理固定成一套流程。
模型通道这边,TaoToken 的 Coding Plan 适合长期编码场景,Key 和通道统一管理,不用每次换项目就重新配一遍。接入文档里有完整的参数说明和示例,遇到不确定的字段先查文档再改配置,比反复试错快。
- Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite
- 接入文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite
如果你用的是 Claude Code 这类工具,Anthropic 兼容通道的配置方式在文档里有单独说明,base URL 和 Key 的填法和 Gateway 一致,只是入口不同。
- ClaudeCodeAnthropic:https://taotoken.net/claudecode-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claudecode-anthropic&utm_campaign=rewrite
最后给一个实操建议:把 Gateway 的 token 和 TaoToken 的 Key 分开管理,Gateway token 只在本地配置文件里出现,TaoToken Key 按用途分创建。这样一旦某条链路出问题,你能快速判断是握手层还是模型层的问题,不用把整条链路推倒重来。配置改完后先跑一遍第 4 节的 WebSocket 验证脚本,确认握手通了再开 UI,能省掉大量“到底是 UI 问题还是 Gateway 问题”的纠结。