Spring AI ChatMemory integration with Amazon AgentCore Memory service.
For quick start and usage examples, see the main README.
- Spring AI Integration: Implements
ChatMemoryRepositoryinterface - Auto-configuration: Zero-configuration setup with Spring Boot
- Short-Term Memory: Conversation history with
MessageWindowChatMemory - Long-Term Memory: 4 consolidation strategies (Semantic, User Preference, Summary, Episodic)
- Implements
ChatMemoryRepositoryinterface for conversation history - Works with
MessageWindowChatMemoryfor sliding window conversations
- Semantic: Semantic search for user facts using the current query
- User Preference: Lists ALL stored preferences regardless of query — preferences should always apply
- Summary: Semantic search for conversation summaries by session
- Episodic: Semantic search for past interactions and reflections
LTM advisors run before STM advisor (lower order = earlier execution):
| Order | Advisor | Target | Purpose |
|---|---|---|---|
| 100 | Semantic | System prompt | Add relevant facts |
| 101 | User Preference | System prompt | Add preferences |
| 102 | Summary | User prompt | Augment query with context |
| 103 | Episodic | System prompt | Add past interactions |
| 1000+ | STM (MessageChatMemoryAdvisor) | Messages | Add conversation history |
Why LTM before STM? LTM enriches the prompt with persistent knowledge (facts, preferences) before STM adds recent conversation history. This ensures the model has full context: who the user is (LTM) + what was just discussed (STM).
| Memory Type | Target | Reason |
|---|---|---|
| Semantic | System | Stable context about user, cacheable |
| User Preference | System | Stable settings, cacheable |
| Episodic | System | Background context, cacheable |
| Summary | User | Query-specific augmentation, varies per request |
Prompt Caching Benefits: Facts, preferences, and episodic memories go to the system prompt because they're relatively stable across requests. With Bedrock's prompt caching (cache-options.strategy: SYSTEM_AND_TOOLS), the system prompt is cached and reused, reducing latency and cost. Only summaries augment the user prompt since they're query-specific.
agentcore:
memory:
memory-id: your-memory-id # Required: AgentCore Memory ID (shared with LTM)
short-term:
total-events-limit: 100 # Optional: Max events to retrieve (context window)
default-session: default-session # Optional: Default session name
page-size: 50 # Optional: API pagination sizeMigration (1.1.0): STM-only properties moved from
agentcore.memory.*toagentcore.memory.short-term.*for consistency withagentcore.memory.long-term.*. The old keys still work in 1.1.x but log a deprecation warning at startup and will be removed in a future release. See issue #49.The default of
ignore-unknown-roleshas changed fromfalsetotrue. Spring AI 2.0.0-M7+ runs tool execution at the advisor layer, which routesToolResponseMessagethroughChatMemory.add(...). With the previous default the repository threwIllegalStateException: Unsupported message typeon any tool-using turn. The new default skips non-dialogue messages (TOOL,OTHER) instead, which is the only sensible behaviour for M7+ agents — tool results are point-in-time facts that should not be persisted into conversation history. The property itself (ignore-unknown-roles) is now deprecated and will be removed in a future major: skipping non-dialogue messages becomes hardcoded behaviour. The misnomer ("unknown roles" —TOOL/OTHERare first-class AgentCore roles) and the lack of a usefulfalsemode mean the toggle has no production value. See issue #109.
There are two ways to configure Long-Term Memory:
Automatically discover all strategies from your AgentCore Memory:
agentcore:
memory:
memory-id: ${MEMORY_ID}
long-term:
auto-discovery: true # Discovers strategies from AWSAutodiscovery behavior:
- Queries AWS to discover all strategies configured in your memory
- Creates advisors only for supported types:
SEMANTIC,SUMMARIZATION,USER_PREFERENCE,EPISODIC - Skips
CUSTOMstrategy types (not supported by autodiscovery) - Uses the first namespace if a strategy has multiple namespaces
- Uses default
topKvalues for each strategy type
Overriding discovered defaults:
You can override specific settings for discovered strategies by providing explicit configuration. The explicit config is applied only when the strategy-id matches the discovered one:
agentcore:
memory:
memory-id: ${MEMORY_ID}
long-term:
auto-discovery: true
semantic:
strategy-id: discovered-semantic-id # Must match discovered ID
top-k: 5 # Override default topK
namespace-pattern: /custom/namespace # Override namespace (must exist in AWS)
summary:
strategy-id: discovered-summary-id
top-k: 3Override rules:
strategy-idmust match the discovered strategy ID for overrides to apply- If
strategy-iddoesn't match, the explicit config is ignored namespace-patternmust match one of the namespaces discovered from AWS, or useauto-register=true
Namespace auto-registration:
If you want to use a namespace that doesn't exist in AWS yet:
agentcore:
memory:
long-term:
auto-discovery: true
namespace:
auto-register: true # Register new namespaces in AWS
semantic:
strategy-id: discovered-semantic-id
namespace-pattern: /new/custom/namespace # Will be registered in AWSManually specify each strategy:
agentcore:
memory:
long-term:
semantic:
strategy-id: ${SEMANTIC_STRATEGY_ID} # Enables strategy (omit to disable)
top-k: 3 # Default: 3
scope: ACTOR # Default: ACTOR
user-preference:
strategy-id: ${USER_PREFERENCE_STRATEGY_ID} # Enables strategy (no top-k: lists all)
scope: ACTOR # Default: ACTOR
summary:
strategy-id: ${SUMMARY_STRATEGY_ID} # Enables strategy
top-k: 3 # Default: 3
scope: SESSION # Default: SESSION
episodic:
strategy-id: ${EPISODIC_STRATEGY_ID} # Enables strategy
reflections-strategy-id: ${REFLECTIONS_STRATEGY_ID} # Optional: enables reflections
episodes-top-k: 3 # Default: 3
reflections-top-k: 2 # Default: 2
scope: ACTOR # Default: ACTOR| Scope | Namespace Pattern | Use Case |
|---|---|---|
ACTOR |
/strategies/{memoryStrategyId}/actors/{actorId} |
Search across all sessions for the user |
SESSION |
/strategies/{memoryStrategyId}/actors/{actorId}/sessions/{sessionId} |
Search only current session |
You can override the default namespace patterns with custom ones using the namespace-pattern property:
agentcore:
memory:
long-term:
summary:
strategy-id: ${SUMMARY_STRATEGY_ID}
namespace-pattern: custom-namespace/strategies/{memoryStrategyId}/actors/{actorId}/sessions/{sessionId}Important: The custom namespace pattern must match the namespace configured in your AgentCore Memory strategy. At startup, the library validates that the configured pattern matches what's in AWS. If there's a mismatch, the application will fail to start with a clear error message.
Available placeholders:
{memoryStrategyId}- The strategy ID{actorId}- The user/actor ID{sessionId}- The session ID (required for session-scoped patterns)
Note: Only these predefined placeholders are supported. Custom placeholders are not allowed.
| Strategy | top-k | scope |
|---|---|---|
| semantic | 3 | ACTOR |
| user-preference | n/a (lists all) | ACTOR |
| summary | 3 | SESSION |
| episodic | episodes: 3, reflections: 2 | ACTOR |
Set enabled: true to activate LTM, then configure individual strategies. Each strategy is optional - only configure the ones you need. Advisors are auto-created for configured strategies. Set enabled: false to temporarily disable all LTM without removing strategy configuration.
The repository supports flexible conversation ID formats:
- Simple:
user123→ actor:user123, session:default-session - With Session:
user123:session456→ actor:user123, session:session456
Messages with non-dialogue roles (e.g. ToolResponseMessage, system messages) are skipped with a WARN log line rather than persisted, since they are point-in-time facts that should not be replayed from conversation history. This is the only behaviour in 1.1.x and will be hardcoded in the next major.
The legacy agentcore.memory[.short-term].ignore-unknown-roles property is deprecated in 1.1.0 (@Deprecated(since = "1.1.0", forRemoval = true)); setting it logs a deprecation warning at startup and will be removed in the next major. See issue #109.
All AWS SDK exceptions are wrapped in AgentCoreMemoryException.
List<Message> findByConversationId(String conversationId);
void saveAll(String conversationId, List<Message> messages);
void deleteByConversationId(String conversationId);| Property | Type | Default | Description |
|---|---|---|---|
agentcore.memory.memory-id |
String | null | AgentCore Memory ID (required, shared with LTM) |
agentcore.memory.short-term.total-events-limit |
Integer | null | Context window size |
agentcore.memory.short-term.default-session |
String | "default-session" | Default session |
agentcore.memory.short-term.page-size |
Integer | 100 | API pagination size |
agentcore.memory.short-term.ignore-unknown-roles |
Boolean | true | Deprecated (since 1.1.0, for removal). Skipping non-dialogue messages will become hardcoded — see #109 |
| Spring AI Message | AgentCore Role |
|---|---|
UserMessage |
USER ✅ |
AssistantMessage |
ASSISTANT ✅ |
SystemMessage |
Filtered |
ToolResponseMessage |
Filtered |
- Page Size: Adjust
agentcore.memory.short-term.page-sizebased on typical conversation length - Total Limit: Use
agentcore.memory.short-term.total-events-limitto control context window size - Logging: Set
org.springaicommunity.agentcore.memory: DEBUGfor detailed logs
-
Memory ID not found: Verify
AGENTCORE_MEMORY_MEMORY_IDenvironment variable -
AWS Permissions: Required:
bedrock-agentcore:ListEventsbedrock-agentcore:CreateEventbedrock-agentcore:DeleteEventbedrock-agentcore:RetrieveMemoryRecords(for LTM)
-
Debug logging:
logging: level: org.springaicommunity.agentcore.memory: DEBUG
- Java 17+
- Spring Boot 4.x
- Spring AI 2.0.0+
See the Build & Test and Integration Test Environment Variables sections in AGENTS.md for testing instructions.
Apache License 2.0