它不是一个大模型,它是一台机器,很多人把 OpenClaw 当成"更聪明的 ChatGPT"。这个认知是错的。
OpenClaw 是一个运行在你机器上的 Agent Runtime——它把 LLM(大模型)当成一个零件,像工厂的机械臂,而不是工厂本身。
大模型是"脑子",OpenClaw 是"身体 + 神经系统 + 工厂流水线"。
要真正理解 OpenClaw 底层在干什么,你需要回答四个问题:
一条消息进来,谁接的?(Gateway 路由层) 大模型怎么决定"下一步干什么"?(ReAct 循环 / Agent Loop) 工具调用是怎么执行的?(Pi SDK + 工具链) 它为什么不会忘事?(记忆系统 + 上下文压缩)
下面逐层拆解。
1、分层架构:OpenClaw 不是一个东西,是四层叠起来的
先看整体结构。OpenClaw 的源码组织是典型的"嵌套套娃"架构:
┌────────────────────────────────────────────────────┐│ Layer 4: OpenClaw Gateway(消息路由 + 会话管理) ││ Node.js 长驻进程,默认监听 ws://127.0.0.1:18789 │├────────────────────────────────────────────────────┤│ Layer 3: pi-coding-agent(完整编程 Agent,含工具集) ││ 内嵌调用,非子进程,非 RPC │├────────────────────────────────────────────────────┤│ Layer 2: pi-agent-core(Agent 循环 + 工具调用框架) ││ 事件驱动,支持 Extension 钩子 │├────────────────────────────────────────────────────┤│ Layer 1: pi-ai(LLM 统一抽象层) ││ 归一化 Claude / GPT / Gemini / Ollama 等所有接口 │└────────────────────────────────────────────────────┘这四层是同一个 TypeScript monorepo(badlogic/pi-mono,作者 Mario Zechner,libGDX 的创造者)的四个 npm 包:
{"@mariozechner/pi-ai": "0.49.3","@mariozechner/pi-agent-core": "0.49.3","@mariozechner/pi-coding-agent": "0.49.3","@mariozechner/pi-tui": "0.49.3"}关键设计决策:OpenClaw 是嵌入式调用,不是进程通信。它直接 import { createAgentSession } from pi-coding-agent,两者运行在同一个 Node.js 进程里。好处是延迟低、控制精细;坏处是出问题一起挂。
2、消息从 WhatsApp 到大模型,走了哪条路?
一条消息进来,经历 6 个阶段:
[WhatsApp 消息] ↓① Channel Adapter(协议适配) WhatsApp → Baileys 库(WebSocket 逆向 WhatsApp Web) Telegram → grammY Discord → discord.js 统一转换为内部 Message Envelope 格式 ↓② Gateway 路由(Session Resolution) 根据 dmScope 规则判断归属哪个 Session main 模式:所有 DM 共用一个 Session(跨设备连续性) ↓③ Lane Queue(串行化队列) 每个 Session 有一条 Lane 同一 Session 的请求严格串行执行 防止工具调用 / 会话状态竞争冲突 ↓④ Agent Runner(上下文组装) 拼装 System Prompt 加载 JSONL 会话历史 注入可用工具列表 ↓⑤ Agent Loop(ReAct 推理循环) ↓⑥ 流式回传(Streaming Reply) EmbeddedBlockChunker 按段落/句子智能切分 实时推回 WhatsApp / Telegram 同步写入 JSONL Transcript这第 ③ 步:Lane Queue 是 OpenClaw 可靠性的核心保障。同一个 Session 里的请求不会并行——这防止了 "AI 还没执行完上一个工具,新消息又来了" 的经典竞态问题。
3、Agent Loop:大脑是怎么"想然后动"的
这是整个系统最核心的部分。
OpenClaw 使用 ReAct 模式(Reasoning + Acting):
思考 → 调用工具 → 观察结果 → 继续思考 → 直到任务完成
实际执行在 src/agents/pi-embedded-runner/run.ts 里,简化后的核心逻辑是:
// 简化版,非原始代码while (true) {const attempt = await runEmbeddedAttempt({ sessionId, sessionKey, prompt, model, tools, ... });if (attempt.success) break; // 任务完成,退出循环if (attempt.contextOverflow) {await compactSession(); // 上下文满了,压缩后重试continue; }if (attempt.authError) {await rotateApiKey(); // Key 失效,轮换后重试continue; }break; // 其他错误,退出}每一轮 runEmbeddedAttempt 内部是标准的 ReAct 步骤:
① 发送 [System Prompt + 历史消息 + 当前问题] → LLM② 解析 LLM 返回: - 纯文本 → 直接回复用户 - tool_use 块 → 执行对应工具③ 工具执行结果 → 追加到消息历史④ 再次发给 LLM(下一轮)⑤ 重复,直到 LLM 不再调用工具(任务完成)一个真实的调用序列长这样:
User: 帮我检查一下 ~/projects/api/ 下有没有未提交的代码LLM turn 1: [思考] 需要先列目录,再检查 git 状态 [tool_call] bash("ls ~/projects/api/")Tool result: src/ tests/ README.md package.jsonLLM turn 2: [思考] 有项目,检查 git 状态 [tool_call] bash("cd ~/projects/api && git status")Tool result: On branch main, 3 files modified: src/auth.ts, src/db.ts, tests/auth.test.tsLLM turn 3: [思考] 找到了,准备回复 [text] 发现 3 个未提交的文件:src/auth.ts、src/db.ts 和 tests/auth.test.ts, 均在 main 分支。需要我帮你查看变更内容或直接提交吗?→ Loop 结束,回复用户重要细节:Pi 的基础工具只有 4 个——read、write、edit、bash。OpenClaw 在此基础上替换了 bash(改为更安全的 exec/process),并增加了 messaging、browser、canvas、sessions、cron、gateway 等专属工具。
4、System Prompt 是怎么拼出来的?
每次 Agent Loop 开始前,OpenClaw 在 buildAgentSystemPrompt() 里组装一个结构化的系统提示词。它包含以下分区:
[Tooling] ← 工具使用规范[Tool Call Style] ← 调用格式约定[Safety guardrails]← 安全约束[OpenClaw CLI ref] ← /compact /reset /stop 等命令说明[Skills] ← 仅注入技能元数据(不是全文!见下节)[Docs] ← 相关文档引用[Workspace] ← 工作目录和项目上下文[Sandbox] ← 沙箱权限设置[Messaging] ← 回复格式和通道规范[Reply Tags] ← NO_REPLY 等特殊标记[Memory] ← 记忆文件引用(如启用)[Runtime metadata] ← 当前时间、模型、会话 ID 等[Extra context] ← 用户自定义注入这个 Prompt 在每次请求前重新构建,通过 applySystemPromptOverrideToSession() 覆盖注入到会话中。
5、Skills 系统:大模型不会一次读完所有文档
这是 OpenClaw 一个非常精妙的设计,很多人没注意到。
Skills 不是全量注入 System Prompt 的。 如果有 5700 个技能,全塞进去直接撑爆 Context Window。
实际上,System Prompt 里只有一个技能元数据清单:
<available_skills><skill><n>weather</n><description>Get current weather and forecasts</description><location>/path/to/weather/SKILL.md</location></skill><skill><n>github</n><description>Manage GitHub repos, issues, PRs</description><location>/path/to/github/SKILL.md</location></skill> ...</available_skills>当 LLM 判断某个任务需要某项技能时,它会主动调用 read 工具去读取对应的 SKILL.md 文件——按需加载,不是预加载。
类比:开发者不会把所有文档背熟再写代码;他们知道文档在哪,需要的时候查。OpenClaw 的 Skills 系统就是这个逻辑。
技能优先级解析顺序:
工作区技能(优先级最高) └── <workspace>/skills/管理员技能 └── ~/.openclaw/skills/内置技能(优先级最低) └── <install>/skills/6、记忆系统:一个 Markdown 文件比向量数据库更可靠?
OpenClaw 的记忆存储方案让很多工程师惊讶:不用数据库,用 Markdown 文件。
~/.openclaw/agents/<agentId>/├── sessions/│ └── <sessionId>.jsonl ← 会话历史(JSONL 树)└── memory/ ├── 2026-03-01.md ← 日期记忆文件 ├── 2026-03-02.md └── 2026-03-03.md为什么这个方案有效?
JSONL 会话树:每条记录是
{ id, parentId, type, timestamp, data }的 append-only DAG。分支对话不会覆盖历史——像 Git 一样,切换分支只是移动"叶子指针"。Markdown Memory:Agent 运行时会主动将重要信息写入带日期的 .md 文件。这些文件在 Context Window 之外持久保存,不受压缩影响。
混合检索:需要回忆历史时,同时使用向量语义搜索(找相似概念)和 SQLite FTS5 全文关键词匹配(找精确短语),两者互补。例如搜索"authentication bug"可同时命中"login issues"(语义)和精确技术词组(关键词)。
一句话概括这个设计哲学(来自系统架构研究者 Laurent Bindschaedler):
把 LLM Context 当 CPU Cache,把磁盘文件当内存,再加一个压缩器来管理 Cache 淘汰——这是认知的虚拟内存系统。
7、上下文压缩:最容易踩坑的底层机制
这是 OpenClaw 底层最复杂、也最容易出问题的部分。
问题根源:LLM 有 Context Window 上限(比如 Claude 的 200K tokens)。对话越来越长,迟早会溢出。
OpenClaw 有两套处理机制,很多人搞混了:
机制一:Pruning(修剪)—— 无损、临时
触发时机:每次请求前 操作对象:只修剪工具调用的返回结果( toolResult)持久化:否,只影响这一次发给模型的内容 特点:永远不碰用户消息和助手回复,lossless
机制二:Compaction(压缩)—— 有损、永久
触发时机:Context 接近上限时自动触发,或手动 /compact操作对象:整个会话历史 持久化:是,写入 JSONL 文件 特点:有损!旧对话被摘要替换
Compaction 的完整执行流程:
① Context Window Guard 持续监控 Token 数② 触发软阈值(contextWindow - reserveTokensFloor - softThresholdTokens)③ 静默记忆刷新(Silent Memory Flush) → Agent 发起一个不可见的"内部对话" → Prompt:"把重要信息写入 memory/YYYY-MM-DD.md,没有就回复 NO_REPLY" → 用户完全不知道这次对话的存在④ 压缩执行 → 旧消息 → 摘要条目(保留最近约 20,000 tokens 不动) → 摘要写入 JSONL,创建新分支 → 文件路径和 ID 类标识符默认严格保留(identifierPolicy: "strict")⑤ 使用 [摘要 + 近期消息] 重试原始请求**"好路径" vs "坏路径"**:
好路径(提前预防): Context 趋近上限 → Memory Flush 先保存 → Compaction 摘要 → 继续工作,信息损失最小坏路径(溢出恢复): Context 已经超出,API 拒绝请求 → 强制全量压缩 → 没有 Memory Flush 保护,损失不可控实际配置建议(来自官方文档和社区实践):
// openclaw.json{"agents": {"defaults": {"compaction": {"reserveTokens": 40000, // 默认 16384,建议调高"keepRecentTokens": 20000, // 最近对话不压缩的 token 数"reserveTokensFloor": 20000 } } }}8、插件钩子系统:事件驱动的可扩展架构
OpenClaw 的扩展性通过两套机制实现:
Gateway Hooks(命令级事件)
// 可挂载的事件点agent:bootstrap // System Prompt 最终定稿前command:new// /new 命令触发command:reset // /reset 命令触发command:stop // /stop 命令触发gateway:startup // 所有 Channel 启动后Plugin Hooks(运行时生命周期)
Plugins 在 Gateway 同进程内运行,可以拦截整个 Agent 生命周期:
before_agent_start → agent_endbefore_compaction → after_compactionbefore_tool_call → after_tool_calltool_result_persistmessage_received → message_sending → message_sentsession_start → session_endgateway_start → gateway_stop实际应用案例:OpenClaw 自己用 Extension 实现了两个核心功能:
Context Pruning 扩展:静默修剪超大工具返回结果,节省 Token Compaction Safeguard 扩展:替换 Pi 默认的摘要管线,用多阶段管线确保文件操作历史和工具失败信息在压缩后依然保留
9、Heartbeat:不等你说话,它自己会醒来
OpenClaw 和普通聊天机器人的本质区别之一:它可以主动触发,不需要你发消息。
Heartbeat 子系统支持多种激活方式:
Cron 定时任务("每天早 8 点检查邮件") Webhook 触发(外部事件推入) Gmail 新邮件轮询 群组 @ 提及触发 声音唤醒检测
同时,每个"主动任务"运行在独立的 Docker 容器内——不污染主会话的对话状态,崩了也不影响主进程。
10、WebSocket 通信协议:客户端与 Gateway 怎么握手
最后补一层底层细节。
OpenClaw Gateway 是一个长驻 WebSocket 服务器(ws://127.0.0.1:18789)。客户端连接时的握手流程:
Client Gateway |--- req:connect ----------->| |<-- res (hello-ok) ---------| (presence + health snapshot) |<-- event:presence ---------| |<-- event:tick -------------| (心跳) |--- req:agent ------------->| (发送任务) |<-- res:agent (ack) --------| (runId + status:"accepted") |<-- event:agent (streaming)-| (流式内容) |<-- res:agent (final) ------| (runId + status + summary)信任模型:
本地连接(loopback / 同主机 Tailnet):自动授信 远程连接:必须签名 challenge nonce + 显式审批 设备 Token:配对后颁发,用于后续重连 OPENCLAW_GATEWAY_TOKEN对所有连接生效
这也是 CVE-2026-25253(CVSS 8.8)的攻击入口:漏洞版本的 Control Plane 存在未认证的 WebSocket 握手端点,攻击者可以发送特制帧实现宿主机级别的 RCE(远程代码执行)。v2026.1.29 已修复,未打补丁的部署应视为已全面沦陷。
11、Multi-Agent:让 AI 管 AI
2026 年 3 月,社区开发者 Gabriel Gondim 贡献了一个完整的确定性多 Agent 流水线方案,并向 OpenClaw 的工作流引擎 Lobster 提交了 PR #20(新增子工作流循环支持)。
核心架构思路值得单独说明:
[Lobster YAML 工作流](编排层,确定性) ↓ step 1: 调用 Programmer Agent ↓ step 2: 调用 Reviewer Agent(最多 3 次迭代) ↓ step 3: 调用 Tester Agent ↓ step 4: 提交 PR每个 Agent: 通过 agentToAgent RPC 接收任务 通过 sessions_send 传递上下文 LLM 只做创造性工作(写代码/审代码) 编排逻辑完全由 YAML 控制,不依赖 LLM 决策这个设计验证了一个反直觉的结论:最好的多 Agent 架构里,编排层本身不需要是 LLM。 LLM 负责智能,YAML 负责流程——各司其职。
12、一张图看懂所有层
用户消息(WhatsApp/Telegram/...) ↓[Channel Adapter] → 协议归一化 ↓[Gateway] → Session 路由 + Lane 串行队列 ↓[Agent Runner] → System Prompt 组装 + JSONL 历史加载 ↓[ReAct Loop] ↓ LLM 推理 → tool_call ↓ 工具执行(bash/read/write/browser/...) ↓ 结果追加历史 ↓ 继续推理... 直到 stop_reason=end_turn ↓[Context Guard] → 超限触发 Memory Flush + Compaction ↓[Memory System] → JSONL 树持久化 + Markdown 长期记忆 ↓[Streaming Reply] → 流式推回用户 + JSONL Transcript 写入最后想说的是,OpenClaw 的天才不在于它做了什么,而在于它把正确的东西组合在了一起——极简的 4 工具 Pi Core + 可靠的 Lane 队列 + 直觉式的 Markdown 记忆 + 精心设计的上下文压缩管线。每一层都不复杂,但叠在一起,就成了一台能连续工作的 AI 执行机器。
"The model provides intelligence; OpenClaw provides the operating system."
夜雨聆风