我花了一个下午把 OpenClaw 接进了 KIMI 的 Web 会话窗口里。现在我在浏览器里跟 KIMI 聊天聊着聊着就能让它去操作我本地的 OpenClaw执行自动化任务、读日志、跑脚本甚至管理技能包。整个过程做完之后最大的感受是这两样东西本来就应该这么配合。OpenClaw 的本体是个跑在你自己机器上的自动化助理而 KIMI 的网页端又是一个随手就能打开的对话入口把它俩关联上你就等于给自己的 AI 工作流装了一个“浏览器遥控器”。这篇文章就把我的操作过程、踩过的坑、以及背后的设计思路完整写下来。不管你是刚接触 OpenClaw 的新手还是已经在用但一直觉得命令行交互不够顺手的老用户都可以参考这份记录来做同样的接线。1. 为什么非要在 KIMI 的 Web 会话台里关联 OpenClaw1.1 命令行交互的痛点OpenClaw 官方默认的使用方式是你先启动它的服务端然后通过本地终端或者客户端工具跟它对话。这种方式没问题但对于我这种日常大部分时间泡在浏览器里的人来说来回切终端窗口特别打断思路。举个例子我经常在调研一件事情的时候一边开着网页查资料一边想让 OpenClaw 去跑一个数据处理脚本。传统做法是我得离开浏览器打开终端敲命令再等结果输出然后再切回浏览器继续查资料。这个切换过程看着只有几秒钟但一天反复十几次之后你会觉得特别累。后来我就想能不能在 KIMI 的对话窗口里正常用自然语言跟它聊天同时让 OpenClaw 在后台执行任务。也就是说KIMI 负责“对话理解”OpenClaw 负责“任务执行”。中间只需要一个桥。1.2 Web 会话台做入口的三个优势先说结论把关联入口放在 KIMI 的 Web 会话台上对比直接用终端或者自建前端有三个明显优势。第一零部署成本。KIMI 的网页端不用本地安装任何客户端浏览器打开就能用。你不需要额外维护一个前端页面也不用处理本地服务的跨域问题只需要一个轻量级的桥接服务在本地跑着。第二移动设备也能用。我在手机浏览器上打开 KIMI 的网页端同样可以指挥家里的台式机跑任务。前提是桥接服务暴露到局域网或者内网穿透出去当然这是后话。第三对话上下文天然整合。KIMI 本身在多轮对话的理解能力上表现不错所以当你需要根据上下文调整任务参数的时候直接在同一个会话里改描述就好OpenClaw 那边也会收到更新后的指令这种交互方式比在终端里改参数更自然。1.3 我的方案选型过程在动手之前其实我考虑过三种方案。第一种是从 KIMI 的浏览器端发起请求通过 WebSocket 直连本地 OpenClaw 的端口。这个方案最直接但问题是浏览器端直接连本地 WebSocket 会碰到权限和安全限制而且如果你对 OpenClaw 的协议不熟悉调试起来会很痛苦。第二种方案是写一个浏览器插件把 KIMI 页面里识别到的指令转发到本地服务。这个方案更灵活但浏览器插件的开发、审核、更新链路太长不符合我“尽快用起来”的需求。第三种方案也就是最终采用的是在本地跑一个轻量级的桥接服务它同时充当 HTTP 接口和 WebSocket 客户端。KIMI 网页端通过注入一段用户脚本把对话中特定格式的消息发送给这个桥接服务桥接服务再把消息转发给 OpenClaw 并返回执行结果。这样就把复杂的协议对接集中在一个独立的小服务里出了问题也好排查。这个方案的好处是职责清晰KIMI 只管展示和输入桥接服务管协议翻译OpenClaw 管任务执行。每一层都能单独测试和替换。2. 核心原理OpenClaw 与 KIMI Web 端的对接逻辑拆解2.1 OpenClaw 本质上是“带工具扩展的对话代理”我接触到 OpenClaw 之后发现它本质上是一个对话代理框架底层接入了大语言模型但上层扩展了一套工具调用体系。它不只是能聊更重要的是它能执行任务。比如你可以给 OpenClaw 配置技能包Skills每个技能包对应一个具体的能力像是操作文件、调用 API、执行 Shell 命令等。当用户在对话中提出需求OpenClaw 会把需求拆解成若干个步骤然后按步骤调用对应的工具完成操作。所以从架构上看OpenClaw 对外暴露的能力可以通过两种方式访问一种是通过它自身的命令行交互界面另一种是通过它提供的 HTTP 或 WebSocket 接口协议。我这次做的桥接本质上就是绕开它自带的界面直接通过协议层发消息、收回复。这样 KIMI 网页端就可以变成一个远程遥控面板。2.2 KIMI Web 会话台的集成点在哪里KIMI 的 Web 会话台本身是一个网页应用在浏览器里运行。想要在它的页面里扩展功能主要有两个切入点一是浏览器扩展Extension通过 Content Script 注入脚本可以读取和修改页面中的 DOM 结构也能监听输入框事件和消息区域的 DOM 变化。二是用户脚本User Script通过 Tampermonkey 这类工具在页面加载后注入自定义 JavaScript。这种方式不需要发布到应用商店开发调试更快适合个人使用。我采用的是第二种因为 Tampermonkey 的管理模式够轻而且脚本更新只要改一下本地文件再重新加载就行不需要走任何审核流程。脚本需要做的事不算复杂监听消息框的消息发送事件匹配以特定前缀开头的消息比如“/claw ”或“claw ”然后把消息内容从页面中抓出来通过 HTTP 请求发给本地桥接服务。桥接服务处理完成后再把结果作为一条提示消息插入到对话窗口里。2.3 桥接服务的设计思路桥接服务是整个链条中最核心的部分。我把它想得很简单核心职责就是三件事接收、转发、回传。接收指的是监听来自浏览器脚本的 HTTP 请求这些请求承载了用户的指令文本。转发指的是把指令文本按 OpenClaw 能识别的格式发出去。回传则是指把 OpenClaw 生成的执行结果包装成浏览器能显示的消息返回到 KIMI 页面。我选择用 Python 写这个桥接服务因为我对 Python 的生态更熟处理 JSON 和网络请求都顺。服务通过 FastAPI 提供 HTTP 接口同时内部内置一个 WebSocket 客户端用于和 OpenClaw 的长连接通信。之所以用 WebSocket 而不用普通的 HTTP 轮询是因为 OpenClaw 的任务执行可能是长时间运行的比如跑一个数据爬取脚本可能要几分钟WebSocket 可以保持连接实时推送状态信息体验上比轮询好很多。2.4 用生活化类比理解整套流程如果不太好理解你可以把整套系统想成一个餐厅的就餐流程。KIMI 的网页端就像是餐桌前的服务员顾客你跟服务员说想吃什么服务员记录下来。桥接服务就像是厨房里的传菜员他拿到服务员写的点菜单转身递给大厨。OpenClaw 就是大厨负责实际做菜做完之后把菜品递回给传菜员传菜员再告诉服务员“这道菜好了可以上了”。KIMI 本身不负责做菜它只负责传话。OpenClaw 不负责接待你他闷头干活。中间那层桥接服务保证了订单格式是双方都认识的。这个类比基本就是整套系统的真实运作逻辑。3. 实操过程从零配置到跑通第一个任务3.1 环境准备清单动手之前先列一下需要准备的东西方便你对号入座一台装了 Python 3.10 及以上版本的电脑Windows、macOS、Linux 都行OpenClaw 已安装并初始化完成能通过本机命令行启动KIMI 的账号以及浏览器推荐 Chrome 或 EdgeTampermonkey 扩展已安装一个支持 WebSocket 通信的 Python 环境FastAPI 和 websockets 库我的实际环境是 Windows 11 Python 3.11 最新版 OpenClaw Chrome 浏览器。不过这套配置不挑系统关键的是那几个依赖库装对版本。3.2 第一步启动并验证 OpenClaw 的接口启动 OpenClaw 之前先确认你的配置文件中打开了外部访问开关。这一步不少人在第一次做集成的时候都会卡住因为默认情况下 OpenClaw 只回应来自本机命令行工具的请求外部服务即使在同一台机器上也不一定能连上。你需要去 OpenClaw 的配置目录下找到主配置文件检查有没有类似enable_api、websocket_port这样的字段。没有的话手动加上。我用的端口是 18789因为我本机 8000 被别的东西占了顺手挑了一个不容易撞车的端口。改完配置后启动 OpenClaw 服务然后在终端里用一条命令验证接口是否正常监听。curl http://127.0.0.1:18789/health如果返回一个包含status: ok的 JSON 响应说明服务已经就绪。3.3 第二步编写桥接服务桥接服务的代码我写得不长大约一百多行但逻辑上覆盖了三个核心功能。为了让你快速跑起来我这里给出一份精简可用的版本。import json import asyncio from fastapi import FastAPI, Request from fastapi.responses import JSONResponse import websockets app FastAPI() OPENCLAW_WS ws://127.0.0.1:18789/ws async def send_to_openclaw(message: str, timeout: int 60): try: async with websockets.connect(OPENCLAW_WS) as ws: # 构造符合 OpenClaw 协议的消息格式 payload json.dumps({type: user_message, content: message}) await ws.send(payload) # 等待执行结果返回超时则断开 response await asyncio.wait_for(ws.recv(), timeouttimeout) return response except websockets.exceptions.ConnectionClosedError as e: return json.dumps({error: OpenClaw connection closed, detail: str(e)}) app.post(/relay) async def relay(request: Request): body await request.json() user_msg body.get(message, ) if not user_msg: return JSONResponse({error: empty message}, status_code400) result await send_to_openclaw(user_msg) return JSONResponse({result: result}) app.get(/health) async def health(): return {status: ok} if __name__ __main__: import uvicorn uvicorn.run(app, host127.0.0.1, port8800)这里有个关键参数timeout 60我刚开始调参时设的是 10 秒但 OpenClaw 在处理稍微复杂的任务时经常超过这个时间所以会频繁报超时。后来调整到 60 秒情况好多了。如果你有长时间运行的脚本任务建议改成 300 秒甚至更高。桥接服务跑起来之后同样可以用 curl 验证curl -X POST http://127.0.0.1:8800/relay -H Content-Type: application/json -d {\message\: \你好OpenClaw\}如果返回了 OpenClaw 那边的回复那就说明桥的搭建已经完成了八成。3.4 第三步编写 Tampermonkey 用户脚本接下来是浏览器端的部分。我写了一段 Tampermonkey 脚本逻辑很直接监听 KIMI 页面上输入框的发送事件一旦检测到消息以/claw开头就把去掉前缀的原文发送给桥接服务并把返回结果显示在页面上。// UserScript // name KIMI-OpenClaw Bridge // namespace https://your-local-bridge/ // version 0.1 // description 将KIMI对话中指定命令转发给本地OpenClaw桥接服务 // match https://*.kimi.com/* // grant GM_xmlhttpRequest // /UserScript (function() { const BRIDGE_URL http://127.0.0.1:8800/relay; function isCommandMessage(text) { return text.trim().startsWith(/claw ); } function sendToBridge(rawText) { const message rawText.trim().replace(/^\/claw\s/, ); GM_xmlhttpRequest({ method: POST, url: BRIDGE_URL, data: JSON.stringify({ message: message }), headers: { Content-Type: application/json }, onload: function(res) { try { const data JSON.parse(res.responseText); let resultText data.result || data.error || ; insertResultToPage(resultText); } catch (e) { insertResultToPage(解析返回结果失败请查看桥接服务日志); } }, onerror: function() { insertResultToPage(无法连接到本地桥接服务请确认服务是否运行); } }); } function insertResultToPage(text) { // 通过 DOM 插入一段文本到对话区域 // 具体选择器要根据 KIMI 当前页面结构动态匹配 const chatArea document.querySelector([data-testidchat-message-container]); if (!chatArea) return; const fakeMessage document.createElement(div); fakeMessage.className openclaw-result; fakeMessage.innerText [OpenClaw] text; chatArea.appendChild(fakeMessage); } function monitorInput() { const inputBox document.querySelector([contenteditabletrue], textarea); if (!inputBox) return; const observer new MutationObserver(() { // 这个监听块主要用来捕捉 KIMI 动态渲染的输入区域变化 }); const keyHandler function(e) { if (e.key Enter !e.shiftKey) { const text (this.innerText || this.value || ).trim(); if (isCommandMessage(text)) { e.preventDefault(); e.stopPropagation(); sendToBridge(text); // 清空输入框 if (this.innerText) { this.innerText ; } else { this.value ; } } } }; inputBox.addEventListener(keydown, keyHandler); } window.addEventListener(load, function() { setTimeout(monitorInput, 2000); }); })();这里有两个需要注意的细节。第一match规则写法取决于 KIMI 的实际域名你需要看浏览器的地址栏把真实域名匹配写进去否则脚本不会生效。我在这里写的.kimi.com是个示例实际部署时一定要改成你自己的访问地址。第二insertResultToPage里使用的 DOM 选择器也得根据页面实际结构调整。KIMI 的前端布局有过多次变动建议打开浏览器开发者工具点选对话框区域拿到完整的 class 或 data 属性再替换。3.5 第四步实际跑通第一个任务配置完成后我在 KIMI 对话框里输入了这样一条命令/claw 帮我在 D:/work 目录下新建一个名字为 test_claw 的文件夹并在里面生成一个 hello.txt 文件内容写“Hello from OpenClaw”。按下回车后大概是两三秒的等待时间聊天区域底部就插入了 OpenClaw 返回的结果信息内容显示文件创建成功并且把目录结构也列了出来。那一刻的感受是值了。因为我发现我全程没有离开浏览器窗口也没有打开终端更没有手动敲任何一行 Shell 命令。所有操作都是通过聊天式输入完成的OpenClaw 在后台安静地执行KIMI 在界面上负责展示。4. 实操中常踩的坑与排查速查4.1 OpenClaw 返回空结果这个我碰到过好几次后来排查下来发现原因基本一致消息格式不匹配。OpenClaw 对消息类型有严格要求如果你发过去的 JSON 里缺了type字段或者content字段不是字符串类型它可能不会报错但也不会返回实际内容。遇到这种情况先别急着改业务逻辑你可以直接在桥接服务的测试脚本里输出 OpenClaw 返回的原始内容看看它到底是空字符串还是错误对象。很多时候问题就出在你自己的消息构造上。4.2 Tampermonkey 脚本不生效这一步是我个人觉得最坑的地方。Tampermonkey 的脚本并不总是第一时间注入到页面里特别是 KIMI 这种使用了大量异步渲染的页面脚本可能在输入框出现之前就已经跑完了。我自己的解决方式是给脚本加了一个 2 秒的延迟启动同时用 MutationObserver 监听页面的变化。但这也不能保证 100% 覆盖所有情况如果发现脚本完全没反应先打开浏览器的开发者工具看看 Console 里有没有报错信息最常见的是选择器拿不到元素。4.3 WebSocket 连接频繁断开如果你发现桥接服务日志里全是 ConnectionClosed 报错大概率有两个可能。一是你的 OpenClaw 服务端在空闲时主动断开连接二是桥接服务所在的网络环境有代理中间层干扰了长连接。针对前一种情况OpenClaw 配置里一般有ping_interval这样的字段调小一点可以保持连接活跃。针对后一种情况最简单粗暴的做法是把桥接服务和 OpenClaw 都跑在本机回环地址上绕过局域网和代理的干扰。4.4 本地服务端口冲突8800 和 18789 这两个端口看着不常见但还真有可能会被其他软件占掉。排查命令很简单Windows 下用netstat -ano | findstr 8800macOS/Linux 下用lsof -i :8800。如果发现端口被占用可以顺手换一个高位端口比如 18900 或者 28100同时把 Tampermonkey 脚本里的地址也一起改掉。整个项目做下来我最大的体会是桥接服务的价值不在于它有多复杂而在于它把两个本来独立运行的系统安静地连接在一起。你可以完全不管 KIMI 前端的渲染逻辑也可以完全不深入 OpenClaw 的协议细节只需要在中间搭一个轻量的“翻译层”工作流就能跑起来。如果你后续也想做类似的扩展我建议从最简单的场景切入比如先跑通“让 OpenClaw 帮你查本机进程”这种小任务再去扩展复杂工作流。因为真正容易出问题的从来不是功能设计而是消息格式、端口、选择器这类细节。最后说一个小技巧如果你觉得从页面手动输入/claw前缀有点烦完全可以在 Tampermonkey 脚本里再加一个别名列表把整段常用指令存成快捷键。比如输入!status就自动展开成“查看当前系统内存和 CPU 占用率并生成摘要”这样一来日常使用会更顺手。