docs(architecture): 添加 OpenClaw 系统架构全景图解
- 新增 15 个 Mermaid 架构图解文件,涵盖系统核心组件 - 添加系统架构全景图,展示外部消息平台到 LLM 提供商的完整流程 - 新增网关层、通道管理、路由层、ACP 协议层、Agent 运行时等模块架构图 - 添加记忆系统、心跳系统、插件系统、安全架构等专项设计图 - 新增消息流转序列图和启动流程图 - 添加容器化部署架构和数据存储结构图 - 配置 Mermaid 图表样式,统一科技感视觉主题 - 添加完整的系统设计模式思维导图 - 新增 456 行深度架构分析文章,覆盖六大核心子系统
95
articles/002/diagram-01.mmd
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
graph TB
|
||||||
|
subgraph "外部消息平台"
|
||||||
|
TG[Telegram]
|
||||||
|
SL[Slack]
|
||||||
|
DC[Discord]
|
||||||
|
WA[WhatsApp]
|
||||||
|
SG[Signal]
|
||||||
|
FS[飞书]
|
||||||
|
MORE[30+ 其他平台...]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "OpenClaw 核心运行时"
|
||||||
|
subgraph "Gateway 网关层"
|
||||||
|
WS[WebSocket Server<br/>端口 18789]
|
||||||
|
AUTH[认证中间件<br/>Ed25519 设备身份]
|
||||||
|
PROTO[协议处理器<br/>AJV Schema 校验]
|
||||||
|
RL[速率限制]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "通道管理"
|
||||||
|
CM[Channel Manager]
|
||||||
|
CP1[Telegram Plugin]
|
||||||
|
CP2[Slack Plugin]
|
||||||
|
CP3[Discord Plugin]
|
||||||
|
CPN[... N 个通道插件]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "路由层"
|
||||||
|
RT[Route Resolver<br/>消息 → Agent 映射]
|
||||||
|
SK[Session Key Parser<br/>会话键解析]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "ACP 协议层"
|
||||||
|
ACP_SVR[ACP Server]
|
||||||
|
ACP_TR[ACP Translator<br/>协议翻译器]
|
||||||
|
ACP_SM[ACP Session Manager<br/>会话管理器 + Actor 队列]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "Agent 运行时"
|
||||||
|
PI[Pi Agent Runner<br/>LLM 推理引擎]
|
||||||
|
TC[Tool Catalog<br/>工具注册表]
|
||||||
|
SKL[Skills System<br/>技能加载器]
|
||||||
|
SA[Subagent Registry<br/>子 Agent 注册]
|
||||||
|
AP[Auth Profiles<br/>模型凭证管理]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "记忆系统"
|
||||||
|
MM[Memory Index Manager]
|
||||||
|
VEC[向量检索<br/>sqlite-vec]
|
||||||
|
FTS[全文搜索<br/>SQLite FTS5]
|
||||||
|
EMB[Embedding Providers<br/>OpenAI/Gemini/Voyage/Ollama]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "心跳系统"
|
||||||
|
HB[Heartbeat Runner<br/>定时唤醒]
|
||||||
|
HMD[HEARTBEAT.md<br/>任务配置文件]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "存储层"
|
||||||
|
SS[Session Store<br/>JSON/JSONL 文件]
|
||||||
|
CF[Config Store<br/>config.json]
|
||||||
|
DI[Device Identity<br/>密钥对存储]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "LLM 提供商"
|
||||||
|
CLAUDE[Claude / Anthropic]
|
||||||
|
GPT[GPT / OpenAI]
|
||||||
|
GEM[Gemini / Google]
|
||||||
|
QWEN[Qwen / 通义]
|
||||||
|
OL[Ollama 本地模型]
|
||||||
|
MORE_LLM[Grok/Groq/Azure/...]
|
||||||
|
end
|
||||||
|
|
||||||
|
TG & SL & DC & WA & SG & FS & MORE --> CM
|
||||||
|
CM --> CP1 & CP2 & CP3 & CPN
|
||||||
|
CP1 & CP2 & CP3 & CPN --> RT
|
||||||
|
RT --> SK --> ACP_SM
|
||||||
|
WS --> AUTH --> PROTO --> ACP_SVR
|
||||||
|
ACP_SVR --> ACP_TR --> ACP_SM
|
||||||
|
ACP_SM --> PI
|
||||||
|
PI --> TC & SKL & SA
|
||||||
|
PI --> MM
|
||||||
|
MM --> VEC & FTS
|
||||||
|
VEC & FTS --> EMB
|
||||||
|
PI --> AP --> CLAUDE & GPT & GEM & QWEN & OL & MORE_LLM
|
||||||
|
PI --> SS
|
||||||
|
HB --> HMD --> PI
|
||||||
|
ACP_SM --> SS
|
||||||
|
|
||||||
|
style WS fill:#4A90D9,color:#fff
|
||||||
|
style PI fill:#E74C3C,color:#fff
|
||||||
|
style MM fill:#27AE60,color:#fff
|
||||||
|
style HB fill:#F39C12,color:#fff
|
||||||
|
style CM fill:#8E44AD,color:#fff
|
||||||
BIN
articles/002/diagram-01.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
articles/002/diagram-02-test.png
Normal file
|
After Width: | Height: | Size: 538 KiB |
21
articles/002/diagram-02.mmd
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
sequenceDiagram
|
||||||
|
participant Client as 客户端/CLI
|
||||||
|
participant GW as Gateway Server
|
||||||
|
participant Auth as 认证中间件
|
||||||
|
participant Proto as 协议处理器
|
||||||
|
participant CM as Channel Manager
|
||||||
|
participant RT as Route Resolver
|
||||||
|
|
||||||
|
Client->>GW: WebSocket 连接 (ws://localhost:18789)
|
||||||
|
GW->>Auth: 设备认证 (Ed25519 签名)
|
||||||
|
Auth-->>GW: 认证通过 + 设备 Token
|
||||||
|
GW->>Proto: Hello 握手 (PROTOCOL_VERSION)
|
||||||
|
Proto-->>Client: HelloOk (capabilities, scopes)
|
||||||
|
|
||||||
|
Note over Client,RT: 消息流
|
||||||
|
|
||||||
|
Client->>GW: RequestFrame: chat.send
|
||||||
|
GW->>Proto: AJV Schema 校验
|
||||||
|
Proto->>RT: 路由解析 (channel + peer → agent)
|
||||||
|
RT-->>GW: sessionKey + agentId
|
||||||
|
GW->>CM: 分发到对应通道
|
||||||
BIN
articles/002/diagram-02.png
Normal file
|
After Width: | Height: | Size: 538 KiB |
11
articles/002/diagram-03.mmd
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
graph LR
|
||||||
|
A[加载配置] --> B[校验认证配置]
|
||||||
|
B --> C[初始化 Secrets]
|
||||||
|
C --> D[加载插件]
|
||||||
|
D --> E[创建 Channel Manager]
|
||||||
|
E --> F[初始化 Memory Manager]
|
||||||
|
F --> G[启动 Heartbeat Runner]
|
||||||
|
G --> H[启动 WebSocket Server]
|
||||||
|
H --> I[挂载协议处理器]
|
||||||
|
I --> J[启动 Sidecars<br/>发现/健康监控/Cron]
|
||||||
|
J --> K[✅ Ready]
|
||||||
BIN
articles/002/diagram-03.png
Normal file
|
After Width: | Height: | Size: 221 KiB |
19
articles/002/diagram-04.mmd
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
graph TB
|
||||||
|
subgraph "ACP 协议栈"
|
||||||
|
EXT[外部 ACP 客户端<br/>stdin/stdout]
|
||||||
|
CONN[AgentSideConnection<br/>ndJSON 流]
|
||||||
|
AGENT[AcpGatewayAgent<br/>协议翻译器]
|
||||||
|
CLIENT[GatewayClient<br/>WebSocket]
|
||||||
|
MGR[AcpSessionManager<br/>会话管理单例]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "运行时缓存"
|
||||||
|
CACHE[RuntimeCache<br/>sessionKey → Handle]
|
||||||
|
QUEUE[ActorQueue<br/>每会话串行化]
|
||||||
|
EVICT[空闲驱逐<br/>TTL 超时清理]
|
||||||
|
end
|
||||||
|
|
||||||
|
EXT --> CONN --> AGENT --> CLIENT
|
||||||
|
AGENT --> MGR
|
||||||
|
MGR --> CACHE & QUEUE
|
||||||
|
CACHE --> EVICT
|
||||||
BIN
articles/002/diagram-04.png
Normal file
|
After Width: | Height: | Size: 393 KiB |
48
articles/002/diagram-05.mmd
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
graph TB
|
||||||
|
subgraph "Agent 运行时"
|
||||||
|
PI[Pi Agent Runner<br/>核心推理引擎]
|
||||||
|
|
||||||
|
subgraph "模型集成"
|
||||||
|
MC[Model Catalog<br/>模型目录]
|
||||||
|
AP[Auth Profiles<br/>凭证管理]
|
||||||
|
FB[Fallback Chains<br/>模型降级链]
|
||||||
|
TH[Thinking Mode<br/>思考/推理模式]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "工具系统"
|
||||||
|
TC[Tool Catalog]
|
||||||
|
T1[web_search 网络搜索]
|
||||||
|
T2[browser_tool 浏览器]
|
||||||
|
T3[system.run 终端执行]
|
||||||
|
T4[system.spawn_acp 子Agent]
|
||||||
|
T5[channel actions 通道操作]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "技能系统"
|
||||||
|
SL[Skill Loader<br/>jiti 动态导入]
|
||||||
|
SF[skill.json 元数据]
|
||||||
|
SH[skill.ts 运行时处理器]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "子 Agent"
|
||||||
|
SR[Subagent Registry]
|
||||||
|
SP[Spawn ACP<br/>隔离会话派生]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
PI --> MC --> AP --> FB
|
||||||
|
PI --> TC --> T1 & T2 & T3 & T4 & T5
|
||||||
|
PI --> SL --> SF & SH
|
||||||
|
PI --> SR --> SP
|
||||||
|
MC --> TH
|
||||||
|
|
||||||
|
subgraph "LLM 提供商"
|
||||||
|
L1[Anthropic Claude]
|
||||||
|
L2[OpenAI GPT]
|
||||||
|
L3[Google Gemini]
|
||||||
|
L4[Qwen 通义千问]
|
||||||
|
L5[Ollama 本地]
|
||||||
|
L6[Groq / Grok / Azure / Minimax / 火山引擎]
|
||||||
|
end
|
||||||
|
|
||||||
|
FB --> L1 & L2 & L3 & L4 & L5 & L6
|
||||||
BIN
articles/002/diagram-05.png
Normal file
|
After Width: | Height: | Size: 766 KiB |
16
articles/002/diagram-06.mmd
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
sequenceDiagram
|
||||||
|
participant Agent as Agent Runtime
|
||||||
|
participant EA as ExecApprovalManager
|
||||||
|
participant Admin as 管理员
|
||||||
|
participant CMD as 命令执行
|
||||||
|
|
||||||
|
Agent->>EA: system.run("rm -rf /tmp/data")
|
||||||
|
EA->>EA: 检查是否为危险操作
|
||||||
|
EA->>Admin: 显示审批请求
|
||||||
|
Admin-->>EA: ✅ 批准 / ❌ 拒绝
|
||||||
|
alt 批准
|
||||||
|
EA->>CMD: 执行命令
|
||||||
|
CMD-->>Agent: 返回结果
|
||||||
|
else 拒绝
|
||||||
|
EA-->>Agent: 操作被拒绝
|
||||||
|
end
|
||||||
BIN
articles/002/diagram-06.png
Normal file
|
After Width: | Height: | Size: 336 KiB |
19
articles/002/diagram-07.mmd
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
graph TB
|
||||||
|
subgraph "插件生命周期"
|
||||||
|
D[1. Discovery 发现<br/>扫描 extensions/ 目录]
|
||||||
|
M[2. Manifest 加载<br/>读取 openclaw.plugin.json]
|
||||||
|
R[3. Runtime 创建<br/>初始化 Hook Runner]
|
||||||
|
REG[4. Registration 注册<br/>setActivePluginRegistry]
|
||||||
|
end
|
||||||
|
|
||||||
|
D --> M --> R --> REG
|
||||||
|
|
||||||
|
subgraph "插件类型"
|
||||||
|
CH[通道插件 ×34<br/>Telegram/Slack/Discord/...]
|
||||||
|
MEM[记忆插件<br/>memory-core / memory-lancedb]
|
||||||
|
AUTH_P[认证插件<br/>google-gemini-cli-auth 等]
|
||||||
|
DIAG[诊断插件<br/>diagnostics-otel]
|
||||||
|
SPEC[特殊插件<br/>thread-ownership / llm-task]
|
||||||
|
end
|
||||||
|
|
||||||
|
REG --> CH & MEM & AUTH_P & DIAG & SPEC
|
||||||
BIN
articles/002/diagram-07.png
Normal file
|
After Width: | Height: | Size: 510 KiB |
39
articles/002/diagram-08.mmd
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
graph TB
|
||||||
|
subgraph "记忆系统架构"
|
||||||
|
Q[搜索查询]
|
||||||
|
|
||||||
|
subgraph "混合搜索引擎"
|
||||||
|
VS[向量检索<br/>sqlite-vec]
|
||||||
|
BM[BM25 全文搜索<br/>SQLite FTS5]
|
||||||
|
HY[混合排序<br/>加权合并 + 时间衰减]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "Embedding 提供商"
|
||||||
|
E1[OpenAI<br/>text-embedding-3-small/large]
|
||||||
|
E2[Gemini<br/>Generalist Multimodal]
|
||||||
|
E3[Voyage<br/>voyage-large-2-instruct]
|
||||||
|
E4[Mistral<br/>mistral-embed]
|
||||||
|
E5[Ollama<br/>本地模型]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "存储层"
|
||||||
|
DB[(SQLite 数据库)]
|
||||||
|
CV[chunks_vec 表<br/>向量嵌入]
|
||||||
|
CF[chunks_fts 表<br/>FTS5 全文索引]
|
||||||
|
EC[embedding_cache 表<br/>查询缓存 + TTL]
|
||||||
|
end
|
||||||
|
|
||||||
|
RES[搜索结果<br/>相关度排序]
|
||||||
|
end
|
||||||
|
|
||||||
|
Q --> VS & BM
|
||||||
|
VS --> HY
|
||||||
|
BM --> HY
|
||||||
|
VS --> E1 & E2 & E3 & E4 & E5
|
||||||
|
E1 & E2 & E3 & E4 & E5 --> CV
|
||||||
|
BM --> CF
|
||||||
|
HY --> RES
|
||||||
|
DB --> CV & CF & EC
|
||||||
|
|
||||||
|
style HY fill:#27AE60,color:#fff
|
||||||
|
style DB fill:#3498DB,color:#fff
|
||||||
BIN
articles/002/diagram-08.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
25
articles/002/diagram-09.mmd
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
sequenceDiagram
|
||||||
|
participant Timer as 定时器 (默认 30 分钟)
|
||||||
|
participant HB as Heartbeat Runner
|
||||||
|
participant FS as 文件系统
|
||||||
|
participant Agent as Agent Runtime
|
||||||
|
participant LLM as LLM 提供商
|
||||||
|
participant Channel as 消息通道
|
||||||
|
|
||||||
|
loop 每 30 分钟
|
||||||
|
Timer->>HB: 触发心跳
|
||||||
|
HB->>FS: 读取 HEARTBEAT.md
|
||||||
|
alt HEARTBEAT.md 为空或不存在
|
||||||
|
HB->>HB: 跳过,不调用 API
|
||||||
|
else HEARTBEAT.md 有任务内容
|
||||||
|
HB->>Agent: 发送 HEARTBEAT_PROMPT
|
||||||
|
Agent->>LLM: 推理 + 任务执行
|
||||||
|
LLM-->>Agent: 执行结果
|
||||||
|
alt 返回 HEARTBEAT_OK
|
||||||
|
Agent-->>HB: 无需操作,静默
|
||||||
|
else 有实际输出
|
||||||
|
Agent->>Channel: 发送结果到通道
|
||||||
|
Channel-->>HB: 显示 ACK 反应 (👀)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
BIN
articles/002/diagram-09.png
Normal file
|
After Width: | Height: | Size: 595 KiB |
45
articles/002/diagram-10.mmd
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
graph TB
|
||||||
|
subgraph "① 消息接收"
|
||||||
|
MSG[用户消息<br/>Telegram/Slack/...]
|
||||||
|
SDK[平台 SDK<br/>原生协议接收]
|
||||||
|
NORM[消息标准化<br/>统一格式]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "② 路由决策"
|
||||||
|
RT[Route Resolver<br/>channel + peer → agentId]
|
||||||
|
BIND[Session Binding<br/>会话绑定服务]
|
||||||
|
SK[Session Key<br/>生成会话键]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "③ 会话管理"
|
||||||
|
ACP[ACP Session Manager]
|
||||||
|
LOCK[Session Write Lock<br/>防并发写入]
|
||||||
|
LOAD[加载会话历史<br/>JSONL 转录]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "④ Agent 推理"
|
||||||
|
PI[Pi Agent Runner]
|
||||||
|
LLM[LLM API 调用<br/>含 Thinking Mode]
|
||||||
|
TOOL[工具调用<br/>审批 → 执行]
|
||||||
|
MEM[记忆检索<br/>混合搜索]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "⑤ 响应投递"
|
||||||
|
STREAM[流式响应<br/>逐 Token 返回]
|
||||||
|
TRANS[格式转换<br/>适配目标平台]
|
||||||
|
DELIVER[投递到通道<br/>支持线程/回复]
|
||||||
|
PERSIST[持久化<br/>会话 + 记忆写入]
|
||||||
|
end
|
||||||
|
|
||||||
|
MSG --> SDK --> NORM
|
||||||
|
NORM --> RT --> BIND --> SK
|
||||||
|
SK --> ACP --> LOCK --> LOAD
|
||||||
|
LOAD --> PI --> LLM
|
||||||
|
LLM --> TOOL
|
||||||
|
TOOL --> MEM
|
||||||
|
LLM --> STREAM --> TRANS --> DELIVER
|
||||||
|
DELIVER --> PERSIST
|
||||||
|
|
||||||
|
style MSG fill:#9B59B6,color:#fff
|
||||||
|
style PI fill:#E74C3C,color:#fff
|
||||||
|
style DELIVER fill:#2ECC71,color:#fff
|
||||||
BIN
articles/002/diagram-10.png
Normal file
|
After Width: | Height: | Size: 800 KiB |
27
articles/002/diagram-11.mmd
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
graph LR
|
||||||
|
subgraph "~/.openclaw/ 存储结构"
|
||||||
|
subgraph "设备层"
|
||||||
|
DI[device-identity.json<br/>Ed25519 密钥对]
|
||||||
|
CRED[credentials/<br/>设备 Token]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "配置层"
|
||||||
|
CONFIG[config.json<br/>全局配置]
|
||||||
|
SECRETS[secrets/<br/>API Key 引用]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "Agent 层 (per-agent)"
|
||||||
|
subgraph "agents/main/"
|
||||||
|
SESS[sessions.json<br/>会话元数据]
|
||||||
|
TRANS[sessions/*.jsonl<br/>会话转录]
|
||||||
|
WS[workspace/<br/>工作区文件]
|
||||||
|
HMD2[HEARTBEAT.md]
|
||||||
|
MEMDB[memory.sqlite<br/>向量+全文索引]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
style DI fill:#E67E22,color:#fff
|
||||||
|
style CONFIG fill:#3498DB,color:#fff
|
||||||
|
style SESS fill:#2ECC71,color:#fff
|
||||||
|
style MEMDB fill:#9B59B6,color:#fff
|
||||||
BIN
articles/002/diagram-11.png
Normal file
|
After Width: | Height: | Size: 505 KiB |
33
articles/002/diagram-12.mmd
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
graph TB
|
||||||
|
subgraph "安全层级"
|
||||||
|
subgraph "L1: 网络层"
|
||||||
|
TLS[TLS/mTLS 加密]
|
||||||
|
FP[证书指纹验证]
|
||||||
|
CWE[CWE-319 防护<br/>禁止明文WS到非回环]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "L2: 认证层"
|
||||||
|
DEV[设备认证<br/>Ed25519 签名]
|
||||||
|
TOKEN[设备 Token<br/>长期访问令牌]
|
||||||
|
OAUTH[OAuth 集成<br/>Google/Discord 等]
|
||||||
|
PWD[密码认证<br/>本地网关备选]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "L3: 授权层"
|
||||||
|
SCOPE[操作域 Scopes]
|
||||||
|
PAIR[设备配对审批]
|
||||||
|
ROLE[Owner vs User 角色]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "L4: 执行层"
|
||||||
|
APPROVE[工具审批门<br/>危险操作拦截]
|
||||||
|
SANDBOX[沙箱策略<br/>inherit/require/forbidden]
|
||||||
|
AUDIT[审计日志]
|
||||||
|
SCAN[危险工具扫描]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
TLS --> DEV --> SCOPE --> APPROVE
|
||||||
|
FP --> TOKEN --> PAIR --> SANDBOX
|
||||||
|
CWE --> OAUTH --> ROLE --> AUDIT
|
||||||
|
PWD --> SCAN
|
||||||
BIN
articles/002/diagram-12.png
Normal file
|
After Width: | Height: | Size: 620 KiB |
24
articles/002/diagram-13.mmd
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
graph TB
|
||||||
|
subgraph "通道插件架构"
|
||||||
|
IF[ChannelPlugin 接口]
|
||||||
|
|
||||||
|
subgraph "插件实现"
|
||||||
|
TG[Telegram<br/>Bot API]
|
||||||
|
SL[Slack<br/>Bolt SDK]
|
||||||
|
DC[Discord<br/>discord.js]
|
||||||
|
WA[WhatsApp<br/>Baileys]
|
||||||
|
SIG[Signal<br/>signal-cli]
|
||||||
|
FS[飞书<br/>Open API]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "生命周期"
|
||||||
|
INIT[initialize<br/>认证 + 连接]
|
||||||
|
LISTEN[listen<br/>消息监听]
|
||||||
|
ROUTE[route<br/>路由到 Agent]
|
||||||
|
DELIVER[deliver<br/>回传响应]
|
||||||
|
SHUTDOWN[shutdown<br/>优雅断开]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
IF --> TG & SL & DC & WA & SIG & FS
|
||||||
|
TG & SL & DC & WA & SIG & FS --> INIT --> LISTEN --> ROUTE --> DELIVER --> SHUTDOWN
|
||||||
BIN
articles/002/diagram-13.png
Normal file
|
After Width: | Height: | Size: 683 KiB |
24
articles/002/diagram-14.mmd
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
graph TB
|
||||||
|
subgraph "Docker Compose"
|
||||||
|
GW_SVC[gateway 服务<br/>Node.js 运行时]
|
||||||
|
CLI_SVC[cli 服务<br/>命令行交互]
|
||||||
|
HC[健康检查<br/>端口 18789]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "Docker 镜像"
|
||||||
|
BASE[Dockerfile<br/>多阶段构建]
|
||||||
|
SB[Dockerfile.sandbox<br/>沙箱镜像]
|
||||||
|
SBB[Dockerfile.sandbox-browser<br/>浏览器沙箱]
|
||||||
|
SBC[Dockerfile.sandbox-common<br/>公共沙箱基础]
|
||||||
|
end
|
||||||
|
|
||||||
|
subgraph "其他部署"
|
||||||
|
FLY[fly.toml<br/>Fly.io 部署]
|
||||||
|
RENDER[render.yaml<br/>Render 部署]
|
||||||
|
PODMAN[Podman<br/>无 root 容器]
|
||||||
|
end
|
||||||
|
|
||||||
|
GW_SVC --> BASE
|
||||||
|
CLI_SVC --> BASE
|
||||||
|
GW_SVC --> HC
|
||||||
|
BASE --> SB & SBB & SBC
|
||||||
BIN
articles/002/diagram-14.png
Normal file
|
After Width: | Height: | Size: 541 KiB |
BIN
articles/002/diagram-15-test.png
Normal file
|
After Width: | Height: | Size: 188 KiB |
23
articles/002/diagram-15.mmd
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
mindmap
|
||||||
|
root((OpenClaw<br/>设计模式))
|
||||||
|
消息驱动
|
||||||
|
WebSocket 双向通信
|
||||||
|
EventFrame 事件流
|
||||||
|
RequestFrame 请求/响应
|
||||||
|
插件化
|
||||||
|
34 个通道插件
|
||||||
|
Hook 系统 7 个钩子
|
||||||
|
动态加载 jiti
|
||||||
|
会话隔离
|
||||||
|
Actor 队列串行化
|
||||||
|
Session Write Lock
|
||||||
|
Per-agent 存储隔离
|
||||||
|
安全纵深
|
||||||
|
L1 网络加密
|
||||||
|
L2 设备认证
|
||||||
|
L3 域控授权
|
||||||
|
L4 执行审批
|
||||||
|
韧性设计
|
||||||
|
模型降级链
|
||||||
|
连接重试退避
|
||||||
|
嵌入失败恢复
|
||||||
BIN
articles/002/diagram-15.png
Normal file
|
After Width: | Height: | Size: 568 KiB |
37
articles/002/mermaid-config.json
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"theme": "base",
|
||||||
|
"themeVariables": {
|
||||||
|
"primaryColor": "#0d2137",
|
||||||
|
"primaryTextColor": "#e0f7fa",
|
||||||
|
"primaryBorderColor": "#00e5ff",
|
||||||
|
"lineColor": "#00b8d4",
|
||||||
|
"secondaryColor": "#0a1628",
|
||||||
|
"secondaryTextColor": "#b2ebf2",
|
||||||
|
"secondaryBorderColor": "#00bcd4",
|
||||||
|
"tertiaryColor": "#112240",
|
||||||
|
"tertiaryTextColor": "#e0f7fa",
|
||||||
|
"tertiaryBorderColor": "#26c6da",
|
||||||
|
"noteBkgColor": "#0d2137",
|
||||||
|
"noteTextColor": "#e0f7fa",
|
||||||
|
"noteBorderColor": "#00e5ff",
|
||||||
|
"edgeLabelBackground": "#0a1628",
|
||||||
|
"clusterBkg": "#0a1a2e",
|
||||||
|
"clusterBorder": "#1a5276",
|
||||||
|
"titleColor": "#00e5ff",
|
||||||
|
"actorBkg": "#0d2137",
|
||||||
|
"actorBorder": "#00e5ff",
|
||||||
|
"actorTextColor": "#e0f7fa",
|
||||||
|
"actorLineColor": "#00b8d4",
|
||||||
|
"signalColor": "#00e5ff",
|
||||||
|
"signalTextColor": "#e0f7fa",
|
||||||
|
"labelBoxBkgColor": "#0d2137",
|
||||||
|
"labelBoxBorderColor": "#00e5ff",
|
||||||
|
"labelTextColor": "#e0f7fa",
|
||||||
|
"loopTextColor": "#80deea",
|
||||||
|
"activationBorderColor": "#00e5ff",
|
||||||
|
"activationBkgColor": "#112240",
|
||||||
|
"sequenceNumberColor": "#00e5ff",
|
||||||
|
"fontFamily": "SF Pro Display, -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica Neue, Arial, sans-serif",
|
||||||
|
"fontSize": "15px"
|
||||||
|
}
|
||||||
|
}
|
||||||
7
articles/002/mermaid-fix.css
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
.mindmap-node text, .mindmap-node tspan,
|
||||||
|
.node text, .node tspan,
|
||||||
|
.label text, .label tspan,
|
||||||
|
text, tspan {
|
||||||
|
fill: #ffffff !important;
|
||||||
|
color: #ffffff !important;
|
||||||
|
}
|
||||||
44
articles/002/mermaid-mindmap.css
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/* Mindmap sci-fi style - force visible node backgrounds */
|
||||||
|
|
||||||
|
text, tspan {
|
||||||
|
fill: #e0f7fa !important;
|
||||||
|
font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Root node */
|
||||||
|
.mindmap-node:first-of-type circle {
|
||||||
|
fill: #0d2137 !important;
|
||||||
|
stroke: #00e5ff !important;
|
||||||
|
stroke-width: 3px !important;
|
||||||
|
filter: drop-shadow(0 0 12px rgba(0, 229, 255, 0.6)) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All mindmap section/node shapes */
|
||||||
|
.mindmap-node rect,
|
||||||
|
.mindmap-node polygon,
|
||||||
|
.mindmap-node circle,
|
||||||
|
.mindmap-node ellipse,
|
||||||
|
.mindmap-node path {
|
||||||
|
stroke: #00b8d4 !important;
|
||||||
|
stroke-width: 2px !important;
|
||||||
|
filter: drop-shadow(0 0 6px rgba(0, 229, 255, 0.35)) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Force different section colors instead of black */
|
||||||
|
.section-0 rect, .section-0 path { fill: #0d3b66 !important; stroke: #00e5ff !important; }
|
||||||
|
.section-1 rect, .section-1 path { fill: #1a3a4a !important; stroke: #26c6da !important; }
|
||||||
|
.section-2 rect, .section-2 path { fill: #1b3044 !important; stroke: #4dd0e1 !important; }
|
||||||
|
.section-3 rect, .section-3 path { fill: #14293d !important; stroke: #00bcd4 !important; }
|
||||||
|
.section-4 rect, .section-4 path { fill: #0f2b3d !important; stroke: #80deea !important; }
|
||||||
|
|
||||||
|
/* Generic fallback: any rect/path that ends up black */
|
||||||
|
rect[fill="#000"], rect[fill="#000000"], rect[fill="black"],
|
||||||
|
path[fill="#000"], path[fill="#000000"], path[fill="black"] {
|
||||||
|
fill: #0d3b66 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lines between nodes */
|
||||||
|
line, path.edge {
|
||||||
|
stroke: #00b8d4 !important;
|
||||||
|
stroke-width: 2px !important;
|
||||||
|
}
|
||||||
115
articles/002/mermaid-tech.css
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/* Sci-fi / Tech style for mermaid diagrams */
|
||||||
|
|
||||||
|
/* Node styling */
|
||||||
|
.node rect, .node polygon, .node circle, .node ellipse {
|
||||||
|
stroke-width: 2px !important;
|
||||||
|
filter: drop-shadow(0 0 6px rgba(0, 229, 255, 0.4)) !important;
|
||||||
|
rx: 8 !important;
|
||||||
|
ry: 8 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All text white/cyan */
|
||||||
|
text, tspan {
|
||||||
|
fill: #e0f7fa !important;
|
||||||
|
font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cluster/subgraph borders */
|
||||||
|
.cluster rect {
|
||||||
|
stroke: #1a6a8a !important;
|
||||||
|
stroke-width: 2px !important;
|
||||||
|
stroke-dasharray: 6 3 !important;
|
||||||
|
fill: rgba(10, 26, 46, 0.7) !important;
|
||||||
|
rx: 12 !important;
|
||||||
|
ry: 12 !important;
|
||||||
|
filter: drop-shadow(0 0 8px rgba(0, 184, 212, 0.2)) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cluster labels */
|
||||||
|
.cluster text, .cluster tspan {
|
||||||
|
fill: #4dd0e1 !important;
|
||||||
|
font-weight: 600 !important;
|
||||||
|
font-size: 14px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Edge/arrow lines */
|
||||||
|
.edge-pattern-solid, .flowchart-link {
|
||||||
|
stroke: #00b8d4 !important;
|
||||||
|
stroke-width: 2px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Arrow markers */
|
||||||
|
marker path {
|
||||||
|
fill: #00e5ff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sequence diagram lines */
|
||||||
|
.messageLine0, .messageLine1 {
|
||||||
|
stroke: #00b8d4 !important;
|
||||||
|
stroke-width: 2px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sequence diagram actors */
|
||||||
|
.actor {
|
||||||
|
stroke: #00e5ff !important;
|
||||||
|
fill: #0d2137 !important;
|
||||||
|
stroke-width: 2px !important;
|
||||||
|
filter: drop-shadow(0 0 6px rgba(0, 229, 255, 0.3)) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Labels on edges */
|
||||||
|
.edgeLabel rect {
|
||||||
|
fill: #0a1628 !important;
|
||||||
|
opacity: 0.9 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edgeLabel span, .edgeLabel text, .edgeLabel tspan {
|
||||||
|
fill: #80deea !important;
|
||||||
|
color: #80deea !important;
|
||||||
|
font-size: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note boxes */
|
||||||
|
.note {
|
||||||
|
fill: #112240 !important;
|
||||||
|
stroke: #00e5ff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mindmap specific */
|
||||||
|
.mindmap-node rect, .mindmap-node circle, .mindmap-node polygon {
|
||||||
|
filter: drop-shadow(0 0 6px rgba(0, 229, 255, 0.4)) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mindmap-node text, .mindmap-node tspan {
|
||||||
|
fill: #e0f7fa !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Activation bars in sequence diagrams */
|
||||||
|
.activation0, .activation1, .activation2 {
|
||||||
|
fill: #112240 !important;
|
||||||
|
stroke: #00e5ff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop/alt boxes */
|
||||||
|
.loopLine {
|
||||||
|
stroke: #1a6a8a !important;
|
||||||
|
stroke-dasharray: 4 3 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loopText tspan, .loopText text {
|
||||||
|
fill: #4dd0e1 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Label styling */
|
||||||
|
.label text, .label tspan {
|
||||||
|
fill: #e0f7fa !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Highlighted nodes with custom styles from mermaid */
|
||||||
|
[style*="fill:#4A90D9"], [style*="fill:#E74C3C"], [style*="fill:#27AE60"],
|
||||||
|
[style*="fill:#F39C12"], [style*="fill:#8E44AD"], [style*="fill:#9B59B6"],
|
||||||
|
[style*="fill:#2ECC71"], [style*="fill:#3498DB"], [style*="fill:#E67E22"] {
|
||||||
|
filter: drop-shadow(0 0 10px rgba(0, 229, 255, 0.6)) !important;
|
||||||
|
stroke: #00e5ff !important;
|
||||||
|
stroke-width: 2px !important;
|
||||||
|
}
|
||||||
456
articles/给龙虾做了个 CT:43 万行代码的 OpenClaw 架构全拆解.md
Normal file
@ -0,0 +1,456 @@
|
|||||||
|
# 给龙虾做了个 CT:43 万行代码的 OpenClaw 架构全拆解
|
||||||
|
|
||||||
|
> 分析日期:2026-03-11
|
||||||
|
> 源码版本:基于 GitHub 最新主分支
|
||||||
|
> 分析工具:Claude Opus 4.6
|
||||||
|
> 代码规模:约 43 万行 TypeScript,monorepo 架构
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、项目总览
|
||||||
|
|
||||||
|
OpenClaw 是一个**多通道 AI 智能体网关系统**——它不是一个简单的聊天机器人框架,而是一个完整的「AI 员工」运行时平台。其核心能力是:让大语言模型通过多种消息渠道(Slack、Telegram、Discord、WhatsApp 等 30+ 平台)接收指令、自主执行任务、并将结果回传。
|
||||||
|
|
||||||
|
### 1.1 Monorepo 结构
|
||||||
|
|
||||||
|
```
|
||||||
|
openclaw/
|
||||||
|
├── src/ # 核心运行时源码(主体)
|
||||||
|
│ ├── gateway/ # WebSocket 网关服务器
|
||||||
|
│ ├── acp/ # Agent Client Protocol 协议层
|
||||||
|
│ ├── agents/ # Agent 运行时、模型集成、工具系统
|
||||||
|
│ ├── memory/ # 向量检索 + 全文搜索记忆系统
|
||||||
|
│ ├── plugins/ # 插件加载、注册、Hook 执行
|
||||||
|
│ ├── channels/ # 通道管理器
|
||||||
|
│ ├── routing/ # 消息路由与会话键解析
|
||||||
|
│ ├── auto-reply/ # 心跳机制与自动回复
|
||||||
|
│ ├── config/ # 配置加载与会话持久化
|
||||||
|
│ ├── security/ # 安全审计与策略执行
|
||||||
|
│ ├── infra/ # 基础设施(设备身份、TLS、投递)
|
||||||
|
│ ├── cli/ # CLI 命令行界面
|
||||||
|
│ ├── web/ # Web/WhatsApp Webhook 处理
|
||||||
|
│ ├── terminal/ # 终端 TUI 组件
|
||||||
|
│ └── media-understanding/# 多媒体理解(图片/音频)
|
||||||
|
├── extensions/ # 34 个通道/功能插件
|
||||||
|
├── packages/ # 兼容包(clawdbot、moltbot 旧名)
|
||||||
|
├── apps/ # 原生客户端(macOS/iOS/Android)
|
||||||
|
├── ui/ # React Web 管理界面
|
||||||
|
├── skills/ # 内置技能
|
||||||
|
├── docs/ # 文档
|
||||||
|
├── test/ # 测试套件
|
||||||
|
└── vendor/ # 第三方依赖(a2ui 等)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2 技术栈
|
||||||
|
|
||||||
|
| 层面 | 技术选型 |
|
||||||
|
|------|---------|
|
||||||
|
| 语言 | TypeScript (ESM),Node.js 22+ |
|
||||||
|
| 构建 | tsdown (基于 Rolldown) + Vite (UI) |
|
||||||
|
| 包管理 | pnpm workspace (monorepo) |
|
||||||
|
| 协议 | WebSocket + ACP (Agent Client Protocol) |
|
||||||
|
| 存储 | SQLite (sqlite-vec + FTS5) + JSON 文件 |
|
||||||
|
| 验证 | AJV Schema Validation |
|
||||||
|
| 测试 | Vitest + V8 Coverage |
|
||||||
|
| 容器 | Docker / Podman 多阶段构建 |
|
||||||
|
| 桌面 | SwiftUI (macOS) / React Native (移动端) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、核心架构全景
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、六大核心子系统详解
|
||||||
|
|
||||||
|
### 3.1 Gateway(通信网关)
|
||||||
|
|
||||||
|
Gateway 是整个系统的**中枢神经**,负责接收所有外部连接、认证设备、路由消息。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**核心文件:**
|
||||||
|
|
||||||
|
| 文件 | 职责 |
|
||||||
|
|------|------|
|
||||||
|
| `src/gateway/server.impl.ts` | 网关启动入口 `startGatewayServer()` |
|
||||||
|
| `src/gateway/client.ts` | WebSocket 客户端,含重连与退避策略 |
|
||||||
|
| `src/gateway/server-chat.ts` | 聊天消息处理器 |
|
||||||
|
| `src/gateway/protocol/index.ts` | 协议帧定义与 AJV 校验 |
|
||||||
|
| `src/gateway/auth.ts` | 认证中间件 |
|
||||||
|
| `src/gateway/auth-rate-limit.ts` | 速率限制策略 |
|
||||||
|
| `src/gateway/server-channels.ts` | 通道生命周期管理 |
|
||||||
|
|
||||||
|
**Gateway 启动序列:**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**协议帧类型:**
|
||||||
|
|
||||||
|
| 帧类型 | 方向 | 用途 |
|
||||||
|
|--------|------|------|
|
||||||
|
| `RequestFrame` | Client → Server | chat.send, config.get, sessions.list 等 |
|
||||||
|
| `ResponseFrame` | Server → Client | 请求响应数据 |
|
||||||
|
| `EventFrame` | Server → Client | agent_message, tool_call, usage_update 等 |
|
||||||
|
| `HelloOk` | Server → Client | 握手响应,含协议版本和能力声明 |
|
||||||
|
|
||||||
|
**安全特性:**
|
||||||
|
- **CWE-319 防护**:`isSecureWebSocketUrl()` 禁止非回环地址使用明文 `ws://`
|
||||||
|
- **设备身份**:Ed25519 密钥对存储于 `~/.openclaw/credentials/`
|
||||||
|
- **TLS 指纹**:支持证书指纹验证(Certificate Pinning)
|
||||||
|
- **连接序列号**:检测消息间隙,防止重放攻击
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.2 ACP(Agent Client Protocol 协议层)
|
||||||
|
|
||||||
|
ACP 是 OpenClaw 定义的**标准化 Agent 通信协议**,作为 Gateway 与 Agent 运行时之间的翻译层。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**AcpGatewayAgent 核心职责:**
|
||||||
|
- 翻译 ACP 协议 ↔ Gateway 协议
|
||||||
|
- 管理会话生命周期(initialize → prompt → response)
|
||||||
|
- 速率限制(默认 120 请求 / 10 秒窗口)
|
||||||
|
- 追踪待处理的 prompt 和 tool call
|
||||||
|
|
||||||
|
**AcpSessionManager 核心职责:**
|
||||||
|
- 所有 ACP 运行时会话的单例管理器
|
||||||
|
- 运行时缓存(空闲 TTL 驱逐)
|
||||||
|
- 活跃回合与延迟统计
|
||||||
|
- **Actor 队列**:防止对同一会话的并发写入
|
||||||
|
|
||||||
|
**会话键格式:**
|
||||||
|
|
||||||
|
```
|
||||||
|
@main → 默认主会话
|
||||||
|
@jane → 名为 "jane" 的 Agent 会话
|
||||||
|
$subagent-id:child-key → 子 Agent 会话
|
||||||
|
thread:123 → 线程绑定会话
|
||||||
|
acp:uuid → ACP/IDE 会话
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.3 Agent Runtime(Agent 运行时)
|
||||||
|
|
||||||
|
Agent 运行时是系统的**大脑**,负责 LLM 推理、工具调用、子 Agent 调度。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**支持的 LLM 提供商(10+):**
|
||||||
|
|
||||||
|
| 提供商 | 说明 |
|
||||||
|
|--------|------|
|
||||||
|
| Anthropic | Claude Opus / Sonnet / Haiku |
|
||||||
|
| OpenAI | GPT 系列 |
|
||||||
|
| Google | Gemini 系列 |
|
||||||
|
| Qwen | 通义千问(阿里) |
|
||||||
|
| Minimax | 国产大模型 |
|
||||||
|
| Ollama | 本地部署任意开源模型 |
|
||||||
|
| Groq | 高速推理 |
|
||||||
|
| Grok | xAI |
|
||||||
|
| Azure | Azure OpenAI Service |
|
||||||
|
| Volc | 火山引擎(字节) |
|
||||||
|
|
||||||
|
**模型降级链(Fallback Chains):** 当主模型不可用时,自动切换到备用模型,保证服务连续性。
|
||||||
|
|
||||||
|
**工具审批机制:**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.4 Plugin System(插件系统)
|
||||||
|
|
||||||
|
插件系统是 OpenClaw 可扩展性的核心——所有通道集成、记忆后端、诊断工具都以插件形式存在。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**已包含的 34 个通道插件:**
|
||||||
|
|
||||||
|
| 类别 | 插件 |
|
||||||
|
|------|------|
|
||||||
|
| 即时通讯 | Telegram, WhatsApp, Signal, iMessage, Line, Zalo |
|
||||||
|
| 团队协作 | Slack, Discord, MS Teams, Mattermost, Google Chat, 飞书 |
|
||||||
|
| 社交/社区 | Matrix, IRC, Nostr, Twitch, Tlon |
|
||||||
|
| 企业通讯 | Synology Chat, Nextcloud Talk, BlueBubbles |
|
||||||
|
| 语音 | voice-call |
|
||||||
|
| 开发/集成 | acpx, copilot-proxy, lobster |
|
||||||
|
|
||||||
|
**Plugin Runtime API:**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
PluginRuntime = {
|
||||||
|
subagent: {
|
||||||
|
run(), // 运行子 Agent
|
||||||
|
waitForRun(), // 等待运行完成
|
||||||
|
getSessionMessages(),
|
||||||
|
deleteSession()
|
||||||
|
},
|
||||||
|
channel: {
|
||||||
|
list(), // 列出通道
|
||||||
|
inspect(), // 检查通道状态
|
||||||
|
sendMessage() // 发送消息
|
||||||
|
},
|
||||||
|
core: {
|
||||||
|
config, // 全局配置
|
||||||
|
workspaceDir, // 工作区目录
|
||||||
|
agentId // 当前 Agent ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Hook 系统:**
|
||||||
|
|
||||||
|
| Hook | 触发时机 |
|
||||||
|
|------|---------|
|
||||||
|
| `gateway.startup()` | 网关启动时 |
|
||||||
|
| `gateway.shutdown()` | 优雅关闭时 |
|
||||||
|
| `channel.ready()` | 通道连接就绪 |
|
||||||
|
| `channel.message()` | 收到消息时 |
|
||||||
|
| `session.start()` | 会话开始 |
|
||||||
|
| `session.prompt()` | LLM 推理前 |
|
||||||
|
| `session.response()` | LLM 响应后 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.5 Memory System(记忆系统)
|
||||||
|
|
||||||
|
记忆系统实现了**向量检索 + BM25 全文搜索**的混合搜索架构,是 Agent 长期记忆的基础。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**MemoryIndexManager 是单例模式**,每个 Agent + Workspace 一个实例:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 获取或创建记忆管理器
|
||||||
|
const memory = await MemoryIndexManager.get({
|
||||||
|
cfg: config,
|
||||||
|
agentId: "main",
|
||||||
|
purpose: "chat"
|
||||||
|
});
|
||||||
|
|
||||||
|
// 混合搜索
|
||||||
|
const results = await memory.search({
|
||||||
|
query: "用户上周提到的跑步习惯",
|
||||||
|
limit: 10,
|
||||||
|
threshold: 0.7,
|
||||||
|
hybrid: { weight: 0.6 } // 向量权重 60%, BM25 权重 40%
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**关键特性:**
|
||||||
|
- **时间衰减**:近期记忆权重更高
|
||||||
|
- **批量嵌入**:失败自动恢复
|
||||||
|
- **查询缓存**:TTL 控制的 embedding 缓存层
|
||||||
|
- **额外记忆路径**:可引入外部文档目录
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.6 Heartbeat(心跳机制)
|
||||||
|
|
||||||
|
心跳是 OpenClaw 最具争议也最核心的设计——让 AI **主动醒来执行任务**,而不是被动等待指令。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**HEARTBEAT.md 示例:**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## 每日任务
|
||||||
|
|
||||||
|
- 每天早上 9:00 检查未读邮件,分类后发送摘要到 Slack #daily
|
||||||
|
- 监控竞品价格变动,降幅超过 10% 立即通知
|
||||||
|
- 每周五下午生成本周工作总结
|
||||||
|
|
||||||
|
## 触发条件
|
||||||
|
|
||||||
|
- 仅在工作日执行
|
||||||
|
- 静默模式:无变化时不发送消息
|
||||||
|
```
|
||||||
|
|
||||||
|
**可见性控制:**
|
||||||
|
|
||||||
|
| 配置项 | 说明 | 默认值 |
|
||||||
|
|--------|------|--------|
|
||||||
|
| `heartbeat.every` | 心跳间隔 | 30m |
|
||||||
|
| `heartbeat.enabled` | 是否启用 | true |
|
||||||
|
| `heartbeat.ackMaxChars` | ACK 最大字符数 | 300 |
|
||||||
|
| `SILENT_REPLY_TOKEN` | 静默回复标记 | #SILENT_ACK |
|
||||||
|
| `HEARTBEAT_OK` | 无需操作标记 | HEARTBEAT_OK |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、数据流全链路
|
||||||
|
|
||||||
|
一条消息从外部平台进入到最终响应,经过的完整链路:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、持久化与存储架构
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**会话存储细节:**
|
||||||
|
|
||||||
|
| 存储项 | 格式 | 说明 |
|
||||||
|
|--------|------|------|
|
||||||
|
| 会话元数据 | JSON | 模型、Token 用量、思考级别等 |
|
||||||
|
| 会话转录 | JSONL (追加写入) | 不可变的消息日志,按大小/数量自动轮转 |
|
||||||
|
| 记忆索引 | SQLite | 向量表 + FTS 表 + 缓存表 |
|
||||||
|
| 设备身份 | JSON | Ed25519 公私钥对 |
|
||||||
|
| 配置 | JSON | 全局配置,含 Secret 引用 |
|
||||||
|
|
||||||
|
**Secrets 引用机制:**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"providers": {
|
||||||
|
"anthropic": {
|
||||||
|
"apiKey": "${file://~/.openclaw/secrets/anthropic.key}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
支持 `${file://path}` 和 `${env://VAR_NAME}` 两种引用方式。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、安全架构
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**操作域(Scopes)细粒度控制:**
|
||||||
|
|
||||||
|
| Scope | 权限 |
|
||||||
|
|-------|------|
|
||||||
|
| `gateway:full` | 网关完全控制 |
|
||||||
|
| `gateway:read` | 只读访问 |
|
||||||
|
| `channels:read` | 读取通道信息 |
|
||||||
|
| `messages:send` | 发送消息 |
|
||||||
|
| `config:write` | 修改配置 |
|
||||||
|
| `agents:manage` | Agent 管理 |
|
||||||
|
|
||||||
|
**沙箱策略:**
|
||||||
|
|
||||||
|
| 策略 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `inherit` | 继承父会话沙箱模式 |
|
||||||
|
| `require` | 强制更严格的沙箱 |
|
||||||
|
| `forbidden` | 禁止子 Agent 派生 |
|
||||||
|
|
||||||
|
**安全审计(`src/security/`):**
|
||||||
|
- `dangerous-tools.ts` — 危险工具扫描器
|
||||||
|
- `dangerous-config-flags.ts` — 危险配置标记检测
|
||||||
|
- `audit.ts` — 审计日志记录器
|
||||||
|
- 临时路径防护、外部内容策略
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、通道集成架构
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**通道插件必须实现的接口:**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface ChannelPlugin {
|
||||||
|
// 配置 Schema 定义
|
||||||
|
configSchema: JSONSchema;
|
||||||
|
|
||||||
|
// 生命周期
|
||||||
|
initialize(config: ChannelConfig): Promise<void>;
|
||||||
|
shutdown(): Promise<void>;
|
||||||
|
|
||||||
|
// 消息处理
|
||||||
|
onMessage(handler: MessageHandler): void;
|
||||||
|
sendMessage(target: Target, message: Message): Promise<void>;
|
||||||
|
|
||||||
|
// 状态
|
||||||
|
getStatus(): ChannelStatus;
|
||||||
|
getAccounts(): AccountInfo[];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**消息标准化:** 所有通道的消息都会被标准化为统一格式,包括:
|
||||||
|
- 文本内容
|
||||||
|
- 附件(图片/文件/音频)
|
||||||
|
- 发送者身份
|
||||||
|
- 线程/回复关系
|
||||||
|
- 通道特定元数据
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、构建与部署
|
||||||
|
|
||||||
|
### 8.1 Docker 部署架构
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 8.2 发布通道
|
||||||
|
|
||||||
|
| 通道 | 版本格式 | npm dist-tag |
|
||||||
|
|------|---------|--------------|
|
||||||
|
| Stable | vYYYY.M.D | `latest` |
|
||||||
|
| Beta | vYYYY.M.D-beta.N | `beta` |
|
||||||
|
| Dev | main 分支 | 无 tag |
|
||||||
|
|
||||||
|
### 8.3 客户端矩阵
|
||||||
|
|
||||||
|
| 平台 | 技术栈 | 位置 |
|
||||||
|
|------|--------|------|
|
||||||
|
| CLI | Commander.js + Clack | `src/cli/` |
|
||||||
|
| Web UI | React + Vite | `ui/` |
|
||||||
|
| macOS | SwiftUI + XPC Bridge | `apps/macos/` |
|
||||||
|
| iOS | React Native | `apps/ios/` |
|
||||||
|
| Android | React Native | `apps/android/` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、关键设计模式总结
|
||||||
|
|
||||||
|
### 9.1 架构模式
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 9.2 核心设计决策
|
||||||
|
|
||||||
|
| 决策 | 选择 | 理由 |
|
||||||
|
|------|------|------|
|
||||||
|
| 协议 | WebSocket + 自定义协议 | 双向实时通信,低延迟 |
|
||||||
|
| 存储 | 文件系统 + SQLite | 零外部依赖,本地优先 |
|
||||||
|
| 插件加载 | jiti 动态导入 | 支持 TypeScript 直接加载,无需预编译 |
|
||||||
|
| 并发控制 | Actor 队列 | 避免锁竞争,每会话串行保证一致性 |
|
||||||
|
| 记忆检索 | 向量 + BM25 混合 | 语义理解 + 精确匹配,互补短板 |
|
||||||
|
| 安全模型 | 设备身份 + Scopes | 零信任架构,最小权限原则 |
|
||||||
|
| 心跳 | 文件驱动 (HEARTBEAT.md) | 无需额外调度基础设施,用户可直接编辑 |
|
||||||
|
|
||||||
|
### 9.3 值得关注的工程亮点
|
||||||
|
|
||||||
|
1. **协议翻译器模式(ACP Translator)**:将外部标准协议与内部网关协议解耦,允许独立演进
|
||||||
|
2. **运行时缓存 + 空闲驱逐**:会话不用时自动回收资源,用时自动恢复
|
||||||
|
3. **Secret 引用而非内联**:配置文件中不存储明文密钥,而是引用外部文件或环境变量
|
||||||
|
4. **会话转录追加写入**:不可变日志,天然支持故障恢复和审计
|
||||||
|
5. **嵌入提供商可替换**:同一套记忆系统可无缝切换 OpenAI、Gemini、本地 Ollama 等后端
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十、架构风险与局限
|
||||||
|
|
||||||
|
| 风险点 | 说明 | 影响 |
|
||||||
|
|--------|------|------|
|
||||||
|
| **明文 Markdown 存储** | HEARTBEAT.md、MEMORY.md 等以明文存储 | API Key 泄露风险 |
|
||||||
|
| **Root 级终端权限** | `system.run` 工具可执行任意命令 | 需依赖审批机制,但默认可绕过 |
|
||||||
|
| **心跳无人值守** | Agent 可在用户不知情时自主行动 | MoltMatch 等事件的根因 |
|
||||||
|
| **第三方 Skill 生态** | ClawHub 26% 插件含漏洞/恶意代码 | 供应链攻击面 |
|
||||||
|
| **单体网关** | Gateway 是单点,承载所有通道 | 高可用需额外架构 |
|
||||||
|
| **文件系统依赖** | 会话存储依赖本地文件系统 | 不原生支持分布式部署 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> **总结**:OpenClaw 的架构本质上是一个**面向消息的分布式系统**——Gateway 是交换机,Agent 是 LLM 驱动的任务执行器,Channel 是双向传输管道。记忆、安全和可扩展性是一等公民,而非事后补丁。但其"本地优先"的设计哲学也带来了明文存储和单点依赖的固有风险。
|
||||||