Memory store adapters
Where memory lives. InMemoryStore for dev; RedisStore + AgentCoreStore production-ready; DynamoDB / Postgres / Pinecone planned.
Memory's TYPE × STRATEGY combinations are agnostic about WHERE the bytes live. The store is the third axis — the persistence boundary that turns memory from "ephemeral local state" into "production multi-tenant state with GDPR forget + multi-instance access". Pick by access pattern + durability needs.
What ships today
| Store | Subpath | Peer-dep | Vector search | When to use |
|---|---|---|---|---|
InMemoryStore | (top-level) | — | ✅ | Dev, tests, single-process scenarios |
RedisStore | agentfootprint/memory-providers | ioredis | ❌ (RedisSearch later) | Hot recent memory + signatures + feedback aggregation |
AgentCoreStore | agentfootprint/memory-providers | @aws-sdk/client-bedrock-agentcore | ❌ (server-side retrieve later) | Bedrock-native session + event memory |
Both store adapters live on the canonical agentfootprint/memory-providers subpath. Per-adapter aliases (agentfootprint/memory-redis, agentfootprint/memory-agentcore) still resolve for back-compat, but new code should import from agentfootprint/memory-providers.
All three implement the same MemoryStore interface — defineMemory({ store }) doesn't care which one you pass. Drop-in.
InMemoryStore
The default for dev / tests. O(n) linear scan for search(); fine for thousands of entries; bounded by process memory:
import { InMemoryStore } from 'agentfootprint';
const store = new InMemoryStore();Resets on process restart. Per-process — multi-instance deploys lose state.
RedisStore
Subpath import keeps the main barrel small. Lazy-required ioredis:
import { RedisStore } from 'agentfootprint/memory-providers';
const store = new RedisStore({ url: 'redis://localhost:6379' });
// or share an existing client:
// const store = new RedisStore({ client: existingIoredisClient });Implements every MemoryStore method except search(). putIfVersion uses an atomic Lua compare-and-swap; putMany uses pipelining; forget() uses SCAN (never KEYS — KEYS blocks Redis). Tested with mock-injected _client; CI doesn't need a live Redis.
Vector search NOT included. RedisSearch is a separate Redis module with its own API. A RedisSearchStore may ship in a future release.
AgentCoreStore
AWS Bedrock AgentCore Memory adapter. Subpath import; lazy-required AWS SDK:
import { AgentCoreStore } from 'agentfootprint/memory-providers';
const store = new AgentCoreStore({
memoryId: 'arn:aws:bedrock-agentcore:us-west-2:...:memory/my-mem',
region: 'us-west-2',
});Maps MemoryStore onto AgentCore's append-only event log (CreateEvent / ListEvents /
DeleteEvent on @aws-sdk/client-bedrock-agentcore). Caveats (also in JSDoc):
putappends;listisListEvents(window / episodic memory is the natural fit);get/deleteby id are list-then-find (server-assigned event ids);forgetlists + deletes each event (noDeleteSession).putIfVersionis emulated client-side;seen/feedbackare in-process shadow state — don't survive process restart. Use Redis for durable recognition.search()not wired today — AgentCore'sRetrieveMemoryRecordslands as a separate helper.
BedrockAgentMemory (legacy Bedrock Agents — read-only)
AWS has two memory systems. AgentCoreStore above targets the newer AgentCore platform
(the go-forward path). The prior-generation Bedrock Agents product has its own memory — but
it's read-only: the agent auto-generates SESSION_SUMMARY records; you can read and delete
them, but you can't put arbitrary entries. So it's not a MemoryStore (that would be a
"store that can't store") — it's a small reader:
import { BedrockAgentMemory } from 'agentfootprint/memory-providers';
const mem = new BedrockAgentMemory({ agentId, agentAliasId, region: 'us-west-2' });
const summaries = await mem.readSummaries(userMemoryId); // the summaries Bedrock generated
const text = await mem.readText(userMemoryId); // joined, ready to inject as a Fact
await mem.forget(userMemoryId); // DeleteAgentMemoryUse it to surface Bedrock's built-in memory in an agentfootprint agent (e.g. inject text
as a Fact). Peer-dep @aws-sdk/client-bedrock-agent-runtime. Prefer AgentCoreStore for a
real read/write store — BedrockAgentMemory exists mainly for teams migrating off Bedrock Agents.
Choosing per layer
In hybrid memory setups (multiple .memory(...) calls on one agent), each layer can use a different store optimized for its access pattern:
import { defineMemory, MEMORY_TYPES, MEMORY_STRATEGIES } from 'agentfootprint';
import { RedisStore, AgentCoreStore } from 'agentfootprint/memory-providers';
const recent = defineMemory({
id: 'recent',
type: MEMORY_TYPES.EPISODIC,
strategy: { kind: MEMORY_STRATEGIES.WINDOW, size: 10 },
store: new RedisStore({ url: redisUrl }), // sub-ms hot reads, TTL
});
const causal = defineMemory({
id: 'causal',
type: MEMORY_TYPES.CAUSAL,
strategy: { kind: MEMORY_STRATEGIES.TOP_K, topK: 1, threshold: 0.7, embedder },
store: new AgentCoreStore({ memoryId, region }), // managed durability
});
agent.memory(recent).memory(causal);See Auto memory (hybrid) for the layered pattern.
Planned
| Store | Why it's planned |
|---|---|
| DynamoDB | AWS-native, globally distributed, serverless-friendly |
| Postgres (with pgvector) | Vector search built-in; queryable + joinable with app data |
| Pinecone / Qdrant / Weaviate | Vector-first; serious-scale RAG / semantic-retrieval workloads |
RedisSearchStore | Vector search via the RedisSearch module |
All four follow the same peer-dep + subpath import pattern as RedisStore + AgentCoreStore.
Multi-tenant identity is enforced at the store
Every MemoryStore method takes MemoryIdentity as the first arg. Adapters MUST namespace internal keys by the full tuple. A bug passing the wrong identity surfaces as "no data" — not as a cross-tenant leak.
Next steps
- Memory guide — types × strategies × stores
- Auto memory (hybrid) — layer multiple stores per their access pattern
- Deployment — production checklist
