Session Management
Session management in Strands Agents provides a robust mechanism for persisting agent state and conversation history across multiple interactions. This enables agents to maintain context and continuity even when the application restarts or when deployed in distributed environments.
Overview
Section titled “Overview”A session represents all of stateful information that is needed by agents and multi-agent systems to function, including:
Single Agent Sessions:
- Conversation history (messages)
- Agent state (key-value storage)
- Other stateful information (like Conversation Manager)
Multi-Agent Sessions (Python only):
- Orchestrator state and configuration
- Individual agent states and result within the orchestrator
- Cross-agent shared state and context
- Execution flow and node transition history
Strands provides built-in session persistence capabilities that automatically capture and restore this information, allowing agents to seamlessly continue conversations where they left off.
Beyond the built-in options, third-party session managers provide additional storage and memory capabilities.
Basic Usage
Section titled “Basic Usage”Single Agent Sessions
Section titled “Single Agent Sessions”Simply create an agent with a session manager and use it:
from strands import Agentfrom strands.session.file_session_manager import FileSessionManager
# Create a session manager with a unique session IDsession_manager = FileSessionManager(session_id="test-session")
# Create an agent with the session manageragent = Agent(session_manager=session_manager)
# Use the agent - all messages and state are automatically persistedagent("Hello!") # This conversation is persistedconst session = new SessionManager({ sessionId: 'test-session', storage: { snapshot: new FileStorage('./sessions') },})
const agent = new Agent({ sessionManager: session })
// Use the agent - all messages and state are automatically persistedawait agent.invoke('Hello!') // This conversation is persistedSessionManager is a Plugin. The sessionManager field on AgentConfig is a convenience shorthand — it is equivalent to passing it in the plugins array:
const session = new SessionManager({ sessionId: 'test-session', storage: { snapshot: new FileStorage('./sessions') },})
// Equivalent to passing via sessionManager fieldconst agent = new Agent({ plugins: [session] })await agent.invoke('Hello!')The conversation, and associated state, is persisted to the underlying storage backend.
Multi-Agent Sessions (Python only)
Section titled “Multi-Agent Sessions (Python only)”Multi-agent systems (Graph/Swarm) can also use session management to persist their state:
from strands.multiagent import Graphfrom strands.session.file_session_manager import FileSessionManager
# Create agentsagent1 = Agent(name="researcher")agent2 = Agent(name="writer")
# Create a session manager for the graphsession_manager = FileSessionManager(session_id="multi-agent-session")
# Create graph with session managementgraph = Graph( agents={"researcher": agent1, "writer": agent2}, session_manager=session_manager)
# Use the graph - all orchestrator state is persistedresult = graph("Research and write about AI")Built-in Session Managers
Section titled “Built-in Session Managers”Strands offers two built-in session managers for persisting agent sessions:
- FileSessionManager: Stores sessions in the local filesystem
- S3SessionManager: Stores sessions in Amazon S3 buckets
The TypeScript SDK uses a single SessionManager class paired with a pluggable storage backend:
FileStorage: Stores snapshots on the local filesystemS3Storage: Stores snapshots in Amazon S3
FileSessionManager / FileStorage
Section titled “FileSessionManager / FileStorage”The FileSessionManager provides a simple way to persist both single agent and multi-agent sessions to the local filesystem:
from strands import Agentfrom strands.session.file_session_manager import FileSessionManager
# Create a session manager with a unique session IDsession_manager = FileSessionManager( session_id="user-123", storage_dir="/path/to/sessions" # Optional, defaults to a temp directory)
# Create an agent with the session manageragent = Agent(session_manager=session_manager)
# Use the agent normally - state and messages will be persisted automaticallyagent("Hello, I'm a new user!")
# Multi-agent usagemulti_session_manager = FileSessionManager( session_id="orchestrator-456", storage_dir="/path/to/sessions")graph = Graph( agents={"agent1": agent1, "agent2": agent2}, session_manager=multi_session_manager)FileStorage persists snapshots to the local filesystem. Pass it to SessionManager via the storage.snapshot config:
const session = new SessionManager({ sessionId: 'user-123', storage: { snapshot: new FileStorage('./sessions') },})
const agent = new Agent({ sessionManager: session })await agent.invoke("Hello, I'm a new user!")File Storage Structure
Section titled “File Storage Structure”When using FileSessionManager, sessions are stored in the following directory structure:
/<sessions_dir>/└── session_<session_id>/ ├── session.json # Session metadata ├── agents/ # Single agent storage │ └── agent_<agent_id>/ │ ├── agent.json # Agent metadata and state │ └── messages/ │ ├── message_<message_id>.json │ └── message_<message_id>.json └── multi_agents/ # Multi-agent storage └── multi_agent_<orchestrator_id>/ └── multi_agent.json # Orchestrator state and configuration<baseDir>/└── <sessionId>/ └── scopes/ └── agent/ └── <agentId>/ └── snapshots/ ├── snapshot_latest.json # Latest mutable snapshot └── immutable_history/ ├── snapshot_<uuid7>.json # Immutable checkpoint └── snapshot_<uuid7>.jsonS3SessionManager / S3Storage
Section titled “S3SessionManager / S3Storage”For cloud-based persistence, especially in distributed environments, use the S3SessionManager:
from strands import Agentfrom strands.session.s3_session_manager import S3SessionManagerimport boto3
# Optional: Create a custom boto3 sessionboto_session = boto3.Session(region_name="us-west-2")
# Create a session manager that stores data in S3session_manager = S3SessionManager( session_id="user-456", bucket="my-agent-sessions", prefix="production/", # Optional key prefix boto_session=boto_session, # Optional boto3 session region_name="us-west-2" # Optional AWS region (if boto_session not provided))
# Create an agent with the session manageragent = Agent(session_manager=session_manager)
# Use the agent normally - state and messages will be persisted to S3agent("Tell me about AWS S3")
# Use with multi-agent orchestratorswarm = Swarm( agents=[agent1, agent2, agent3], session_manager=session_manager)
result = swarm("Coordinate the task across agents")S3Storage persists snapshots to an S3 bucket. You can provide a pre-configured S3Client or let the SDK create one from a region:
const session = new SessionManager({ sessionId: 'user-456', storage: { snapshot: new S3Storage({ bucket: 'my-agent-sessions', prefix: 'production', // Optional key prefix s3Client: new S3Client({ // Optional pre-configured client region: 'us-west-2', }), // Alternatively, use region directly (cannot be combined with s3Client): // region: 'us-west-2', }), },})
const agent = new Agent({ sessionManager: session })await agent.invoke('Tell me about AWS S3')S3 Storage Structure
Section titled “S3 Storage Structure”<s3_key_prefix>/└── session_<session_id>/ ├── session.json # Session metadata ├── agents/ # Single agent storage │ └── agent_<agent_id>/ │ ├── agent.json # Agent metadata and state │ └── messages/ │ ├── message_<message_id>.json │ └── message_<message_id>.json └── multi_agents/ # Multi-agent storage └── multi_agent_<orchestrator_id>/ └── multi_agent.json # Orchestrator state and configuration[<prefix>/]<sessionId>/└── scopes/ └── agent/ └── <agentId>/ └── snapshots/ ├── snapshot_latest.json └── immutable_history/ ├── snapshot_<uuid7>.json └── snapshot_<uuid7>.jsonRequired S3 Permissions
Section titled “Required S3 Permissions”To use S3-backed session storage, your AWS credentials must have the following permissions:
s3:PutObject- To create and update session datas3:GetObject- To retrieve session datas3:DeleteObject- To delete session datas3:ListBucket- To list objects in the bucket
Here’s a sample IAM policy that grants these permissions for a specific bucket:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::my-agent-sessions/*" }, { "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::my-agent-sessions" } ]}How Session Management Works
Section titled “How Session Management Works”Session Persistence Triggers
Section titled “Session Persistence Triggers”Session persistence is automatically triggered by lifecycle events in the agent:
Single Agent Events
- Agent Initialization: When an agent is created with a session manager, it automatically restores any existing state and messages from the session.
- Message Addition: When a new message is added to the conversation, it’s automatically persisted to the session.
- Agent Invocation: After each agent invocation, the agent state is synchronized with the session to capture any updates.
- Message Redaction: When sensitive information needs to be redacted, the session manager can replace the original message with a redacted version while maintaining conversation flow.
- Agent Initialization: Restores state from
snapshot_latestif it exists. - Message Addition (
saveLatestOn: 'message'): Saves after every message and after model calls with guardrail redactions. - Agent Invocation (
saveLatestOn: 'invocation', default): Saves after each invocation completes. - Snapshot Trigger: Creates an immutable checkpoint when the
snapshotTriggercallback returnstrue.
See Basic Usage for configuration examples.
Multi-Agent Events (Python only):
- Multi-Agent Initialization: Restores orchestrator state from the session.
- Node Execution: Synchronizes orchestrator state after node transitions.
- Multi-Agent Invocation: Captures final orchestrator state after execution.
Immutable Snapshots (TypeScript only)
Section titled “Immutable Snapshots (TypeScript only)”In addition to snapshot_latest, the TypeScript SDK supports immutable snapshots — append-only checkpoints identified by UUID v7. These enable time-travel restore: you can restore the agent to any prior checkpoint, not just the latest state.
Creating Immutable Snapshots
Section titled “Creating Immutable Snapshots”Use the snapshotTrigger callback to control when an immutable snapshot is created. The callback receives the current agent data and returns true to trigger a snapshot:
const session = new SessionManager({ sessionId: 'my-session', storage: { snapshot: new FileStorage('./sessions') }, // Create an immutable snapshot after every 4 messages snapshotTrigger: ({ agentData }) => agentData.messages.length % 4 === 0,})
const agent = new Agent({ sessionManager: session })await agent.invoke('First message') // 2 messages — no snapshotawait agent.invoke('Second message') // 4 messages — immutable snapshot createdListing and Restoring Snapshots
Section titled “Listing and Restoring Snapshots”Snapshot IDs are UUID v7, so they sort lexicographically in chronological order. Use listSnapshotIds on the storage backend to retrieve them, then pass a snapshotId to restoreSnapshot on the SessionManager:
const storage = new FileStorage('./sessions')const location = { sessionId: 'my-session', scope: 'agent' as const, scopeId: 'default' }
// List all immutable snapshot IDs (chronological order)const snapshotIds = await storage.listSnapshotIds({ location })
// Paginate: get the next 10 snapshots after a cursorconst page2 = await storage.listSnapshotIds({ location, limit: 10, startAfter: snapshotIds.at(-1),})
// Restore agent to a specific checkpointconst session = new SessionManager({ sessionId: 'my-session', storage: { snapshot: storage } })const agent = new Agent({ sessionManager: session })await agent.initialize()await session.restoreSnapshot({ target: agent, snapshotId: snapshotIds[0]! })Deleting Sessions (TypeScript only)
Section titled “Deleting Sessions (TypeScript only)”To remove all snapshots and manifests for a session, call deleteSession() on the SessionManager. This removes the entire session root directory (filesystem) or all objects under the session prefix (S3):
const session = new SessionManager({ sessionId: 'my-session', storage: { snapshot: new FileStorage('./sessions') },})
// Remove all snapshots and manifests for this sessionawait session.deleteSession()Data Models
Section titled “Data Models”Session data is stored using these key data models:
Session
The Session model is the top-level container for session data:
- Purpose: Provides a namespace for organizing multiple agents and their interactions
- Key Fields:
session_id: Unique identifier for the sessionsession_type: Type of session (currently"AGENT"for both agent & multiagent in order to keep backward compatibility)created_at: ISO format timestamp of when the session was createdupdated_at: ISO format timestamp of when the session was last updated
SessionAgent
The SessionAgent model stores agent-specific data:
- Purpose: Maintains the state and configuration of a specific agent within a session
- Key Fields:
agent_id: Unique identifier for the agent within the sessionstate: Dictionary containing the agent’s state data (key-value pairs)conversation_manager_state: Dictionary containing the state of the conversation managercreated_at: ISO format timestamp of when the agent was createdupdated_at: ISO format timestamp of when the agent was last updated
SessionMessage
The SessionMessage model stores individual messages in the conversation:
- Purpose: Preserves the conversation history with support for message redaction
- Key Fields:
message: The original message content (role, content blocks)redact_message: Optional redacted version of the message (used when sensitive information is detected)message_id: Index of the message in the agent’s messages arraycreated_at: ISO format timestamp of when the message was createdupdated_at: ISO format timestamp of when the message was last updated
These data models work together to provide a complete representation of an agent’s state and conversation history. The session management system handles serialization and deserialization of these models, including special handling for binary data using base64 encoding.
Multi-Agent State
Multi-agent systems serialize their state as JSON objects containing:
- Orchestrator Configuration: Settings, parameters, and execution preferences
- Node State: Current execution state and node transition history
- Shared Context: Cross-agent shared state and variables
The TypeScript SDK stores session state as a Snapshot object written to JSON. Each snapshot contains:
data.messages: The full conversation historydata.state: Agent key-value statedata.systemPrompt: The agent’s system promptschemaVersion: Schema version for forward compatibilitycreatedAt: ISO 8601 timestamp
There are two kinds of snapshots:
snapshot_latest.json: A single mutable file overwritten on each save. Used to resume the most recent state after a restart.- Immutable snapshots (
immutable_history/snapshot_<uuid7>.json): Append-only checkpoints created whensnapshotTriggerfires. Used for time-travel restore.
Third-Party Session Managers
Section titled “Third-Party Session Managers”The following third-party session managers extend Strands with additional storage and memory capabilities:
| Session Manager | Provider | Description | Documentation |
|---|---|---|---|
| AgentCoreMemorySessionManager | Amazon | Advanced memory with intelligent retrieval using Amazon Bedrock AgentCore Memory. Supports both short-term memory (STM) and long-term memory (LTM) with strategies for user preferences, facts, and session summaries. | View Documentation |
| Contribute Your Own | Community | Have you built a session manager? Share it with the community! | Learn How |
Custom Session Repositories (Python only)
Section titled “Custom Session Repositories (Python only)”For advanced use cases, you can implement your own session storage backend by creating a custom session repository:
from typing import Optionalfrom strands import Agentfrom strands.session.repository_session_manager import RepositorySessionManagerfrom strands.session.session_repository import SessionRepositoryfrom strands.types.session import Session, SessionAgent, SessionMessage
class CustomSessionRepository(SessionRepository): """Custom session repository implementation."""
def __init__(self): """Initialize with your custom storage backend.""" # Initialize your storage backend (e.g., database connection) self.db = YourDatabaseClient()
def create_session(self, session: Session) -> Session: """Create a new session.""" self.db.sessions.insert(asdict(session)) return session
def read_session(self, session_id: str) -> Optional[Session]: """Read a session by ID.""" data = self.db.sessions.find_one({"session_id": session_id}) if data: return Session.from_dict(data) return None
# Implement other required methods... # create_agent, read_agent, update_agent # create_message, read_message, update_message, list_messages
# Use your custom repository with RepositorySessionManagercustom_repo = CustomSessionRepository()session_manager = RepositorySessionManager( session_id="user-789", session_repository=custom_repo)
agent = Agent(session_manager=session_manager)This approach allows you to store session data in any backend system while leveraging the built-in session management logic.
Session Persistence Best Practices
Section titled “Session Persistence Best Practices”When implementing session persistence in your applications, consider these best practices:
- Use Unique Session IDs: Generate unique session IDs for each user or conversation context to prevent data overlap.
- Session Cleanup: Implement a strategy for cleaning up old or inactive sessions. Consider adding TTL (Time To Live) for sessions in production environments.
- Understand Persistence Triggers: Remember that changes to agent state or messages are only persisted during specific lifecycle events.
- Concurrent Access: Session managers are not thread-safe; use appropriate locking for concurrent access.
- Secure Storage Directories: The session storage directory is a trusted data store. Restrict filesystem permissions so that only the agent process can read and write to it. In shared or multi-tenant environments (shared volumes, containers), be aware that the SDK does not block symlinks in the session storage directory. If an attacker with write access to the storage directory creates a symlink (e.g.,
message_0.jsonpointing to an arbitrary file), the SDK will follow it, which could cause sensitive file contents to be loaded into the agent’s conversation history.