Agent Memory
Working memory, long-term memory, episodic memory — how agents remember and learn
Types of Memory
AI Agents need different types of memory, just like the human brain:
Working Memory
Information right now — the agent’s current context.
const messages: Message[] = [
{ role: "system", content: systemPrompt },
{ role: "user", content: "Book a flight to Tokyo" },
{ role: "assistant", content: "I'll search flights for you..." },
{ role: "tool", content: JSON.stringify(flightResults) }
];
Limitation: Erased when session ends, limited by context window.
Short-Term Memory
Information within one conversation, allowing context understanding:
// User: "Find flights to Tokyo"
// Agent searches...
// User: "How much is it there?" ← "there" = Tokyo (short-term memory)
Long-Term Memory
Information across sessions — preferences, facts, history.
import { createClient } from "@supabase/supabase-js";
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY);
// Long-term memory schema
// create table agent_memories (
// id uuid primary key default gen_random_uuid(),
// user_id text not null,
// type text not null,
// content text not null,
// metadata jsonb,
// embedding vector(1536),
// created_at timestamptz default now(),
// last_accessed timestamptz default now()
// );
async function saveMemory(userId: string, content: string, type: string) {
const embedding = await getEmbedding(content);
await supabase.from("agent_memories").insert({
user_id: userId,
type,
content,
embedding,
metadata: { source: "conversation" }
});
}
async function recallMemories(userId: string, query: string, limit = 5) {
const queryEmbedding = await getEmbedding(query);
const { data } = await supabase.rpc("match_memories", {
query_embedding: queryEmbedding,
target_user_id: userId,
match_count: limit
});
return data;
}
Persona Memory
Memory that shapes the agent’s personality:
const personaMemory = {
role: "Senior Travel Advisor",
expertise: ["Adventure travel", "Budget optimization", "Asian destinations"],
communicationStyle: "Friendly, detailed, uses emojis",
preferences: {
alwaysSuggestLocalFood: true,
avoidTouristTraps: true,
prioritizeSafety: true
}
};
Episodic Memory
Agent remembers sequences of actions in complex tasks:
interface Episode {
taskId: string;
steps: {
action: string;
result: "success" | "failure";
duration: number;
notes: string;
}[];
outcome: "completed" | "failed" | "partial";
lessonsLearned: string[];
}
async function consultEpisodicMemory(currentTask: string) {
const similarEpisodes = await recallMemories(userId, currentTask);
const failedApproaches = similarEpisodes
.filter(ep => ep.outcome === "failed")
.map(ep => ep.lessonsLearned);
return {
avoid: failedApproaches,
successful: similarEpisodes.filter(ep => ep.outcome === "completed")
};
}
Integrating Memory Into Agents
import { generateText, tool } from "ai";
import { openai } from "@ai-sdk/openai";
import { z } from "zod";
const memorize = tool({
description: "Save important information to long-term memory",
parameters: z.object({
content: z.string(),
type: z.enum(["preference", "fact", "experience"]),
importance: z.enum(["low", "medium", "high"])
}),
execute: async ({ content, type }) => {
await saveMemory(userId, content, type);
return { saved: true, type };
}
});
const recall = tool({
description: "Search for saved information in memory",
parameters: z.object({
query: z.string(),
type: z.enum(["all", "preference", "fact", "experience"]).optional()
}),
execute: async ({ query }) => {
const memories = await recallMemories(userId, query);
return { memories };
}
});
async function agentWithMemory(userId: string, message: string) {
const memories = await recallMemories(userId, message);
const result = await generateText({
model: openai("gpt-4o"),
system: `You are a personal assistant with long-term memory.
Memories about this user:
${memories.map(m => `- [${m.type}] ${m.content}`).join("\n")}
Use memories to personalize responses.
If the user shares important new information, save it to memory.`,
tools: { memorize, recall, searchWeb },
maxSteps: 5,
prompt: message
});
return result.text;
}
Knowledge Agent Pattern
A specialized agent observes conversations and automatically saves knowledge:
async function knowledgeAgent(conversationHistory: Message[]) {
const { object } = await generateObject({
model: openai("gpt-4o-mini"),
schema: z.object({
valuableInsights: z.array(z.object({
content: z.string(),
type: z.enum(["preference", "fact", "experience"]),
shouldSave: z.boolean(),
reason: z.string()
}))
}),
prompt: `Analyze the conversation. Find information worth saving:
- User preferences (likes, dislikes)
- Facts about the user (name, job, hobbies)
- Experiences (successful/failed tasks, lessons learned)
Conversation:
${conversationHistory.map(m => `${m.role}: ${m.content}`).join("\n")}`
});
for (const insight of object.valuableInsights) {
if (insight.shouldSave) {
await saveMemory(userId, insight.content, insight.type);
}
}
}
Memory Lifecycle
Input → Short-term (session) → Knowledge Agent evaluates
↓
Worth saving?
├── Yes → Long-term (Supabase)
└── No → Discard
New session → Recall relevant long-term memories → Inject into context
Summary
- Working/Short-term: Current context, lost when session ends
- Long-term: Stored in Supabase, persists across sessions
- Episodic: Remembers action sequences, learns from past
- Persona: Fixed agent personality
- Knowledge Agent: Automatically extracts and saves important information