Build

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

StoreSubpathPeer-depVector searchWhen to use
InMemoryStore(top-level)Dev, tests, single-process scenarios
RedisStoreagentfootprint/memory-providersioredis❌ (RedisSearch later)Hot recent memory + signatures + feedback aggregation
AgentCoreStoreagentfootprint/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):

  • put appends; list is ListEvents (window / episodic memory is the natural fit); get/delete by id are list-then-find (server-assigned event ids); forget lists + deletes each event (no DeleteSession).
  • putIfVersion is emulated client-side; seen / feedback are in-process shadow state — don't survive process restart. Use Redis for durable recognition.
  • search() not wired today — AgentCore's RetrieveMemoryRecords lands 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);                          // DeleteAgentMemory

Use 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 storeBedrockAgentMemory 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

StoreWhy it's planned
DynamoDBAWS-native, globally distributed, serverless-friendly
Postgres (with pgvector)Vector search built-in; queryable + joinable with app data
Pinecone / Qdrant / WeaviateVector-first; serious-scale RAG / semantic-retrieval workloads
RedisSearchStoreVector 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

On this page