Lesson 9: Persistent Memory with Session Managers
Code for this lesson: samples/09-persistent-memory
Persisting Conversation History
Section titled “Persisting Conversation History”Session managers persist conversation history and agent state across runs. Without them, everything resets when the process stops. They’re implemented as hook providers, so persistence is just another harness behavior layered in through hooks.
Snapshot Session Manager (Recommended)
Section titled “Snapshot Session Manager (Recommended)”The recommended approach for new single-agent sessions. It saves the entire agent state as one atomic blob instead of individual message records, and supports immutable checkpoints for restoring to any prior point.
from strands import Agentfrom strands.session import SnapshotSessionManagerfrom strands.storage import LocalFileStorage
session_manager = SnapshotSessionManager( session_id="customer-session-001", storage=LocalFileStorage("./sessions"),)
agent = Agent( tools=[lookup_customer, get_order_history, process_refund], system_prompt=SYSTEM_PROMPT, context_manager="auto", session_manager=session_manager,)Persistence happens automatically: agent state is saved after each invocation by default. Use save_latest_on="message" to save after every message instead.
For production, swap LocalFileStorage for S3Storage:
from strands.storage import S3Storage
session_manager = SnapshotSessionManager( session_id="customer-session-001", storage=S3Storage(bucket="my-agent-sessions", prefix="production/"),)File Session Manager (Record-Based)
Section titled “File Session Manager (Record-Based)”The record-based approach persists each message individually. It’s still supported for existing sessions and required for Graph/Swarm multi-agent persistence.
from strands import Agentfrom strands.session.file_session_manager import FileSessionManager
session_manager = FileSessionManager( session_id="customer-session-001", storage_dir="./sessions",)
agent = Agent( tools=[lookup_customer, get_order_history, process_refund], system_prompt=SYSTEM_PROMPT, context_manager="auto", session_manager=session_manager,)S3 Session Manager (Record-Based)
Section titled “S3 Session Manager (Record-Based)”Same record-based approach, backed by S3 instead of local disk:
from strands.session.s3_session_manager import S3SessionManager
session_manager = S3SessionManager( session_id="customer-session-001", bucket="my-agent-sessions", prefix="customer-service/", region_name="us-east-1",)
agent = Agent(..., session_manager=session_manager)When to Use Which
Section titled “When to Use Which”| Manager | Best For |
|---|---|
SnapshotSessionManager | New single-agent sessions. Simpler, atomic saves, supports checkpoints. |
FileSessionManager | Existing record-based sessions, Graph/Swarm multi-agent, bidirectional streaming. |
S3SessionManager | Same as File but with S3 for cross-machine access. |
Sessions, Memory, and Storage
Section titled “Sessions, Memory, and Storage”Session managers are one of three related pieces, and it helps to keep them straight:
- Session manager: persists the conversation so the agent can resume where it left off. Scoped to one session.
- Memory manager: durable knowledge that carries across sessions (user preferences, facts, decisions) without replaying old conversations. Backed by one or more memory stores.
- Storage: the byte-level backend underneath both.
LocalFileStorage,S3Storage, and community backends implement the sameStorageinterface, so a session manager, a memory store, and the context manager’s stash can all share one backend.
Memory is opt-in and separate from sessions. Attach a MemoryManager with a store and the agent gets recall (a tool to search what it knows) and injection (relevant memories folded into the prompt automatically):
from strands import Agentfrom strands.memory import MemoryManagerfrom strands.vended_memory_stores.test_memory_store import TestMemoryStore
# Zero-setup store for prototyping; swap for a production store laterstore = TestMemoryStore(name="customer-service")
agent = Agent( session_manager=session_manager, # this conversation memory_manager=MemoryManager(stores=[store]), # knowledge across conversations)Production Storage: DynamoDB
Section titled “Production Storage: DynamoDB”Because sessions, memory, and offloaded context all sit on the Storage interface, one production backend can serve all of them. Strands DynamoDB Storage is an AWS-maintained backend that fits agent workloads well: serverless, single-digit-millisecond reads, native TTL so stale sessions expire themselves, and vector search on the same table for semantic memory.
Set it once at the agent level and every subsystem that persists bytes inherits it under its own namespace:
from strands import Agentfrom strands.session import SnapshotSessionManagerfrom strands_dynamodb_storage import DynamoDBStorage
storage = DynamoDBStorage("agent-storage", region_name="us-east-1")
agent = Agent( tools=[lookup_customer, get_order_history, process_refund], system_prompt=SYSTEM_PROMPT, context_manager="auto", storage=storage, # shared backend session_manager=SnapshotSessionManager("customer-session-001"), # inherits storage)You own the table (a string pk partition key and string sk sort key is all it needs), and the package only ever issues PutItem, GetItem, DeleteItem, and Query.
More Backends
Section titled “More Backends”The integrations catalog lists additional session managers, memory stores, and storage backends. They implement the same interfaces, so you can swap them in without changing agent code.
| Integration | What It Is |
|---|---|
| Strands DynamoDB Storage | Storage backend on Amazon DynamoDB, with TTL, S3 offload, and vector search |
| AgentCore Memory | Session manager backed by Amazon Bedrock AgentCore Memory, with long-term recall |
| Valkey Session Manager | Session manager on Valkey (Redis-compatible) for fast distributed storage |
| Memory stores | Community-built MemoryStore backends for the MemoryManager |
| Storage backends | Community-built Storage implementations |