记忆与知识

小龙虾HOOK记忆研究-虾说蓉城

文章目录
  1. 一、定位与性质
  2. 调用链路
  3. 二、接受的事件对象
  4. 三、可返回的结果
  5. 四、OpenClaw 现有记忆系统全貌
  6. 当前体系的短板
  7. 五、优化记忆系统的三条路线
  8. 方案 A:用 before_prompt_build 做主动记忆注入(轻量级)
  9. 方案 B:基于 Context Engine 的 systemPromptAddition(更深度)
  10. 方案 C:改进现有的 Active Memory 配置(改动最少)
  11. 六、方案对比
  12. 七、后续行动建议
蓝色像素虾在 prompt 构建前的插件钩子链路中注入上下文
图 1:before_prompt_build 是提示词构建阶段的插件插口,具体能力取决于运行时。

原报告生成于 2026-05-07;2026-10-13 按 OpenClaw 官方仓库提交 5584b0ad 复核。 本文讨论插件契约与方案设计,不是已部署插件的实测记录。


一、定位与性质

before_prompt_build 是插件钩子(Plugin Hook),不是 agent:bootstrap 这样的内部钩子。使用 api.on("before_prompt_build", handler) 注册,处理器收到两个参数 (event, ctx)。

调用链路

在 embedded / CLI 的提示词准备路径,可以概括为:

消费排队的注入
→ agent_turn_prepare
→ heartbeat_prompt_contribution(心跳时)
→ 普通 before_prompt_build
→ 工具策略最终确定
→ requiresToolAuthority 授权后的 before_prompt_build
→ before_agent_run(该运行时支持时)
→ 模型提交

模型解析、回复短路、自然答案最终验收和结束观察属于其他生命周期位置,不能全部串成一条“所有运行时都会经过”的流水线。当前源码的类型列表也已不再列出 before_agent_start,新插件应使用明确的阶段钩子。

关键结论:它能修改提示词,但不能称为“所有主模型调用前最后一个改 prompt 的位置”。Context Engine、运行时适配与授权后的增强阶段都会影响最终输入。before_agent_run 在 embedded / CLI 可作输入门控;不要据此推断 Codex / Copilot 也有相同门控,node admission 也不提供节点最终组装的 system prompt。官方 Hook 契约、运行时边界。


二、接受的事件对象

// 关键类型摘录;event 与 ctx 是分开的参数
type BeforePromptBuildEvent = {
  prompt: string;
  messages: unknown[];
  currentUserMessage?: string;
  currentUserMessageId?: string;
};

不是 event.context.prompt,也没有这里通用可读的 event.context.systemPrompt。prompt 是已准备输入,可能带重建历史;需要识别本次意图时优先用 currentUserMessage。它为显式空串时,表示本次没有文本输入,不能回退到历史。ctx 提供 agent/session 等运行上下文,部分字段可能缺失。源码类型。


三、可返回的结果

最终工具策略经授权检查后允许有界检索和文本增量
图 2:工具支持的数据增强应核对本轮权限,返回的只是本轮文本增量。
字段 作用
prependContext 在该轮准备的 prompt 前添加上下文,不等于插到整个历史列表最前
appendContext 在该轮准备的 prompt 后添加上下文
systemPrompt 提供系统提示覆盖,效果须核对目标运行时
prependSystemContext 添加系统提示前缀
appendSystemContext 添加系统提示后缀
toolsAllow 只能缩小该轮工具集合;多个 hook 的限制取交集,部分运行时拒绝此能力

多处理器按优先级顺序合并;第一个已定义的 systemPrompt 获采用,文本增量拼接。这只是插件结果合并规则,不是模型的安全指令优先级。系统文本位置、插件 priority 都不能替代工具授权。

普通 hook 与授权增强的权限不同。设置 requiresToolAuthority: true 后,处理器在最终工具策略确定后运行,只允许返回 prependContext / appendContext;不能再换 system prompt 或缩小工具。合并实现。


四、OpenClaw 现有记忆系统全貌

