首页>AI>正文

OpenClaw 架构拆解:二十种消息入口打通

Feng 62 阅读 AI

一条消息从聊天窗口发出,最终变成磁盘上的文件、终端里的一行输出、屏幕上的一次点击。OpenClaw 干的就是这件事。它跑在你自己的机器上,不租云服务器,支持 WhatsApp、TG、Discord、Slack、Signal、iMessage 等海外渠道,飞书、企业微信、QQ 则通过插件接入。此外还有 macOS / iOS / Android 原生应用、终端命令行和 Web 控制台。

二十多种入口,一个本地大脑,一套工具集。这个定位决定了它的架构必须解决两个问题:入口的异构性,以及意图到动作的穿透。

从一条 webhook 脚本说起

项目最早叫 Warelay,即 WA Relay 的缩写。那时它只是一个 Express 路由加 webhook:Twilio 或 Baileys 收到 WhatsApp 消息,调一次 AI API,把回复原路返回。没有 Gateway,没有会话管理,没有 Agent 循环。

一个关键选择延续至今:用开源的 Baileys 协议库收发 WhatsApp,而不是商业 API。省了钱,也不依赖第三方中转,代价是 Baileys 对会话唯一性要求很严。

实际部署里最常见的坑就在这里。同一份 WhatsApp 凭据被两个进程同时加载,或者旧容器没停干净就起了新实例,Baileys 会抛出 401 或 440 类断连,日志里表现为 connection closed 后反复重连又反复失败。根因不是网络,是凭据被抢占。排查顺序:先确认没有残留的 node 进程持有 auth 目录,再检查 auth 状态目录是否被挂载到多个实例,最后才怀疑代理。清掉冲突实例后重新扫二维码即可恢复,不需要重新注册。

三件事同时发生的那两周

Clawdis 阶段是整个项目最剧烈的跃迁。引入 Pi SDK 让 OpenClaw 从”收消息调一次 API”变成真正的 agent:消息进 prompt、流式调模型、解析工具调用、执行、再回到模型,循环到结束。同期两周内接了 TG、Discord、Signal、iMessage、WhatsApp 五个渠道,每个平台的格式、API 风格、群组概念都不一样。差异逼出了 Adapter 模式和 Channel Dock 注册中心。

Gateway 也是这时候诞生的。它从命令行工具变成常驻后台服务,所有客户端走 WebSocket 接入,内部管消息路由、队列、会话、Cron、Hook 和插件注册。

再往后是 Clawdbot 到 OpenClaw 的生产化。核心思路很明确:新功能通过插件长出来,核心库不再膨胀。插件导出 register(api) 即可声明能力,可注册渠道、工具、钩子、HTTP 路由、CLI 子命令和后台服务。Node.js 的 ESM/CJS 分裂是插件加载的老大难,项目用 jiti 做运行时 TypeScript 编译加载,插件不用预编译,装完就能跑。目前四十多个扩展——飞书、LINE、Matrix、Twitch、语音通话——都是插件形态。

大脑站在 Pi 的肩膀上

OpenClaw 的 agent 能力不是自研的。Pi 是一个七包 monorepo,自底向上三层。

pi-ai 是 LLM 抽象层,把十六家以上供应商统一成 stream(model, context) 一个调用。每家实现一个 StreamFunction,把私有流式响应转成标准事件:text_delta、thinking_delta、toolcall_start/end。模型注册表自动生成,带成本、上下文窗口、输入类型和推理能力。

pi-agent-core 是运行时,提供核心循环:用户消息进入,流式调 LLM,解析工具调用,按序执行,结果回灌,继续循环直到 end_turn。工具参数用 TypeBox 定义 schema,运行时自动校验,流式进度通过事件总线回调。

pi-coding-agent 是 SDK 层,createAgentSession() 一次性组装工具集、上下文钩子和会话存储。SessionManager 用 JSONL 存对话树,每条消息带 id 和 parentId,支持分支、恢复和压缩。上下文管线两步走:transformContext() 在 AgentMessage 层裁剪注入,convertToLlm() 转成模型能吃的标准格式。

OpenClaw 在 Pi 外面包了六层:接入层、调度层、Provider 路由、Model Failover、Context Engine、Prompt 构建。主模型挂了自动切备用,长对话靠 Context Engine 兜住,系统指令和 Skills 拼进 prompt,流式回调再推回渠道。

消息流水线的九个环节

一条消息进来,依次经过:接收原始消息、归一化、去重、Hook 与路由、媒体理解、入队策略、Agent 执行、回复调度、投递。

入队有三种策略:eager 立即处理,batch 把短时间多条合并,debounce 等用户停止输入再触发。媒体理解负责语音转文字和图片生成描述。

两个设计值得单独说。Steering 让 agent 生成回复途中接收新消息,通过 session.steer() 实时注入当前运行,AI 立刻调整方向,不用等上一轮跑完。仿人延迟则是把回复分块发送,块间插随机间隔,在即时通讯里读起来像真人打字。

十个细粒度接口,而不是一个大而全

WhatsApp 有已读回执,TG 有群组管理 API,Discord 有权限体系,Signal 几乎没有管理接口。想设计一个统一大接口让所有通道实现,必然大量空实现。

