9ad88986
tangwang
up`
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
|
# OpenClaw 源码技术方案解读
> 面向源码阅读者的技术剖析:从 CLI 入口、Gateway 控制面、渠道插件、路由与会话、Agent 执行到媒体与安全。
## 1. 总体架构(控制面 + 执行面)
OpenClaw 把系统拆成两层:
- **Gateway 控制面**:统一承载 WebSocket/HTTP、方法分发、客户端连接、鉴权、配置热重载、渠道生命周期。
- **Agent/Channel 执行面**:负责模型调用、会话持久化、消息路由、跨渠道发送、媒体处理、插件扩展。
这种设计把“系统连接与治理”与“具体业务执行”分离,便于在不改动主干的前提下持续增加新渠道和新能力。
## 2. CLI 启动链:轻入口 + 按需加载命令
`src/index.ts` 作为统一入口,先做运行时守护(环境变量归一化、运行时版本检查、全局异常处理),再交给 Commander 程序对象解析命令。核心思路是:**先把运行环境稳定,再执行命令逻辑**。
CLI 命令注册使用“延迟加载”策略:`registerCoreCliCommands` 会先挂占位命令,在真正执行时动态 `import` 对应模块并二次解析参数。这显著降低了冷启动成本,也能避免一次性加载全部命令依赖。
## 3. Gateway 服务器:集中式编排器
`startGatewayServer` 是系统级编排入口,启动前会串行处理:
1. 读取并迁移历史配置;
2. 校验配置合法性并补齐启动鉴权;
3. 自动启用满足条件的插件;
4. 组装基础能力 + 渠道插件能力形成完整方法集;
5. 构建运行时状态(鉴权、限流、心跳、节点、插件、通道、发现服务等);
6. 挂载 WS 处理器并对外广播统一事件。
这让 Gateway 成为“单一控制平面”:无论来自 CLI、WebChat、桌面端还是移动端,最终都走同一套 RPC/Event 协议。
## 4. 方法协议:基础方法 + 插件方法拼接
`server-methods-list.ts` 维护内置方法集合(如 `agent`、`send`、`channels.status`、`node.invoke`、`chat.send`),再合并渠道插件额外暴露的方法,形成完整 capability 列表。
这相当于“内核 API + 扩展 API”模型:内核保持稳定,插件在边界内扩展。
## 5. 渠道插件体系:注册表驱动
渠道并不是硬编码在主流程中,而是通过插件注册表统一管理。`listChannelPlugins` 从活动插件注册表读取渠道定义并排序输出;Gateway 在启动时基于这些定义动态创建日志上下文、运行时环境与方法集合。
这意味着新增渠道的关键不是修改核心 switch-case,而是实现符合接口的插件并注册,整体可维护性更好。
## 6. 渠道生命周期管理:可观测 + 自恢复
`createChannelManager` 负责渠道账户的启动/停止/状态维护,具备:
- 多账户粒度运行时快照;
- 启动前配置完整性检查;
- 崩溃后指数退避重启;
- 手动停用后禁止自动拉起;
- 统一暴露运行状态给上层 health/status。
这套机制让各渠道实现从“业务代码”中抽离,收敛到统一的运维语义。
## 7. 路由与会话键:多维绑定解析
`resolve-route.ts` 把输入上下文(channel/account/peer/guild/team/roles)映射到目标 agent 与 sessionKey。其本质是一套优先级匹配规则:
- peer 精确匹配;
- parent peer 继承;
- guild + roles;
- guild/team/account/channel;
- 默认 agent 回退。
并且它带有按 `channel+account` 的评估缓存,避免在高频消息场景重复解析绑定规则。
## 8. Agent 执行:Gateway 方法到模型调用
Gateway 侧 `agent` 方法会完成请求校验、幂等处理、附件规范化、会话键解析与重置语义,然后调用 `agentCommand` 执行一次 Agent turn。
`agentCommand` 再根据模型/Provider/思考等级/会话状态选择执行路径:
- CLI Provider 走 `runCliAgent`;
- 内嵌执行走 `runEmbeddedPiAgent`;
- 并支持模型回退、会话更新、事件发射、结果投递。
因此 OpenClaw 的 Agent 调用并不是“直接请求模型”,而是带有会话与路由语义的受控执行流水线。
## 9. Outbound 抽象:优先插件动作,回退核心发送
`outbound-send-service.ts` 体现了一个关键策略:
1. 先尝试调用渠道插件动作(send/poll);
2. 插件未处理时回退到核心 `sendMessage/sendPoll`;
3. 在发送链路中支持中断信号、镜像写回会话、网关上下文。
这保证了不同渠道可做差异化实现,同时保留统一兜底路径。
## 10. 媒体管线:安全优先
`media/store.ts` 中可见明显的“安全默认”策略:
- 限制协议仅 HTTP/HTTPS;
- 使用 SSRF 防护与主机名解析钉扎;
- 限制文件大小(默认 5MB);
- 临时目录权限收紧(700/600);
- 文件名净化与过期清理;
- 安全读取本地文件并映射错误类型。
这使媒体能力在可用性与安全性间取得平衡。
## 11. 配置系统:JSON5 + 兼容迁移 + 环境变量注入
`config/io.ts` 不是简单读写配置文件,而是完整的配置编排层:
- 支持 JSON5;
- include/merge patch/env 引用替换;
- 默认值补全、路径归一化、版本迁移;
- 写入审计与备份轮转;
- 与插件 schema 联合校验。
这套机制让 OpenClaw 能在长期迭代中保持配置向后兼容。
## 12. 具体案例:从用户一句话到系统动作链
下面用两个典型请求,说明 OpenClaw 在真实场景里会触发什么动作。
### 案例 A:"帮我在 GitHub 搜索 xx 相关项目,筛选能迁移到 xx 的方案,仔细阅读并讲技术方案和关键代码"
这个需求不是一次普通问答,而是一条“检索 -> 过滤 -> 深读 -> 结构化输出”的多阶段流水线。典型动作链如下:
1. **消息入站**
用户消息通过 Telegram/Discord/WebChat 等渠道进入 Gateway;渠道插件先归一化消息、账户信息、线程信息,再转为统一 `agent` 请求。
2. **会话与目标 agent 解析**
路由层用 channel/account/peer/thread 上下文解析 `agentId + sessionKey`,把任务绑定到既有会话(避免每轮丢上下文)。
3. **请求校验与幂等**
Gateway `agent` handler 校验参数、附件、渠道合法性和幂等键,然后把任务交给 `agentCommand`。
4. **任务规划(Agent 内部)**
Agent 将原句拆成可执行子任务,例如:
- 关键词扩展(xx 的同义词、上下游术语);
- 候选项目召回(stars/更新时间/语言/许可证);
- 迁移可行性筛选维度(架构耦合度、依赖复杂度、部署形态、数据模型兼容性);
- 深读清单(README、docs、核心目录、关键 entrypoint)。
5. **候选项目检索**
Agent 通过浏览器或 HTTP 工具抓取 GitHub 搜索页/项目页,得到候选仓库列表与基础元信息。
6. **第一轮筛选(可迁移性粗筛)**
基于显性信号先过滤:
- 是否活跃维护;
- 是否与目标技术栈接近;
- 是否有可运行示例与清晰模块边界;
- 许可证是否满足使用场景。
7. **第二轮深读(代码级)**
对入围项目进行“关键代码阅读”:
- 定位入口文件与启动链;
- 识别核心模块边界与数据流;
- 抽取关键实现片段(例如路由层、调度层、插件层、存储抽象层);
- 记录迁移风险(强绑定云服务、隐式全局状态、非标准构建流程)。
8. **输出构建**
Agent 生成结构化结论:
- 项目对比表(适配度/迁移成本/风险);
- 每个项目的技术方案摘要;
- 关键代码位置与原因说明(为什么这段代码关键);
- 推荐优先级与迁移路径建议(PoC -> 灰度 -> 全量)。
9. **结果发送与会话沉淀**
结果经 outbound 发送到原渠道(插件优先、核心兜底),并写入会话 transcript。后续用户说“把第 2 个项目展开到模块级改造方案”时,可直接沿用当前上下文继续执行。
#### 这个案例在系统内触发的关键机制
- **Gateway 控制面**:统一承接请求、鉴权、方法分发。
- **路由层**:保证请求进入正确 agent/session。
- **Agent 执行层**:负责任务分解与工具编排。
- **Outbound 层**:统一回传,不同渠道差异由插件吸收。
- **会话存储层**:沉淀中间结论与最终报告,支撑多轮深挖。
### 案例 B:"在 Twitter 上搜集 xx 相关信息,写一篇调查报告"
一个典型执行链如下:
1. **请求入站与鉴权**
用户请求到达 Gateway 后,先经过鉴权与方法白名单控制。
2. **任务分解**
Agent 将任务拆成“检索关键词集合、时间窗口、可信账号优先级、去重规则、证据归档格式”。
3. **数据采集**
通过浏览器/HTTP 等工具抓取公开推文、线程、外链文章与引用关系,必要时抓页面快照做证据留存。
4. **清洗与聚类**
依据主题、立场、时间线、传播强度进行聚类,过滤明显噪声与重复转发。
5. **报告生成**
输出“事实层(发生了什么)+ 观点层(各方怎么说)+ 风险层(哪些结论证据不足)+ 建议层(下一步怎么验证)”。
6. **多渠道投递**
按当前会话策略发送到用户指定渠道;如果是群聊线程,还会带上 thread 信息以保持上下文连续。
### 两个案例背后的共性机制
- **同一控制面**:不管是 GitHub 调研还是 Twitter 调研,都是同一条 Gateway RPC/Event 主干。
- **同一路由语义**:都通过 sessionKey/agentId 保证上下文连续,而不是每次“无状态回答”。
- **同一执行模式**:都属于“规划 -> 工具调用 -> 归纳输出”的 agentic 工作流。
- **同一发送抽象**:都走 outbound 统一接口,渠道差异由插件吸收。
- **同一安全基线**:媒体下载、外链抓取、文件读写都受限于安全策略(协议、大小、路径、SSRF)。
## 13. 一句话总结
OpenClaw 的核心技术方案可以概括为:
**“以 Gateway 为统一控制面,以插件与路由为扩展骨架,以 Agent 会话语义为执行核心,并在媒体/配置层默认内建安全与可运维能力。”**
|