openclaw架构原理-单进程应用 + 插件式扩展
文章目录
OpenClaw
github: https://github.com/openclaw/openclaw
从 Clawbot到 Moltbot再到 OpenClaw,这个爆火的项目经过 3 次改名,截至 2 月 4 日已经在 github 累积获得了 160K star。 OpenClaw 是一款开源自托管的个人 AI 代理网关,本质是运行在用户自有设备上的自主式智能体助手,主打 “本地优先、隐私可控” 的设计理念,通过自然语言指令实现 PC 全功能自动化,真正做到 替用户做事 而非 仅回答问题。
OpenClaw 火爆全网!它不是第一个 AI Agent,但却是少数真正开始接管系统操作的那一类:读文件、跑命令、改代码,甚至拥有完整系统权限。
该项目由 Peter Steinberger([PSPDFKit]( 创始人)创建,目前已有 378 位贡献者,并催生了一个由 8,900+ 开发者组成的社区,致力于构建个人 AI 基础设施。
与云端聊天机器人不同,OpenClaw 持续运行在用户自有硬件(比如 Mac Mini 以及各种 PC 设备)上,执行 shell 命令、管理文件,并协调多步骤工作流程,无需人工审核。
用户可以在 PC 或者手机上的 WhatsApp、Telegram、Slack、Discord、Google Chat、Signal、iMessage、Microsoft Teams、WebChat 等通讯软件上通过文字或者语音发布任务,它就可以在 PC 另一台设备上完成工作并把结果发送到用户的通讯软件上。
openclaw架构-单进程应用 + 插件式扩展
OpenClaw 的核心是一个基于 TypeScript 开发的命令行应用(CLI),既非 Python 开发、也非基于 Next.js 的网页应用。作为一个独立运行进程。
核心理念是:常驻控制平面 + 可插拔大模型大脑 + 可扩展工具技能 + 会话/记忆/安全策略。
┌─────────────────────────────────────────────────────────────────┐ │ 消息渠道(Channels) │ │ ┌──────┐ ┌──────┐ ┌────┐ ┌────┐ ┌────────┐ ┌──────┐ │ │ │企业微信│ │Telegram│ │飞书│ │QQ │ │WhatsApp│ │Web UI│ … │ │ └───┬──┘ └───┬──┘ └──┬─┘ └──┬─┘ └───┬────┘ └───┬──┘ │ │ └────────┴───────┴──────┴───────┴──────────┘ │ │ │ 统一内部事件格式 │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Gateway(网关守护进程):18789 │ │ │ │ │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ │ │ Router │ │ Session │ │ Security │ │ │ │ │ │ 路由分发 │ │ 会话管理 │ │ 安全策略 │ │ │ │ │ │ 鉴权/限流 │ │ 上下文恢复│ │ 审批机制 │ │ │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ └───────────────────────┬─────────────────────────────────┘ │ │ │ │ │ ┌─────────────┼──────────────┐ │ │ ▼ ▼ ▼ │ │ ┌──────────────┐ ┌───────────┐ ┌──────────────┐ │ │ │ Agent Runtime│ │ Nodes │ │ Skills & │ │ │ │ 智能体运行时 │ │ 设备节点 │ │ Sandbox │ │ │ │ │ │ │ │ 技能系统+沙箱 │ │ │ │ ┌────────┐ │ │ macOS │ │ │ │ │ │ │Prompt │ │ │ iOS │ │ SKILL.md │ │ │ │ │Builder │ │ │ Android │ │ Docker 隔离 │ │ │ │ ├────────┤ │ │ Linux │ │ ClawHub 市场 │ │ │ │ │Context │ │ │ │ │ │ │ │ │ │Guard │ │ └───────────┘ └──────────────┘ │ │ │ ├────────┤ │ │ │ │ │Tool │ │ │ │ │ │Executor│ │ │ │ │ └────────┘ │ │ │ └──────┬──────┘ │ │ │ │ │ ▼ │ │ ┌──────────────────────────────────────────┐ │ │ │ LLM Provider(模型适配层) │ │ │ │ │ │ │ │ Claude │ GPT │ DeepSeek │ Ollama │ … │ │ │ └──────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────┐ │ │ │ Memory(记忆系统) │ │ │ │ │ │ │ │ .jsonl 会话历史 │ Markdown 长期记忆 │ │ │ │ SQLite 索引 │ Git 版本管理 │ │ │ └──────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ 在即时通讯工具中向 Clawd 发送指令后,会依次触发以下环节:
1. 接入层 Channel(通道适配器)
```text 用户在 IM 发送消息 → 平台服务器回调/推送 → Gateway Channel Adapter 接收 → 消息标准化(提取文本、附件、发送者信息等) → 生成统一的内部事件 → 交给 Router 分发 ``` 通道适配器接收用户消息并进行预处理,包括消息标准化、提取附件等。不同的即时通讯工具和输入流,都配有专属的适配器。 每个通道适配器还负责反向通路:**将 Agent 的回复格式化为目标平台所需的格式 (如 Markdown 转 IM 富文本、长文本分段、文件直链等),并通过原通道发回**。 2. 网关服务器:路由与会话层 Router + Session
Gateway 是整个系统的控制中心,是单机唯一实例的常驻守护进程。
- Router:鉴权、去重、限流、把消息分发给对应 Agent/工作流
- Session:找到/创建会话(conversation_id),取出最近对话、用户信息等上下文
通信协议:
所有组件间通过 WebSocket + JSON 通信,消息分三种类型:
类型 方向 说明
req 客户端 → 服务端 请求,包含唯一 id(UUID)
res 服务端 → 客户端 对 req 的响应,含 ok 状态
event 服务端 → 客户端 单向推送(消息到达、状态变更等)
连接鉴权流程:
客户端发起 WebSocket 连接 → 服务端发送 connect.challenge(含 nonce + 时间戳,防重放) → 客户端发送 req: connect(含协议版本、角色、权限范围、设备签名) → 若配置了 Token,验证 Bearer Token → 若是新设备,进入 Device Pairing 配对流程 → 鉴权通过,连接建立 会话映射规则:
场景 Session Key 说明
私聊(DM) 默认共享主会话 dmScope: “main”,可配 per-peer 隔离
群组 agent:::group: 每个群独立会话
定时任务 cron:: 独立会话
Webhook webhook:: 独立会话
3. Agent 核心 Orchestrator(编排器) ——“大脑”
Agent Runtime 是系统的决策核心,负责推理与编排。
- 决定下一步做什么:直接回答还是调用工具
- 维护对话回合:模型→工具→模型→…直到产出最终回复
- 这里通常包含:提示词组装、策略、错误恢复、输出格式化
这是真正承载 AI 能力的模块。该模块会确定待调用的模型、匹配对应的 API 密钥(若密钥失效,会将该配置标记为冷却状态并尝试下一个),若主模型调用失败,会自动切换至备用模型。 智能体运行器会结合可用工具、技能、记忆内容动态生成系统提示词,再加入会话历史(存储于.jsonl 文件),随后将完整提示词传入上下文窗口防护机制,校验是否有足够的上下文空间。若上下文空间即将耗尽,系统会选择压缩会话内容(对上下文进行总结)或优雅降级终止执行。
系统提示词由多层动态组合而成:
最终 Prompt = 基础身份(AGENTS.md) + 工具声明(TOOLS.md,紧凑 XML 格式以节省 Token) + 动态技能列表 + 安全策略提示 + 用户记忆(USER.md 等 Markdown 文件) + 压缩后的会话历史 + 当前用户消息 Agent Runtime 会结合可用工具、已加载的技能、记忆内容动态生成系统提示词, 再加入会话历史,随后将完整提示词传入上下文窗口守护者(Context Window Guard)。
4. LLM 适配层 LLM Provider(模型网关)
- 把“调用模型”统一成一个接口
- 适配不同厂商/本地模型;处理流式输出、重试、超时、并发等
大模型调用环节会以流式方式返回结果,同时对不同服务商的 API 做了一层抽象封装;若所调用的模型支持深度思考功能,该模块还会触发模型的扩展思考逻辑。
Context Window Guard(上下文窗口守护)
这是确保输入不超过模型上下文限制的关键机制:
完整提示词 → Context Window Guard 校验 ├─ 空间充足 → 直接发送给 LLM ├─ 空间紧张 → 压缩会话历史(总结摘要替代原始对话) └─ 空间耗尽 → 优雅降级(告知用户需开启新会话) - Pruning(剪枝):在发送给模型前,自动裁剪过时的工具调用中间结果
- Compression(压缩):将冗长的历史对话替换为总结摘要
- Graceful Degradation(优雅降级):空间不足时终止执行并通知用户
模型调用与容错
选择主模型 → 匹配 API Key ├─ 调用成功 → 流式返回结果 ├─ Key 失效 → 标记冷却,尝试下一个 Key └─ 主模型故障 → 自动切换备用模型(Fallback) LLM Provider(模型适配层)
将"调用模型"统一抽象为一个接口,屏蔽各厂商 API 差异。
支持的模型提供商:
Provider 示例模型 备注
Anthropic Claude 3.5/4 原生支持
OpenAI GPT-4o/o1 原生支持
DeepSeek DeepSeek-V3/R1 兼容 OpenAI 格式
OpenRouter 多模型聚合 统一入口
Ollama Llama/Qwen 等 本地模型
模型管理:
- CLI 命令:openclaw models list/set/scan
- 支持热切换模型,无需重启 Gateway
- 配置集中在 models.json
Nodes(设备节点)——能力提供者
Nodes 是运行在各类设备上的能力提供者,通过 WebSocket 以 role: “node” 连接 Gatew
提供的能力:
能力 说明 system.run 执行系统命令(Bash/Shell) file.read / file.write 文件读写 browser.* 浏览器控制(Computer Use) camera.* 摄像头操作 canvas.* UI 画布操作 执行流程:
Agent 决定调用工具 → Gateway 检查权限/安全策略 → Gateway 通过 node.invoke 转发指令给目标 Node → Node 在本地执行 → 执行结果返回 Gateway → Gateway 将结果传回 Agent Runtime Skills & Sandbox(技能系统与沙箱隔离)
Skills(技能系统)
Skills 是 OpenClaw 的插件式扩展机制,本质上是对工具的语义封装:
skill/ ├── SKILL.md # 技能描述(LLM 可读的说明文档) ├── tools/ # 工具脚本(Bash/Python/Node.js) └── prompts/ # 可选的提示词模板 技能来源:
- 本地目录
- Agent Workspace 内嵌
- ClawHub 在线市场(社区贡献的 93+ 预置技能)
https://clawhub.ai/
ClawHub 是一个最小化的技能注册中心。启用 ClawHub 后,代理可以自动搜索技能并根据需要拉取新技能。
覆盖领域:办公自动化、开发工具、智能家居、内容创作等。
Sandbox(沙箱隔离)
对于非主会话(如群聊场景),默认启用 Docker 沙箱隔离执行
会话类型 执行环境 权限 主对话(DM) 本地直接执行 完整权限 群组对话 Docker 沙箱 受限工具(bash, read 等) Webhook 触发 Docker 沙箱 受限 5.智能体循环(Agent Loop)
若大模型返回工具调用指令,Clawd 会在本地执行该指令,并将执行结果补充至对话中。这一过程会反复执行,直至大模型返回最终文本结果,或达到最大循环次数(默认约 20 次)。 正是在这一环节,Clawd 实现了其核心能力——电脑操作功能。
用户发送消息 │ ▼ ┌─────────────────────────────────────┐ │ Agent Runtime 接收 │ │ 构造 Prompt + 会话历史 + 工具列表 │ │ Context Window Guard 校验 │ └───────────────┬─────────────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ 调用 LLM(流式) │ │ LLM Provider 适配 + 重试 + 超时 │ └───────────────┬─────────────────────┘ │ ┌───────┴───────┐ │ │ ▼ ▼ ┌──────────┐ ┌──────────────┐ │ 最终文本 │ │ 工具调用指令 │ │ 回复用户 │ │ │ └──────────┘ └──────┬───────┘ │ ▼ ┌────────────────┐ │ 权限检查 │ │ 安全审批 │ │ 沙箱策略判断 │ └───────┬────────┘ │ ▼ ┌────────────────┐ │ 执行工具 │ │ (本地/Node/ │ │ Docker 沙箱) │ └───────┬────────┘ │ ▼ ┌────────────────┐ │ 执行结果 │ │ 追加到对话 │ └───────┬────────┘ │ ▼ 回到 "调用 LLM" 步骤 (循环直至最终文本或达到上限) 默认最大循环次数:约 20 次 这是 OpenClaw 实现核心能力的关键机制。当大模型返回工具调用指令时, 系统会在本地执行该指令,并将执行结果补充至对话中, 这一过程反复执行直至大模型返回最终文本结果。
审批机制:高危命令(如 system.run 执行危险操作)可配置为需要人工审批:
Agent 请求执行危险工具 → Gateway 广播 exec.approval.requested 事件 → Operator(用户)在 Web UI 或 IM 中确认/拒绝 → Gateway 将审批结果传回 Agent → 继续或终止执行 6.记忆系统
OpenClaw 的记忆系统遵循 “文件即记忆” 的设计哲学, Markdown 是真相的来源(Source of Truth)。
会话记忆(短期)
存储格式:.jsonl(JSON Lines),每行一个 JSON 对象
存储路径:~/.openclaw/agents//sessions/.jsonl
记录内容:用户消息、工具调用指令、执行结果、模型回复
元数据:sessions.json 记录所有会话的索引信息
长期记忆(持久)
存储格式:Markdown 文件
关键文件:
USER.md:用户偏好、习惯、个人信息
AGENTS.md:Agent 身份定义
TOOLS.md:工具声明
Workspace 中的其他 .md 文件
记忆管理策略
策略 说明 Pruning(剪枝) 发送给模型前裁剪过时的工具调用中间结果 Compression(压缩) 将冗长历史替换为总结摘要 Lifecycle(生命周期) 按空闲时间/固定时间重置,或 /new 命令手动重置 Git 版本管理 记忆文件可被 Git 追踪,支持回溯和协作 OpenClaw 有意选择 Markdown + SQLite 而非向量数据库,原因是:
- 可读性:开发者可直接打开文件查看 Agent 记住了什么
- 可编辑性:人类可以直接修正 Agent 的错误认知
- 可审计性:Git 历史记录所有变更
- 轻量级:无需额外的向量数据库依赖
OpenClaw 认证机制-公网暴露的最佳实践
不需要 Nginx Basic Auth,OpenClaw 自身的两层防护就足够:
| 层级 | 机制 | 保护什么 ||| ----- | ------------------------------- | ------------------ | ---- || 第1层 | **Device Identity**(设备配对) | Control UI 界面 ||| 第2层 | **Gateway Token** | API/WebSocket 调用 ||你的浏览器首次访问 → 发起配对请求(Pending)
↓
你在服务器终端执行:devices approve
↓
浏览器获得设备凭证(存 localStorage)→ 以后自动认证
别人的浏览器访问 → 也发起配对请求 → 但你不 approve → 永远进不去。
这比密码更安全,因为:
- 没有密码可以暴力破解
- 每台设备需要服务器端显式批准
- 可以随时
devices revoke撤销某台设备的访问权
配置(openclaw.json):
{"gateway":{"controlUi":{"dangerouslyDisableDeviceAuth":false}}}⚠️ 切勿设置dangerouslyDisableDeviceAuth: true,这会关闭设备认证,任何人打开 URL 都能直接控制你的 AI Agent。名字中的dangerously就是在警告你。
最佳实践
打开 Device Auth,关掉dangerouslyDisableDeviceAuth:
1. Gateway Auth Token(API 层认证)
配置位置:
"auth":{"mode":"token","token":"xxxxxxxxxxxxxxxxxxxxxxx"}所有 API/WebSocket 请求必须携带 Authorization: Bearer <token>,否则拒绝。这保护了你的 AI Agent 不被随意调用。
作用:保护 Gateway 的 API/WebSocket 接口(如 /v1/chat、/v1/agents 等)。
使用方式:客户端(如 Cursor、Claude Desktop、MCP Client)在连接时通过 HTTP Header 传递:
2. Device Identity(Control UI 层认证)
专门保护 Web 控制面板(即你浏览器打开的那个界面)。流程是:
浏览器打开 UI → WebSocket 连接 → Gateway 要求 device identity ↓ 浏览器本地没有已授权的设备凭证 ↓ 连接被拒绝 (code=1008) 这是专门保护 Control UI 的。正常流程:
- 浏览器首次打开 UI → 提示
device identity required - 在服务器终端运行授权命令,批准该设备
- 浏览器获得设备凭证,之后都能访问
这就是 OpenClaw 的最佳实践 —— 不是用密码,而是用设备授权,类似 SSH 的 trust-on-first-use 机制。
3. Bind 范围限制
"bind":"lan" // 只监听局域网 3. dangerouslyDisableDeviceAuth: true 的作用
"gateway":{"controlUi":{"dangerouslyDisableDeviceAuth":true}}这个配置的意思是:跳过 Device Identity 验证,任何人打开 UI 都不需要设备授权就能直接使用。
名字带 dangerously 是因为这意味着只要知道 URL 的人都能控制你的 AI Agent。
OpenClaw 安装部署架构
典型的生产部署架构如下:
┌──────────┐ │ 浏览器 │ │ (Web UI) │ └────┬─────┘ │ HTTPS ▼ ┌─────────────────────────────────────────────────────────────┐ │ Nginx 反代层 (:443) │ │ • SSL 终止 • WebSocket 代理 │ │ • Origin 覆写 • 信任边界 │ └──────────┬───────────────────────────────────┬──────────────┘ │ proxy_pass │ │ http://127.0.0.1:18789 │ ▼ │ ┌──────────────────────────┐ │ │ IM 通道 Webhook 回调 │ │ │ 企业微信/QQ/钉钉/飞书 │ │ └──────────┬───────────────┘ │ │ │ ▼ ▼ ┌─────────────────────────────────────────────────────────────┐ │ OpenClaw Gateway (:18789 仅本地监听) │ │ │ │ Channel Adapters → Router → Session → Agent Runtime │ │ ↕ │ │ LLM Provider │ │ ↕ │ │ Tool Execution │ │ (Nodes / Sandbox) │ │ ↕ │ │ Memory System │ │ (.jsonl + .md) │ └─────────────────────────────────────────────────────────────┘ 端口说明: :443 — Nginx HTTPS(对外唯一入口) :18789 — OpenClaw Gateway(仅 127.0.0.1,不对外暴露) :18790 — OpenClaw Bridge(多设备局域网发现通道) 使用总结
配置企业微信通道
编辑 openclaw.json
配置文件位于:data/.openclaw/openclaw.json(相对于 docker-compose.yml 目录)
在 channels 中添加 wecom 配置:
{"channels":{"wecom":{"enabled":true,"token":"<你的企业微信 Token>","encodingAESKey":"<你的企业微信 EncodingAESKey>"}}}手动注册插件(关键步骤)
这是最容易踩的坑! OpenClaw 的 doctor 会自动尝试在 plugins.entries 中以通道 ID(wecom)注册插件,但实际的插件 ID 是 openclaw-wecom,导致 plugin not found: wecom 错误。
必须手动在 openclaw.json 中添加:
{"plugins":{"entries":{"openclaw-wecom":{"enabled":true}}}}注意:plugins.entries的 key 必须是openclaw-wecom(npm 包名去掉@marshulll/前缀),而不是wecom(通道 ID)。