OpenClaw进阶:如何通过九层塔架构打造高效能AI Agent
OpenClaw Agent 的长期记忆、主动召回与自我进化架构
一个真正长期运行的 AI Agent,需要的不是更大的上下文窗口,而是一套完整的上下文治理体系。
基于 OpenClaw 多 Agent 环境三个多月的实际运行经验,以及近一个多月对九层上下文架构的集中升级与整理。九层塔不是一次性设计出来的,而是在解决一个又一个实际问题的过程中逐步演化而成。运维治理本身也是架构成熟的一部分。
引言:大窗口的幻觉#
上下文窗口从 4K 到 128K 再到 1M+,很多人以为”窗口够大就不需要记忆管理了”。
这是一个危险的幻觉。
窗口变大解决的是”能放多少”,但没有解决:
-
放什么进去? -
什么时候放? -
过期的怎么清? -
跨会话怎么延续? -
多 Agent 怎么共享又隔离? -
错误记忆怎么修正? -
经验怎么沉淀成能力?
这些问题,不是靠”更大的窗口”能解决的。它们需要的是 Context Engineering——对上下文的工程化治理。
本文介绍一套在 OpenClaw 多 Agent 环境中运行三个多月、并在近一个多月集中升级整理出的上下文管理架构。我们称之为”九层塔”。
从三层到九层:为什么简单记忆不够#
最基础的记忆架构分三层:
- Layer 0
:身份与规范(静态,低频修改) - Layer 1
:知识积累与检索(持续增长) - Layer 2
:驱动行动(实时运转)
三层架构能让 Agent “记住东西”。但当你开始长期运行——跨天、跨周、多会话、多 Agent 协作——你会发现三层不够:
- 记忆膨胀
:文件越来越多,bootstrap 注入被截断 - 噪声累积
:系统日志、heartbeat、maintenance 消息混入记忆 - 召回失败
:记了但找不到,或找到的不是最相关的 - 压缩丢失
:长会话被 compaction 后,关键决策丢了 - 重复劳动
:同样的任务做了十次,每次从零开始
九层塔就是为了解决这些问题而逐步演化出来的。
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
九层塔不是替代三层架构,而是在三层之上回答了”系统化治理”这个新问题。两者读起来可对比,但本文不依赖你读过前文。
九层塔总览#
|
L9 |
能力进化层⚠ 3 经验 → 可复用技能 |
|
L8 |
自我迭代层⚠ 5🚨 2 错误 / 反馈 → 行为规则 |
|
L7 |
后台整理层⚠ 3🚨 1 短期上下文 → 长期记忆 |
|
L6 |
会话生存层⚠ 5🚨 2 Lossless Context Engine / compaction / flush |
|
L5 |
主动召回层⚠ 3🚨 1 消息前自动注入相关上下文 |
|
L4 |
语义检索层⚠ 4🚨 1 embedding / search / fallback |
|
L3 |
文件记忆层⚠ 3 Markdown 长期事实 |
|
L2 |
规则治理层⚠ 3 行为边界 / 工具协议 |
|
L1 |
身份注入层⚠ 3 身份 / 用户 / persona |
⚠ 数字 为常见坑数 · 🚨 数字 为高严重度坑数
三组,每组三层:
- 基础层(L1-L3)
:定义 Agent 是谁、该怎么做、记住了什么 - 运行时层(L4-L6)
:让记忆在对话中真正发挥作用 - 进化层(L7-L9)
:让系统随时间变得更好
L1身份注入层:Agent 是谁#
解决的问题:Agent 需要一个稳定的身份锚点,否则在长对话或多 Agent 场景中会”人格漂移”。
OpenClaw 中的实现:
SOUL.md
— 定义人格、语气、行为边界 IDENTITY.md
— 基本信息:名字、角色、emoji USER.md
— 用户画像:偏好、沟通风格、技术栈
关键设计:这些文件在每次 session 启动时自动注入 context window,不依赖 Agent 主动读取。
常见坑:
-
身份文件写得太长,挤占有效上下文空间 -
多 Agent 场景中,从 chat history 推断身份而非从配置文件确认 -
persona 写得太强,压过任务目标
L2规则治理层:Agent 该怎么行动#
解决的问题:Agent 需要明确的操作边界——什么能做、什么不能做、怎么做。
OpenClaw 中的实现:
AGENTS.md
— 操作手册:读写边界、协作协议、安全规则 TOOLS.md
— 工具使用规范:什么场景用什么工具 -
Bootstrap 配置 — 启动时的行为指令
关键设计:规则分层——身份规则 > 安全规则 > 任务协议 > 工具偏好。优先级明确,冲突时高优先级覆盖。
常见坑:
-
规则堆太多,Agent 遵循率下降 -
规则没有分层,任务协议和人格描述混在一起 -
缺少”完成后必须汇报 / 落盘”的闭环要求
L3文件记忆层:长期事实载体#
解决的问题:Agent 需要一个持久化的、可人工修正的知识库。
OpenClaw 中的实现:
memory/ shared/ ← 所有 Agent 可读写:项目、偏好、决策 daily/ ← 每日共享日志 private/ ← 各 Agent 私有记忆 self-improving/ ← 行为改进记录
关键设计:
-
Markdown 格式:可读、可 diff、可版本控制、可人工修正 -
shared / private 分区:多 Agent 协作时既共享又隔离 -
写入规则明确:什么信息写哪里,由 AGENTS.md 定义
常见坑:
-
MEMORY.md 变成垃圾桶,什么都往里塞,导致 bootstrap 截断 -
shared 区被某个 Agent 意外覆盖 -
短期日志和长期事实混在一起,信噪比下降
L4语义检索层:从记忆中找上下文#
解决的问题:记忆文件越来越多,不可能全部塞进 prompt。需要按需召回。
OpenClaw 中的实现:
-
向量索引(embedding)+ 混合搜索(BM25 + semantic) -
多源检索:memory 文件 + session transcript -
Fallback 机制:primary backend 超时时降级到 builtin index
关键设计:
-
不只是”向量相似度”,还有 temporal decay(时间衰减)和 MMR(多样性) -
索引定期更新(扫描 + embedding) -
搜索结果有质量阈值,不是”找到就注入”
工程 Insight:
搜索 timeout 从 15s 提到 60s 只解决了配置层问题。真正的瓶颈在 query expansion + LLM rerank 路径。搜索系统需要区分:索引是否更新、embedding 是否覆盖、query path 是否稳定、ranking 是否符合预期。
常见坑:
-
只看”文件已索引”,忽略 embedding 覆盖率 -
Fallback 静默工作,掩盖 primary backend 的性能问题 -
exact query 被日志文件排在源文件前面(rerank 偏差) -
检索 CLI 的 stdout 不是干净 JSON——遇到 collection 不存在 / 参数异常时会先打印 Warning:或Usage:文本再给 JSON。下游 parser 必须容错地跳过非 JSON 前缀,抛错会让多 collection 路径整体退化到慢 fallback -
per-agent 索引会累积大量 orphan 向量(content 已删但 vector 留着),需要周期性 cleanup;orphan 占比 > 50% 是 sqlite 体积膨胀的常见原因
L5主动召回层:消息前自动带上下文#
解决的问题:用户不应该每次都说”帮我查一下记忆”。系统应该自动判断需要什么上下文。
OpenClaw 中的实现:
-
Active Memory 插件:在用户消息进入 Agent 前,自动搜索相关记忆 -
将召回结果压缩为短摘要注入 prompt -
结果标记为 untrusted context:明确告知 Agent 这部分内容来自自动召回而非用户原话,可质疑、可忽略、可反向校验,不作为权威事实直接采用
关键设计:
-
主动召回 ≠ 无脑注入。有质量阈值、空结果过滤、相关性判断 -
注入内容明确标记来源,Agent 可以选择忽略 -
对慢 query 可以选择更轻的搜索模式
常见坑:
-
低质量摘要污染当前对话 -
Active memory 输出被误当作 trusted fact -
召回 subagent timeout 太短,导致频繁空结果 - 检索后端单点失败传染整条召回链
:active memory 调底层多 collection 检索时,任一子查询抛错会让整条召回退化到 builtin slow path(>10s / 0 hits)。L4 parser 必须 fail-soft(warn + 返回空数组),主动召回层才能稳定
L6会话生存层:长会话不丢上下文#
L6 是九层塔最复杂、也最容易”安静吃亏”的一层——本节多数 critical 标注集中在这里,建议慢读。
解决的问题:长对话会超过模型上下文窗口。只靠简单截断或一次性 compaction,会让早期约定、任务状态和关键决策从当前对话里消失。
OpenClaw 中的实现:
-
Lossless Context Engine(lossless-claw):作为 plugins.slots.contextEngine的运行时上下文引擎,实时摄入消息,并用 DAG / 摘要 / 分层压缩来组装下一轮模型上下文 -
Session Memory hook:实时保存会话 transcript,保留可审计的原始时间线 -
Compaction Memory Flush:压缩前自动将重要信息写入 durable memory,作为最后一道持久化防线 -
Session transcript 被索引,可供 L4 语义检索和后续 Dreaming 使用
关键设计:
-
L6 的中心不是单纯 flush,而是”运行时上下文生存”:谁负责摄入、压缩、组装当前会话 -
检索层回答”该找回什么长期记忆”,context engine 回答”当前这条长会话怎样继续保持连贯”——两者互补,不互相替代 -
memoryFlush / safeguard compaction 是 fallback safety rail,不是替代 context engine 的主机制 -
长任务应该外化 plan 到文件,而不是只存在 context 里 - 必须显式绑定
plugins.slots.contextEngine
:不绑不会报错,只会悄悄退化到 legacy 截断引擎(详见 坑 #6) - 摘要 LLM 调用前必须 regex redact secrets
:否则 sk-XXX / token 会经 FTS + vector 持续放大注入(详见 坑 #7) - 短源 (< 200 tokens) 跳过 summarizer
:避免”摘要 = timestamp + 原文”的反向膨胀(详见 坑 #8)
工程 Insight:
compaction / heartbeat / system prompt 被写入 transcript 后,可能被后台整理层(L7)错误晋升为长期记忆。会话生存层和后台整理层之间需要噪声过滤机制。
Secrets 在 raw 消息里容易识别(grep 一抓一个准),但 LLM 摘要把它换个上下文重新表述后,固定的 grep 规则就不一定 catch 得到了。在源头 redact 比事后 audit 容易得多——这是 L6 必须正视的安全责任。
常见坑:
-
只依赖大窗口模型,不做显式 context engine / 持久化治理 -
把 memoryFlush 当成主机制,而不是 fallback safety rail -
长任务没有外化 plan,压缩后目标漂移 -
系统消息混入 transcript,污染下游
L7后台整理层:Dreaming 消化上下文#
解决的问题:短期记忆和 session transcript 会无限增长。需要定期整理、去重、提炼。
OpenClaw 中的实现:
-
Memory Core Dreaming:每日自动运行 -
Deep sleep:修复 recall store -
Light sleep:从 session corpus 中提炼候选记忆 -
REM:生成摘要和关联 -
Post-sweep watchdog:检查 Dreaming 产物、清理噪声、统计健康指标
关键设计:
-
Dreaming 不是简单的”把所有东西都记住”,而是有选择地晋升 - Promotion threshold
:只有高价值内容才会从短期进入长期 -
噪声清理是 Dreaming 的必要后置步骤 - L7 还要监控 L6 引擎本身
:context engine 是个安静失败的组件(不写入即等于沉默)。L7 应当包含一个周度健康监控 cron,监控 lcm.db 增长、DAG leaf / condensed 比例、WAL 状态。否则一次配置回归可能要 40 天才被发现
工程 Insight:
Dreaming 会把 heartbeat、maintenance、compaction 通知等系统噪声纳入候选。因此需要 post-sweep watchdog:每天 Dreaming 完成后自动清理噪声、统计 promotion ratio、报告异常。典型数据:每天清理 200+ 行噪声,promotion 率约 4-6%。
健康监控阈值要分级——🔴 才告警(ingest 沉默 / lcm 停摆 / WAL 损坏),🟡 只写报告不打扰(DAG 浅 / WAL 滞后),🟢 静默通过。否则告警疲劳会让真问题被淹没。
常见坑:
-
后台任务成功但报告投递失败,无人知道结果 -
噪声进入 corpus 后被长期污染 -
Promotion threshold 太宽,低价值内容晋升
L8自我迭代层:从错误中改进行为#
解决的问题:Agent 会犯错。同样的错误不应该犯第二次。
OpenClaw 中的实现:
memory/self-improving/ hot/ ← 当前活跃的行为信号 corrections/ ← 被纠正的错误记录 signals/ ← 观察到的行为模式 shared-rules/ ← 晋升为稳定规则的条目
关键设计:
-
错误记录 → 信号积累 → 规则晋升:不是一次犯错就改规则,而是重复出现才晋升 -
shared-rules 跨 Agent 共享:一个 Agent 的教训,所有 Agent 受益 -
有 reviewer 和 threshold,防止规则膨胀 - agent identity 用唯一规范
:自我迭代目录用 agent id( agent-A/agent-B/ …),不用 persona name(Persona-A/Persona-B这类用户自定义显示名)。所有跨进程协作(cron、patrol、promotion)用同一份 mapping - cron payload 用绝对路径
:周期性自反思任务里写 memory/self-improving/X/hot.md这种相对路径会被不同 cwd 解析到不同 workspace,造成同一 agent 的内容分裂到多处。统一用/root/.openclaw/workspace/memory/self-improving/<id>/...的绝对路径 - patrol 用枚举白名单
: KNOWN_AGENTS+KNOWN_FILES列表化,扫到不在白名单的就报警。这能在第 1 周内发现命名漂移、拼写错误(如corrrections.md多打一个 r)、persona vs agent-id 大小写分裂
常见坑:
-
把一次性偏好过早晋升为全局规则 -
没有 deprecation 机制,过时规则永远存在 -
目录命名不一致,导致扫描漏项 -
persona name vs agent id 双轨命名不统一,cron 跟 patrol 各走各的写出多份目录 -
cron payload 用相对路径,cwd 一漂全军覆没
L9能力进化层:把经验变成技能#
解决的问题:Agent 反复做同样的事情,每次从零开始。经验应该固化为可复用能力。
OpenClaw 中的实现:
-
Skill Evolution:从历史任务中 harvest → synthesize → review → promote -
产出的 skill 存入 shared-skills 目录,所有 Agent 可调用 -
定期审计:清理过窄、过时、重复的 skill
关键设计:
-
技能不是手动写的,而是从实际任务中自动提炼 -
有 review 环节:不是所有 workflow 都值得变成 skill -
技能有生命周期:创建 → 使用 → 验证 → 可能 deprecate
常见坑:
-
技能过窄,只适用于特定场景 -
命名差,其他 Agent 找不到 -
私有上下文被错误抽象成 shared skill
九层之间的数据流#
点击任一节点跳到对应章节 · 虚线表示跨轮闭环
这不是线性流程,而是一个闭环。每一层的输出都是其他层的输入。
搭建路径建议#
不需要一次性搭建九层。建议分阶段:
第一阶段:基础可用(L1-L3)
|
第二阶段:检索与召回(L4-L6)
|
第三阶段:自动进化(L7-L9)
|
源码层的小修整:把开源组件做成”工程资产”#
诚实地说,把九层塔落到生产时,光配置是不够的。前文 L4(parser fail-soft)和 L6(摘要前 redact secrets / 短源跳过 LLM)提到的几处问题,都需要在开源组件源码上做小幅适配。
这一节不再重复”改什么”,重点谈”怎样让这种修改活下去”——临时 hotfix 会随着 npm 升级或上游 git pull 失效;只有做成可观测、可重启自愈的工程资产,才能真正成为架构的一部分。最佳实践是:
|
|
|
|---|---|
|
|
// PATCH:<name> 注释,apply 脚本据此判断幂等 |
|
|
|
|
|
ExecStartPre 自动跑 apply 脚本——上游覆盖目标后下次重启自动重打 |
|
|
|
|
|
.patch
|
|
|
|
让对开源组件的小修整可被持续维护,而不是”换台机器就丢”。
运维真心话:14 个最容易踩的坑#
九层塔架构清单容易看,但落地时会反复踩一些坑。以下是从实际运行里整理出的高频陷阱,按层归类:
筛选全部14L1–L31L44L52L64L72L82运维1🚨 高严重度2
|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
context engine slot 没绑定 = 安静失败 |
|
plugins.slots.contextEngine
|
|
|
LLM 摘要把 secrets 经 FTS 放大 |
|
|
|
|
|
|
|
|
|
|
|
ignoreSessionPatterns
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
. 被默认忽略 |
|
/etc/sudoers.d/X.tmp
X 不带后缀 |
没有匹配的坑。换一个筛选条件试试。
其中 #6 和 #7 是这套架构最容易”安静吃亏”的两点:context engine 不绑 slot,整个 L6 等于没装;摘要器没做 secrets redaction,secrets 会经 FTS 持续放大。这两条强烈建议在搭建 L6 时就一次到位。
结语#
九层塔不是为了复杂而复杂——长期运行的 Agent 面临的问题天然分布在九个不同维度(身份 / 规则 / 记忆 / 检索 / 召回 / 会话生存 / 整理 / 自我迭代 / 技能化),缺一层就会在某个时刻”漏出来”。
好的 Agent 不是”记得更多”,而是知道什么该记、什么时候召回、何时压缩、如何清噪、怎样从经验中进化。
这就是 Context Engineering 的本质:不是管理上下文的大小,而是把上下文的整个生命周期做成 可观测、可修复、可进化 的工程闭环。
夜雨聆风