Files
openclaw-notes/architecture-overview.md
T

163 lines
7.1 KiB
Markdown

# OpenClaw 整体架构设计
> 本文是对 OpenClaw 代码库的架构梳理笔记(基于 2026.6.2 版本源码与 `docs/concepts/architecture.md`、根 `AGENTS.md`),
> 从三个视角描述系统:运行时拓扑、代码分层、消息流转。
## 1. 运行时拓扑:单 Gateway 控制平面
整个系统的核心是一个**单实例、长驻的 Gateway 守护进程**(每台主机一个,默认绑定 `127.0.0.1:18789`,
由 launchd/systemd 托管)。它是唯一的控制平面:所有消息渠道连接、所有控制面客户端、所有设备节点都汇聚到这里。
```mermaid
flowchart TB
subgraph Channels["消息渠道(用户在这里说话)"]
WA[WhatsApp<br/>Baileys]
TG[Telegram<br/>grammY]
DC[Discord / Slack /<br/>Signal / iMessage / 微信...]
WC[WebChat]
end
subgraph GW["Gateway 守护进程(单实例,launchd/systemd 托管)"]
WS[WebSocket 服务<br/>typed req/res + event,JSON Schema 校验]
RT[路由层<br/>渠道/账号/对端 → agent]
AG[Agent 运行时<br/>会话、队列、工具调用循环]
CRON[Cron / Webhook<br/>自动化触发]
CANVAS["Canvas Host<br/>/__openclaw__/canvas + a2ui"]
DB[(SQLite 状态库<br/>state/openclaw.sqlite<br/>+ 每 agent 独立库)]
end
subgraph Clients["控制面客户端(role: client)"]
CLI[openclaw CLI]
MAC[macOS 菜单栏 App]
WIN[Windows Hub]
ADMIN[Web 管理 UI]
end
subgraph Nodes["设备节点(role: node,设备配对)"]
IOS[iOS 节点<br/>语音唤醒/Canvas]
AND[Android 节点<br/>相机/录屏/语音]
end
subgraph LLM["模型提供商"]
P1[Anthropic / OpenAI /<br/>Gemini / 本地模型...]
end
Channels <--> RT
RT --> AG
AG <--> P1
AG --> DB
Clients <-->|WebSocket| WS
Nodes <-->|WebSocket| WS
WS --> AG
CRON --> AG
AG --> CANVAS
```
### 协议关键不变量
- 每台主机只有一个 Gateway,它是唯一打开 WhatsApp(Baileys)会话的进程。
- WebSocket 握手第一帧必须是 `connect`,否则硬关闭连接。
- 所有客户端(操作端 + 节点)在 `connect` 时携带设备身份,新设备需配对审批
(签名 challenge nonce + 签发设备 token);本机回环连接可自动批准,非本地连接必须显式审批。
- 副作用方法(`send``agent`)要求幂等键,服务端维护短期去重缓存。
- 事件不重放;客户端检测到序号断档后需主动刷新快照。
## 2. 代码分层:核心与插件的边界
这是根 `AGENTS.md` 中最强调的设计约束:**core 保持 plugin-agnostic**,
插件只能通过 `openclaw/plugin-sdk/*` 公开门面进入核心,禁止反向或越界 import。
```mermaid
flowchart LR
subgraph Repo["pnpm workspace 单仓"]
subgraph Core["核心 src/(发布进 dist)"]
GWY[gateway/<br/>WS 服务与协议方法]
CHN[channels/<br/>渠道传输实现]
AGS[agents/<br/>agent 循环/工具/会话]
SKL[skills/ cron/ memory/<br/>media/ tts/ ...]
CFG[config/ state/<br/>canonical 配置 + SQLite]
SDK[plugin-sdk/<br/>唯一对外门面 barrel]
end
subgraph Ext["extensions/(插件,对外叫 plugins)"]
E1[telegram / discord /<br/>slack / whatsapp ...]
E2[codex / copilot /<br/>bedrock / vertex ...<br/>模型提供商]
E3[memory-lancedb /<br/>voice-call / ...]
end
PKG[packages/*<br/>gateway-protocol, llm-core,<br/>agent-core, sdk ...]
UI[ui/ — Control UI]
APPS[apps/ — macOS/iOS/Android]
DOCS[docs/ → docs.openclaw.ai]
end
Ext -->|"仅允许 import<br/>openclaw/plugin-sdk/*"| SDK
SDK --> Core
Core --> PKG
Core -.->|"禁止 import 插件内部<br/>(只走 manifest/registry)"| Ext
APPS -->|"Swift 模型由<br/>JSON Schema 生成"| PKG
```
### 边界规则(核心设计哲学)
- **插件 → 核心**:只能走 `openclaw/plugin-sdk/*`、manifest 元数据、注入的 runtime helper、
文档化的 barrel(`api.ts``runtime-api.ts`);禁止 import 核心 `src/**` 或其他插件内部。
- **核心 → 插件**:核心代码中不允许出现任何具体插件的 id/默认值/策略,
只通过 manifest/registry/capability 这类通用契约发现插件。
- **渠道是纯传输层**:只负责渲染可移植的 presentation/action、执行传输限制、映射原生回调封套;
产品命令树、provider 策略、功能菜单归核心/owner 插件所有。
- **提供商插件**拥有自己的 auth/catalog/runtime hooks;核心只拥有通用 agent 循环。
- **状态只进 SQLite**(Kysely 访问,禁止裸 SQL 字符串,DDL/迁移除外):
全局状态在 `state/openclaw.sqlite`,agent 级状态在 `agents/<agentId>/agent/openclaw-agent.sqlite`
旧文件格式只在 `openclaw doctor --fix` 迁移代码中处理,运行时无兼容分支、无 fallback 读取。
- **配置只有 canonical 形态**:运行时只读当前配置形态;旧配置由 doctor 迁移,不做静默兼容。
- **协议链**:TypeBox schema → 生成 JSON Schema → 生成 Swift 模型;
协议变更必须先做加法兼容,不兼容变更需要版本化 + 文档 + 客户端跟进。
## 3. 一条消息的生命周期
```mermaid
sequenceDiagram
participant U as 用户(Telegram 等)
participant CH as 渠道插件<br/>(transport-only)
participant GW as Gateway
participant RT as 路由
participant A as Agent 会话
participant LLM as 模型提供商
U->>CH: 发消息
CH->>GW: 标准化入站 envelope
GW->>RT: 渠道/账号/对端匹配
Note over RT: DM 配对检查:陌生人<br/>收到 pairing code,消息不处理
RT->>A: 投递到目标 agent 会话(队列)
A->>A: 组装 prompt:系统提示 + skills<br/>快照 + 记忆 + 会话历史
loop Agent 循环
A->>LLM: completion 请求
LLM-->>A: 文本 / 工具调用
A->>A: 执行工具(浏览器/bash/canvas...<br/>非 main 会话可进沙箱)
end
A->>GW: 回复 payload(分块/媒体处理)
GW->>CH: 映射为渠道原生格式
CH->>U: 回复送达
GW-->>GW: 会话/状态写入 SQLite,<br/>事件推送给 WS 订阅者
```
### 安全模型要点
- 入站 DM 默认视为**不可信输入**:主流渠道默认 `dmPolicy="pairing"`,
陌生发送者只收到配对码,消息不进 agent;公开 DM 需要显式 `dmPolicy="open"` + 通配 allowlist。
- `main` 会话默认在宿主机直接执行工具(单用户场景);群组/多人场景可配
`agents.defaults.sandbox.mode: "non-main"`,非 main 会话进 Docker/SSH/OpenShell 沙箱,
并按工具族 allow/deny。
- 第三方 skill 视为不可信代码:安装走 ClawHub 信任信封 + 安全扫描,
可配 `security.installPolicy` 本地策略命令,失败即拒绝(fail-closed)。
## 一句话总结
OpenClaw = **"一个本地 Gateway 进程 + 插件化的渠道/提供商生态 + 通用 agent 循环"**。
所有外部世界(聊天软件、设备、模型 API)都被插件适配成统一契约,
核心只做路由、会话、工具循环和状态管理;
客户端和设备节点统一走带配对认证的 WebSocket 协议接入。
完整官方文档:<https://docs.openclaw.ai/concepts/architecture>