OpenClaw 拆成十种 Adapter:Security、Auth、Group、Messaging、Outbound、Media、Lifecycle、Setup、Config、Status、Heartbeat。每个通道只实现需要的子集。WhatsApp 实现 HeartbeatAdapter,因为 Baileys 连接不稳需要保活;Discord 实现 SecurityAdapter 应对复杂权限;Signal 不需要 GroupAdapter。社区写飞书、LINE 插件时实现同样的接口就能接入,核心代码零改动。

让 AI 看见并操控 macOS 桌面

在聊天里说”看看屏幕上是什么”,AI 截屏、理解、回答。说”点击登录按钮”,它找到按钮点下去。背后是 Peekaboo,给 AI 装上眼睛和手。

看:截屏、录屏、标注 UI 元素并分配 ID。操作:点击、打字、组合键、滚动、拖拽,可定位到具体元素。管理:启停应用、调窗口、切空间、读写剪贴板。典型工作流是截屏标注、识别元素 ID、点击输入、再截屏确认,全程在聊天窗口完成。

权限是这里最棘手的一环。macOS 的屏幕录制和辅助功能权限按应用授予,但 agent 调用的是命令行工具。Bridge 架构解决这个问题:CLI 通过 UNIX Socket 连到 OpenClaw.app 内的 BridgeHost,BridgeHost 先验调用方代码签名和 Team ID,通过后才借出 app 已拿到的权限。用户只需在系统设置里授权一次。

这个方案有明确边界。它依赖一个带 GUI 会话的宿主进程,纯 SSH 远程、无图形会话的 CI 环境、容器里没有 WindowServer 的场景,Bridge 都借不到权限,Peekaboo 相关能力直接不可用。这类环境要跑桌面自动化,得换成有虚拟显示的服务端方案,不能指望 Bridge 兜底。

元素检测走 Accessibility 树遍历,按类型编号,按钮 B1、B2,输入框 T1、T2。遍历限制深度 8 层、子节点 200 个、150ms 超时,结果缓存 1.5 秒避免重复遍历。之后 click B1 直接命中目标。

Peekaboo 自带基于 Tachikoma 的 agent 循环,支持 OpenAI、Anthropic、Ollama,可以脱离 OpenClaw 独立跑多步任务。在 OpenClaw 里它不以代码依赖形式存在,而是一个 Skill,声明”仅限 macOS、需要 peekaboo 命令”,运行时按需注入 system prompt,非 macOS 用户完全感知不到。

定时任务不是 setInterval

Cron 调度器做了几件生产级的事。SHA256 Stagger 用任务 ID 的哈希做确定性偏移,默认在 5 分钟窗口内分散,一百个”早上 9 点”的任务不会同一秒涌进来打爆 CPU 和 API 配额。执行分两种模式:systemEvent 把消息注入主会话,像用户自己发了一条;agentTurn 启动独立运行,互不干扰。失败走指数退避,30 秒、1 分钟、5 分钟、15 分钟、1 小时,连续失败告警,临时 session 自动回收。

本地记忆与它的验证方式

跨会话长期记忆靠 sqlite-vec。文本切片转向量,存本地 SQLite,用 sqlite-vec 扩展做余弦相似度检索。搜索是混合策略:向量语义匹配加 BM25 关键词匹配,兼顾”意思相近”和”关键词命中”。数据全在本地磁盘,也能通过 MCP 桥接外部知识库。

部署完想确认这套东西真在工作,别只看有没有报错。在 Node 里加载扩展后执行 SELECT vec_version();,能返回版本号说明扩展加载成功。再对记忆表跑一次 SELECT count(*) FROM chunks;,确认切片确实写进去了。检索侧构造一个语义相近但用词不同的查询,如果混合检索返回的结果里既有语义命中又有 BM25 命中,且排序合理,才算链路通了。只测关键词能召回,证明不了向量通道有效。

技能与插件的分工

插件扩展渠道和工具,技能则共享 AI 的行为模式。ClawHub 是公开技能注册中心,技能本质是注入 system prompt 的声明文件,描述特定场景下该怎么做,比如操控 macOS 桌面、生成代码后自动跑测试。安装一条命令:clawhub install <slug>。加载优先级是 workspace 高于本地、本地高于内置。社区有点赞、评论、举报和独立审核。项目的 VISION.md 写得很直白:新技能先发 ClawHub,不要默认塞进核心仓库。

上下文怎么不丢

模型上下文窗口有限,聊久了必然溢出。Pi 提供两步管线打底,OpenClaw 在上面实现 Context Engine,定义五个生命周期钩子:bootstrap 初始化、ingest 新消息进入、assemble 组装上下文、compact 超长时压缩、afterTurn 一轮结束清理。默认实现用 token 计数加 LLM 摘要压缩历史。整个引擎可插拔,社区写一个基于向量检索的长期记忆实现替换进去,核心代码一行不用改。

意图穿透介质

Gateway、Adapter、Bridge、Agent Loop,拆开看是不同模块,合起来是同一件事:让意图穿过消息协议、归一化流水线、模型概率空间和工具调用,落到真实世界的状态上。每一层抽象都在削减这条路径上的摩擦。维纳说智能的本质是与环境之间有效的信息交换,OpenClaw 的架构基本就是这句话的工程注脚。

ID:6922

Feng
这位作者很神秘,还没有填写简介。