ClawdBot(MoltBot)实现研究 (一)
来自应用:启动/退出/隐藏/切换、列表。窗口:列表、焦点、移动/缩放、关闭/最小化/最大化。输入:按元素 ID/坐标点击、拖拽、按键、打字、滚动、手势。菜单:应用菜单、菜单栏图标(如 WiFi)。Dock:启动、右键、显示/隐藏。视觉:截屏、带标注的“see”、可选视觉分析。所以,在 Mac 上只要 Peekaboo 能识别的界面,都可以被当作“任意桌面 app”来间接控制。
现在大火的ClawdBot(MoltBot)成为一个现象级产品,网上很多关于使用和安装的视频和文章。其实我最感兴趣的是它内部的实现机制。因为我也在做微信客服机器人,先从几个基本的我感兴趣的点做了点研究。
一、这个项目里,它是怎么控制浏览器的?是通过playwrite吗?
是的,和 Playwright 有关,但不是完整 Playwright
项目里浏览器控制主要靠这两块配合:
1. playwright-core(核心依赖)
- 根目录
package.json里只有playwright-core(版本 1.58.0),没有装完整版playwright。 src/browser/pw-session.ts里从playwright-core引入chromium和类型,用 Playwright 的Browser/Page做会话、快照、交互等。
2. CDP(Chrome DevTools Protocol)
- 本地/回环场景下,很多操作是直接走 CDP 的 HTTP 接口,不经过 Playwright:
- 例如在
server-context.ts里用fetch请求appendCdpPath(profile.cdpUrl, "/json/list")、/json/new等。
- 例如在
src/browser/cdp.ts、cdp.helpers.ts里封装了 CDP 相关逻辑(如createTargetViaCdp、snapshotAria等)。
3. 本地 vs 远程
- 本地 (loopback):以 CDP 为主(直接请求
cdpUrl的/json/list、/json/new等),部分能力会再配合 playwright-core。 - 远程 (remote):用 Playwright 做“持久连接”,避免远程 CDP 会话不稳定,例如:
listPagesViaPlaywright({ cdpUrl: profile.cdpUrl })createPageViaPlaywright({ cdpUrl: profile.cdpUrl, url })
(见server-context.ts104–156 行)
4. 和 Puppeteer 的关系
- 项目里没有使用 Puppeteer,只用了 CDP + playwright-core。
5. 完整 Playwright 只出现在 UI 测试里
ui/package.json里的playwright和@vitest/browser-playwright是给 Vitest 的浏览器测试用的(例如ui/vitest.config.ts里provider: playwright()),不是产品里“控制用户浏览器”的那套逻辑。
结论:
产品里控制浏览器 = CDP(直接 HTTP 调 Chrome 的调试接口)+ playwright-core(启动/连接浏览器、页面会话、快照与交互)。所以可以说是“通过 Playwright(playwright-core)和 CDP 一起控制浏览器”,而不是 Puppeteer,也不是完整安装版的 Playwright(完整版只在 UI 测试里用)。
二、这个项目如何实现和微信的连接
结论:当前项目没有实现和微信的连接
- 代码里没有任何
wechat、weixin、微信相关实现。 docs/channels/和extensions/里也没有微信通道或插件。- 支持的通道/扩展里没有“微信”这一项。
也就是说:这个项目目前并没有“和微信连接”的实现。
项目里已有的消息通道大致有哪些
内置 / 文档里提到的通道示例:
- Telegram、Discord、Slack、Signal、iMessage(BlueBubbles)
- WhatsApp(Web)、Web 控制台
- 以及扩展:Matrix、Mattermost、MS Teams、Google Chat、Line、Zalo、Nostr、Twitch、Nextcloud Talk、Tlon 等
没有微信(WeChat)。
如果你想要“和微信连接”可以怎么做
-
等官方或社区做微信支持
目前仓库里没有,只能看以后是否会有 WeChat 通道或扩展。 -
自己按现有通道方式做一个“微信”扩展
- 参考
extensions/whatsapp、extensions/telegram、extensions/zalo等结构。 - 实现一个插件:注册为一种 channel,实现收消息、发消息、鉴权等(具体取决于你用的微信接口或协议)。
- 微信没有官方 Bot API,通常需要自建协议或使用第三方方案(如企业微信 API、或非官方的协议实现),合规和稳定性都要自己考虑。
- 参考
-
用企业微信代替个人微信
企业微信有官方 API,可以在本项目外单独写一个服务,把企业微信事件转成本项目能消费的 webhook/API,再在项目里当“自定义通道”或通过现有 webhook/自动化入口对接。
如果你说一下目标(例如:个人微信 vs 企业微信、只发消息还是也要收消息),可以再具体说“在本项目里该怎么接、要动哪些目录/接口”。
三、这个项目怎么实现和what’s app连接呢?
1. 整体方式:WhatsApp Web + Baileys
- 协议:走 WhatsApp Web(多设备 / Linked Devices),不是官方 Business API。
- 库:用 @whiskeysockets/baileys(
package.json里"@whiskeysockets/baileys": "7.0.0-rc.9")连 WhatsApp Web,相当于“无头版”的网页客户端。 - 会话归属:Gateway 自己持有并维持会话;CLI / macOS 只和 Gateway 通信,不直接连 Baileys。
2. 登录与鉴权(扫码一次,长期复用)
- 命令:
moltbot channels login(多账号时加--account <id>)。 - 流程:
- 用
createWaSocket(..., { authDir })建一个 Baileys socket(src/web/session.ts)。 - 用
useMultiFileAuthState(authDir)做本地鉴权存储(密钥、会话等)。 - 首次或未登录时,Baileys 会出 QR 码,你在手机 WhatsApp 里:设置 → 已连接的设备 → 连接设备,扫码完成“Linked Devices”绑定。
- 登录成功后,Baileys 把凭据写入
authDir,之后 Gateway 启动时直接用这些凭据重连,不用再扫码(除非登出或会话失效)。
- 用
- 凭据路径:
~/.clawdbot/credentials/whatsapp/<accountId>/creds.json(并有creds.json.bak备份)。
文档说明:Status: WhatsApp Web via Baileys only. Gateway owns the session(s).
3. 建连与收消息(Gateway 里的“一条长连”)
- 入口:Gateway 启动 web 通道时,会跑
monitorWebChannel(src/web/auto-reply/monitor.ts),内部再调monitorWebInbox(src/web/inbound/monitor.ts)。 - 建连:
monitorWebInbox里调用createWaSocket(false, verbose, { authDir }),用同一套authDir建 Baileys socket。- 然后
waitForWaConnection(sock)等connection.update里connection === "open",即 WhatsApp Web 已连上。
- 收消息:
- 监听 Baileys 的
messages.upsert事件(新消息/更新)。 - 在
inbound/monitor.ts里做去重、访问控制(DM/群组策略、allowlist、pairing 等),再转成内部的WebInboundMessage,交给onMessage。 onMessage由 auto-reply 管道处理:路由到对应 agent、会话、发回复等。
- 监听 Baileys 的
- 断线重连:
监听connection.update里connection === "close",按web.reconnect策略做退避重试;重试时再次createWaSocket+waitForWaConnection,用同一authDir自动恢复会话。
所以:和 WhatsApp 的“连接” = 一条由 Baileys 维护的、基于 WhatsApp Web 协议的长连接;建连、收消息、重连都在 Gateway 里通过 Baileys socket 完成。
4. 发消息(必须在这条连接上)
- 前提:发消息走的是 当前已连上的同一个 Baileys socket,所以必须先有 active listener(即
monitorWebChannel已跑起来且连接为 open)。 - 实现:
sendMessageWhatsApp(src/web/outbound.ts)里通过requireActiveWebListener(accountId)拿到当前账号的“活跃 listener”(内部持有该 socket)。- 用 Baileys 的发送接口(如
sendMessage、媒体等)在该 socket 上发给目标 JID。
- 若 Gateway 没起或 web 通道未连上,
requireActiveWebListener会直接报错,避免无连接发送。
5. 代码结构小结
| 作用 | 位置 | 说明 |
|---|---|---|
| 建 Baileys socket、鉴权持久化 | src/web/session.ts |
createWaSocket、useMultiFileAuthState、waitForWaConnection |
| 登录扫码 | src/web/login.ts |
loginWeb → 建 socket、等连上、保存凭据 |
| 收消息 + 连接生命周期 | src/web/inbound/monitor.ts |
monitorWebInbox:建 socket、监听 messages.upsert、connection.update |
| 长跑 + 重连 + 把收消息接到回复管道 | src/web/auto-reply/monitor.ts |
monitorWebChannel 调用 monitorWebInbox,断线按策略重试 |
| 发消息 | src/web/outbound.ts |
sendMessageWhatsApp 依赖 active listener 的 socket |
| 通道注册 / 对外入口 | src/channels/web/index.ts、src/plugins/runtime/index.ts |
把 monitorWebChannel 等注入到 Gateway 的插件/运行时 |
6. 一句话
和 WhatsApp 的连接 = 用 Baileys 连 WhatsApp Web:moltbot channels login 扫码一次把会话存到 ~/.clawdbot/credentials/whatsapp/...,Gateway 启动时用同一凭据建 Baileys socket,通过 messages.upsert 收消息、通过同一 socket 发消息,断线按配置自动重连。 没有用官方 WhatsApp Business API,也没有用 Twilio 等第三方接口。
四、使用baileys安全吗?
1. 技术 / 数据安全(Baileys 本身)
- 协议:Baileys 用的是和官方 WhatsApp Web 一样的 多设备协议,端到端加密由协议保证,和网页版一致。
- 凭据:登录后的密钥、会话等存在你本机(如 Moltbot 的
~/.clawdbot/credentials/whatsapp/...),不经过 Baileys 的服务器,也没有“把聊天内容发给第三方”的逻辑。 - 开源:Baileys 是开源库,代码可审计;Moltbot 里怎么存、怎么用凭据也可以自己看。
所以从「数据是否被 Baileys/第三方偷走」这个角度,用 Baileys 和用官方 WhatsApp Web 在加密与本地存储上是同一级别;安全与否主要看你本机是否被入侵、凭据是否泄露。
五、这个项目可以控制桌面的任意app吗?怎么实现的?
这个项目能控制桌面的任意 app 吗?
在 macOS 上可以,通过 Peekaboo(独立 CLI)+ PeekabooBridge 实现对本机桌面应用的 UI 级控制。
Windows / Linux 目前没有同等的“任意桌面 app 控制”能力(桌面伴侣应用在规划中)。
实现方式概览
1. 整体链路
- Agent 通过 node 下发命令到你的 Mac。
- 在 Mac 上真正执行的是
system.run:在本地跑一条 shell 命令(例如peekaboo ...)。 - Peekaboo 是专门做 macOS UI 自动化的 CLI,能对“任意前台/后台”应用做:截屏、点击、输入、菜单、窗口、Dock 等。
- 所以“控制任意桌面 app”的本质是:Agent 用
system.run在 Mac 节点上执行peekaboo命令,由 Peekaboo 去操作系统级 UI。
2. PeekabooBridge 的作用
- macOS 的 无障碍 / 屏幕录制 等权限是按应用给的;若在无界面的 node 进程里直接跑
peekaboo,往往没有这些权限。 - Moltbot 的 macOS 菜单栏应用可以选“启用 Peekaboo Bridge”,在应用内启动一个 Unix 域套接字(
bridge.sock),实现 PeekabooBridge 协议。 peekabooCLI 会按顺序尝试连接:Peekaboo.app → Claude.app → Moltbot.app。连上 Moltbot 后,实际执行 UI 操作时用的是 Moltbot.app 的 TCC 权限,而不是 node 进程的权限。- 也就是说:Moltbot 不自己实现点击/截屏等,而是作为“桥接宿主”,让
peekaboo通过这座桥用 Moltbot.app 的权限去控桌面。
相关文档与实现位置:
- 文档:
docs/platforms/mac/peekaboo.md、docs/platforms/mac/xpc.md - 桥接宿主:
apps/macos/Sources/Moltbot/PeekabooBridgeHostCoordinator.swift(启动bridge.sock、校验 TeamID 等)
3. Agent 如何触发“控制桌面”
- Agent 侧通过 node 的
system.run下发一条命令,例如:peekaboo see --annotate --path /tmp/see.png或peekaboo click --on B1 --app Safari。 - Gateway 把
node.invoke(system.run, { command: "peekaboo ...", ... })发给 node host。 - Node host 再通过 本地 Unix socket 把这次
system.run请求转给 macOS 菜单栏应用。 - 菜单栏应用在自己的进程/权限环境里执行这条 shell;若已启用 Peekaboo Bridge,
peekaboo会连上 Moltbot 的bridge.sock,用 Moltbot 的权限完成截屏、点击、输入等。 - 执行结果(stdout/stderr)沿原路返回给 Agent。
相关代码:
src/agents/tools/nodes-tool.ts、src/agents/bash-tools.exec.ts:构造并发送system.run。src/node-host/runner.ts:node host 处理system.run并转给 macOS app。
4. Peekaboo 能对“任意 app”做什么(摘要)
来自 skills/peekaboo/SKILL.md 等:
- 应用:启动/退出/隐藏/切换、列表。
- 窗口:列表、焦点、移动/缩放、关闭/最小化/最大化。
- 输入:按元素 ID/坐标点击、拖拽、按键、打字、滚动、手势。
- 菜单:应用菜单、菜单栏图标(如 WiFi)。
- Dock:启动、右键、显示/隐藏。
- 视觉:截屏、带标注的“see”、可选视觉分析。
所以,在 Mac 上只要 Peekaboo 能识别的界面,都可以被当作“任意桌面 app”来间接控制。
小结
| 问题 | 答案 |
|---|---|
| 能控制桌面任意 app 吗? | 在 macOS 上可以,通过 Peekaboo + PeekabooBridge;Windows/Linux 暂无同等能力。 |
| 怎么实现的? | Agent 用 system.run 在 Mac 节点上执行 peekaboo 命令;Moltbot macOS 应用 可选启用 PeekabooBridge,提供 bridge.sock,让 peekaboo 借用 Moltbot 的 TCC 权限做截屏、点击、输入等,从而控制任意桌面应用。 |
使用前需要在 Mac 上:安装 peekaboo(如 brew install steipete/tap/peekaboo)、在 Moltbot 设置里开启 “Enable Peekaboo Bridge”,并授予 Moltbot 所需的辅助功能/屏幕录制等权限。
小结
ClawdBot使用了很多我们已有的现成技术,有一些其实也不是很完善,使用也是有风险的。但是总的效果还是很惊艳的。后面我会再研究一下它对于AI的使用,如何实现长记忆,怎么让AI不仅仅是一个聊天工具。
另外,我做的微信客服机器人的产品也已经逐渐成熟,有需要的可以联系我。这个机器人可以和后台不同大模型连接,实现真正的AI微信客服。
更多推荐




所有评论(0)