AutoGen Tutorial (TypeScript): adding memory to agents for intermediate developers

By Cyprian AaronsUpdated 2026-04-21
autogenadding-memory-to-agents-for-intermediate-developerstypescript

This tutorial shows you how to give an AutoGen TypeScript agent persistent memory so it can remember user preferences, prior decisions, and context across turns. You need this when a stateless chat agent starts repeating questions, losing project details, or failing to carry forward important facts in a long-running workflow.

What You'll Need

  • Node.js 18+ installed
  • A TypeScript project with ts-node or a build step
  • @autogenai/autogen installed
  • An OpenAI API key set as OPENAI_API_KEY
  • Basic familiarity with AutoGen agents, model clients, and async/await
  • A place to persist memory:
    • for this tutorial: a simple JSON file on disk
    • for production: Postgres, Redis, or a vector store

Step-by-Step

  1. Start by installing the package and setting up a minimal TypeScript entrypoint. The memory layer in this tutorial is just a thin wrapper around a file-backed store, which keeps the example executable without extra infrastructure.
npm install @autogenai/autogen
npm install -D typescript ts-node @types/node
// src/index.ts
import { AssistantAgent } from "@autogenai/autogen";
import fs from "node:fs/promises";

const MEMORY_FILE = "./memory.json";

type MemoryRecord = {
  userId: string;
  facts: string[];
};

async function loadMemory(userId: string): Promise<MemoryRecord> {
  try {
    const raw = await fs.readFile(MEMORY_FILE, "utf-8");
    const all = JSON.parse(raw) as MemoryRecord[];
    return all.find((m) => m.userId === userId) ?? { userId, facts: [] };
  } catch {
    return { userId, facts: [] };
  }
}
  1. Next, add two helper functions: one to save memory and one to convert stored facts into system context. This is the part that makes memory useful to the agent instead of just storing data somewhere on disk.
async function saveMemory(record: MemoryRecord): Promise<void> {
  let all: MemoryRecord[] = [];
  try {
    const raw = await fs.readFile(MEMORY_FILE, "utf-8");
    all = JSON.parse(raw) as MemoryRecord[];
  } catch {
    all = [];
  }

  const next = all.filter((m) => m.userId !== record.userId);
  next.push(record);
  await fs.writeFile(MEMORY_FILE, JSON.stringify(next, null, 2), "utf-8");
}

function buildMemoryContext(record: MemoryRecord): string {
  if (record.facts.length === 0) return "No prior memory.";
  return record.facts.map((fact) => `- ${fact}`).join("\n");
}
  1. Now create the agent and inject memory into each turn through the system message. This pattern works well because the agent always sees the latest remembered facts before generating a response.
const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY!,
});

async function main() {
  const userId = "user-123";
  const memory = await loadMemory(userId);

  const agent = new AssistantAgent({
    name: "support_agent",
    modelClient: client,
    systemMessage: `You are a support assistant.
Use these remembered facts when relevant:
${buildMemoryContext(memory)}`,
  });

  const result = await agent.run({
    task: "The user says they prefer short answers and work in insurance.",
  });

  console.log(result.messages.at(-1)?.content);
}
  1. After each interaction, extract new durable facts and write them back to storage. In production you would usually do this with an explicit extraction step or a small classifier; here we do it with simple rules so you can run it immediately.
function extractFacts(message: string): string[] {
  const facts: string[] = [];

  if (message.toLowerCase().includes("prefer short answers")) {
    facts.push("User prefers short answers.");
  }
  if (message.toLowerCase().includes("insurance")) {
    facts.push("User works in insurance.");
  }

  return facts;
}

async function updateMemory(userId: string, message: string): Promise<void> {
  const current = await loadMemory(userId);
  const newFacts = extractFacts(message);

  for (const fact of newFacts) {
    if (!current.facts.includes(fact)) current.facts.push(fact);
  }

  await saveMemory(current);
}
  1. Put it together in one flow so the agent reads memory before responding and writes back after the turn. This is the basic loop you can extend later with summarization, TTLs, or semantic retrieval.
async function main() {
  const userId = "user-123";
  const userMessage =
    "I prefer short answers and I work in insurance.";

  await updateMemory(userId, userMessage);

   const memory = await loadMemory(userId);
   const agent = new AssistantAgent({
     name: "support_agent",
     modelClient: client,
     systemMessage: `You are a support assistant.
Remember these facts:
${buildMemoryContext(memory)}`,
   });

   const result = await agent.run({ task: userMessage });
   console.log(result.messages.at(-1)?.content);
}

main().catch(console.error);

Testing It

Run the script twice with slightly different messages for the same userId. On the second run, check that the system prompt includes previously stored facts like “User prefers short answers” and that the agent’s reply reflects that context.

Also inspect memory.json after each run to confirm that only unique facts are being stored. If you want to test persistence across process restarts, stop Node completely and rerun the script; the memory should still be there because it is loaded from disk each time.

If the agent ignores memory, verify three things first:

  • OPENAI_API_KEY is set
  • your stored facts are actually present in memory.json
  • the memory context is being injected into systemMessage before agent.run()

Next Steps

  • Replace file storage with Postgres or Redis for multi-user deployments
  • Add semantic retrieval so agents can search long histories instead of stuffing everything into prompts
  • Build a dedicated “memory writer” agent that extracts durable facts from conversation turns

Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides