摘要:本系列面向已具备大模型与 Agent 基础的读者,从架构—运行时—源码三层读 OpenClaw。本篇作为导读,除统一术语与读源码方法外,专门对齐 Architecture Overview 中的官方组件总表、设计原则与 Data flow 六步,建立可对照 D1/D2 的架构骨架;并给出资料可信度分级(S0/D1/D2/D3)、固定 commit与rg/测试的阅读约定,以及全系列15 篇目录与阅读顺序。后续各篇将沿「Gateway → Router → Brain/Hands → Memory → Channels → 多 Agent → RFC/Heartbeat/安全/生态」展开。
关键词:OpenClaw;系统架构;Gateway;多 Agent;源码阅读;资料分级;系列导读
1 为什么要单独写一篇「导读」?
OpenClaw 不是「又一个调用 OpenAI API 的脚本集合」,而是一个长期驻留、以 Gateway 为中心、把通道、推理、执行与持久化记忆缝在一起的个人智能体运行时。若直接进入某段 TypeScript 实现,很容易在「这是 CLI 还是网关?」「这是通道回调还是 Brain 循环?」里迷路。
本篇目标有三点:
- 统一术语:后面 14 篇都会用到的 Gateway / Router / Brain / Hands 等词,在本篇一次性对齐含义。
- 统一读法:全系列引用源码时,如何选 commit、如何用
rg/测试定位,避免「对着 main 漂移吵架」。 - 统一路线图:15 篇各自回答什么问题、与已发表的第2、第8篇如何衔接,读者可按表索骥。
💡理解要点:把本篇当成「系列里的README+ glossary + contributing guide」——不追求覆盖 OpenClaw 全部功能,而追求后续篇能站在同一套语言上说话。
2 核心模型:单进程 Gateway 与多 Agent
官方架构叙述(Architecture Overview)把系统压成一张「控制面 + 推理 + 执行 + 记忆 + 通道」的图。可以把它想象成一家餐厅:Gateway 是前台与排号系统(谁先来、谁被服务);Router 决定订单进后厨还是吧台快取;Brain 是主厨的脑子(想菜谱、拆步骤);Hands 是灶台上的手(真炒菜);Memory 是写在便签墙与台账上的持久笔记;Channels 是外卖平台与电话线;Skills 则是可插拔的预制酱料包(扩展能力边界)。
多 Agent 场景下(Multi-Agent Workflows、仓库 docs/concepts/multi-agent.md),OpenClaw 的典型形态是:多个 Agent 共享同一个 Gateway 进程与端口,但每个 Agent 拥有自己的工作区、状态目录、会话存储,并可绑定不同通道与模型。这就像同一栋大厦里有多套独立公寓——共享电梯与物业(Gateway),但室内陈设与门禁卡(workspace / session)彼此隔离。
🔍实际例子:工作与个人各一个 Agent、不同 IM 账号绑定到不同agentId,仍由同一 Gateway 接入;需要更强隔离时再开第二进程(例如不同OPENCLAW_HOME与端口),这在官方文档里作为「Separate Instances」类模式出现。
2.1 组件一览表(全系列共用词汇)
| 组件 | 角色(一句话) | 后续篇目(规划) |
|---|---|---|
| Gateway | 长驻控制面:连接管理、健康、WebSocket 等 | 第3篇起深入 |
| Router | 入站事件分发:决定本轮是否进 Brain、是否走快捷路径 | 第4篇 |
| Brain | 多厂商 LLM 调用、消息拼装、工具调用循环 | 第5篇 |
| Hands | Shell、文件、浏览器等执行面与沙箱边界 | 第6篇 |
| Memory | 本地优先持久化(含与「人格文件」分工) | 第7篇;与第8篇成稿互证 |
| Channels | 各类消息通道与 Gateway 的桥接 | 第9篇 |
| Skills | 工作区技能扩展(与 Built-in、MCP 插件并列) | 第2篇 |
2.2 数据流
以下六步与 Architecture Overview 中的Data flow一致(文中「通道」可对应各类 IM / 邮件等接入;不限于某一具体产品):
- 输入到达:经通道(如新消息)、Heartbeat定时唤醒,或CLI命令进入系统。
- Router 分发:判断本轮需要进入Brain、调用某个Skill,还是允许不经大模型、直接回复。
- Brain 推理:由 LLM 理解请求、形成计划并决定是否走工具链。
- Hands 执行:在此完成 Shell、文件读写、浏览器操作等带副作用的动作。
- Memory 更新:把需在多轮对话中延续的上下文写回持久化载体(具体形态与策略见第7篇)。
- 响应返回:沿本轮输入来源的同一通道(或对应客户端界面)把结果送回用户。
💡理解要点:插图与下文 §2.5 的 mermaid 表达同一套语义;若与某版本源码或本地部署不一致,以S0(pin 的 commit)与D1/D2为准。
2.3 端到端示例:从用户输入到完整回复
为了把抽象的"六步数据流"落地,让我们追踪一条真实的用户请求如何在 OpenClaw 中流动。
场景设定
用户:在微信/WhatsApp 上发送消息:
“帮我查一下明天上海的天气,如果下雨的话提醒我今晚10点关好窗户”
系统配置:
- 已接入WhatsApp 渠道(Channels)
- 已安装天气查询 Skill(
weather-query/SKILL.md) - 已启用定时提醒功能(通过 Hands 调用系统
cron或日历 API)
完整数据流追踪
┌─────────────────────────────────────────────────────────────────────────┐ │ Step 1: 输入到达(Input Arrival) │ ├─────────────────────────────────────────────────────────────────────────┤ │ 用户手机 ──▶ WhatsApp 服务器 ──▶ [Channels 渠道层] ──▶ [Gateway:18789] │ │ │ │ • Channels 插件维持与 WhatsApp 的长连接(WebSocket) │ │ • Gateway 收到原始消息:{from: "用户A", content: "帮我查一下...", ts} │ │ • Gateway 识别出关联的 Agent ID 和 workspace │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Step 2: Router 分发(Routing Decision) │ ├─────────────────────────────────────────────────────────────────────────┤ │ [Gateway] ──▶ [Router] 决策: │ │ │ │ • 这不是简单的问候语,需要 LLM 理解意图 │ │ • 需要调用外部工具(天气 API + 定时器) │ │ • 决策结果:路由到 Brain,携带 context{user, channel, history} │ │ │ │ ❌ 不走的分支:若只是"你好",Router 可能走「快捷回复」直接返回 │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Step 3: Brain 推理(LLM Planning) │ ├─────────────────────────────────────────────────────────────────────────┤ │ [Router] ──▶ [Brain] 加载系统提示词 + 用户消息 │ │ │ │ Brain 拆解为两步计划: │ │ 1. 调用 weather-query Skill 获取明天上海天气 │ │ • read 工具加载 `skills/weather-query/SKILL.md` │ │ • 按 Skill 说明调用天气 API │ │ │ │ 2. 条件判断:如果 rainfall > 0 │ │ • 调用 Hands 设置定时提醒(今晚10点) │ │ • 否则跳过提醒 │ │ │ │ Brain 生成工具调用序列: │ │ ```json │ │ [{"tool": "read", "path": "skills/weather-query/SKILL.md"}, │ │ {"tool": "http_request", "url": "api.weather.com/shanghai/tomorrow"}, │ │ {"tool": "schedule_reminder", "when": "22:00", "what": "关窗户"}] │ │ ``` │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Step 4: Hands 执行(Tool Execution) │ ├─────────────────────────────────────────────────────────────────────────┤ │ [Brain] ──▶ [Skills] ──▶ [Hands] │ │ │ │ 执行层动作: │ │ • Skills 层:读取天气 Skill 的 SKILL.md,按说明格式化 API 请求 │ │ • Hands 层: │ │ - Shell:curl 调用天气 API(或浏览器访问网页) │ │ - File:缓存天气数据到 /tmp/weather-shanghai-20260115.json │ │ - Scheduler:向系统 cron 或日历 API 注册 "22:00 提醒关窗户" │ │ │ │ 执行结果收集: │ │ • 天气:明天上海小雨,15-18℃,降雨概率 80% │ │ • 提醒:已设置今晚 22:00 推送通知 │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Step 5: Memory 更新(State Persistence) │ ├─────────────────────────────────────────────────────────────────────────┤ │ [Brain] ──▶ [Memory] 存储: │ │ │ │ • 对话历史:用户问过天气 + 设置提醒(用于多轮上下文) │ │ • 提醒任务:{id: "rem-001", time: "22:00", content: "关窗户", status: "pending"} │ • 用户偏好:可能记住"该用户关注上海天气"(用于 future 个性化) │ │ │ │ 存储位置: │ │ • 短期:Gateway 内存中的 session snapshot │ │ • 长期:~/.openclaw/agents/<agentId>/sessions/sessions.json │ └─────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ Step 6: 响应返回(Response Delivery) │ ├─────────────────────────────────────────────────────────────────────────┤ │ [Brain 生成回复] ──▶ [Gateway] ──▶ [Channels] ──▶ 用户手机 │ │ │ │ 回复内容: │ │ "明天上海有小雨🌧️,气温 15-18℃,记得带伞。 │ │ 已帮你设置今晚 22:00 的提醒,到时我会再通知你关好窗户。" │ │ │ │ 异步事件(当晚 22:00): │ │ • Heartbeat / Timer 触发 Gateway 唤醒 │ │ • Gateway ──▶ Router ──▶ Brain(生成提醒消息) │ │ • Brain ──▶ Gateway ──▶ Channels ──▶ 用户手机 "⏰ 提醒:关好窗户" │ └─────────────────────────────────────────────────────────────────────────┘关键观察点
| 观察项 | 本例体现 | 对应后续篇目 |
|---|---|---|
| Gateway 的入口角色 | 所有流量(初始请求+定时提醒)都经 18789 端口 | 第3篇 |
| Router 的智能分发 | 区分"需要 Brain" vs “快捷回复” | 第4篇 |
| Skills 的渐进披露 | 按需读取SKILL.md,不常驻内存 | 第2篇 |
| Hands 的副作用 | 真实的 API 调用 + 系统定时器设置 | 第6篇 |
| Memory 的跨会话延续 | 存储的提醒任务在几小时后触发 | 第7篇 |
| Channels 的双向通信 | 接收用户消息 + 推送提醒消息 | 第9篇 |
💡理解要点:这六步不是一次性瀑布流,而是循环往复的协作——当晚 22:00 的提醒,会再次触发 Step 1→6 的完整循环,只是此时"输入来源"是内部定时器而非外部用户。
2.4 架构纵深:官方「Deep dives」索引(自学用)
2.3 架构纵深:官方「Deep dives」索引(自学用)
若要在导读之后立刻往下钻,建议优先读 D1(仓库docs/)中与架构强相关的入口(路径以main为例,精读时请换为你的pin commit链接):
- docs/gateway/index.md — Gateway 总索引
- docs/gateway/network-model.md — 网络与发现
- docs/gateway/authentication.md — 鉴权
- docs/concepts/context-engine.md — 上下文装配(与 Brain 紧密相关)
本篇不展开各文件细节,避免与第3篇及以后重复;你若能读完上述 2~3 个入口,就已经比「只看一张 mermaid」多走了一层架构。
3 资料分级:S0 / D1 / D2 / D3(全系列引用约定)
读开源项目时,最大的噪音来自「博客写完了,但与仓库真实行为不一致」。本系列约定如下档级(与系列规划文档一致):
| 档级 | 含义 | 使用方式 |
|---|---|---|
| S0 | 你本地clone的某一固定 commit上的源码与测试 | 最终裁判:行为以代码为准 |
| D1 | 仓库内docs/Markdown | 与 S0 对照;版本与源码同步演进 |
| D2 | 官方文档站(如 clawdocs.org、docs.openclaw.ai) | 快速建立概念;若与 D1/S0 冲突,以S0+D1为准并在文中说明 |
| D3 | 第三方博客、商业托管站点的「架构解读」类文章 | 叙事与场景可参考;数字、API、能力列表需回 D1/S0 复核 |
💡理解要点:D1/D2/D3 是「资料来源类型」;「第2篇、第8篇」是本系列博客的列表序号,二者不要混读成「D2 等于第2篇」之类。
4 如何读 OpenClaw 源码
4.1 固定 commit(全系列同一 SHA)
main分支会持续合并,若每篇文章引用不同时间点的路径与符号,读者复制链接会对不上。建议:
git clone https://github.com/openclaw/openclaw.git到本地任意目录。- 在本系列开写时执行一次
git rev-parse HEAD,记下40 位 SHA。 - 全系列正文里引用该仓库时,优先使用
https://github.com/openclaw/openclaw/blob/<SHA>/路径;或在篇首写明「以下路径均相对于仓库根目录,commit =<SHA>」。
🔍实际例子:你在 2026-04-11 拉取得到abc1234...,则全系列 15 篇都写「基于abc1234...」;若第12篇写作时上游大改,可**新开一段「自本篇起更新 pin」**而不是悄悄混用。
4.2 CLI、Gateway 与src/一级目录
仓库根目录的package.json、工作区配置(如pnpm-workspace.yaml,若存在)帮助你理解包边界;与 Gateway 强相关的 CLI 行为通常可从src/cli/与仓库内docs/cli/gateway.md对齐认知。
规划文档中归纳的src/一级目录线索(用于第一篇建立「地图感」,具体文件仍以你 pin 的 commit 为准):agents、bindings、channels、chat、cli、commands、bootstrap、auto-reply等。后续篇会各自把子图放大。
4.3 先「搜」再「读」:缩小范围
OpenClaw 仓库体量大,不适合从某个入口文件按顺序硬读到底。更省力的做法是:先有一个具体问题(或报错栈里的符号名),用关键词在目录里搜一遍,只看命中文件与行号,再顺着import/ 调用关系往下追。
终端:安装 ripgrep 后,在克隆下来的仓库根目录执行rg(与grep类似,常用在src/下搜)。示例(引号内|表示「或」):
rg"gateway|WebSocket|daemon"src rg"route|dispatch|incoming"src rg"sandbox|shell|exec"src extensionsVS Code / Cursor:Ctrl + Shift + F(Mac 上多为Cmd + Shift + F)打开在文件中查找,在「要包含的文件」里限制./src等即可;需要跟调用链时用F12转到定义、Shift + F12查看引用`。更多用法见各自主文档与键盘快捷方式设置。
💡理解要点:只记一条主路径——搜 → 打开命中处 → 用定义/引用跟链;其余自行扩展即可。
4.4 用测试当文档
若某行为在 D2 上描述含糊,优先搜*.test.ts/*.spec.ts中与该行为相关的用例名——测试通常给出了最小可复现的输入输出假设,比注释更不容易过期。
5 全系列 15 篇:目录与阅读顺序
| # | 主题 | 说明与链接 |
|---|---|---|
| 1 | 系列导读 | 即本文。术语与官方组件表对齐、S0/D1/D2/D3 资料分级、pin commit、rg与 VS Code 全局搜索、全系列路线图。 |
| 2 | Skills 机制 | SKILL.md目录发现、<available_skills>提示拼装、会话快照与 watcher、ClawHub 与.clawhub/lock.json、Built-in / Skills / Plugins 分层与源码走读。 |
| 3 | Gateway | 单进程控制面:WebSocket、守护与健康、鉴权与设备发现;与docs/gateway/*、src/cli/对照读源码。03_OpenClaw_Gateway.md |
| 4 | Router | 入站事件如何分发:是否进入 Brain、是否走 Skill、是否允许直回;与官方 Data flow 第2步对齐。 |
| 5 | Brain | 多厂商 LLM、消息拼装、工具调用循环、上下文压缩(compaction)与docs/concepts/context-engine.md等。 |
| 6 | Hands | Shell、文件、浏览器执行面;沙箱与权限边界;docs/tools/multi-agent-sandbox-tools.md与多 Agent 场景。 |
| 7 | Memory 子系统 | 持久化 I/O、flush、与内置 memory 文档;与第8篇分工:本篇偏实现与载体,第8篇偏八类人格文件的语义与自修改。 |
| 8 | Learning & Adaptation | SOUL / AGENTS / MEMORY 等八文件、软学习范式、与 LangGraph 示例对照。 |
| 9 | Channels | IM 等通道如何接入 Gateway;src/channels/与extensions/*分工;为第10篇 bindings 路由做铺垫。 |
| 10 | 多 Agent 核心 | agents.list、每 Agent workspace / state / session、bindings匹配规则与默认 Agent。 |
| 11 | 子 Agent | sessions_spawn父子关系、官方文档所述「隔离、主要向父汇报」边界;与「对等协作」差异。 |
| 12 | Agent Teams RFC | RFC: Agent Teams 导读:原生编排 vs 外部工作流引擎、上下文序列化与延迟取舍。 |
| 13 | Heartbeat | 周期唤醒、与 Router/Brain 触发关系;docs/gateway/heartbeat.md与 cron 对照。 |
| 14 | 安全与成本 | 多 Agent 攻击面、OPENCLAW_HOME强隔离、沙箱与按 Agent 选模型;Cost Management 等。 |
| 15 | 生态编排 | Mission Control、Antfarm 等社区编排与 Gateway API 的关系;对照第12篇,收束「内核保证什么、生态补什么」。 |
6 参考文献与链接
- OpenClaw 主仓库:https://github.com/openclaw/openclaw
- Architecture Overview(D2,含 Component Summary / Design Principles / Data flow):http://clawdocs.org/architecture/overview
- Multi-Agent Workflows(D2):http://clawdocs.org/guides/multi-agent
- 仓库内 Gateway 与概念文档(D1):docs/gateway/index.md、context.md、features.md、multi-agent.md
- 第三方架构叙事(D3,需与 D1/S0 交叉验证):OpenClaw Architecture: 3 Concepts(getclaw.sh);How OpenClaw Works(managemyclaw.com)