- Introduce long-term memory for AI Kit agents via a reusable
Memoryobject. - Back Mem0 with a pluggable storage layer (pgvector, MongoDB Atlas Vector Search, etc.), aligning with infrastructure described in
packages/core/src/runtime/store.tsand the agent pipeline inpackages/core/src/agents/index.ts. - Keep the addition optional, so existing callers operate without memory unless explicitly configured.
packages/core/src/agents/index.ts: CentralizesAgent.generate/Agent.stream. This is where memories are recalled before the LLM call and persisted afterward.packages/core/src/runtime/store.ts&packages/core/src/runtime/resources.ts: Provide scoped runtime state and a registry for lazily loaded resources; ideal place to inject a Mem0 client instance and cleanup hooks.packages/core/src/runtime/tools.ts: Runtime-aware tools can access the same Mem0 instance through the store, enabling tool-based recall/write operations if needed.pnpm-workspacepackages: expose the core API; any new memory utilities should live inpackages/coreand be re-exported throughpackages/core/src/index.ts.
- Dependencies & Environment
- Add
mem0aito the workspace (pnpm add mem0ai -w). - Capture configuration via env vars (
MEM0__PROVIDER,MEM0__PG_URI,MEM0__MONGO_URI,MEM0__OPENAI_KEY, optionalMEM0__COLLECTION,MEM0__DIMENSION, etc.) and document them in.env.example. - Provide provider-specific bootstrap docs:
- pgvector: ensure the database has the
vectorextension (CREATE EXTENSION IF NOT EXISTS vector;). - MongoDB (or other supported Mem0 adapters): outline required indexes and Atlas vector search configuration.
- pgvector: ensure the database has the
- Migration scripts and infra steps live alongside other ops docs.
- Runtime Resource for Mem0
- Create
packages/core/src/memory/mem0.tsexportingregisterMem0RuntimeResourceandcreateMem0Memory. - Use
registerRuntimeResource("mem0", …)to lazily instantiate theMemoryclient with the selected provider config (pgvector connection info, MongoDB connection string + database/collection, etc.). Accept a genericMem0Configthat maps cleanly tomem0ai’sMemoryconstructor. - Implement
packages/core/src/memory/Memory.tsso all instantiation flows through a thin wrapper class that proxies tomem0aibut enforces AI Kit defaults (e.g.,provider: "mem0"). - Hook into
RuntimeStore.onCleanupto close database pools if Mem0 exposes aclose/destroymethod; otherwise ensure idempotency. - Define a
Mem0RuntimeStateinterface to type the runtime key (mem0Memory) storing the hydrated client.
- Agent-Level Memory Plumbing
- Extend
AgentConfigwith an optionalmemoryblock and enforce an explicitthreadId:export interface AgentMemoryConfig<State extends RuntimeState> { enable: boolean; resolveUser: (runtime: RuntimeStore<State>, options: AgentCallContext) => Promise<string | undefined>; resolveThreadId: (runtime: RuntimeStore<State>, options: AgentCallContext) => Promise<string | undefined>; client?: Memory; // optional pre-configured wrapper exported by @ai-kit/core providerConfig?: Mem0ProviderConfig; // fallback when client is not provided recallLimit?: number; }
- Thread the memory config through
Agent.generate/Agent.stream. When enabled:- Resolve the runtime (
RuntimeStore.mergeExperimentalContextalready wires it in). - Assert that
resolveThreadIdreturns a non-empty value from the runtime or call options; if missing, skip memory work (and optionally warn). - Load or create the Mem0 client via
runtime.load("mem0", providerConfig), skipping instantiation when aMemorywrapper instance (client) is already supplied. - Build the Mem0
addpayload from the full conversation history and thread metadata (threadId,userId, optional tags). - Automatically call
memory.search(threadId, { userId, limit, includeMetadata: true })before the LLM call. Inject high-relevance memories by prepending a synthetic system message or augmentingexperimental_context. - After receiving the model response, call
memory.add(messages, { userId, metadata: { threadId } })so write-through occurs automatically.
- Resolve the runtime (
- Guard all steps when
userIdis missing or Mem0 raises retrieval errors, logging through existing telemetry (mergeTelemetryConfig) without aborting the agent call.
import { Agent, createRuntime, Memory } from "@ai-kit/core";
const supportMemory = new Memory({
provider: "mem0", // default provider
vectorStore: {
provider: process.env.MEM0__PROVIDER ?? "pgvector",
config: {
collectionName: process.env.MEM0__COLLECTION ?? "support_memories",
dimension: Number(process.env.MEM0__DIMENSION ?? 1536),
host: process.env.MEM0__PG_HOST,
port: Number(process.env.MEM0__PG_PORT ?? 5432),
user: process.env.MEM0__PG_USER,
password: process.env.MEM0__PG_PASSWORD,
},
},
llm: {
provider: "openai",
config: {
apiKey: process.env.OPENAI_API_KEY ?? "",
model: process.env.MEM0__LLM_MODEL ?? "gpt-4o-mini",
},
},
embedder: {
provider: "openai",
config: {
apiKey: process.env.OPENAI_API_KEY ?? "",
model: process.env.MEM0__EMBED_MODEL ?? "text-embedding-3-small",
},
},
});
const agent = new Agent({
name: "support-specialist",
instructions: "You are a helpful assistant that remembers previous tickets.",
model: myLanguageModel,
memory: {
enable: true,
client: supportMemory,
recallLimit: 8,
resolveUser: async (_runtime, { metadata }) => metadata?.userId,
resolveThreadId: async (_runtime, { threadId, metadata }) =>
threadId ?? metadata?.threadId,
},
});
const runtime = createRuntime();
const result = await agent.generate({
runtime,
threadId: "ticket-1876",
messages: [
{ role: "user", content: "I can't log into my dashboard again." },
],
metadata: { userId: "customer-42" },
});Users who prefer explicit provider-specific overrides can pass a different configuration when instantiating the Mem0 client, e.g. MongoDB:
const supportMemory = new Memory({
provider: "mem0",
vectorStore: {
provider: "mongodb",
config: {
uri: process.env.MEM0__MONGO_URI!,
database: "ai-kit",
collectionName: "memories",
indexName: "memories_vector_index",
},
},
});Passing threadId (and optionally metadata.threadId) is required; the agent automatically recalls and persists memories tied to that thread.
-
Helper Utilities
- Provide
packages/core/src/memory/utils.tswith:buildMem0ConfigFromEnv()formatConversationForMem0(messages: Array<Message>, threadId: string)injectMemories(messages, memories, threadId)returning an updated transcript that tags injected memories with the active thread.
- Export the wrapper
Memoryclass that hides provider-specific params, exposesrecall/storehelpers, and is re-exported throughpackages/core/src/index.tsfor consumer DX.
- Provide
-
Tooling & Optional Tools
- Offer a runtime-aware tool (
packages/core/src/memory/tools.ts) usingcreateRuntimeToolto allow agents to explicitly fetch or update memories mid-conversation. - Register it conditionally when the agent is built with
memory.enable === true, so existing tool loops operate unchanged otherwise.
- Offer a runtime-aware tool (
-
Testing Strategy
- Unit tests in
packages/core/tests/memory/mem0.test.tsmocking themem0aiclient to verify:- Runtime resource caching & cleanup.
- Recall injection logic (messages augmented once, correct ordering).
- Persist-after-response flow.
- Integration smoke test behind a CI flag that spins up a disposable Postgres container with pgvector (use
testcontainersor docker-compose) to validate end-to-end recall/store.
- Unit tests in
-
Operational Checklist
- Document required migrations (UUID primary keys, vector columns, indexes) in
/docs/operations/mem0-pgvector.md. - Add telemetry hooks so Mem0 latency/errors feed existing pipelines (
packages/core/src/telemetry/langfuse.ts). - Provide runbook snippets (rotation of API keys, verifying pgvector indexes) inside the ops doc referenced above.
- Document required migrations (UUID primary keys, vector columns, indexes) in
- Ship behind a feature flag (
MEM0_ENABLED), defaulting to false while the feature bakes. - Ensure backward compatibility: agents without
memoryconfig should not import or bundlemem0ai, keeping the package optional for downstream consumers. - Coordinate with infra to provision staging Postgres with pgvector before enabling in production workflows.
- Provide cookbook snippets showing provider-specific configuration (pgvector vs MongoDB vs in-memory) so users can choose their storage layer.