Tutorial: Memory-Enabled AI Agents
Add long-term memory to autonomous AI agents so they learn from feedback and resume across sessions.
Applies to: All Users
Build an agent that remembers past actions, learns from user feedback, and picks up where it left off — across sessions.
Prerequisites
- Node.js 18+
- RetainDB API key (
RETAINDB_KEY) - OpenAI API key
Setup
npm init -y
npm install @retaindb/sdk openaiexport RETAINDB_KEY="rdb_..."
export OPENAI_API_KEY="sk-..."The core pattern
runTurn handles the retrieve → inject → generate → store loop for agents the same way it does for chatbots:
import { RetainDB } from "@retaindb/sdk";
import OpenAI from "openai";
const db = new RetainDB({ apiKey: process.env.RETAINDB_KEY });
const openai = new OpenAI();
export async function agentTurn(
userId: string,
agentId: string,
messages: Array<{ role: "user" | "assistant" | "system"; content: string }>
) {
const { response } = await db.user(userId).session(agentId).runTurn({
messages,
generate: (ctx) =>
openai.chat.completions.create({
model: "gpt-4o",
messages: ctx.messages,
}),
});
return response.choices[0].message.content;
}Using session(agentId) scopes memory to this agent's thread. User-level memory (preferences, facts) is still retrieved if relevant.
Storing explicit agent observations
When the agent observes something worth remembering explicitly:
// Store an action outcome
await db.user(userId).session(agentId).remember(
`Action: wrote tests for the auth module. Outcome: 12 tests passing.`
);
// Store user feedback
await db.user(userId).remember("User preferred direct, action-oriented responses");User-level memories (no session) persist forever and surface across all future sessions.
Learning from feedback
When a user rates an action, store it as a preference:
async function recordFeedback(
userId: string,
action: string,
feedback: "positive" | "negative"
) {
await db.user(userId).remember(
`${feedback === "positive" ? "User liked" : "User disliked"}: ${action}`
);
}Future runTurn calls will automatically include this in context when relevant.
Resuming across sessions
Since memories persist, resuming is just calling runTurn with the same userId:
// Session 1
await agentTurn("user-123", "agent-run-1", messages1);
// Session 2 (days later) — agent has memory from session 1
await agentTurn("user-123", "agent-run-2", [
{ role: "user", content: "Continue where we left off" }
]);
// context contains: past actions, user preferences, outcomesComplete agent class
import { RetainDB } from "@retaindb/sdk";
import OpenAI from "openai";
const db = new RetainDB({ apiKey: process.env.RETAINDB_KEY });
const openai = new OpenAI();
export class MemoryAgent {
private user: ReturnType<typeof db.user>;
constructor(private userId: string, private agentId: string) {
this.user = db.user(userId);
}
async run(
messages: Array<{ role: "user" | "assistant" | "system"; content: string }>
) {
const { response } = await this.user.session(this.agentId).runTurn({
messages,
generate: (ctx) =>
openai.chat.completions.create({
model: "gpt-4o",
messages: ctx.messages,
}),
});
return response.choices[0].message.content;
}
async observe(observation: string) {
await this.user.session(this.agentId).remember(observation);
}
async learn(feedback: string) {
// User-level so it carries across all agent sessions
await this.user.remember(feedback);
}
async getContext(query: string) {
return this.user.getContext(query);
}
}Usage:
const agent = new MemoryAgent("user-123", "run-abc");
await agent.run([{ role: "user", content: "Help me refactor the auth module" }]);
await agent.observe("Refactored auth module — removed legacy JWT logic");
await agent.learn("User prefers small, incremental changes over large rewrites");Next step
- SDK Quickstart
- LangGraph Integration — for graph-based agents
- MCP Setup — use RetainDB with Claude
Was this page helpful?
Your feedback helps us prioritize docs improvements weekly.