这是 OpenClaw 源码解析系列的开篇。在深入具体模块之前,我们先从宏观视角俯瞰整个项目的架构——五层结构、数据流、关键设计决策,帮你建立起一张清晰的全局地图。
项目规模一览
| 模块 | 文件数 | 代码行数 | 定位 |
|---|---|---|---|
extensions/ |
5,006 | 820K | 插件生态(模型/渠道/工具) |
src/agents |
1,395 | 327K | Agent 执行引擎 |
src/gateway |
570 | 161K | 网关服务器 |
src/auto-reply |
475 | 111K | 自动回复调度 |
src/plugins |
424 | 103K | 插件 SDK + 运行时 |
src/config |
311 | 101K | 配置系统 |
ui/ |
285 | 82K | WebUI 前端 |
src/cli |
374 | 68K | 命令行界面 |
src/channels |
280 | 35K | 渠道抽象层 |
src/cron |
157 | 30K | 定时任务 |
src/process |
33 | 5K | 进程管理 + CommandQueue |
总计约 180 万行 TypeScript——OpenClaw 的体量相当庞大。
宏观架构:五层结构
OpenClaw 采用经典的分层架构,从入口启动到插件生态共五层:
┌─────────────────────────────────────────────────────────────────────────┐
│ 第 1 层:入口与启动 │
│ │
│ openclaw.mjs → src/entry.ts → src/cli/run-main.ts │
│ ↓ 解析命令行参数,路由到子命令 │
│ ↓ OpenClaw (无参数) 或 OpenClaw gateway → 启动 Gateway │
│ ↓ OpenClaw chat → 启动 CLI 聊天 │
│ ↓ OpenClaw onboard → 启动安装向导 │
└────────────────────────────────┬────────────────────────────────────────┘
│
┌────────────────────────────────▼────────────────────────────────────────┐
│ 第 2 层:Gateway 服务层(单进程,单线程) │
│ │
│ src/gateway/server.impl.ts — 主服务器 │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ HTTP Server WebSocket Server │ │
│ │ ├── /control-ui (WebUI) ├── 客户端连接认证 │ │
│ │ ├── /v1/chat/completions ├── 事件广播 (broadcast) │ │
│ │ ├── /v1/embeddings ├── 方法调用 (RPC) │ │
│ │ ├── /v1/models └── Presence + Health │ │
│ │ ├── /hooks (webhook 入口) │ │
│ │ └── /health │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ 辅助设施: │
│ • server-maintenance.ts — 定时清理与 GC │
│ • server-broadcast.ts — WebSocket 事件广播 │
│ • server-lanes.ts — CommandQueue 并发配置 │
│ • server-channels.ts — Channel 插件管理 │
│ • server-cron.ts — Cron 服务绑定 │
│ • server-plugins.ts — 插件 HTTP 路由注册 │
└────────────────────────────────┬────────────────────────────────────────┘
│
┌────────────────────────────────▼────────────────────────────────────────┐
│ 第 3 层:调度与编排 │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ CommandQueue │ │ Auto-Reply │ │ Cron Service │ │
│ │ (src/process) │ │ (src/auto-reply)│ │ (src/cron) │ │
│ │ │ │ │ │ │ │
│ │ Lane: main(4) │ │ 消息路由 │ │ 定时触发 │ │
│ │ Lane: cron(1) │ │ 渠道 → Agent │ │ cron 表达式 │ │
│ │ Lane: subagent(8)│ │ 重试/去重 │ │ 隔离执行 │ │
│ │ Lane: session:X │ │ 队列清理 │ │ │ │
│ └──────────────────┘ └──────────────────┘ └──────────────────┘ │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ Hooks │ │ Routing │ │
│ │ (src/hooks) │ │ (src/routing) │ │
│ │ │ │ │ │
│ │ Webhook 接入 │ │ 消息→会话映射 │ │
│ │ 生命周期钩子 │ │ 账户查找 │ │
│ └──────────────────┘ └──────────────────┘ │
└────────────────────────────────┬────────────────────────────────────────┘
│
┌────────────────────────────────▼────────────────────────────────────────┐
│ 第 4 层:Agent 执行引擎(327K 行,最复杂的模块) │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ pi-embedded-runner/ — 核心 Agent 执行器 │ │
│ │ run.ts → Agent 会话执行入口 │ │
│ │ lanes.ts → session/global lane 解析 │ │
│ │ compact.ts → 会话上下文压缩 │ │
│ │ stream-resolution.ts → 流式响应处理 │ │
│ │ system-prompt.ts → 系统提示词构建 │ │
│ │ │ │
│ │ tools/ → 工具执行框架 │ │
│ │ harness/ → Agent 执行约束与沙箱 │ │
│ │ sandbox/ → 代码执行沙箱 │ │
│ │ skills/ → 技能加载与调度 │ │
│ │ schema/ → Agent 配置结构 │ │
│ │ command/ → Agent 命令处理 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ src/context-engine/ — 上下文管理(token 预算、截断) │
│ src/memory/ + extensions/memory-* — 长期记忆 │
│ src/trajectory/ — 执行轨迹记录 │
└────────────────────────────────┬────────────────────────────────────────┘
│
┌────────────────────────────────▼────────────────────────────────────────┐
│ 第 5 层:插件与集成生态 (extensions/ — 820K 行) │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 模型提供商 (LLM Providers) │ │
│ │ openai / anthropic / google / deepseek / ollama / groq / │ │
│ │ mistral / xai / fireworks / qwen / litellm / vllm ... │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 消息渠道 (Channels) │ │
│ │ telegram / whatsapp / discord / slack / signal / matrix / │ │
│ │ irc / msteams / feishu / line / qqbot / imessage ... │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 媒体生成 (Media) │ │
│ │ elevenlabs(TTS) / deepgram(STT) / fal(图像) / comfy / │ │
│ │ runway(视频) / minimax ... │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 搜索 / 工具 │ │
│ │ brave / exa / tavily / browser / codex / github-copilot ... │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 记忆系统 (Memory) │ │
│ │ memory-core / memory-lancedb / memory-wiki / active-memory │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
数据流:一条消息的完整旅程
以用户在 Telegram 发送一条消息为例,追踪一次完整的请求生命周期:
用户在 Telegram 发消息 "帮我总结这篇文章"
│
▼
┌─ extensions/telegram/ ─────────────────────────────────┐
│ Telegram Bot API 收到 update │
│ → 解析消息,调用 Gateway 的 channel delivery 接口 │
└────────────────────────────────────┬───────────────────┘
│
▼
┌─ src/channels/ ──────────────────────────────────────────┐
│ transport 层标准化消息格式 │
│ → routing: 根据 account-id 定位对应 session │
└────────────────────────────────────┬─────────────────────┘
│
▼
┌─ src/auto-reply/ ────────────────────────────────────────┐
│ 判断是否需要 AI 回复,准备 Agent 执行参数 │
│ → enqueueCommandInLane("session:xxx", agentTask) │
└────────────────────────────────────┬─────────────────────┘
│
▼
┌─ src/process/command-queue.ts ───────────────────────────┐
│ 检查 lane 空位 (session max=1, global max=4) │
│ → 有空位直接 pump(),满了排队等待 │
└────────────────────────────────────┬─────────────────────┘
│
▼
┌─ src/agents/pi-embedded-runner/run.ts ───────────────────┐
│ 构建系统提示词 → 加载技能/工具/会话历史/记忆 │
│ → 调用 LLM API(流式接收响应) │
│ → LLM 要求调用工具时:执行工具 → 结果回传 → 继续推理 │
│ → 最终回复写入 session transcript 文件 │
└────────────────────────────────────┬─────────────────────┘
│
▼
┌─ 回复路由 ──────────────────────────────────────────────┐
│ auto-reply 将回复文本送回 channel │
│ → 广播 "chat.done" 事件通知 WebUI │
└──────────────────────────────────────────────────────────┘
关键设计决策
了解 OpenClaw 为什么长成现在这样,比知道它长什么样更有价值:
| 决策 | 选择 | 原因 | 代价 |
|---|---|---|---|
| 进程模型 | 单进程 | 简单、状态共享便利 | 存在阻塞风险 |
| 插件策略 | 全在 extensions/ | 核心精简、按需加载 | 820K 行仍挂同一进程 |
| 会话存储 | JSONL 文件 | 零数据库依赖、可 cat 查看 | 大文件 readFileSync 阻塞 |
| 任务调度 | CommandQueue lane | 同会话串行、跨会话并行 | 非真并行,仅调度排序 |
| 实时通信 | WebSocket 广播 | 推送 agent streaming | stringify 成本随连接线性增长 |
| 配置管理 | YAML + 热重载 | 改配置不需重启 | 增加 generation tracking 复杂度 |
各模块一句话定位
| 模块 | 定位 |
|---|---|
src/gateway |
HTTP+WS 服务器,所有外部请求的入口 |
src/agents |
AI Agent 执行引擎,LLM 调用与工具编排 |
src/auto-reply |
消息到 Agent 的调度器 |
src/channels |
渠道抽象层,统一多平台消息格式 |
src/config |
YAML 配置 + 热重载 + sessions 管理 |
src/plugins |
插件 SDK 与运行时 |
src/process |
CommandQueue,唯一任务调度队列 |
src/cron |
类 crontab 的周期性 Agent 触发 |
src/hooks |
Webhook 钩子与生命周期管理 |
src/mcp |
MCP 协议支持 |
src/memory |
长期记忆入口 |
src/tts |
语音合成 |
src/canvas-host |
Canvas 实时可视化(A2UI) |
src/cli |
命令行界面 |
src/routing |
account-id → session 映射 |
extensions/ |
所有插件实现 |
ui/ |
Vite + React WebUI |
apps/ |
iOS/Android/macOS 原生客户端 |
packages/ |
独立 npm 包(plugin-sdk 等) |
下一步
五层架构为你提供了一张全局地图。但地图只是起点——接下来我们将逐层深入:
- 第二集:Agent 执行引擎 — 327K 行的核心,LLM 怎么调、工具怎么执行、上下文怎么压
- 第三集:消息调度 — 从飞书/Telegram 消息到 Agent 回复的完整链路
- 第四集:插件系统 — 插件 SDK 设计、加载机制、扩展点
本系列将持续更新,欢迎关注。