构建约 15 分钟

ContextEngine 与五种记忆

上下文窗口满了怎么办:处理器链卸载大结果、压缩历史,超窗口时补救一次;跨会话的东西交给长期记忆。

依据 agent-core 0.1.20 · develop@fbe6a0d9(2026-11-13)核实

两个不同的问题

智能体要"记住东西",其实是两个问题:

问题时间尺度负责的模块
这一次对话太长,塞不进模型窗口一个会话之内ContextEngine(上下文引擎)
下次再来,还记得这个客户的偏好跨会话长期记忆 LongTermMemory

上下文引擎:一条处理器链

ContextEngine 给每个会话建上下文,并在消息写入、模型调用前跑一串处理器(processor)来控制窗口大小。内置的处理器分两类:

类别处理器思路
卸载MessageOffloader、MessageSummaryOffloader、工具结果预算类把大的旧消息换成"开头一小段 + 省略标记",原文另存,需要时再取回
压缩DialogueCompressor、RoundLevelCompressor、CurrentRoundCompressor、MicroCompactProcessor、FullCompactProcessor用摘要等方式压缩对话历史
源码ContextEngineagent-core/openjiuwen/core/context_engine/context_engine.py:28@fbe6a0d9

在 ReActAgentConfig 上按名字配置处理器:

config.configure_context_processors([
    ("MessageOffloader", MessageOffloaderConfig(
        tokens_threshold=20000,           # 累计超过就触发(默认值)
        large_message_threshold=1000,     # 多大算"大消息"
        trim_size=100,                    # 卸载后保留开头多少
        offload_message_type=["tool"],    # 只动工具结果(默认)
        protected_tool_names=["read_file"],  # 这些工具的结果永不卸载(默认)
        keep_last_round=True,             # 正在进行的这一轮不动(默认)
    )),
])
说明

示意代码,参数名和默认值取自 MessageOffloaderConfig;本站没有运行它。

源码MessageOffloaderConfigagent-core/openjiuwen/core/context_engine/processor/offloader/message_offloader.py:22@fbe6a0d9

两个容易误解的点:

  • keep_last_round 保护的是"最后一次完整答复之后"的全部消息,也就是当前这张询单的所有工具结果。被卸载的只会是之前已经答完的轮次。
  • 保护名单是给"必须原文保留"的工具用的。 把大结果工具放进去,卸载器就无事可做。

超窗口之后:只补救一次

即使配了处理器,模型仍可能以"上下文超长"拒绝请求。ReActAgent 在 Rail 的重试用尽后,会请上下文引擎做一次补救:

  1. 看错误文本是不是上下文超长(源码里列了一组常见说法,比如 "context length"、"prompt is too long")
  2. 如果已经流式输出过内容,放弃(重试会重复推送)
  3. 主动压缩一次;确实压缩了才重试,否则保留原异常
源码recover_from_model_exceptionagent-core/openjiuwen/core/context_engine/context_engine.py:426@fbe6a0d9

长期记忆:五种类型

跨会话的记忆由 LongTermMemory 管理(进程内单例),按记忆空间(scope)隔离。记忆单元的类型枚举是:

类型枚举值直观理解
用户画像USER_PROFILE这个人是谁、有什么偏好
语义记忆SEMANTIC_MEMORY事实性知识
情景记忆EPISODIC_MEMORY发生过的具体事情
变量VARIABLE结构化的键值
摘要SUMMARY历史对话的摘要
源码MemoryTypeagent-core/openjiuwen/core/memory/manage/mem_model/memory_unit.py:9@fbe6a0d9

常用入口:add_messages 写入对话、search_user_mem 检索用户记忆、search_user_history_summary 检索历史摘要、get_variables / update_variables 读写变量。智能体侧用 ReActAgentConfig.configure_mem_scope(...) 指定记忆空间。

源码search_user_memagent-core/openjiuwen/core/memory/long_term_memory.py:965@fbe6a0d9
说明

openJiuwen 还有独立的 agent-memory 仓库,园区地图上留了"规划中"的地块,等它的内容核实后再上线。本关只讲 agent-core 里的记忆接口。

动手:别让窗口撑爆

模拟器加载中…

小结

  • 会话内的窗口问题交给 ContextEngine 的处理器链:先卸载大的旧工具结果,再考虑压缩。
  • 超窗口后的补救只有一次,而且流式输出开始后不补救,别把它当主要手段。
  • 跨会话的记忆用 LongTermMemory,五种类型对应画像、知识、经历、变量和摘要。

源码出处

链接指向固定提交,仓库后续更新不影响这里的行号。

过关测验

  1. 1. MessageOffloader 默认会卸载哪种消息?

  2. 2. keep_last_round=True 时,哪些消息一定不会被卸载?

  3. 3. 流式输出已经推送了几个字,模型才报上下文超长。框架会怎么做?

通关条件

  • ○ 完成模拟器任务(0/2)
  • ○ 测验全部答对