diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-file/pom.xml b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-file/pom.xml
new file mode 100644
index 00000000000..b4805b36429
--- /dev/null
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-file/pom.xml
@@ -0,0 +1,86 @@
+
+
+
+ 4.0.0
+
+ org.springframework.ai
+ spring-ai-parent
+ 1.0.0-SNAPSHOT
+ ../../../../../../pom.xml
+
+ spring-ai-autoconfigure-model-chat-memory-repository-file
+ jar
+ Spring AI File Chat Memory Repository Auto Configuration
+ Spring File AI Chat Memory Repository Auto Configuration
+ https://github.com/spring-projects/spring-ai
+
+
+ https://github.com/spring-projects/spring-ai
+ git://github.com/spring-projects/spring-ai.git
+ git@github.com:spring-projects/spring-ai.git
+
+
+
+
+
+ org.springframework.ai
+ spring-ai-model-chat-memory-repository-file
+ ${project.parent.version}
+
+
+
+ org.springframework.ai
+ spring-ai-autoconfigure-model-chat-memory
+ ${project.parent.version}
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-autoconfigure-processor
+ true
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.testcontainers
+ junit-jupiter
+ test
+
+
+
+
+
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-file/src/main/java/org/springframework/ai/model/chat/memory/repository/file/autoconfigure/FileChatMemoryRepositoryAutoConfiguration.java b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-file/src/main/java/org/springframework/ai/model/chat/memory/repository/file/autoconfigure/FileChatMemoryRepositoryAutoConfiguration.java
new file mode 100644
index 00000000000..9e221c52fe6
--- /dev/null
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-file/src/main/java/org/springframework/ai/model/chat/memory/repository/file/autoconfigure/FileChatMemoryRepositoryAutoConfiguration.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2025-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.model.chat.memory.repository.file.autoconfigure;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.ai.chat.memory.ChatMemoryRepository;
+import org.springframework.ai.chat.memory.repository.file.FileChatMemoryRepository;
+import org.springframework.ai.model.chat.memory.autoconfigure.ChatMemoryAutoConfiguration;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * @author John Dahle
+ */
+@AutoConfiguration(before = ChatMemoryAutoConfiguration.class)
+@EnableConfigurationProperties(FileChatMemoryRepositoryProperties.class)
+@ConditionalOnProperty(prefix = FileChatMemoryRepositoryProperties.CONFIG_PREFIX, name = "enabled",
+ havingValue = "true", matchIfMissing = true)
+public class FileChatMemoryRepositoryAutoConfiguration {
+
+ private final FileChatMemoryRepositoryProperties props;
+
+ public FileChatMemoryRepositoryAutoConfiguration(FileChatMemoryRepositoryProperties props) {
+ this.props = props;
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(ChatMemoryRepository.class)
+ public FileChatMemoryRepository fileChatMemoryRepository(ObjectMapper objectMapper) {
+ Path baseDir = Paths.get(props.getBaseDir());
+ return new FileChatMemoryRepository(baseDir, objectMapper);
+ }
+
+}
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-file/src/main/java/org/springframework/ai/model/chat/memory/repository/file/autoconfigure/FileChatMemoryRepositoryProperties.java b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-file/src/main/java/org/springframework/ai/model/chat/memory/repository/file/autoconfigure/FileChatMemoryRepositoryProperties.java
new file mode 100644
index 00000000000..649abf2aad2
--- /dev/null
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-file/src/main/java/org/springframework/ai/model/chat/memory/repository/file/autoconfigure/FileChatMemoryRepositoryProperties.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2025-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.model.chat.memory.repository.file.autoconfigure;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * @author John Dahle
+ */
+
+@ConfigurationProperties(FileChatMemoryRepositoryProperties.CONFIG_PREFIX)
+public class FileChatMemoryRepositoryProperties {
+
+ public static final String CONFIG_PREFIX = "spring.ai.chat.memory.repository.file";
+ private boolean enabled = true;
+ private String baseDir = System.getProperty("user.home") + "/.spring-ai/chat-memory";
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public String getBaseDir() {
+ return baseDir;
+ }
+
+ public void setBaseDir(String baseDir) {
+ this.baseDir = baseDir;
+ }
+
+}
diff --git a/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-file/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-file/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 00000000000..a214e883aba
--- /dev/null
+++ b/auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-file/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,16 @@
+#
+# Copyright 2024-2025 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+org.springframework.ai.model.chat.memory.repository.file.autoconfigure.FileChatMemoryRepositoryAutoConfiguration
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-file/pom.xml b/memory/repository/spring-ai-model-chat-memory-repository-file/pom.xml
new file mode 100644
index 00000000000..d583972f2e7
--- /dev/null
+++ b/memory/repository/spring-ai-model-chat-memory-repository-file/pom.xml
@@ -0,0 +1,64 @@
+
+
+
+
+ 4.0.0
+
+ org.springframework.ai
+ spring-ai-parent
+ 1.0.0-SNAPSHOT
+ ../../../pom.xml
+
+
+ spring-ai-model-chat-memory-repository-file
+ Spring File-based Chat Memory Repository
+ Spring File-based Chat Memory Repository implementation
+
+ https://github.com/spring-projects/spring-ai
+
+
+ https://github.com/spring-projects/spring-ai
+ git://github.com/spring-projects/spring-ai.git
+ git@github.com:spring-projects/spring-ai.git
+
+
+
+
+ org.springframework.ai
+ spring-ai-client-chat
+ ${project.version}
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.springframework.ai
+ spring-ai-test
+ ${project.version}
+ test
+
+
+
+
+
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/FileChatMemoryRepository.java b/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/FileChatMemoryRepository.java
new file mode 100644
index 00000000000..ff00a1a460e
--- /dev/null
+++ b/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/FileChatMemoryRepository.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2025-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.chat.memory.repository.file;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.ai.chat.memory.ChatMemoryRepository;
+import org.springframework.ai.chat.memory.repository.file.dto.MessageDto;
+import org.springframework.ai.chat.memory.repository.file.dto.MessageDtoMapper;
+import org.springframework.ai.chat.messages.Message;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+/**
+ * @author John Dahle
+ */
+public class FileChatMemoryRepository implements ChatMemoryRepository {
+
+ private final Path baseDir;
+
+ private final ObjectMapper objectMapper;
+
+ public FileChatMemoryRepository(Path baseDir, ObjectMapper objectMapper) {
+ this.baseDir = baseDir;
+ this.objectMapper = objectMapper;
+ try {
+ Files.createDirectories(baseDir);
+ }
+ catch (IOException e) {
+ throw new RuntimeException("Failed to create base directory: " + baseDir, e);
+ }
+ }
+
+ private Path fileFor(String conversationId) {
+ return baseDir.resolve(conversationId + ".json");
+ }
+
+ @Override
+ public List findConversationIds() {
+ try (var stream = Files.list(baseDir)) {
+ return stream.filter(p -> p.toString().endsWith(".json"))
+ .map(p -> p.getFileName().toString().replaceFirst("\\.json$", ""))
+ .collect(Collectors.toList());
+ }
+ catch (IOException e) {
+ throw new RuntimeException("Failed to list conversation IDs", e);
+ }
+ }
+
+ @Override
+ public List findByConversationId(String conversationId) {
+ Path file = fileFor(conversationId);
+ if (!Files.exists(file)) {
+ return Collections.emptyList();
+ }
+ try {
+ // 1. Read DTOs from disk
+ List dtos = objectMapper.readValue(file.toFile(), new TypeReference>() {
+ });
+ // 2. Map them back to domain Messages
+ return MessageDtoMapper.toDomainList(dtos);
+ }
+ catch (IOException e) {
+ throw new RuntimeException("Failed to read messages for conversation: " + conversationId, e);
+ }
+ }
+
+ @Override
+ public void saveAll(String conversationId, List messages) {
+ try {
+ // 1. Convert domain Messages into DTOs
+ List dtos = MessageDtoMapper.toDtoList(messages);
+ // 2. Tell Jackson they’re DTOs and write them
+ objectMapper.writerFor(new TypeReference>() {
+ }).writeValue(fileFor(conversationId).toFile(), dtos);
+ }
+ catch (IOException e) {
+ throw new RuntimeException("Failed to write messages for conversation: " + conversationId, e);
+ }
+ }
+
+ @Override
+ public void deleteByConversationId(String conversationId) {
+ try {
+ Files.deleteIfExists(fileFor(conversationId));
+ }
+ catch (IOException e) {
+ throw new RuntimeException("Failed to delete conversation: " + conversationId, e);
+ }
+ }
+
+}
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/dto/AssistantMessageDto.java b/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/dto/AssistantMessageDto.java
new file mode 100644
index 00000000000..b81756f2a20
--- /dev/null
+++ b/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/dto/AssistantMessageDto.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2025-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.chat.memory.repository.file.dto;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import org.springframework.ai.chat.messages.AssistantMessage;
+import org.springframework.ai.chat.messages.Message;
+
+/**
+ * @author John Dahle
+ */
+
+@JsonTypeName("assistant")
+public record AssistantMessageDto(@JsonProperty("text") String text) implements MessageDto {
+
+ @JsonCreator
+ public AssistantMessageDto {
+ } // Jackson will call this record‐canonical ctor
+
+ @Override
+ public Message toDomain() {
+ return new AssistantMessage(text);
+ }
+}
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/dto/MessageDto.java b/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/dto/MessageDto.java
new file mode 100644
index 00000000000..ce3fcf87829
--- /dev/null
+++ b/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/dto/MessageDto.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2025-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.chat.memory.repository.file.dto;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import org.springframework.ai.chat.messages.Message;
+
+/**
+ * @author John Dahle
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "kind")
+@JsonSubTypes({ @JsonSubTypes.Type(value = AssistantMessageDto.class, name = "assistant"),
+ @JsonSubTypes.Type(value = UserMessageDto.class, name = "user"),
+ @JsonSubTypes.Type(value = SystemMessageDto.class, name = "system") })
+public sealed interface MessageDto permits AssistantMessageDto, UserMessageDto, SystemMessageDto {
+
+ Message toDomain();
+
+}
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/dto/MessageDtoMapper.java b/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/dto/MessageDtoMapper.java
new file mode 100644
index 00000000000..4c2aeb62efc
--- /dev/null
+++ b/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/dto/MessageDtoMapper.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2025-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.chat.memory.repository.file.dto;
+
+import org.springframework.ai.chat.messages.Message;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author John Dahle
+ */
+public final class MessageDtoMapper {
+
+ private MessageDtoMapper() {
+ /* no-op */ }
+
+ public static MessageDto toDto(Message msg) {
+ return switch (msg.getMessageType()) {
+ case ASSISTANT -> new AssistantMessageDto(msg.getText());
+ case USER -> new UserMessageDto(msg.getText());
+ case SYSTEM -> new SystemMessageDto(msg.getText());
+ default -> throw new IllegalArgumentException("Unsupported message type: " + msg.getMessageType());
+ };
+ }
+
+ public static Message toDomain(MessageDto dto) {
+ return dto.toDomain();
+ }
+
+ public static List toDtoList(List messages) {
+ return messages.stream().map(MessageDtoMapper::toDto).collect(Collectors.toList());
+ }
+
+ public static List toDomainList(List dtos) {
+ return dtos.stream().map(MessageDto::toDomain).collect(Collectors.toList());
+ }
+
+}
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/dto/SystemMessageDto.java b/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/dto/SystemMessageDto.java
new file mode 100644
index 00000000000..2b2d627ce9f
--- /dev/null
+++ b/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/dto/SystemMessageDto.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2025-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.chat.memory.repository.file.dto;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import org.springframework.ai.chat.messages.Message;
+import org.springframework.ai.chat.messages.SystemMessage;
+
+/**
+ * @author John Dahle
+ */
+@JsonTypeName("system")
+public record SystemMessageDto(@JsonProperty("text") String text) implements MessageDto {
+
+ @JsonCreator
+ public SystemMessageDto {
+ }
+
+ @Override
+ public Message toDomain() {
+ return new SystemMessage(text);
+ }
+}
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/dto/UserMessageDto.java b/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/dto/UserMessageDto.java
new file mode 100644
index 00000000000..4eb1d37381f
--- /dev/null
+++ b/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/dto/UserMessageDto.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2025-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.chat.memory.repository.file.dto;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import org.springframework.ai.chat.messages.Message;
+import org.springframework.ai.chat.messages.UserMessage;
+
+/**
+ * @author John Dahle
+ */
+@JsonTypeName("user")
+public record UserMessageDto(@JsonProperty("text") String text) implements MessageDto {
+ @JsonCreator
+ public UserMessageDto {
+ }
+
+ @Override
+ public Message toDomain() {
+ return new UserMessage(text);
+ }
+}
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/package-info.java b/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/package-info.java
new file mode 100644
index 00000000000..60758af4de8
--- /dev/null
+++ b/memory/repository/spring-ai-model-chat-memory-repository-file/src/main/java/org/springframework/ai/chat/memory/repository/file/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2023-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@NonNullApi
+@NonNullFields
+package org.springframework.ai.chat.memory.repository.file;
+
+import org.springframework.lang.NonNullApi;
+import org.springframework.lang.NonNullFields;
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-file/src/test/java/org/springframework/ai/chat/memory/repository/file/FileChatMemoryRepositoryDtoIT.java b/memory/repository/spring-ai-model-chat-memory-repository-file/src/test/java/org/springframework/ai/chat/memory/repository/file/FileChatMemoryRepositoryDtoIT.java
new file mode 100644
index 00000000000..e30cc14c4ab
--- /dev/null
+++ b/memory/repository/spring-ai-model-chat-memory-repository-file/src/test/java/org/springframework/ai/chat/memory/repository/file/FileChatMemoryRepositoryDtoIT.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2025-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.chat.memory.repository.file;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.springframework.ai.chat.memory.ChatMemoryRepository;
+import org.springframework.ai.chat.messages.AssistantMessage;
+import org.springframework.ai.chat.messages.Message;
+import org.springframework.ai.chat.messages.SystemMessage;
+import org.springframework.ai.chat.messages.UserMessage;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author John Dahle
+ */
+class FileChatMemoryRepositoryDtoIT {
+
+ private static final String SAMPLE_JSON = """
+ [
+ {
+ "kind": "assistant",
+ "text": "Hello from assistant"
+ },
+ {
+ "kind": "user",
+ "text": "Hello from user"
+ },
+ {
+ "kind": "system",
+ "text": "System initialization"
+ }
+ ]
+ """;
+
+ @Test
+ void loadSampleMemoryIncludingSystem(@TempDir Path tempDir) throws Exception {
+ String conversationId = "sample-convo";
+ Path file = tempDir.resolve(conversationId + ".json");
+ Files.writeString(file, SAMPLE_JSON);
+ ChatMemoryRepository repo = new FileChatMemoryRepository(tempDir, new ObjectMapper());
+ List ids = repo.findConversationIds();
+ assertThat(ids).containsExactly(conversationId);
+ List messages = repo.findByConversationId(conversationId);
+ assertThat(messages).hasSize(3);
+ assertThat(messages.get(0)).isInstanceOf(AssistantMessage.class)
+ .extracting(Message::getText)
+ .isEqualTo("Hello from assistant");
+ assertThat(messages.get(1)).isInstanceOf(UserMessage.class)
+ .extracting(Message::getText)
+ .isEqualTo("Hello from user");
+ assertThat(messages.get(2)).isInstanceOf(SystemMessage.class)
+ .extracting(Message::getText)
+ .isEqualTo("System initialization");
+ }
+
+}
diff --git a/memory/repository/spring-ai-model-chat-memory-repository-file/src/test/java/org/springframework/ai/chat/memory/repository/file/FileChatMemoryRepositoryIT.java b/memory/repository/spring-ai-model-chat-memory-repository-file/src/test/java/org/springframework/ai/chat/memory/repository/file/FileChatMemoryRepositoryIT.java
new file mode 100644
index 00000000000..5d3c390b1f4
--- /dev/null
+++ b/memory/repository/spring-ai-model-chat-memory-repository-file/src/test/java/org/springframework/ai/chat/memory/repository/file/FileChatMemoryRepositoryIT.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2025-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.ai.chat.memory.repository.file;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.springframework.ai.chat.memory.ChatMemoryRepository;
+import org.springframework.ai.chat.messages.AssistantMessage;
+import org.springframework.ai.chat.messages.Message;
+import org.springframework.ai.chat.messages.MessageType;
+import org.springframework.ai.chat.messages.SystemMessage;
+import org.springframework.ai.chat.messages.UserMessage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.UUID;
+
+import static org.assertj.core.api.Assertions.assertThat;
+/**
+ * @author John Dahle
+ */
+@SpringBootTest(classes = FileChatMemoryRepositoryIT.TestConfig.class)
+public class FileChatMemoryRepositoryIT {
+
+ @TempDir
+ static Path tempDir;
+
+ @Autowired
+ private ChatMemoryRepository chatMemoryRepository;
+
+ @Test
+ void correctChatMemoryRepositoryInstance() {
+ assertThat(chatMemoryRepository).isInstanceOf(FileChatMemoryRepository.class);
+ }
+
+ @ParameterizedTest
+ @CsvSource({ "Message from assistant,ASSISTANT", "Message from user,USER", "Message from system,SYSTEM" })
+ void saveMessagesSingleMessage(String content, MessageType messageType) {
+ String conversationId = UUID.randomUUID().toString();
+ Message message = switch (messageType) {
+ case ASSISTANT -> new AssistantMessage(content + " - " + conversationId);
+ case USER -> new UserMessage(content + " - " + conversationId);
+ case SYSTEM -> new SystemMessage(content + " - " + conversationId);
+ default -> throw new IllegalArgumentException("Unsupported type: " + messageType);
+ };
+
+ chatMemoryRepository.saveAll(conversationId, List.of(message));
+ List results = chatMemoryRepository.findByConversationId(conversationId);
+
+ assertThat(results).hasSize(1);
+ assertThat(results.get(0).getText()).isEqualTo(message.getText());
+ assertThat(results.get(0).getMessageType()).isEqualTo(messageType);
+ }
+
+ @Test
+ void deleteMessagesByConversationId() {
+ String conversationId = UUID.randomUUID().toString();
+ List messages = List.of(new AssistantMessage("Assistant"), new UserMessage("User"),
+ new SystemMessage("System"));
+
+ chatMemoryRepository.saveAll(conversationId, messages);
+ assertThat(chatMemoryRepository.findByConversationId(conversationId)).hasSize(3);
+
+ chatMemoryRepository.deleteByConversationId(conversationId);
+ assertThat(chatMemoryRepository.findByConversationId(conversationId)).isEmpty();
+ }
+
+ @Configuration
+ static class TestConfig {
+
+ @Bean
+ public ChatMemoryRepository chatMemoryRepository() throws Exception {
+ ObjectMapper mapper = new ObjectMapper();
+
+ // Attach @class metadata only for Message types
+ mapper.addMixIn(Message.class, MessageMixin.class);
+
+ // Register concrete Message subtypes
+ mapper.registerSubtypes(AssistantMessage.class, UserMessage.class, SystemMessage.class);
+
+ // Prepare the temporary directory
+ Files.createDirectories(tempDir);
+ return new FileChatMemoryRepository(tempDir, mapper);
+ }
+
+ @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
+ private abstract static class MessageMixin {
+
+ }
+
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index 599bf8b4237..1153943adfc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -44,6 +44,7 @@
memory/repository/spring-ai-model-chat-memory-repository-cassandra
memory/repository/spring-ai-model-chat-memory-repository-jdbc
memory/repository/spring-ai-model-chat-memory-repository-neo4j
+ memory/repository/spring-ai-model-chat-memory-repository-file
@@ -89,6 +90,7 @@
auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory
auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-cassandra
auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-jdbc
+ auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-file
auto-configurations/models/chat/memory/repository/spring-ai-autoconfigure-model-chat-memory-repository-neo4j
auto-configurations/models/chat/observation/spring-ai-autoconfigure-model-chat-observation
@@ -195,9 +197,11 @@
spring-ai-spring-boot-starters/spring-ai-starter-model-deepseek
spring-ai-spring-boot-starters/spring-ai-starter-model-chat-memory-repository-cassandra
+ spring-ai-spring-boot-starters/spring-ai-starter-model-chat-memory-repository-file
spring-ai-spring-boot-starters/spring-ai-starter-model-chat-memory-repository-jdbc
spring-ai-spring-boot-starters/spring-ai-starter-model-chat-memory-repository-neo4j
+
spring-ai-spring-boot-starters/spring-ai-starter-mcp-client
spring-ai-spring-boot-starters/spring-ai-starter-mcp-server
spring-ai-spring-boot-starters/spring-ai-starter-mcp-client-webflux
diff --git a/spring-ai-spring-boot-starters/spring-ai-starter-model-chat-memory-repository-file/pom.xml b/spring-ai-spring-boot-starters/spring-ai-starter-model-chat-memory-repository-file/pom.xml
new file mode 100644
index 00000000000..1610338d8e9
--- /dev/null
+++ b/spring-ai-spring-boot-starters/spring-ai-starter-model-chat-memory-repository-file/pom.xml
@@ -0,0 +1,64 @@
+
+
+
+
+ 4.0.0
+
+ org.springframework.ai
+ spring-ai-parent
+ 1.0.0-SNAPSHOT
+ ../../pom.xml
+
+ spring-ai-starter-model-chat-memory-repository-file
+ jar
+ Spring AI Starter - JDBC Chat Memory Repository
+ Spring AI JDBC Chat Memory Repository Starter
+ https://github.com/spring-projects/spring-ai
+
+
+ https://github.com/spring-projects/spring-ai
+ git://github.com/spring-projects/spring-ai.git
+ git@github.com:spring-projects/spring-ai.git
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.ai
+ spring-ai-autoconfigure-model-chat-memory
+ ${project.parent.version}
+
+
+
+ org.springframework.ai
+ spring-ai-autoconfigure-model-chat-memory-repository-file
+ ${project.parent.version}
+
+
+
+ org.springframework.ai
+ spring-ai-model-chat-memory-repository-file
+ ${project.parent.version}
+
+
+
+