OpenClaw 这类项目,最容易被写偏。
只看 openclaw agent,它像一个 CLI;只看 extensions/,它像一个插件平台;只看 MEMORY.md,又像一个“给 Agent 做笔记”的文件系统。把源码、官方文档、运行链路和插件边界一起串起来后,我对它的判断更明确了:
OpenClaw 的本体不是聊天机器人,也不是一个“套壳模型调用器”。它是一套以 Gateway 为控制面、以嵌入式 Agent Runtime 为执行核、以 Tool/Plugin/Channel/Node 为扩展面、以 Context/Memory 为持续性机制的本地优先 Agent 平台。
这篇文章基于官方仓库 openclaw/openclaw 的本地源码快照分析,基线提交为 4792a50,提交日期 2026-04-23。我也额外翻了几篇社区文章和 memory 方向的讨论,发现一个普遍问题是:很多文章把 OpenClaw 写成了“一个带 MEMORY.md 的 AI 助手”,但源码里的真实结构比这复杂得多。
这次不再从启动细节直接扎进去,而是按下面这条主线来讲:
- 先讲整体框架,回答 OpenClaw 到底由哪几层组成。
- 再讲控制面、执行核、工具/插件、Channel/Node 这些模块各自的职责与设计。
- 最后单独深挖记忆系统,回答它为什么能“越来越聪明”,以及这种“聪明”到底是怎样实现出来的。
01 一张图先看懂:OpenClaw 的整体框架
图 1:OpenClaw 高层结构。入口很多,但主线很稳定:请求先进入 Gateway 控制面,再由 Gateway 驱动 Agent Runtime、Tools、Plugins、Channels 与 Nodes。
如果只保留最核心的分层,OpenClaw 可以理解成下面六层:
| 层 | 主要职责 | 关键源码 | 设计重点 |
|---|---|---|---|
| 入口层 | CLI 启动、参数路由、帮助快路径、异常托底 | openclaw.mjs、src/index.ts、src/cli/run-main.ts | 顶层尽量薄,重量级模块延后加载 |
| Gateway 控制面 | WS/HTTP 接入、鉴权、方法分发、事件广播、Channel/Node 统一接入 | src/gateway/server.impl.ts、src/gateway/server-methods.ts、src/gateway/server/ws-connection.ts | 把状态、连接、渠道、设备全部收口到同一个控制面 |
| Agent Runtime | Session 解析、workspace/bootstrap、模型选择、skills snapshot、转录和投递 | src/agents/agent-command.ts、src/agents/command/attempt-execution.ts | 不重写 Agent Core,而是在外层包一层厚 runtime |
| Tool 层 | 工具装配、权限过滤、sandbox 约束、平台工具暴露 | src/agents/pi-tools.ts、src/agents/openclaw-tools.ts、src/agents/tool-policy-pipeline.ts | 工具不是静态列表,而是动态装配后的有效工具集 |
| Plugin / Channel / Node | provider、channel、web/media、消息动作、设备能力接入 | src/plugins/runtime/index.ts、extensions/slack/index.ts、src/gateway/server-node-session-runtime.ts | Channel 和 Node 都是平台级能力,不是边缘外挂 |
| Context / Memory | 当前轮模型上下文、会话压缩、长期记忆检索、主动召回、Dreaming 晋升 | docs/concepts/context-engine.md、extensions/memory-core/src/tools.ts、extensions/active-memory/index.ts | 真正的“长期可用性”来自 memory/context 闭环,而不是单次 prompt |
这张表背后最重要的结论是:OpenClaw 不是把模型、工具和聊天 UI 放在一起,而是先做了一层控制面,再把 Agent 执行、会话状态、工具策略、扩展能力都编入这个控制面。
这也是为什么它看起来比很多 Agent 项目更“重”,但同时也更像一套真正能长期运行、可治理、可审计的系统。
02 一次请求到底怎么跑:先有控制面,再有回答
OpenClaw 的用户入口很多,但一轮请求大致都走这条路径:
openclaw.mjs和src/index.ts负责冷启动,尽可能少加载模块。- CLI 进入
runCli(),做环境初始化、路由分发和延迟注册。 openclaw agent默认优先走agent-via-gateway.ts,把请求发给 Gateway。- Gateway 完成握手、鉴权、session 解析和 RPC 分发,再调起实际的 agent run。
- Agent Runtime 组装本轮上下文:session、workspace、skills、模型、工具、memory/context。
- 模型执行中需要工具时,再走 Tool Policy 管线决定当前会话到底能看到哪些工具。
- 回复、工具结果、session 元数据、转录和事件流一起落盘或回推给 CLI、Web UI、Channel、Node。
这里最值得注意的是第 3 步:OpenClaw 的默认路径不是“CLI 直接调模型”,而是“CLI 先当成 Gateway 的一个 client”。
图 2:CLI 启动链路。入口做得很薄,复杂度被推迟到真正需要的时候才加载。
src/commands/agent-via-gateway.ts 里最关键的设计不是如何发请求,而是它的 fallback 策略:
- 正常路径:通过 Gateway 统一接管 session、状态、投递、事件流。
- 兜底路径:如果 Gateway 不可用,再回退到本地 embedded agent。
这意味着 OpenClaw 的基本哲学是:
单次回答只是平台的一种能力,真正的一等公民是“持续运行中的 Agent 会话”。
03 Gateway:OpenClaw 真正的控制中枢
图 3:Gateway 控制面。CLI、Web UI、Channel、Node、Cron 与自动化都会在这里汇合。
很多项目会把 Gateway 写成“请求转发器”。OpenClaw 不是。它的 Gateway 更像宿主进程里的控制内核。
3.1 Gateway 不是薄路由,而是长期运行的系统宿主
src/gateway/server.ts 本身很薄,只暴露 startGatewayServer();真正的复杂度都在 server.impl.ts。
这个文件负责的事情非常多:
- 配置快照与 override 合并。
- auth、TLS、secret、runtime service 初始化。
- plugin bootstrap。
- channel manager、cron service、request context、live state 建立。
- HTTP/WS server 启动。
- runtime subscription 和 event relay 接好。
这种组织方式说明 Gateway 在 OpenClaw 里不是“对外接口层”,而是整套系统的宿主。
3.2 Gateway 的方法表是显式维护的
src/gateway/server-methods.ts 会把所有 RPC 方法明确拼出来,例如:
connecthealthagentchat.*sessions.*channels.*cron.*devices.*skills.*models.*
这不是一个自动扫描控制器的框架式写法,而是一种平台协议显式化的写法。好处是边界清晰、协议可治理、审计更稳定;代价是实现厚一些,但对 OpenClaw 这种“本地长期运行的 Agent 平台”来说,这是值得的。
3.3 WebSocket 首帧握手被单独对待
源码里一个很容易忽略的点是:connect 不是普通的业务方法。
src/gateway/server-methods/connect.ts 甚至会直接提示 connect is only valid as the first request。真正的握手逻辑是在 src/gateway/server/ws-connection.ts 这一层完成的,握手时会单独处理:
- 连接预算
- handshake timeout
- payload size
- origin / host / user-agent
- role / scope 鉴权
- device identity 与 node pairing
这反映出一个很成熟的平台观:连接生命周期本身也是要治理的对象。
3.4 Node 和 Channel 不是外挂,而是同一协议体系里的角色
OpenClaw 的一个“平台味”很重的地方在于:
- Channel 不是“UI 皮肤”,而是通过 plugin contract 注册进系统。
- Node 不是“远程终端”,而是以
role=node的身份接入同一个 Gateway WS 体系。
这一点后面讲插件和设备接入时会更明显。
04 Agent Runtime:真正的复杂度不在模型调用,而在会话编排
如果说 Gateway 是控制中枢,那么 src/agents/agent-command.ts 就是 OpenClaw 的执行编排中枢。
4.1 先解决“这是谁、在哪、接着谁的会话说”
prepareAgentCommandExecution() 的职责不是调模型,而是先把运行上下文变完整。它会解决:
- 这次请求属于哪个
agentId - 对应的
workspaceDir/agentDir是什么 - 是新 session 还是续接旧 session
- 这轮是否允许延续历史
- bootstrap 文件和 workspace 是否准备好了
- 是 embedded session 还是 ACP session
这一步的价值非常大。很多 Agent 框架把“上下文”理解成 prompt 片段拼接,但 OpenClaw 在模型调用前先解的是运行时身份问题。
4.2 模型调用前,先把会话壳子套好
agentCommandInternal() 真正负责把下面这些东西串起来:
- session 状态与转录位置
- skills snapshot
- 模型选择、provider 解析与 fallback
- delivery runtime
- transcript / session entry 持久化
- 结果回传给 CLI、WebChat、Channel 或其他 peer
所以 OpenClaw 的“模型调用”其实被包在一层很厚的会话壳里。这个壳子的职责不是炫技,而是解决产品级问题:
- 模型坏了怎么办
- 会话切换怎么处理
- 输出如何持久化
- 多入口如何共享状态
- 子 Agent 如何隔离
4.3 OpenClaw 没有重写 Agent Core,而是有选择地复用
src/agents/command/attempt-execution.ts 明确依赖了 @mariozechner/pi-coding-agent 的能力。也就是说,OpenClaw 没有从零再造一个“推理循环内核”,而是把真正独特的复杂度放在外围:
- 会话编排
- 控制面接入
- 工具装配与权限收缩
- 多 Agent / 多入口 / 多设备管理
- memory/context 持续性机制
这是一个很成熟的工程取舍。因为很多项目会在最不值得重写的地方重写一遍,结果把精力消耗在“再造一个模型循环”上。OpenClaw 的做法更克制:能复用 Agent Core,就把火力留给 runtime 层。
05 Tool 系统:不是工具清单,而是动态装配出来的“有效工具集”
图 4:工具拼装过程。Pi Core 工具、OpenClaw 平台工具、插件工具、Channel 工具最终会经过策略管线过滤,形成当前 session 的有效工具集。
5.1 工具来源是多股拼装,而不是一份固定列表
src/agents/pi-tools.ts 很能体现 OpenClaw 的工具观。工具至少来自四类来源:
- Pi Core 自带 coding tools
- OpenClaw 平台自带工具
- plugin 暴露的工具
- channel 侧扩展出来的动作工具
也就是说,工具不是“代码里写死一张表”,而是随着 agent、session、sandbox、provider、channel、plugin enablement 动态变化的。
5.2 OpenClaw 暴露的是平台级工具
src/agents/openclaw-tools.ts 里新增的很多工具,其实已经不是“单机读写文件”这个级别了,而是对整个平台的控制接口,比如:
messagenodescrongatewaysessions_listsessions_historysessions_sendsessions_spawnsubagentsweb_searchimage_generatevideo_generate
这件事非常关键。它说明 OpenClaw 想让模型操作的,不只是本地文件系统,而是整套运行环境。
5.3 apply_patch 是很典型的平台级编辑工具
src/agents/apply-patch.ts 没有简单暴露“把整个文件重写”的接口,而是提供了 patch DSL:
*** Begin Patch*** Add File*** Update File*** Delete File
同时还可以限制 workspaceOnly,并桥接 sandbox。
这种设计背后的思想很明确:代码修改应该尽量可审计、可追踪、可做多文件结构化变更,而不是一把梭把整个文件覆盖掉。
5.4 工具权限不是一个开关,而是一条策略管线
src/agents/tool-policy-pipeline.ts 会串联多层策略:
tools.profiletools.byProvider.profiletools.allowtools.byProvider.allowagents.<id>.tools.allowagents.<id>.tools.byProvider.allow- group 级别覆盖
这意味着工具可见性不是单点配置,而是按 provider、agent、group、profile 叠加求解。
5.5 子 Agent 的权限还会继续收缩
src/agents/pi-tools.policy.ts 对 subagent 做了额外 deny,比如 gateway、cron、sessions_send 等平台级能力会被限制,叶子 subagent 上还会进一步收缩 subagents、sessions_history、sessions_spawn。
这说明 OpenClaw 并不是“每个 Agent 都给同一套神力”,而是开始认真治理谁可以调度谁、谁可以影响全局状态。
06 插件、Channel 与 Node:这部分决定了它像平台,而不是像单机助手
图 5:多 Agent 与多 Session 路由。入站消息会先被映射到 agent/workspace/session;Node 则作为另一类 WebSocket peer 接入同一个 Gateway。
6.1 Plugin Runtime 是正式运行时,不是配置附件
src/plugins/runtime/index.ts 暴露出来的不是“读取插件配置”,而是一整套 runtime facade,包括:
agentsubagentsystemmediawebSearchchanneleventstaskstaskFlow
而且很多能力用 lazy module 的方式延迟绑定。这跟 CLI、Gateway 的做法一致:顶层薄壳,真正用到时再挂载重能力。
6.2 Channel 是通过 contract 注册进系统的
比如 extensions/slack/index.ts 和 extensions/discord/index.ts 都是通过 defineBundledChannelEntry(...) 注册。
这意味着:
- core 不需要为每个渠道写分支判断
- channel 的能力边界由插件 contract 决定
- 能力发现、schema 拼装、动作执行可以被插件化
这是一种非常“平台化”的做法。
6.3 message 工具是统一入口,具体动作由 channel runtime 决定
OpenClaw 并没有让核心 runtime 直接写 Slack/Discord/Telegram API。它的做法是:
- 统一暴露
message工具。 - 让当前 channel runtime 声明自己支持哪些 message actions。
- 动态拼出当前可用 schema。
- 真正执行时再下沉到 channel plugin。
也就是说,core 只负责统一体验,plugin 负责落地执行。
6.4 Node 也是平台协议中的一等角色
src/gateway/server-node-session-runtime.ts 和 src/node-host/config.ts 说明,macOS、iOS、Android 或 headless 设备在 OpenClaw 里不是边缘工具,而是通过 WS 协议、配对 token、node registry、event relay 明确纳入了统一控制面。
这也是为什么 OpenClaw 给人的感觉不像“聊天工具”,而更像“个人 Agent 操作系统”。
07 记忆系统:不是一个 MEMORY.md,而是一条完整闭环
这是这篇文章最值得展开的部分。
很多外部文章会把 OpenClaw 的 memory 简化成一句话:“它把记忆存到 Markdown 文件里。”这句话不算错,但只说了最表面的一层。真正的源码实现至少包含五段链路:
- 明文记忆文件层
- 检索与索引层
- 主动召回层
- 短期信号晋升与 Dreaming 层
- Compaction 前的记忆保全层
图 6:OpenClaw 记忆闭环。记忆文件只是底座,真正让系统“越用越顺手”的是 recall、tracking、promotion 与 flush 之间的联动。
7.1 先把三个概念分开:Memory、Context、Compaction
OpenClaw 的官方文档其实讲得很清楚,但社区文章常把它们混在一起。
| 概念 | 它是什么 | 核心职责 | 对应源码 / 文档 |
|---|---|---|---|
| Memory | 落在磁盘上的可持续知识 | 跨会话保存事实、偏好、决策、每日笔记 | docs/concepts/memory.md |
| Context | 当前这一轮真正送进模型的上下文 | 决定模型此刻“看到了什么” | docs/concepts/context-engine.md |
| Compaction | 当上下文太长时做的摘要压缩 | 保持会话继续跑下去 | docs/concepts/compaction.md |
一句话概括:
- Memory 决定“哪些东西能活到下一次会话”。
- Context 决定“模型这一次到底看见了什么”。
- Compaction 决定“上下文满了以后如何不丢主线继续聊”。
这三个概念不分清,很容易把 OpenClaw 的持续性机制看扁。
7.2 第一层:记忆文件是显式的、明文的、可编辑的
官方 memory 文档给出的核心文件只有三个:
MEMORY.md:长期记忆,适合稳定事实、偏好、长期决策。memory/YYYY-MM-DD.md:每日笔记,保存运行中的上下文和当天观察。DREAMS.md:Dreaming 的日记和阶段输出,方便人审阅。
这套设计看起来很朴素,但它的优点很硬:
- 透明:你能直接看到 Agent 记住了什么。
- 可控:记错了就能人工改。
- 可迁移:不依赖隐藏状态和闭源后端。
从工程角度看,OpenClaw 明确选择了“文件优先”的记忆哲学,而不是先做一个神秘数据库。
7.3 第二层:真正可用的记忆,不靠文件名,而靠检索系统
只把内容写到 MEMORY.md 或 memory/*.md 并不等于会用。真正把记忆变成能力的是检索层。
extensions/memory-core/src/tools.ts 里,memory_search 的工具描述写得很重,它把自己定义成:
- 回答“以前做过什么、谁喜欢什么、有什么待办、过去做了什么决定”时的 mandatory recall step
- 默认搜索
MEMORY.md + memory/*.md - 还可以扩展到 session transcripts 或 wiki corpus
也就是说,memory 在 OpenClaw 里不是“想到再查”,而是被设计成回答历史问题前应当显式使用的工具能力。
7.4 第三层:检索不是全文搜索,而是 hybrid recall
extensions/memory-core/src/memory/manager.ts 的 MemoryIndexManager 才是 memory-core 的核心。它负责:
- 读取和索引
MEMORY.md、memory/*.md - 管理 embedding provider
- 维护 SQLite / vector / FTS 状态
- 监听文件变化并增量同步
- 在必要时做一次 bootstrap sync
搜索阶段并不是单一路径,而是 hybrid:
- 语义向量检索
- BM25 关键词检索
- weighted merge
- 可选 temporal decay
- 可选 MMR 去重重排
extensions/memory-core/src/memory/hybrid.ts 明确把向量分和关键词分加权合并;temporal-decay.ts 则会对旧 daily note 做时间衰减,默认半衰期 30 天,而像 MEMORY.md 这样的 evergreen 文件不会衰减。
这很重要,因为它说明 OpenClaw 的记忆不是“把所有历史都一锅端给模型”,而是先做检索,再做排序,再决定哪些片段真正进入上下文。
7.5 第四层:Active Memory 让系统在回答前先“回想一下”
很多 Agent 的问题不是没有 memory,而是 memory 太被动。必须用户自己说“帮我查一下以前怎么做的”,系统才会检索。
extensions/active-memory/index.ts 解决的就是这个问题。它实现的是一个阻塞式、插件拥有的前置记忆子 Agent:
- 在主回复前先跑一次
- 只对符合条件的会话生效
- 默认 query mode 是
recent - 默认 timeout 是
15000ms - 最终把结果注入为 hidden untrusted prompt prefix,而不是直接暴露原始 prompt 标签
这层能力的意义很大。它让记忆从“用户要求时才查”变成“系统在回答前先做一次有界的回忆”。
换句话说,Active Memory 做的不是多一个数据库,而是多了一次回答前的认知准备动作。
7.6 第五层:真正让它“越来越聪明”的,是 recall tracking 和 promotion
如果只做到前四层,OpenClaw 已经有长期记忆和主动召回了,但还不够“进化”。真正让它具备持续学习味道的,是 recall tracking 和 Dreaming promotion 这条链。
关键逻辑在 extensions/memory-core/src/short-term-promotion.ts。
这里有几件非常关键的事:
- 每次
memory_search给出结果后,系统会 best-effort 记录本次 recall。 - 这些 recall 事件会写到
memory/.dreams/short-term-recall.json。 - 每条候选会累计
recallCount、queryHashes、recallDays、conceptTags、totalScore、maxScore等信号。 - 只有达到 promotion threshold 的候选,才有资格被 Dreaming 晋升进长期记忆。
默认门槛也写得很明确:
DEFAULT_PROMOTION_MIN_SCORE = 0.75DEFAULT_PROMOTION_MIN_RECALL_COUNT = 3DEFAULT_PROMOTION_MIN_UNIQUE_QUERIES = 2
这组阈值的意义在于:OpenClaw 并不希望“被提到过一次的东西”直接污染长期记忆,它更偏向把“多次被召回、在不同查询语境下仍然有用的内容”升级成长期记忆。
这就是一个很典型的“短期信号 -> 稳定知识”的过滤机制。
7.7 第六层:Dreaming 负责把高价值短期信号晋升成长期记忆
extensions/memory-core/src/dreaming.ts 和 dreaming-phases.ts 负责 Dreaming 的调度与阶段处理。
它做的事情不是“无脑把短期记录搬到 MEMORY.md”,而是:
- 收集短期 recall 信号
- 做分阶段处理与筛选
- 把过程输出到
DREAMS.md - 最后只把合格项 promotion 到
MEMORY.md
官方文档也明确说明 Dreaming 是可选能力,而且默认不是强制开启。这一点非常重要,因为它意味着 OpenClaw 的“越来越聪明”不是凭空发生的,而是一个可配置、可关闭、可审查的机制。
7.8 第七层:Compaction 之前,OpenClaw 还会先做一次 memory flush
这是我觉得源码里最容易被忽略、但其实非常关键的一层。
src/auto-reply/reply/agent-runner-memory.ts 在会话接近 context limit 时,不会直接 compaction,而是先检查是否需要做 memory flush。
如果触发,它会:
- 先跑一轮 silent embedded agent turn
trigger标记为memory- 给这轮运行单独指定
memoryFlushWritePath - 引导 agent 先把重要、耐久的内容写入 memory 文件
- 然后才进入 compaction
这意味着 OpenClaw 在设计上非常清楚一个事实:
如果不先把重要事实写到 memory 文件里,compaction 再漂亮,也只是在“压缩遗忘”。
这层 memory flush,解决的是“上下文溢出前如何先把该留住的东西留住”。
7.9 第八层:还有两个补充机制,经常被漏讲
第一个是 session-memory hook。
src/hooks/bundled/session-memory/handler.ts 会在 /new 或 /reset 时,把最近 session 内容整理成一个带日期和 slug 的 memory 文件。它不是主记忆机制,但对“切换会话前的上下文归档”很有用。
第二个是 memory-wiki。
extensions/memory-wiki/README.md 明确写了:它不是 active memory 的替代品,而是一个编译型知识层。它会把 durable memory 编译成带 provenance、claim/evidence、dashboard 的 wiki vault。也就是说:
memory-core负责 recall、promotion、dreamingmemory-wiki负责把长期知识整理成更像知识库的形态
这个分层很合理,因为它把“怎么回忆”与“怎么治理长期知识”分成了两件事。
08 OpenClaw 为什么会“越来越聪明”
如果只用一句话回答,这句话应该是:
OpenClaw 变“聪明”,不是因为模型自己长了记忆,而是因为它把“持久化、检索、主动召回、晋升、压缩前保全”做成了一条闭环。
更具体一点,可以拆成四个层面。
8.1 它会越来越会“记住对你有用的东西”
只要 memory 文件写得对,系统就能跨会话保留:
- 用户偏好
- 项目背景
- 历史决策
- 长期待办
- 常见坑和经验
这不是模型能力的提升,而是运行时连续性的提升。
8.2 它会越来越会“在回答前先想到相关历史”
如果开启 Active Memory,它在主回复前就会做一次 bounded recall。用户不需要每次显式说“回忆一下我之前喜欢什么”,系统自己会先尝试把 relevant memory 拉进来。
这提升的是交互自然度。
8.3 它会越来越会“把真正高频有用的东西升级成长期知识”
短期 recall 不是立即 promotion,而是先打分、统计重复召回次数和查询多样性,之后再通过 Dreaming 进入 MEMORY.md。
这提升的是长期知识质量,而不是单次回答速度。
8.4 它会越来越不容易在长会话里“把重要东西聊丢”
Compaction 前的 memory flush 让系统在上下文快爆掉时,先做一次耐久化保全。这意味着长会话中的关键事实更不容易被摘要吞掉。
这提升的是上下文完整性。
09 但也别神化:它的“聪明”有明确边界
写源码解析时,最容易滑向 marketing。OpenClaw 的 memory 系统确实做得比很多项目完整,但它的边界也很清楚。
9.1 它不会自动提升底层模型的推理上限
OpenClaw 能做的是:
- 让模型拿到更相关的历史
- 让偏好和决策更连续
- 让长期知识更稳定进入上下文
它不能做的是把一个弱模型直接变成强模型。
9.2 它的长期表现仍然依赖记忆质量
如果 MEMORY.md、daily notes、Dreaming promotion 的内容本身噪声很大,那么系统只会更稳定地把噪声带进未来会话。
所以 OpenClaw 的核心不是“永不遗忘”,而是“显式、可审计地管理遗忘与保留”。
9.3 “越来越聪明”这件事依赖功能是否开启
这点需要说得很具体:
memory-core的文件记忆和检索机制是基础层。active-memory是可选的主动召回增强层。dreaming是可选的晋升层,而且默认不是强制开启。
也就是说,如果你没有启用主动召回和 Dreaming,那它更多体现为“有长期记忆和 recall 能力”;如果你把这两层也打开,才更接近大家口中那种“越用越懂你”的体验。
10 我对这份源码的总体评价
读完整个仓库后,我认为 OpenClaw 最值得学的是四件事。
10.1 最值得学的地方
第一,控制面收口很彻底。
CLI、Web UI、Channel、Node、Cron、自动化任务最终都归到 Gateway 上,这让状态一致性、可治理性和扩展一致性明显更强。
第二,它把最宝贵的复杂度放在了 runtime,而不是重复造轮子。
Pi Core 负责推理循环,OpenClaw 把主要精力投入在 session、delivery、tool policy、plugin runtime、memory/context 这类真正影响产品体验的地方。
第三,它对 memory 的理解比“写个 MEMORY.md”成熟得多。
文件层、检索层、主动召回层、promotion 层、compaction flush 层叠加起来,才构成了现在这套比较完整的持续记忆体系。
第四,它已经有平台级抽象,而不是 feature pile。
Channel contract、plugin runtime、node registry、tool policy pipeline 这些抽象都说明,作者不是在不停堆功能,而是在试图让能力长期可维护。
10.2 也确实存在的代价
第一,系统复杂度非常高。
像 server.impl.ts、agent-command.ts 这种文件,单看一个文件很难吃透,必须跨模块连读。
第二,很多关键能力的边界不在单文件里。
比如 memory 就得同时看 docs、tool、manager、active-memory、dreaming、compaction 才能讲完整。
第三,配置面已经很宽。
这对高级用户是优势,对普通用户则是学习门槛。
但总体上,我依然会给出一个很明确的判断:
OpenClaw 最大的价值,不是“能调用很多模型和工具”,而是它已经把 Agent 从一次性 prompt 工具,推进成了一套可持续运行、可积累知识、可接入多端、可治理权限与状态的平台运行时。
如果你是做 Agent 工程的人,这个仓库真正值得读的,不是某个 prompt,也不是某个花哨插件,而是它如何把控制面、执行核、扩展边界、记忆闭环四件事同时做起来。
11 参考资料
下面这些资料里,官方源码和官方文档是本文的事实基线;社区文章我主要拿来对比“外界通常会怎么误读 OpenClaw”,不把它们当最终依据。
官方源码与文档
社区文章与讨论
- Building a memory system for OpenClaw
- OpenClaw Dreaming Guide: Memory Consolidation Explained
- OpenClaw Memory Architecture Explained
一句话总结
如果只看表层,OpenClaw 像一个会调用工具的聊天助手;如果顺着源码往下读,它更像一套本地优先、控制面收口、具备长期记忆闭环的 Agent 平台。真正让它与普通 Agent 项目拉开差距的,不是某个模型接入,而是它把“会话、工具、插件、节点、记忆”这些本来分散的问题,收敛成了同一套运行时体系。