Long-Term Memory in Spring AI with AutoMemoryTools
AutoMemoryTools lets a Spring AI agent keep useful facts between sessions without treating the whole conversation transcript as permanent context. This article explains the idea and builds a small Spring Boot chat endpoint around it.
1. Understanding Long-Term Memory with AutoMemoryTools
An LLM call is stateless unless the application provides context. ChatMemory maintains recent conversation history, but it is typically bounded, meaning older messages may be removed as new ones are added. Long-term information, such as a user’s preferred response style, a project decision, or a confirmed correction, should therefore not rely on this limited conversation window. AutoMemoryTools, available through the Spring AI community spring-ai-agent-utils toolkit, provides file-backed long-term memory that allows an agent to read, create, update, rename, or delete memory files within a configured root directory. Because these files persist across application restarts, future chat sessions can retrieve relevant information when needed. Chat memory serves as the agent’s recent working conversation, while auto memory acts as a curated and durable knowledge store; using both enables an agent to maintain long-term continuity while preserving the context required for the current task.
1.1 How AutoMemoryTools Stores and Manages Memory
The toolset uses a simple Markdown convention. MEMORY.md is the index, containing short pointers to topic files. The agent reads that index at the beginning of a session, then opens only the files relevant to the user’s question. This keeps the prompt compact as memory grows. A topic file can use YAML front matter for a name, description, and type, followed by the actual notes. Common types are user, feedback, project, and reference.
--- name: user profile description: Priya is a backend developer who prefers concise answers. type: user --- Priya works mainly with Java and Spring Boot. Prefers short, direct explanations.
The dedicated tools are sandboxed to the memory directory and map to six focused actions:
| Tool | What it does |
|---|---|
MemoryView | Lists memory files or reads a file with line numbers. |
MemoryCreate | Creates a new memory file. |
MemoryStrReplace | Replaces one exact, unique section in an existing file. |
MemoryInsert | Inserts content after a line, commonly to add an index entry. |
MemoryDelete | Deletes a memory file or directory under the configured root. |
MemoryRename | Renames or moves a memory file under the configured root. |
AutoMemoryToolsAdvisor is the easiest integration. It supplies the memory instructions and registers these tools for each request. The model still chooses whether a fact is worth saving; it is not an automatic database of every utterance.
2. Building a Spring AI Application with AutoMemoryTools
This example exposes POST /chat. It uses OpenAI through Spring AI, recent chat memory for the active conversation, and an AutoMemoryToolsAdvisor for durable memory. Set OPENAI_API_KEY before starting the application.
2.1 Configure Maven Dependencies
Start by adding the required Spring Boot, Spring AI, and agent utility dependencies to the project’s pom.xml file. The following configuration sets up dependency version management and includes the libraries needed to integrate the OpenAI model and long-term memory capabilities.
<properties>
<java.version>stable__version</java.version>
<spring-ai.version>stable__version</spring-ai.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<dependency>
<groupId>org.springaicommunity</groupId>
<artifactId>spring-ai-agent-utils</artifactId>
<version>stable__version</version>
</dependency>
</dependencies>
The <properties> section defines the Java and Spring AI versions in one place, making them easier to maintain and update. The spring-ai-bom dependency is imported through <dependencyManagement> and acts as a Bill of Materials (BOM), providing consistent versions for compatible Spring AI modules so that individual Spring AI dependencies generally do not need their own version declarations. The spring-boot-starter-web dependency supplies the core Spring MVC and web application infrastructure required to expose HTTP endpoints and run the application as a web service. The spring-ai-starter-model-openai dependency adds Spring AI’s OpenAI model integration and the supporting auto-configuration required to connect the application to OpenAI models using Spring configuration. Finally, spring-ai-agent-utils adds the Spring AI community agent utilities used by the application, including AutoMemoryTools for file-backed long-term memory. Its version is declared explicitly because it is a separate community library rather than a dependency whose version is managed by the Spring AI BOM. Together, these dependencies provide the foundation for building a Spring Boot application that can expose web endpoints, communicate with an OpenAI model through Spring AI, and equip the agent with persistent memory capabilities.
2.2 Configure OpenAI and the Memory Directory
Configure the OpenAI API credentials and the directory used for persistent agent memory in the application’s application.properties file. Keeping these values in configuration makes it easy to change credentials and storage locations without modifying the application code.
spring.ai.openai.api-key=${OPENAI_API_KEY}
agent.memory.dir=${user.home}/.demo-agent/memory
The spring.ai.openai.api-key property configures the API key used by Spring AI when communicating with OpenAI. Instead of placing the key directly in the configuration file, ${OPENAI_API_KEY} resolves its value from the OPENAI_API_KEY environment variable, which helps keep sensitive credentials out of the application source code and version control. The agent.memory.dir property defines the root directory where the agent’s file-backed long-term memory will be stored. The ${user.home} placeholder resolves to the current operating system user’s home directory, so the resulting location is ~/.demo-agent/memory. This property can later be injected into the application configuration and supplied to AutoMemoryTools as its memory root. Because the memory is stored on the file system rather than only in the current chat context, information written to this directory can remain available across application restarts and subsequent chat sessions.
2.3 Configure ChatClient and the Memory-Enabled REST API
Create the following configuration and REST controller to connect the application to the configured ChatModel, maintain a bounded window of recent conversation messages, and enable file-backed long-term memory. The ChatClient is configured once as a Spring bean and then injected into the controller to process requests sent to the /chat endpoint.
package com.example.memory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.ToolCallAdvisor;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springaicommunity.agent.advisors.AutoMemoryToolsAdvisor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@Configuration
class AiConfiguration {
@Bean
ChatClient chatClient(ChatModel chatModel, @Value("${agent.memory.dir}") String memoryDirectory) {
return ChatClient.builder(chatModel)
.defaultSystem("You are a helpful assistant. Keep answers concise.")
.defaultAdvisors(
AutoMemoryToolsAdvisor.builder().memoriesRootDirectory(memoryDirectory).build(),
MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder().maxMessages(20).build()).build(),
ToolCallAdvisor.builder().disableInternalConversationHistory().build())
.build();
}
}
@RestController
class MemoryChatController {
private final ChatClient chatClient;
MemoryChatController(ChatClient chatClient) {
this.chatClient = chatClient;
}
@PostMapping("/chat")
String chat(@RequestBody ChatRequest request) {
return chatClient.prompt().user(request.message()).call().content();
}
record ChatRequest(String message) {}
}
The AiConfiguration class defines the application’s reusable ChatClient bean. Spring automatically supplies the configured ChatModel, while @Value("${agent.memory.dir}") injects the persistent memory directory defined in application.properties. The client is created with ChatClient.builder(chatModel), and defaultSystem(...) establishes a system instruction that asks the model to behave as a helpful assistant and keep its responses concise. The defaultAdvisors(...) configuration then adds the components responsible for memory and tool-call behavior. AutoMemoryToolsAdvisor uses memoriesRootDirectory(memoryDirectory) to configure the root directory for file-backed long-term memory, allowing memory information to be persisted outside the immediate conversation. MessageChatMemoryAdvisor provides short-term conversational context using MessageWindowChatMemory; setting maxMessages(20) limits this working memory to a maximum of 20 messages, preventing the recent conversation history from growing indefinitely. ToolCallAdvisor manages tool-call execution, and disableInternalConversationHistory() disables its separate internal conversation-history handling so that conversational history is managed explicitly by the configured chat-memory advisor instead. The resulting ChatClient is registered as a Spring bean and injected into MemoryChatController through constructor injection. The @PostMapping("/chat") method exposes a POST endpoint that accepts a JSON request body mapped to the ChatRequest record, extracts the user’s message, passes it to chatClient.prompt().user(...), executes the model request with call(), and returns the generated text through content(). In this arrangement, MessageWindowChatMemory supplies bounded recent conversational context, while AutoMemoryToolsAdvisor provides access to durable file-backed memory, allowing the agent to combine immediate conversation history with information that can persist beyond the current application session.
2.4 Run and Test the Memory-Enabled Application
After configuring the dependencies, application properties, and controller, run the Spring Boot application from the project’s root directory using Maven. Make sure the OPENAI_API_KEY environment variable is configured before starting the application.
mvn spring-boot:run
Once the application starts successfully, it runs on the configured Spring Boot server port, which is 8080 by default. You can now test the /chat endpoint by sending a POST request containing a JSON message. For example, send a message containing information that the agent may need during subsequent interactions.
curl -X POST http://localhost:8080/chat \
-H "Content-Type: application/json" \
-d '{"message":"My preferred programming language is Java. Please remember this."}'
The request is passed to the ChatClient, which sends the message to the configured OpenAI model. MessageChatMemoryAdvisor maintains the recent conversation history within the configured 20-message window, while AutoMemoryToolsAdvisor makes the file-backed memory tools available so that useful long-lived information can be persisted under the configured agent.memory.dir directory when the agent determines that it should be remembered. The model’s generated response is returned directly by the /chat endpoint. To verify that the agent can use previously supplied information, send another request asking about the preference mentioned earlier.
curl -X POST http://localhost:8080/chat \
-H "Content-Type: application/json" \
-d '{"message":"What is my preferred programming language?"}'
The response will reflect the previously provided preference when that information is available through the configured memory mechanisms. During the same running conversation, recent context can be supplied by MessageWindowChatMemory; information selected for durable storage can be recovered from the file-backed memory managed through AutoMemoryToolsAdvisor. You can also inspect the ${user.home}/.demo-agent/memory directory to observe memory files created or updated by the agent. This demonstrates the distinction between bounded chat memory, which maintains recent conversational context, and durable auto memory, which is intended to preserve selected information beyond the immediate conversation window and across application restarts.
3. Conclusion
Spring AI AutoMemoryTools adds a focused long-term memory layer to an agent. It is useful when facts must outlive a single chat window but should remain inspectable as ordinary files. Start with AutoMemoryToolsAdvisor, keep the memory root private and writable only by the application, and ask the model to save only durable, useful information. Pair it with bounded ChatMemory rather than trying to make either mechanism do both jobs.