磁盘事实与索引
├── USER.md / MEMORY.md:偏好与长期事实,加载受运行时和隐私门控制
├── memory/*.md:详细笔记,通常按需检索
├── memory_search / memory_get:搜索片段、读取原文
├── 确定性触发召回:匹配可信长期条目,有限注入
├── Active Memory:需要时升级到 blocking 深度召回
└── Dreaming:后台 light → REM → deep,整理长期记忆

这里没有“记忆来源优先级从高到低”的通用规则。Bootstrap 是内容入口,不代表其中所有文本都有更高安全权限。普通轮次不自动注入今天、昨天的每日笔记;裸 /new / /reset 的首轮可加载近期笔记。

截至本次版本,Dreaming 默认启用;Active Memory 的默认 mode 是 escalate,不是每条消息都启动子代理。native Codex 在记忆工具可用时通常按需读 MEMORY.md,不能笼统写“每次都注入”。记忆概览、系统提示词、Active Memory 流程。

当前体系的短板

  • 按需召回仍可能漏检、误检;有索引不等于模型一定想起或正确使用。
  • blocking 深度召回会增加等待,但只在符合触发条件时发生;15 秒是默认召回预算,不是整个回复延迟上限。
  • 非 Codex 路径的大 MEMORY.md 可能占用提示词预算并被截断;先整理内容,再评估是否提高限制。

五、优化记忆系统的三条路线

三类记忆需求分别对应配置调优、授权钩子和上下文引擎
图 3:按职责选择方案,不按未经测试的速度、质量或安全等级排名。

方案 A:用 before_prompt_build 做主动记忆注入(轻量级)

思路:检索本次问题所需的记忆片段,限制数量与长度,再注入当前输入。使用工具支持的数据能力时,要在授权增强阶段核对该轮 memory_search 权限。

用户消息 → 工具策略确定 → 授权增强 hook → 有界检索 → 注入 → 主模型

实现要点(结构示意,不是完整可运行插件):

api.on("before_prompt_build", async (event, ctx) => {
  const authority = ctx.toolAuthority;
  if (!authority?.allows("memory_search")) return;
  const query = event.currentUserMessage ?? event.prompt;
  if (!query.trim()) return;

  // 插件自有适配器:还需落实会话可见性、超时、来源与长度限制。
  const snippets = await recallForPrompt(query, ctx);
  authority.assertActive();
  if (snippets) return { prependContext: snippets };
}, { requiresToolAuthority: true });

recallForPrompt 是插件自己实现的帮助函数,不是 SDK 提供的 memory_search 调用。原报告的 memorySearch(query) 同样只是占位名称。

优点:可以自定义查询和注入量,不必改变现有记忆文件结构。

代价:async 不等于非阻塞。主流程需要等待这次检索才能消费结果;后台预取只能把结果留给以后,不能保证改善当前轮。超时结束宿主等待也不自动取消插件 I/O,需要传递取消信号。

非 bundled 插件需设置 plugins.entries.<id>.hooks.allowConversationAccess: true;还要保证 allowPromptInjection 没有被关闭。这些许可不是沙箱,原生插件仍是受信任代码。权限说明。

方案 B:基于 Context Engine 的 systemPromptAddition(更深度)

在 assemble() 返回消息集合和 systemPromptAddition,可以统一控制 token 预算、检索与压缩。但应区分“往提示词加一句话”和“负责整套上下文生命周期”:当前接口必需 info / ingest / assemble / compact;afterTurn 等是可选能力,持久化引擎还要处理原子提交、重试和清理。

这更适合已有明确上下文管理需求的插件,不是单纯召回偏好的第一步。官方接口。

方案 C:改进现有的 Active Memory 配置(改动最少)

先确认插件启用、agent 与聊天范围匹配,再调 plugins.entries.active-memory.config:

  • mode: "escalate":只在符合条件时升级深度召回。
  • queryMode: "recent":适合需要近期对话的跟进问题。
  • promptStyle: "preference-only":偏好型问题可考虑,但可能漏掉决策和事件。
  • maxSummaryChars: 220:默认长度预算,不是准确率保证。

用同一批实际问题检查漏检、误检、隐私范围和耗时,才知道是否改善。“改动少”不等于天然最安全。配置字段。


六、方案对比

目标 推荐方案
最少代码,先验证召回需求 调优现有配置(方案 C)
自定义查询、过滤与注入 授权后的 before_prompt_build(方案 A)
接管上下文组装与压缩 Context Engine(方案 B)

七、后续行动建议

  1. 先分清是漏召回、误召回、上下文膨胀,还是旧记忆没有及时失效。
  2. 建立一小组包含“无相关记忆”和“过期记忆”的检查题,记录命中来源与错误。
  3. 优先用现有配置验证;仍不满足时,再决定是否增加 hook 或上下文引擎。

2026-10-13 资料核对:已读取上述固定提交的官方文档、Hook 类型与合并源码;未运行 OpenClaw、插件或召回测试。2026-05-07 的原分析保留历史定位,配置与流程以本次注明版本为准。

记录到这里,判断留给实践。