Browse docs

SDK

Tap to expand

Contribute

SDKUpdated 2026-03-18

Memory Module Guide

Store, retrieve, and manage memories with db.user(id) — the complete reference.

Applies to: @retaindb/sdk

The db.user(userId) interface is how you interact with a user's memory. Everything in this guide applies to both user-level and session-scoped operations.

typescript
import { RetainDB } from "@retaindb/sdk";

const db = new RetainDB({ apiKey: process.env.RETAINDB_KEY });

Set RETAINDB_KEY once in your environment. No project setup required.


runTurn is the recommended starting point. It handles everything:

typescript
const { response, context } = await db.user(userId).runTurn({
  messages,
  generate: (ctx) => openai.chat.completions.create({
    model: "gpt-4o",
    messages: ctx.messages, // memories already injected
  }),
});

Use manual methods below when you need explicit control over what gets stored or retrieved.


Storing memories

Single fact or preference

typescript
await db.user(userId).remember("Prefers concise, bullet-point responses");

Conversation dump (auto-extraction)

Pass the full message array — RetainDB extracts facts, preferences, and events automatically:

typescript
await db.user(userId).remember([
  { role: "user", content: "I work at Acme as a senior engineer" },
  { role: "assistant", content: "Got it! What are you working on?" },
  { role: "user", content: "Trying to reduce our API latency below 100ms" },
]);

Scoped to a session

typescript
await db.user(userId).session(sessionId).remember("User asked about billing issue");

Retrieving context

typescript
const { context, raw } = await db.user(userId).getContext("How should I respond?");

// context — formatted string ready for a system prompt
// raw     — full search response with scores and metadata

Control how many results come back:

typescript
const { context } = await db.user(userId).getContext("query", 10); // topK = 10

Forgetting a memory

typescript
await db.user(userId).forget(memoryId);

Memory types

Memories are automatically classified. You can also specify the type when storing manually:

TypeWhat it capturesExample
factualStable facts about the user"Works at Acme Corp"
preferenceCommunication style, tool choices"Prefers bullet points"
eventThings that happened at a point in time"Deployed to production on March 15"
relationshipConnections between people or entities"Reports to Jordan"
opinionStated views or assessments"Thinks Tailwind is overrated"
goalObjectives being worked toward"Trying to reduce latency below 100ms"
instructionExplicit directives for future behavior"Always verify security before shipping"

What ctx contains in runTurn

typescript
interface TurnContext {
  context: string;   // formatted memory string
  messages: Message[]; // original messages + memory injected as system message
}

If there are no memories yet, context is an empty string and messages is passed through unchanged.


Automatic learning

Every runTurn call stores the conversation after generating the response. This is non-blocking — it never delays your response. Over time, the memory store grows richer with every interaction, and getContext results improve automatically.


Error handling

typescript
try {
  await db.user(userId).remember("Some fact");
} catch (error) {
  if (error.code === "RATE_LIMITED") {
    // Back off and retry
  }
}

Next step

Was this page helpful?

Your feedback helps us prioritize docs improvements weekly.