作者:互联网 时间: 2026-07-07 09:18:00
import io.agentscope.core.memory.LongTermMemory;import io.agentscope.core.memory.LongTermMemoryBase;import io.agentscope.core.memory.Mem0LongTermMemory;import io.agentscope.core.ReActAgent;public class Chapter17_LegacyLongTerm { public static void main(String[] args) { LongTermMemory memory = new Mem0LongTermMemory("https://api.mem0.ai",System.getenv("MEM0_API_KEY"));ReActAgent agent = ReActAgent.builder().name("assistant").sysPrompt("你是一个长期记忆助理。").model(model()).longTermMemory(memory)// 1.x.build();}}
2.0 仍可编译:ReActAgent.longTermMemory(...) 在 RC2 中标记为 @Deprecated(forRemoval = true),编译通过但会告警。

workspace 下两份文件,按不同"时间粒度"组织:
workspace/├── MEMORY.md# 长期稳定的事实笔记└── memory/├── 2026-06-05.md# 当天事件流├── 2026-06-06.md└── 2026-06-07.md
MEMORY.md跨会话、跨天都会用到的"稳定信息"——
# MEMORY.md## 用户偏好- 常驻城市:杭州- 时区:UTC 8- 语言:中文## 长期目标- 2026 年内学完 Rust
memory/YYYY-MM-DD.md按天追加的"事件流"——
# 2026-06-07## 14:32- 用户问"今天杭州天气",回答:22~28℃,局部多云,建议带伞## 15:01- 用户问"我常驻哪里",agent 从 MEMORY.md 知道"杭州",回答一致
io.agentscope.core.middleware 提供两个跟记忆直接相关的中间件:
| 中间件 | 何时触发 | 副作用 |
|---|---|---|
CompactionMiddleware | 上下文 token 超过阈值 | 早期消息压成摘要写进 MEMORY.md |
MemoryFlushMiddleware | 每轮 call 结束 | 把"该记的"刷到当日 memory/YYYY-MM-DD.md |
CompactionMiddleware 由 HarnessAgent 在 build() 时根据 MemoryConfig 自动挂载,业务方通过 .memory() 配置即可:
HarnessAgent agent = HarnessAgent.builder()....memory(MemoryConfig.builder().compactionEnabled(true)// 超过 token 阈值自动压缩.build()).build();
CompactionMiddleware 工作流程:
MEMORY.md 的"近期摘要"小节 旧消息从 AgentState 移除 import io.agentscope.harness.agent.middleware.MemoryFlushMiddleware;HarnessAgent agent = HarnessAgent.builder()....memory(MemoryConfig.builder().build()) // 默认开启每轮结束后冲刷记忆.build();
MemoryFlushMiddleware 由 HarnessAgent 根据 MemoryConfig 自动挂载,业务方无需手动构造。工作流程:
memory/2026-06-07.md 没有 → 跳过,不写 HarnessAgent agent = HarnessAgent.builder().name("assistant").sysPrompt("...").model(model()).workspace(Path.of("./workspace")).memory(MemoryConfig.builder().build()) // 默认开启 MemoryFlushMiddleware.build(); // CompactionMiddleware 按 CompactionConfig 挂载
主 agent 在每轮推理时会自动读 MEMORY.md 顶部几行作为"已知背景"。如果你想"agent 决定更新 MEMORY.md"——给它 @Tool:
@Tool(name = "update_long_term_memory", description = "更新长期记忆")// 注册为 agent 可调工具public String updateMemory(@ToolParam(name = "section") String section, // 比如 "用户偏好"@ToolParam(name = "content") String content) { // 比如 "默认中文回答"Path memFile = Path.of("./workspace/MEMORY.md");// 记忆文件固定路径String existing = memFile.toFile().exists()? Files.readString(memFile) // 已有记忆 → 追加: "# MEMORY.md";// 新文件 → 创建String updated = existing "## " section "- " content "";Files.writeString(memFile, updated);// 写回文件return "memory updated";}
把工具通过 Toolkit 注册进 agent,LLM 看到用户说"以后请默认中文回答"会自己调这个工具写进 MEMORY.md,下次对话时立刻生效。
这个例子在演示什么?
public class Chapter17_MemoryStack { public static void main(String[] args) { DashScopeChatModel model = DashScopeChatModel.builder().apiKey(System.getenv("DASHSCOPE_API_KEY")).modelName("qwen-plus").build();// 1. 手工更新记忆的工具(agent 主动决策"记住这个")Toolkit toolkit = new Toolkit();toolkit.registerTool(new UpdateMemoryTool());// 2. agent:三层记忆机制一起跑HarnessAgent agent = HarnessAgent.builder().name("assistant").sysPrompt("你是一个有长期记忆的助理。用户告诉你的事如果需要长期记住,调用 update_long_term_memory 工具写下来。").model(model).workspace(Path.of("./workspace")).toolkit(toolkit).compaction(CompactionConfig.builder().build())// 上下文太长时自动压缩.memory(MemoryConfig.builder().build())// 默认 flush=每轮结束自动冲刷.build();// 3. 多轮对话(同一个 session,演示跨轮记忆)RuntimeContext ctx = RuntimeContext.builder().sessionId("user-9527-2026-06-07").userId("9527").build();// Round 1:agent 记住用户基本信息agent.call(List.of(new UserMessage("user", "我叫小李,住在杭州。")), ctx).block();// Round 2:agent 应该能从记忆里调出信息agent.call(List.of(new UserMessage("user", "我叫什么?住在哪?")), ctx).block();// Round 3:agent 主动调 update_long_term_memory 写偏好agent.call(List.of(new UserMessage("user", "以后请用中文回答。")), ctx).block();}}
跑完你会看到:
workspace/MEMORY.md — CompactionMiddleware 写的摘要 UpdateMemoryTool 写的用户偏好(@ToolParam 缺了这里会是 null) workspace/memory/ — 不一定生成。MemoryFlushMiddleware 的写入取决于 LLM 判断"是否值得记"以及异步回调是否执行完毕 Round 2 时 agent 能从上下文记忆里知道"小李 / 杭州" Round 3 时 agent 主动调工具把"中文回答"偏好写进 MEMORY.md | 1.x 用法 | 2.0 等价 |
|---|---|
LongTermMemory.retrieve(query) | 业务方手写 @Tool 调自家向量库;或 subagent 用 grep_files |
LongTermMemory.record(messages) | MemoryFlushMiddleware update_long_term_memory 工具 |
LongTermMemoryBase 子类 | 业务方自己实现 @Tool |
agent.longTermMemory(memory) | workspace/MEMORY.md memory/*.md 中间件 |
LongTermMemory 在 2.0 中被标记为弃用,未来会移除。 2.0 用 MEMORY.md memory/YYYY-MM-DD.md 两层文件做长期记忆。 CompactionMiddleware 自动压缩 MemoryFlushMiddleware 自动写入。 业务方可以手写 @Tool 让 agent 主动更新 MEMORY.md。