1. Visión general
A medida que los agentes de IA se vuelven más capaces, la memoria a largo plazo se ha vuelto tan importante como el razonamiento. Mientras que mecanismos como ChatMemory y Retrieval Augmented Generation (RAG) manejan conversaciones y conocimiento externo, no responden a una pregunta diferente: ¿Qué debe recordar permanentemente un agente sobre un usuario o proyecto?
Spring AI AutoMemoryTools aborda esto al permitir que los agentes persistan y recuerden memorias a largo plazo, como las preferencias del usuario y el conocimiento específico del proyecto.
En este artículo, exploraremos AutoMemoryTools, su arquitectura y componentes, y construiremos un chatbot Spring Boot simple que demuestre cómo funciona.
2. Dependencias
Vamos a comenzar definiendo las dependencias mínimas posibles para demostrar Spring AI AutoMemoryTools. Necesitaremos spring-ai-starter-model-openai y spring-ai-agent-utils. El primero es el iniciador para integrar cualquier API compatible con OpenAI con Spring AI, y el segundo contiene las herramientas que estamos explorando en este artículo. Podemos usar las versiones (actuales) más recientes:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.springaicommunity</groupId>
<artifactId>spring-ai-agent-utils</artifactId>
<version>0.10.0</version>
</dependency>
3. Spring AI AutoMemoryTools
Spring AI AutoMemoryTools es una biblioteca de la comunidad Spring AI que implementa memoria a largo plazo para agentes de IA. Utiliza la llamada a herramientas y la persistencia basada en archivos. Es parte de los Spring AI Agent Utils, similar a Agent Skills. Vale la pena mencionar que está fuertemente inspirado en Claude Code y ahorra a los desarrolladores la implementación de capacidades comunes de agentes por sí mismos.
Similar a MessageChatMemoryAdvisor (para la memoria de conversación), Spring AI AutoMemoryTools también implementa BaseChatMemoryAdvisor. Esto significa que está relacionado con la memoria conversacional, pero no se centra en la parte de la conversación. En su lugar, tiene como objetivo almacenar información sobre conceptos como preferencias del usuario, proyectos, retroalimentación y más.
3.1. Tipos de memoria
Echemos un vistazo a los tipos de memoria que objetivo de Spring AI AutoMemoryTools:
- Usuario: Recuerda quién es el usuario y cómo ayudarlo mejor
- Retroalimentación: Recuerda cómo prefiere el usuario que la IA se comporte
- Proyecto: Recuerda el contexto importante del proyecto y las decisiones
- Referencia: Recuerda dónde encontrar información en sistemas externos
Como veremos más adelante, estos se describen mejor en AUTO_MEMORY_TOOLS_SYSTEM_PROMPT.md, que forma parte de los recursos de la dependencia. Otra cosa que veremos es cómo podemos anular este PromptSystemSpec con uno personalizado. Esto significaría que estos tipos de memoria podrían no existir, a menos que los definamos.
3.2. Las herramientas
Ahora, revisemos las seis herramientas distintas de AutoMemoryTools:
- MemoryView: Lee el contenido de un archivo de memoria o lista los archivos de memoria disponibles en un directorio
- MemoryCreate: Crea un nuevo archivo de memoria para persistir información a largo plazo
- MemoryStrReplace: Actualiza una memoria existente reemplazando una pieza exacta de texto
- MemoryInsert: Inserta nuevo contenido en una ubicación específica dentro de un archivo de memoria existente
- MemoryDelete: Elimina un archivo de memoria o un directorio del almacenamiento persistente
- MemoryRename: Renombra o reubica un archivo de memoria mientras conserva su contenido
3.3. Mensaje del sistema de memoria
Como vimos antes, AUTO_MEMORY_TOOLS_SYSTEM_PROMPT.md forma parte de la biblioteca. La biblioteca ofrece dos niveles de abstracción diferentes. El primero es una sandbox, un entorno restringido que limita el acceso del agente, utilizando Spring AI AutoMemoryTools. El otro es el uso sin restricciones de FileSystemTools o ShellTools.
En la práctica, AutoMemoryTools es una abstracción especializada construida sobre operaciones de sistema de archivos genéricas. El Agente puede acceder y gestionar archivos de memoria dentro de los directorios de memoria designados, como memory/user, memory/feedback, etc. Pero no debe tener privilegios para hacer nada fuera del directorio de memoria. Por el contrario, FileSystemTools y ShellTools son sin restricciones a menos que el desarrollador maneje adecuadamente este asunto.
3.4. Cómo funciona — Uniendo todo
Ahora que cubrimos los componentes, veamos cómo fluye una solicitud a través de Spring AI AutoMemoryTools.
Cuando un usuario envía una solicitud, el LLM combina el Mensaje del Sistema de Memoria con el mensaje del usuario para determinar si debe leer o escribir en la memoria. Si es necesario, invoca AutoMemoryTools para gestionar archivos Markdown en el directorio de memoria configurado, como se describe en el AUTO_MEMORY_TOOLS_SYSTEM_PROMPT.md predeterminado.
Después de generar la respuesta, el LLM puede realizar operaciones de memoria adicionales, como invocar más herramientas o consolidar entradas de memoria existentes. Finalmente, devuelve la respuesta al usuario.
4. Aplicación Spring AI AutoMemoryTools
Uniendo todo, veamos esto en acción. Veremos tres escenarios de configuración de un ChatClient para usar Spring AI AutoMemoryTools:
- All-defaults AutoMemoryToolsAdvisor (operación sandbox)
- Manual setup of AutoMemoryToolsAdvisor (operación sandbox)
- FileSystemTools y ShellTools (no sandbox por defecto)
4.1. Configuración predeterminada de AutoMemoryToolsAdvisor
Para el primer escenario, creamos un AutoMemoryToolsAdvisor con la configuración mínima predeterminada necesaria:
@Configuration
class ChatClientConfiguration {
@Value("${agent.memory.dir}")
String memoryDirectory;
ChatClient chatClient(ChatModel chatModel) {
return ChatClient
.builder(chatModel)
.defaultAdvisors(
AutoMemoryToolsAdvisor.builder()
.memoriesRootDirectory(memoryDirectory)
.build(),
MessageChatMemoryAdvisor.builder(
MessageWindowChatMemory.builder()
.maxMessages(100)
.build())
.build(),
ToolCallingAdvisor.builder()
.disableInternalConversationHistory()
.build())
.build();
}
}
Esta configuración utiliza el AUTO_MEMORY_TOOLS_SYSTEM_PROMPT.md predeterminado y define los tipos de memoria que explicamos antes. Usamos el Advisor para interceptar todos los intercambios de mensajes. El método memoriesRootDirectory() establece el directorio de memoria, que también es el límite de acceso para el Agente. Por último, el MessageChatMemoryAdvisor es el Advisor conocido que maneja la memoria para el aspecto de la conversación. Establecemos un valor aleatorio de 100 mensajes de historial.
4.2. Configuración personalizada de AutoMemoryTools
Si todavía queremos AutoMemoryTools sandboxed pero tenemos más mensajes del sistema para incluir, podemos usar un enfoque más personalizado:
@Configuration
class ChatClientConfiguration {
// ...
@Value("classpath:/prompts/AUTO_MEMORY_TOOLS_SYSTEM_PROMPT.md")
Resource memorySystemPromptAutoMemoryTools;
// ....
@Bean
ChatClient chatClientWithMoreSystemPrompt(ChatModel chatModel) {
return ChatClient
.builder(chatModel)
.defaultSystem(p -> p
.text(memorySystemPromptAutoMemoryTools)
.param("MEMORIES_ROOT_DIERCTORY", memoryDirectory))
.defaultTools(
AutoMemoryTools.builder()
.memoriesDir(memoryDirectory)
.build(),
TodoWriteTool.builder()
.build())
.defaultAdvisors(ToolCallingAdvisor.builder()
.build())
.build();
}
}
Aquí hacemos una configuración similar a la anterior, pero usamos las herramientas en su lugar. De esta manera, podemos definir el PromptSystemSpec personalizado, con el mensaje en el archivo .md que proporcionamos. Sin embargo, este mensaje es la esencia de AutoMemoryTools, donde deberíamos definir tipos de memoria, cómo almacenarlos y más. Entonces, si necesitamos anularlo, es mejor copiar el mensaje predeterminado y agregar los mensajes del sistema adicionales.
Debemos notar que ChatMemory no se establece aquí, pero se utiliza TodoWriteTool. Esto no tiene nada que ver con Spring AI AutoMemoryTools. Sirve para mostrar que podemos tener o no más herramientas y asesores, según las necesidades del Agente.
4.3. FileSystemTools y ShellTools
Por último, podemos tener un escenario sin restricciones, usando FileSystemTools y ShellTools. Por ejemplo,si el agente ya tiene FileSystemTools o ShellTools para otras tareas, no necesita AutoMemoryTools:
@Configuration
class ChatClientConfiguration {
// ...
@Value("classpath:/prompts/AUTO_MEMORY_FILESYSTEM_TOOLS_SYSTEM_PROMPT.md")
Resource memorySystemPromptFilesystemTools;
// ....
@Bean
ChatClient chatClientWithoutAutoMemoryTools(ChatModel chatModel) {
return ChatClient
.builder(chatModel)
.defaultSystem(p -> p
.text(memorySystemPromptFilesystemTools)
.param("MEMORIES_ROOT_DIERCTORY", memoryDirectory)) // dice al agente dónde escribir
.defaultTools(
ShellTools.builder()
.build(), // Bash --- mkdir, ls, etc.
FileSystemTools.builder()
.build()) // Leer, escribir, editar --- operaciones de archivo de memoria
.defaultAdvisors(ToolCallingAdvisor.builder()
.build())
.build();
}
}
El archivo AUTO_MEMORY_FILESYSTEM_TOOLS_SYSTEM_PROMPT.md también se puede encontrar en la biblioteca. Para la demostración, podemos copiarlo. Con este, se aplican las mismas convenciones de memoria: archivos .md, guardado en dos pasos, etc. Pero el agente convencionalmente tiene acceso completo al sistema de archivos y permanece solo en el directorio configurado.
Las dos herramientas son las que el Agente necesita para crear, eliminar, editar archivos, etc., y mantener la memoria en el sistema de archivos.
4.4. Otros archivos del proyecto
Para la demostración, usaremos spring-web-mvc, con un RestController:
@PostMapping("/chat-with-memory")
ResponseEntity<String> chat(@RequestBody String question, @RequestHeader("X-Conversation-ID") String conversationId) {
String answer = chatClient
.prompt()
.advisors(a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))
.user(question)
.call()
.content();
return ResponseEntity.ok(answer);
}
Como se mencionó anteriormente, el conversationId es necesario, ya que Spring AI AutoMemoryTools implementa BaseChatMemoryAdvisor.
Ejecutemos la aplicación usando un modelo local Ollama Qwen:

Primero, le pedimos al Agente que guarde algo de información. Luego solicitamos esa información, pero notamos el diferente conversationId ! El Agente no sabe nada sobre session-1. Preguntando como session-2 nuevamente, el Agente recuerda.
Dependiendo de nuestra máquina, la interacción del Agente con el sistema de archivos puede ser bastante lenta. También podemos ver los directorios que el Agente creó, junto con el contenido de los archivos:

5. Conclusión
En este artículo, revisamos Spring AI AutoMemoryTools. Cubrimos los casos de uso y las definiciones básicas. Luego, repasamos las seis operaciones y las tres opciones para usarlas. Finalmente, utilizamos Spring AI para demostrarlo en la práctica.
Como siempre, el código fuente de los ejemplos se puede encontrar en GitHub.
Newsletter Semanal de Java
Cada viernes recibe lo más nuevo del ecosistema Java: frameworks, herramientas y mejores prácticas.
Sin spam. Cancela cuando quieras.