Storage
Pass a Storage backend to the Agent and every subsystem that needs persistence resolves from it automatically. The SDK handles namespacing so sessions and offloaded content never collide. You can also pass storage directly to individual plugins when different subsystems need different backends.
The SDK ships three backends. Pick one based on where you need your data to live:
| Backend | Where data lives | Best for |
|---|---|---|
InMemoryStorage | Process memory | Tests, short-lived agents |
LocalFileStorage | Local filesystem | Development, single-machine |
S3Storage | Amazon S3 | Production, multi-instance |
Agent-level storage
Section titled “Agent-level storage”The simplest approach: pass a single storage backend to the Agent and let subsystems resolve from it.
storage = S3Storage("my-bucket", prefix="agents/prod/")
agent = Agent( storage=storage, session_manager=SnapshotSessionManager("my-session"), context_manager="auto",)import { S3Storage } from '@strands-agents/sdk/storage'import { Agent, SessionManager } from '@strands-agents/sdk'
const storage = new S3Storage('my-bucket', { prefix: 'agents/prod/',})
const agent = new Agent({ storage, sessionManager: new SessionManager({ sessionId: 'my-session', }), contextManager: 'auto',})Both the session manager and context offloader read from the
same backend without extra wiring. Each subsystem
auto-namespaces its keys (session/ for sessions,
offloader/ for offloaded content), so data never collides.
Per-plugin storage
Section titled “Per-plugin storage”When different subsystems need different backends, pass storage directly to the plugin. This overrides the agent-level default for that plugin only.
agent = Agent( session_manager=SnapshotSessionManager( "my-session", storage=S3Storage("my-bucket") ), plugins=[ContextOffloader(storage=InMemoryStorage())],)import { InMemoryStorage, S3Storage } from '@strands-agents/sdk/storage'import { Agent, SessionManager } from '@strands-agents/sdk'import { ContextOffloader } from '@strands-agents/sdk/vended-plugins/context-offloader'
const agent = new Agent({ sessionManager: new SessionManager({ sessionId: 'my-session', storage: new S3Storage('my-bucket'), }), plugins: [ new ContextOffloader({ storage: new InMemoryStorage(), }), ],})Precedence
Section titled “Precedence”Storage resolves in this order for each subsystem:
- Explicit: storage passed directly to the plugin
- Agent-level: the agent’s
parameter (namespaced automatically)storagestorage - Fallback:
InMemoryStoragefor Context Offloader;LocalFileStoragefor Session Manager in Python, or an error in TypeScript
Built-in backends
Section titled “Built-in backends”InMemoryStorage
Section titled “InMemoryStorage”Data lives in process memory. No constructor arguments. Fast, zero-config, gone when the process exits.
storage = InMemoryStorage()import { InMemoryStorage } from '@strands-agents/sdk/storage'
const storage = new InMemoryStorage()LocalFileStorage
Section titled “LocalFileStorage”Each key becomes a file under a base directory. Writes are atomic (temp file + rename).
| Parameter | Default | Description |
|---|---|---|
base_dirbaseDir | "./.strands/" | Root directory |
sandboxsandbox | None/undefined | Optional Sandbox |
storage = LocalFileStorage("./my-data/")import { LocalFileStorage } from '@strands-agents/sdk/storage'
const storage = new LocalFileStorage('./my-data/')You can also bind a sandbox after construction with
for_sandbox(sandbox)forSandbox(sandbox)
S3Storage
Section titled “S3Storage”Stores data as objects in an S3 bucket. The AWS SDK loads lazily,
so applications that never construct an S3Storage pay nothing.
| Parameter | Default | Description |
|---|---|---|
bucket | (required) | S3 bucket name |
prefix | "" | Key prefix (namespace within the bucket) |
region_nameregion | None/undefined | AWS region override |
boto_sessions3Client | None/undefined | Pre-configured client |
storage = S3Storage("my-bucket", prefix="agents/prod/")import { S3Storage } from '@strands-agents/sdk/storage'
const storage = new S3Storage('my-bucket', { prefix: 'agents/prod/',})Required S3 permissions
Section titled “Required S3 permissions”The credentials used by S3Storage need these permissions:
s3:PutObjectto create and update datas3:GetObjectto retrieve datas3:DeleteObjectto delete datas3:ListBucketto list keys under the configured prefix
This policy grants the required permissions for one 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" } ]}You cannot pass both a region and a pre-configured client; pick one or the other.
Custom backends
Section titled “Custom backends”Implement four async methods
(write, read, delete, listwrite, read, delete, listStorage is accepted. In Python,
Storage is a
protocol; in
TypeScript, implement the
interface.
Community backends can add methods beyond the core four (e.g.
search for vector similarity, or structured queries for
databases like DynamoDB). Plugins that only need basic
persistence use the four standard methods; plugins that need
richer access can check for and use the extra surface your
backend provides.
When using agent-level storage, each subsystem scopes its keys
under its own prefix automatically (session/, offloader/),
so you never need to worry about collisions. If you write a
custom plugin that consumes agent-level storage, call
storage.namespace('my-prefix/')storage.namespace('my-prefix/')to claim your own prefix and avoid overlapping with other subsystems.
Next steps
Section titled “Next steps”- Context Offloader: offload large tool results
- Session Management: persist conversations across restarts
- Sandbox: route Storage I/O through a sandboxed environment