diff --git a/articles/002/diagram-01.mmd b/articles/002/diagram-01.mmd
new file mode 100644
index 0000000..af4b72e
--- /dev/null
+++ b/articles/002/diagram-01.mmd
@@ -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
端口 18789]
+ AUTH[认证中间件
Ed25519 设备身份]
+ PROTO[协议处理器
AJV Schema 校验]
+ RL[速率限制]
+ end
+
+ subgraph "通道管理"
+ CM[Channel Manager]
+ CP1[Telegram Plugin]
+ CP2[Slack Plugin]
+ CP3[Discord Plugin]
+ CPN[... N 个通道插件]
+ end
+
+ subgraph "路由层"
+ RT[Route Resolver
消息 → Agent 映射]
+ SK[Session Key Parser
会话键解析]
+ end
+
+ subgraph "ACP 协议层"
+ ACP_SVR[ACP Server]
+ ACP_TR[ACP Translator
协议翻译器]
+ ACP_SM[ACP Session Manager
会话管理器 + Actor 队列]
+ end
+
+ subgraph "Agent 运行时"
+ PI[Pi Agent Runner
LLM 推理引擎]
+ TC[Tool Catalog
工具注册表]
+ SKL[Skills System
技能加载器]
+ SA[Subagent Registry
子 Agent 注册]
+ AP[Auth Profiles
模型凭证管理]
+ end
+
+ subgraph "记忆系统"
+ MM[Memory Index Manager]
+ VEC[向量检索
sqlite-vec]
+ FTS[全文搜索
SQLite FTS5]
+ EMB[Embedding Providers
OpenAI/Gemini/Voyage/Ollama]
+ end
+
+ subgraph "心跳系统"
+ HB[Heartbeat Runner
定时唤醒]
+ HMD[HEARTBEAT.md
任务配置文件]
+ end
+
+ subgraph "存储层"
+ SS[Session Store
JSON/JSONL 文件]
+ CF[Config Store
config.json]
+ DI[Device Identity
密钥对存储]
+ 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
\ No newline at end of file
diff --git a/articles/002/diagram-01.png b/articles/002/diagram-01.png
new file mode 100644
index 0000000..b46a4e6
Binary files /dev/null and b/articles/002/diagram-01.png differ
diff --git a/articles/002/diagram-02-test.png b/articles/002/diagram-02-test.png
new file mode 100644
index 0000000..bbe4983
Binary files /dev/null and b/articles/002/diagram-02-test.png differ
diff --git a/articles/002/diagram-02.mmd b/articles/002/diagram-02.mmd
new file mode 100644
index 0000000..4672afe
--- /dev/null
+++ b/articles/002/diagram-02.mmd
@@ -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: 分发到对应通道
\ No newline at end of file
diff --git a/articles/002/diagram-02.png b/articles/002/diagram-02.png
new file mode 100644
index 0000000..bbe4983
Binary files /dev/null and b/articles/002/diagram-02.png differ
diff --git a/articles/002/diagram-03.mmd b/articles/002/diagram-03.mmd
new file mode 100644
index 0000000..401e8d7
--- /dev/null
+++ b/articles/002/diagram-03.mmd
@@ -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
发现/健康监控/Cron]
+ J --> K[✅ Ready]
\ No newline at end of file
diff --git a/articles/002/diagram-03.png b/articles/002/diagram-03.png
new file mode 100644
index 0000000..894518d
Binary files /dev/null and b/articles/002/diagram-03.png differ
diff --git a/articles/002/diagram-04.mmd b/articles/002/diagram-04.mmd
new file mode 100644
index 0000000..6d0be85
--- /dev/null
+++ b/articles/002/diagram-04.mmd
@@ -0,0 +1,19 @@
+graph TB
+ subgraph "ACP 协议栈"
+ EXT[外部 ACP 客户端
stdin/stdout]
+ CONN[AgentSideConnection
ndJSON 流]
+ AGENT[AcpGatewayAgent
协议翻译器]
+ CLIENT[GatewayClient
WebSocket]
+ MGR[AcpSessionManager
会话管理单例]
+ end
+
+ subgraph "运行时缓存"
+ CACHE[RuntimeCache
sessionKey → Handle]
+ QUEUE[ActorQueue
每会话串行化]
+ EVICT[空闲驱逐
TTL 超时清理]
+ end
+
+ EXT --> CONN --> AGENT --> CLIENT
+ AGENT --> MGR
+ MGR --> CACHE & QUEUE
+ CACHE --> EVICT
\ No newline at end of file
diff --git a/articles/002/diagram-04.png b/articles/002/diagram-04.png
new file mode 100644
index 0000000..e0c8641
Binary files /dev/null and b/articles/002/diagram-04.png differ
diff --git a/articles/002/diagram-05.mmd b/articles/002/diagram-05.mmd
new file mode 100644
index 0000000..c240dc2
--- /dev/null
+++ b/articles/002/diagram-05.mmd
@@ -0,0 +1,48 @@
+graph TB
+ subgraph "Agent 运行时"
+ PI[Pi Agent Runner
核心推理引擎]
+
+ subgraph "模型集成"
+ MC[Model Catalog
模型目录]
+ AP[Auth Profiles
凭证管理]
+ FB[Fallback Chains
模型降级链]
+ TH[Thinking Mode
思考/推理模式]
+ 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
jiti 动态导入]
+ SF[skill.json 元数据]
+ SH[skill.ts 运行时处理器]
+ end
+
+ subgraph "子 Agent"
+ SR[Subagent Registry]
+ SP[Spawn ACP
隔离会话派生]
+ 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
\ No newline at end of file
diff --git a/articles/002/diagram-05.png b/articles/002/diagram-05.png
new file mode 100644
index 0000000..1068dde
Binary files /dev/null and b/articles/002/diagram-05.png differ
diff --git a/articles/002/diagram-06.mmd b/articles/002/diagram-06.mmd
new file mode 100644
index 0000000..61a36f8
--- /dev/null
+++ b/articles/002/diagram-06.mmd
@@ -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
\ No newline at end of file
diff --git a/articles/002/diagram-06.png b/articles/002/diagram-06.png
new file mode 100644
index 0000000..e9d706e
Binary files /dev/null and b/articles/002/diagram-06.png differ
diff --git a/articles/002/diagram-07.mmd b/articles/002/diagram-07.mmd
new file mode 100644
index 0000000..62a399b
--- /dev/null
+++ b/articles/002/diagram-07.mmd
@@ -0,0 +1,19 @@
+graph TB
+ subgraph "插件生命周期"
+ D[1. Discovery 发现
扫描 extensions/ 目录]
+ M[2. Manifest 加载
读取 openclaw.plugin.json]
+ R[3. Runtime 创建
初始化 Hook Runner]
+ REG[4. Registration 注册
setActivePluginRegistry]
+ end
+
+ D --> M --> R --> REG
+
+ subgraph "插件类型"
+ CH[通道插件 ×34
Telegram/Slack/Discord/...]
+ MEM[记忆插件
memory-core / memory-lancedb]
+ AUTH_P[认证插件
google-gemini-cli-auth 等]
+ DIAG[诊断插件
diagnostics-otel]
+ SPEC[特殊插件
thread-ownership / llm-task]
+ end
+
+ REG --> CH & MEM & AUTH_P & DIAG & SPEC
\ No newline at end of file
diff --git a/articles/002/diagram-07.png b/articles/002/diagram-07.png
new file mode 100644
index 0000000..de91eae
Binary files /dev/null and b/articles/002/diagram-07.png differ
diff --git a/articles/002/diagram-08.mmd b/articles/002/diagram-08.mmd
new file mode 100644
index 0000000..1a11c87
--- /dev/null
+++ b/articles/002/diagram-08.mmd
@@ -0,0 +1,39 @@
+graph TB
+ subgraph "记忆系统架构"
+ Q[搜索查询]
+
+ subgraph "混合搜索引擎"
+ VS[向量检索
sqlite-vec]
+ BM[BM25 全文搜索
SQLite FTS5]
+ HY[混合排序
加权合并 + 时间衰减]
+ end
+
+ subgraph "Embedding 提供商"
+ E1[OpenAI
text-embedding-3-small/large]
+ E2[Gemini
Generalist Multimodal]
+ E3[Voyage
voyage-large-2-instruct]
+ E4[Mistral
mistral-embed]
+ E5[Ollama
本地模型]
+ end
+
+ subgraph "存储层"
+ DB[(SQLite 数据库)]
+ CV[chunks_vec 表
向量嵌入]
+ CF[chunks_fts 表
FTS5 全文索引]
+ EC[embedding_cache 表
查询缓存 + TTL]
+ end
+
+ RES[搜索结果
相关度排序]
+ 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
\ No newline at end of file
diff --git a/articles/002/diagram-08.png b/articles/002/diagram-08.png
new file mode 100644
index 0000000..e0eb26e
Binary files /dev/null and b/articles/002/diagram-08.png differ
diff --git a/articles/002/diagram-09.mmd b/articles/002/diagram-09.mmd
new file mode 100644
index 0000000..2a58b82
--- /dev/null
+++ b/articles/002/diagram-09.mmd
@@ -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
\ No newline at end of file
diff --git a/articles/002/diagram-09.png b/articles/002/diagram-09.png
new file mode 100644
index 0000000..b15042a
Binary files /dev/null and b/articles/002/diagram-09.png differ
diff --git a/articles/002/diagram-10.mmd b/articles/002/diagram-10.mmd
new file mode 100644
index 0000000..00bd068
--- /dev/null
+++ b/articles/002/diagram-10.mmd
@@ -0,0 +1,45 @@
+graph TB
+ subgraph "① 消息接收"
+ MSG[用户消息
Telegram/Slack/...]
+ SDK[平台 SDK
原生协议接收]
+ NORM[消息标准化
统一格式]
+ end
+
+ subgraph "② 路由决策"
+ RT[Route Resolver
channel + peer → agentId]
+ BIND[Session Binding
会话绑定服务]
+ SK[Session Key
生成会话键]
+ end
+
+ subgraph "③ 会话管理"
+ ACP[ACP Session Manager]
+ LOCK[Session Write Lock
防并发写入]
+ LOAD[加载会话历史
JSONL 转录]
+ end
+
+ subgraph "④ Agent 推理"
+ PI[Pi Agent Runner]
+ LLM[LLM API 调用
含 Thinking Mode]
+ TOOL[工具调用
审批 → 执行]
+ MEM[记忆检索
混合搜索]
+ end
+
+ subgraph "⑤ 响应投递"
+ STREAM[流式响应
逐 Token 返回]
+ TRANS[格式转换
适配目标平台]
+ DELIVER[投递到通道
支持线程/回复]
+ PERSIST[持久化
会话 + 记忆写入]
+ 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
\ No newline at end of file
diff --git a/articles/002/diagram-10.png b/articles/002/diagram-10.png
new file mode 100644
index 0000000..22ad579
Binary files /dev/null and b/articles/002/diagram-10.png differ
diff --git a/articles/002/diagram-11.mmd b/articles/002/diagram-11.mmd
new file mode 100644
index 0000000..7f079d1
--- /dev/null
+++ b/articles/002/diagram-11.mmd
@@ -0,0 +1,27 @@
+graph LR
+ subgraph "~/.openclaw/ 存储结构"
+ subgraph "设备层"
+ DI[device-identity.json
Ed25519 密钥对]
+ CRED[credentials/
设备 Token]
+ end
+
+ subgraph "配置层"
+ CONFIG[config.json
全局配置]
+ SECRETS[secrets/
API Key 引用]
+ end
+
+ subgraph "Agent 层 (per-agent)"
+ subgraph "agents/main/"
+ SESS[sessions.json
会话元数据]
+ TRANS[sessions/*.jsonl
会话转录]
+ WS[workspace/
工作区文件]
+ HMD2[HEARTBEAT.md]
+ MEMDB[memory.sqlite
向量+全文索引]
+ 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
\ No newline at end of file
diff --git a/articles/002/diagram-11.png b/articles/002/diagram-11.png
new file mode 100644
index 0000000..511a888
Binary files /dev/null and b/articles/002/diagram-11.png differ
diff --git a/articles/002/diagram-12.mmd b/articles/002/diagram-12.mmd
new file mode 100644
index 0000000..954e184
--- /dev/null
+++ b/articles/002/diagram-12.mmd
@@ -0,0 +1,33 @@
+graph TB
+ subgraph "安全层级"
+ subgraph "L1: 网络层"
+ TLS[TLS/mTLS 加密]
+ FP[证书指纹验证]
+ CWE[CWE-319 防护
禁止明文WS到非回环]
+ end
+
+ subgraph "L2: 认证层"
+ DEV[设备认证
Ed25519 签名]
+ TOKEN[设备 Token
长期访问令牌]
+ OAUTH[OAuth 集成
Google/Discord 等]
+ PWD[密码认证
本地网关备选]
+ end
+
+ subgraph "L3: 授权层"
+ SCOPE[操作域 Scopes]
+ PAIR[设备配对审批]
+ ROLE[Owner vs User 角色]
+ end
+
+ subgraph "L4: 执行层"
+ APPROVE[工具审批门
危险操作拦截]
+ SANDBOX[沙箱策略
inherit/require/forbidden]
+ AUDIT[审计日志]
+ SCAN[危险工具扫描]
+ end
+ end
+
+ TLS --> DEV --> SCOPE --> APPROVE
+ FP --> TOKEN --> PAIR --> SANDBOX
+ CWE --> OAUTH --> ROLE --> AUDIT
+ PWD --> SCAN
\ No newline at end of file
diff --git a/articles/002/diagram-12.png b/articles/002/diagram-12.png
new file mode 100644
index 0000000..e6e9c6e
Binary files /dev/null and b/articles/002/diagram-12.png differ
diff --git a/articles/002/diagram-13.mmd b/articles/002/diagram-13.mmd
new file mode 100644
index 0000000..c68eaa0
--- /dev/null
+++ b/articles/002/diagram-13.mmd
@@ -0,0 +1,24 @@
+graph TB
+ subgraph "通道插件架构"
+ IF[ChannelPlugin 接口]
+
+ subgraph "插件实现"
+ TG[Telegram
Bot API]
+ SL[Slack
Bolt SDK]
+ DC[Discord
discord.js]
+ WA[WhatsApp
Baileys]
+ SIG[Signal
signal-cli]
+ FS[飞书
Open API]
+ end
+
+ subgraph "生命周期"
+ INIT[initialize
认证 + 连接]
+ LISTEN[listen
消息监听]
+ ROUTE[route
路由到 Agent]
+ DELIVER[deliver
回传响应]
+ SHUTDOWN[shutdown
优雅断开]
+ end
+ end
+
+ IF --> TG & SL & DC & WA & SIG & FS
+ TG & SL & DC & WA & SIG & FS --> INIT --> LISTEN --> ROUTE --> DELIVER --> SHUTDOWN
\ No newline at end of file
diff --git a/articles/002/diagram-13.png b/articles/002/diagram-13.png
new file mode 100644
index 0000000..4145537
Binary files /dev/null and b/articles/002/diagram-13.png differ
diff --git a/articles/002/diagram-14.mmd b/articles/002/diagram-14.mmd
new file mode 100644
index 0000000..675ab89
--- /dev/null
+++ b/articles/002/diagram-14.mmd
@@ -0,0 +1,24 @@
+graph TB
+ subgraph "Docker Compose"
+ GW_SVC[gateway 服务
Node.js 运行时]
+ CLI_SVC[cli 服务
命令行交互]
+ HC[健康检查
端口 18789]
+ end
+
+ subgraph "Docker 镜像"
+ BASE[Dockerfile
多阶段构建]
+ SB[Dockerfile.sandbox
沙箱镜像]
+ SBB[Dockerfile.sandbox-browser
浏览器沙箱]
+ SBC[Dockerfile.sandbox-common
公共沙箱基础]
+ end
+
+ subgraph "其他部署"
+ FLY[fly.toml
Fly.io 部署]
+ RENDER[render.yaml
Render 部署]
+ PODMAN[Podman
无 root 容器]
+ end
+
+ GW_SVC --> BASE
+ CLI_SVC --> BASE
+ GW_SVC --> HC
+ BASE --> SB & SBB & SBC
\ No newline at end of file
diff --git a/articles/002/diagram-14.png b/articles/002/diagram-14.png
new file mode 100644
index 0000000..1be835f
Binary files /dev/null and b/articles/002/diagram-14.png differ
diff --git a/articles/002/diagram-15-test.png b/articles/002/diagram-15-test.png
new file mode 100644
index 0000000..bf1077c
Binary files /dev/null and b/articles/002/diagram-15-test.png differ
diff --git a/articles/002/diagram-15.mmd b/articles/002/diagram-15.mmd
new file mode 100644
index 0000000..ac353bb
--- /dev/null
+++ b/articles/002/diagram-15.mmd
@@ -0,0 +1,23 @@
+mindmap
+ root((OpenClaw
设计模式))
+ 消息驱动
+ WebSocket 双向通信
+ EventFrame 事件流
+ RequestFrame 请求/响应
+ 插件化
+ 34 个通道插件
+ Hook 系统 7 个钩子
+ 动态加载 jiti
+ 会话隔离
+ Actor 队列串行化
+ Session Write Lock
+ Per-agent 存储隔离
+ 安全纵深
+ L1 网络加密
+ L2 设备认证
+ L3 域控授权
+ L4 执行审批
+ 韧性设计
+ 模型降级链
+ 连接重试退避
+ 嵌入失败恢复
\ No newline at end of file
diff --git a/articles/002/diagram-15.png b/articles/002/diagram-15.png
new file mode 100644
index 0000000..2616d70
Binary files /dev/null and b/articles/002/diagram-15.png differ
diff --git a/articles/002/mermaid-config.json b/articles/002/mermaid-config.json
new file mode 100644
index 0000000..14c54a7
--- /dev/null
+++ b/articles/002/mermaid-config.json
@@ -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"
+ }
+}
diff --git a/articles/002/mermaid-fix.css b/articles/002/mermaid-fix.css
new file mode 100644
index 0000000..0d2e48e
--- /dev/null
+++ b/articles/002/mermaid-fix.css
@@ -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;
+}
diff --git a/articles/002/mermaid-mindmap.css b/articles/002/mermaid-mindmap.css
new file mode 100644
index 0000000..26265ce
--- /dev/null
+++ b/articles/002/mermaid-mindmap.css
@@ -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;
+}
diff --git a/articles/002/mermaid-tech.css b/articles/002/mermaid-tech.css
new file mode 100644
index 0000000..c01c606
--- /dev/null
+++ b/articles/002/mermaid-tech.css
@@ -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;
+}
diff --git a/articles/给龙虾做了个 CT:43 万行代码的 OpenClaw 架构全拆解.md b/articles/给龙虾做了个 CT:43 万行代码的 OpenClaw 架构全拆解.md
new file mode 100644
index 0000000..a29c586
--- /dev/null
+++ b/articles/给龙虾做了个 CT:43 万行代码的 OpenClaw 架构全拆解.md
@@ -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;
+ shutdown(): Promise;
+
+ // 消息处理
+ onMessage(handler: MessageHandler): void;
+ sendMessage(target: Target, message: Message): Promise;
+
+ // 状态
+ 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 是双向传输管道。记忆、安全和可扩展性是一等公民,而非事后补丁。但其"本地优先"的设计哲学也带来了明文存储和单点依赖的固有风险。