AutoMemoryTools 是 Spring AI 对 Anthropic 经典记忆方案的落地实现,完整复刻 Claude Code 与 Claude API Memory Tool 核心设计:[MEMORY.md](MEMORY.md) 索引机制、结构化分类记忆、两步式保存流程、沙箱化操作接口,全面适配各类大语言模型服务商。
长期记忆填补了无状态大模型调用与落地级实用智能代理之间的能力缺口。快速接入 AutoMemoryToolsAdvisor,即可让你的智能代理沉淀跨会话长效知识,大幅提升智能化能力。
基于文件的 Spring AI 智能代理长期记忆
智能代理的价值,取决于其记忆能力。Spring AI 的 ChatMemory 会存储完整对话内容并支持重启后数据持久化,但当上下文窗口存满时,最早的消息会被自动淘汰。即将推出的 Session API 将新增递归摘要功能以缓解该问题,不过细节内容压缩后,精准信息仍会丢失。
AutoMemoryTools 与 AutoMemoryToolsAdvisor 隶属于 spring-ai-agent-utils 工具库,可为智能代理提供基于文件、可长期留存的持久化记忆,实现跨会话数据保存。该设计借鉴 Claude Code 自动记忆机制与 Claude API Memory Tool 规范,并完成 Spring AI 适配,可兼容任意大语言模型服务商。
长期记忆 vs 对话历史
ChatMemory 与 AutoMemoryTools 互为补充,配置完善的智能代理会同时启用两者:
ChatMemory:维护完整对话上下文,自动记录每轮交互,受滑动窗口机制限制;
AutoMemoryTools:精选记忆层,大语言模型仅永久留存关键信息(用户偏好、项目决策、行为修正要求等),并写入结构化 Markdown 文件,长期保存不丢失。
当前任务使用 ChatMemory,需要下周仍可查阅的关键信息则交由 AutoMemoryTools 管理。
本文是《Spring AI 智能代理模式》系列第六篇。此前内容涵盖:智能代理能力、AskUserQuestionTool、TodoWriteTool、子代理编排、A2A 集成。本篇将介绍可跨会话存续的长效记忆能力。
🚀 快速上手?直接跳转快速入门章节。
工作原理
智能代理通过 AutoMemoryTools 内置的六项定向工具管理自身记忆,所有文件均隔离存储在沙箱化的 memories 目录中。完整请求流转逻辑如下:
AutoMemoryTools 执行流程
① 用户请求:用户请求结合记忆系统提示词,经由 Spring AI 顾问链(ToolCallAdvisor + ChatMemoryAdvisor)转发至大语言模型。大语言模型判断是否需要加载、创建或更新记忆,再进行作答。 ② 工具调用:大语言模型调用 AutoMemoryTools 工具,在指定记忆目录中读写结构化 Markdown 文件;其中 [MEMORY.md](MEMORY.md) 为索引文件,同时包含 user\[_profile.md](_profile.md)、project\[_history.md](_history.md) 等专题记忆文件。 ③ 二次检索 / 更新:大语言模型可发起多次工具调用,加载指定记忆文件或更新已有内容;例如通过 [MEMORY.md](MEMORY.md) 索引定位并读取目标文件、整合合并记忆内容。 ④ 最终响应:记忆操作全部完成后,大语言模型生成回答,经由顾问链返回给用户。
记忆系统提示词
记忆系统提示词是该能力的核心驱动,工具包 Jar 内置两套提示词模板:
AUTO_MEMORY_TOOLS_SYSTEM\[_PROMPT.md](_PROMPT.md):适配方案 A、方案 B,对应独立沙箱化 AutoMemoryTools;
AUTO_MEMORY_FILESYSTEM_TOOLS_SYSTEM\[_PROMPT.md](_PROMPT.md):适配方案 C,基于 FileSystemTools 实现通用文件读写、编辑能力。
两套提示词遵循同一套记忆模型规范,仅定义的可调用操作不同。同时约束大语言模型:会话启动时读取 [MEMORY.md](MEMORY.md)、遵循两步保存流程(MemoryCreate → MemoryInsert)、区分四类记忆类型、过滤临时无效内容、使用记忆前校验信息准确性、删除 / 重命名文件时同步更新索引。
[MEMORY.md](MEMORY.md) — 索引文件
[MEMORY.md](MEMORY.md) 为常驻加载的核心索引文件,以单行链接列表形式管理所有记忆文件:
- [User Profile](user_profile.md) — Alice, backend engineer, prefers short answers - [Feedback Testing](feedback_testing.md) — always use real DB in integration tests - [Project Auth Rewrite](project_auth.md) — driven by legal compliance, not tech debt
智能代理每次会话启动时读取该索引,按需加载关联文件,保证记忆数据持续扩容的同时,精简上下文占用。
记忆文件格式
所有记忆文件均为带 YAML 前置元数据的 Markdown 文件:
--- name: user profile description: Alice — backend engineer, prefers short answers type: user --- Backend engineer named Alice. Prefers concise, direct responses without trailing summaries.
记忆类型
并非所有内容都需要长期存储,记忆模型划分四大类型,明确留存规则,确保记忆有效、无冗余:
user(用户):角色、目标、专业能力、沟通风格;
feedback(反馈):修正要求、既定规范(如「禁止自动摘要」「该方案确认可行」);
project(项目):非代码 / 版本库管控的决策与时间节点(迁移目标、冻结日期);
reference(参考):外部系统入口(Linear 看板、Grafana 仪表盘、Slack 频道)。
记忆操作能力
AutoMemoryTools 提供六项专属沙箱化操作;方案 C 可通过通用 FileSystemTools 与 ShellTools 实现等效能力。
AutoMemoryTools 专属工具(方案 A、B)
完全对标 Claude API Memory Tool 规范,操作隔离、语义明确:
工具 | 功能说明 |
MemoryView | 带行号读取文件 / 两层目录列表查询 |
MemoryCreate | 新建记忆文件(两步保存流程第一步) |
MemoryStrReplace | 精准替换文件内唯一指定文本内容 |
MemoryInsert | 指定行后插入内容,主要用于追加更新 [MEMORY.md](MEMORY.md) |
MemoryDelete | 递归删除文件 / 目录 |
MemoryRename | 文件重命名 / 移动,独立同步更新 [MEMORY.md](MEMORY.md) 索引链接 |
FileSystemTools & ShellTools(方案 C)
依托通用文件工具映射等效记忆操作:
通用操作 | 对应专属记忆工具 |
Read | MemoryView |
Write | MemoryCreate |
Edit | MemoryStrReplace / MemoryInsert |
Bash(rm、mv 等指令) | MemoryDelete / MemoryRename |
补充说明:方案 A、B 具备路径沙箱隔离;方案 C 无沙箱限制,智能代理拥有完整文件系统访问权限。
集成实现方案
共有三种方式为 Spring AI 智能代理配置长期记忆,从零模板代码到完全自定义灵活选择,可根据系统提示词定制需求、安全规范、已有工具依赖进行选型。
方案 A:AutoMemoryToolsAdvisor(零代码侵入)
在 ChatClient 构建器中直接注入顾问组件即可快速接入:
ChatClient chatClient = ChatClient.builder(chatModel)
.defaultAdvisors(
// 长期记忆:跨会话永久留存关键信息
AutoMemoryToolsAdvisor.builder()
.memoriesRootDirectory("/home/user/.agent/memories")
.build(),
// 对话历史:当前会话完整消息上下文
MessageChatMemoryAdvisor.builder(
MessageWindowChatMemory.builder().maxMessages(100).build())
.build(),
// 工具调用能力
ToolCallAdvisor.builder().disableInternalConversationHistory().build())
.build();每次用户请求触发时,该顾问会自动注入记忆系统提示词、注册全部六项 AutoMemoryTools(自动去重);配置记忆合并触发器后,可自动推送记忆整理提醒。
AutoMemoryToolsAdvisor 执行逻辑
顾问链中优先执行 AutoMemoryToolsAdvisor,提前注入记忆提示词与工具定义,再流转至 ToolCallAdvisor、ChatMemoryAdvisor。最终传给大语言模型的上下文,已包含对话历史、工具定义、记忆管理规则,支撑模型自主完成记忆加载、保存、更新。
方案 B:手动配置(直接使用 AutoMemoryTools)
手动绑定 AutoMemoryTools 与自定义系统提示词,高度自主可控:
@Value("classpath:/prompt/AUTO_MEMORY_TOOLS_SYSTEM_PROMPT.md")
Resource memorySystemPrompt;
@Value("${agent.memory.dir}")
String memoryDir;
ChatClient chatClient = chatClientBuilder
.defaultSystem(p -> p
.text(memorySystemPrompt)
.param("MEMORIES_ROOT_DIERCTORY", memoryDir))
.defaultTools(
AutoMemoryTools.builder().memoriesDir(memoryDir).build(),
TodoWriteTool.builder().build())
.defaultAdvisors(ToolCallAdvisor.builder().build())
.build();适用于需要自定义系统提示词组合、精细化管控全局配置的业务场景。
方案 C:FileSystemTools + ShellTools
若智能代理已接入通用文件工具,可无需引入 AutoMemoryTools,复用现有文件读写能力实现记忆管理:
@Value("classpath:/prompt/AUTO_MEMORY_FILESYSTEM_TOOLS_SYSTEM_PROMPT.md")
Resource memorySystemPrompt;
@Value("${agent.memory.dir}")
String memoryDir;
ChatClient chatClient = chatClientBuilder
.defaultSystem(p -> p
.text(memorySystemPrompt)
.param("MEMORIES_ROOT_DIERCTORY", memoryDir)) // 指定记忆存储目录
.defaultTools(
ShellTools.builder().build(), // 终端指令:mkdir、ls 等
FileSystemTools.builder().build()) // 文件读写编辑:记忆文件核心操作
.defaultAdvisors(ToolCallAdvisor.builder().build())
.build();该方案遵循统一记忆规范(结构化文件、[MEMORY.md](MEMORY.md) 索引、两步保存),无沙箱隔离,仅依靠提示词约束目录访问范围,设计思路完全对标 Claude Code 原生记忆方案。
方案对比
对比项 | 方案 A/B(AutoMemoryTools) | 方案 C(FileSystemTools) |
路径管控 | 相对路径,强制沙箱隔离 | 绝对路径,全文件系统访问 |
安全防护 | 内置路径遍历防护 | 无沙箱,依赖提示词规范约束 |
工具命名 | 业务语义化(MemoryCreate、MemoryView 等) | 通用基础命名(Write、Read、Edit) |
适用场景 | 纯记忆场景、强安全隔离需求 | 已复用文件工具的存量代理项目 |
⚠️ 安全提示:启用 FileSystemTools 后,智能代理可读写服务器任意文件目录,仅可在可信、隔离的受控环境中使用。
记忆维护优化
长期运行会产生冗余、重复、过期的记忆内容,定期执行记忆合并整理(合并重复内容、清理失效信息、精简描述文本),可精简存储体积、保证 [MEMORY.md](MEMORY.md) 索引清晰可读。
方案 B/C(手动触发):直接向代理下发指令
用户指令:请整理合并所有记忆,剔除过期内容、合并重复信息。
方案 A(自动触发):通过 memoryConsolidationTrigger 断言配置自动规则 示例:交互超时 / 用户告别时自动整理
Instant lastInteraction = Instant.now();
AutoMemoryToolsAdvisor.builder()
.memoriesRootDirectory(memoryDir)
.memoryConsolidationTrigger((request, instant) -> {
var previous = lastInteraction;
lastInteraction = Instant.now();
// 两轮交互间隔超60秒自动整理
if (instant.isAfter(previous.plusSeconds(60))) {
return true;
}
// 检测到用户发送告别用语自动整理
var msg = request.prompt().getLastUserOrToolResponseMessage().getText();
return msg != null && msg.toLowerCase().contains("bye");
})
.build()拓展配置方案:
// 概率触发:5% 请求随机整理 .memoryConsolidationTrigger((req, now) -> Math.random() < 0.05) // 次数触发:每50轮交互整理一次 AtomicInteger counter = new AtomicInteger(); .memoryConsolidationTrigger((req, now) -> counter.incrementAndGet() % 50 == 0)
快速入门
1. 引入依赖
<dependency> <groupId>org.springaicommunity</groupId> <artifactId>spring-ai-agent-utils</artifactId> <version>0.7.0</version> </dependency>
备注:前往 GitHub 版本页获取最新稳定版;依赖要求:Spring AI 2.0.0-M4 及以上。
2. 配置记忆存储目录
# application.properties
agent.memory.dir=${user.home}/.spring-ai-agent/my-app/memory3. 代码快速集成
@Value("${agent.memory.dir}")
String memoryDir;
ChatClient chatClient = chatClientBuilder
.defaultAdvisors(
// 长期记忆组件
AutoMemoryToolsAdvisor.builder()
.memoriesRootDirectory(memoryDir)
.build(),
// 会话级对话记忆
MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder().maxMessages(100).build())
.build(),
// 工具调用适配器
ToolCallAdvisor.builder().disableInternalConversationHistory().build())
.build();4. 效果演示
首次会话:
用户:我叫 Alice,后端工程师,希望你精简回答。 用户:备注:本季度我们将从 PostgreSQL 迁移至 CockroachDB。
全新会话(重启 JVM):
用户:你了解我的哪些信息? 代理回复:你是后端工程师 Alice,偏好精简回答;当前项目本季度计划从 PostgreSQL 数据库迁移至 CockroachDB。