Skip to documentation
Docs navigation
Docs/Chatbot memory
Guide

Chatbot memory

Give a server-side chatbot durable, relevant memory that is recalled before later responses and learned incrementally after each exchange.

Estimated time: 5 minutes
Level: Beginner
Prerequisites:Installation·Quick Start

Overview

MemoGrafterAgent combines conversational history with graph-backed long-term memory. Each call to invoke() can recall relevant active facts, send them to the configured language model, and schedule the completed exchange for incremental ingestion.

The agent owns one generated session ID. Reuse the same agent instance for the active conversation; creating a new agent creates an independent session.

When to use this

Remember preferences and facts mentioned earlier in an active conversation.
Keep prompts bounded instead of replaying an ever-growing transcript.
Allow relevant graph memory to influence later answers.
Inspect and control retained memory through supported lifecycle APIs and Studio.

What you’ll build

A server-side chatbot that recalls relevant memory before responding.
Automatic incremental learning after completed user and assistant turns.
A conversation that remembers a name and response preference on a later turn.

Request lifecycle

The foreground response and write-side memory pipeline are connected but distinct. The first turn may have nothing to recall; later turns can use graph memory after ingestion has created it.

invoke()
Recall facts
LLM response
Background ingest
Graph memory

Step 1: Create one agent

Construct the agent in server code and initialize it after the database has been migrated. Keep the instance alive for the active conversation.

chatbot.ts
import {
  MemoGrafterAgent,
  OpenAIEmbedAdapter,
  OpenAILLMAdapter,
} from "memo-grafter";

const llm = new OpenAILLMAdapter("gpt-4o");
const embedder = new OpenAIEmbedAdapter("text-embedding-3-small");

const agent = new MemoGrafterAgent({
  db: { connectionString: process.env.DATABASE_URL! },
  llm,
  embedder,
});

await agent.initialize();

Step 2: Send turns through invoke()

invoke() owns the normal chat path. Do not manually ingest the same user and assistant turns afterward; that exchange is already scheduled for ingestion.

chatbot.ts
const first = await agent.invoke("My name is Alice.");
const second = await agent.invoke("I prefer concise answers.");
const answer = await agent.invoke("What is my name, and how should you answer?");

console.log(answer);

Step 3: Close cleanly

Close the agent during graceful shutdown. Reads that depend on memory state and close() wait for the agent’s pending ingestion work.

shutdown.ts
process.once("SIGTERM", async () => {
  await agent.close();
  process.exit(0);
});

Full example

chatbot-memory.ts
import {
  MemoGrafterAgent,
  OpenAIEmbedAdapter,
  OpenAILLMAdapter,
} from "memo-grafter";

const llm = new OpenAILLMAdapter("gpt-4o");
const embedder = new OpenAIEmbedAdapter("text-embedding-3-small");

const agent = new MemoGrafterAgent({
  db: { connectionString: process.env.DATABASE_URL! },
  llm,
  embedder,
});

await agent.initialize();

try {
  console.log(await agent.invoke("My name is Alice."));
  console.log(await agent.invoke("I prefer concise answers."));
  console.log(await agent.invoke("What is my name, and how should you answer?"));
} finally {
  await agent.close();
}

Expected conversation

Alice first supplies an identity fact, then a response preference. On a later question, the agent can retrieve those active memories and the assistant can answer that her name is Alice and that replies should be concise.

User: “My name is Alice.”
User: “I prefer concise answers.”
User: “What is my name, and how should you answer?”
Assistant: “Your name is Alice, and I should answer concisely.”

How invoke() works

Checks whether the session already contains topic nodes; empty sessions skip recall.
Recalls active memories related to the incoming user message.
Prepends the memory prompt when matching facts exist, followed by recent raw history and the new message.
Calls the configured LLM adapter and records both completed turns.
Schedules incremental ingestion without clearing existing native or grafted graph memory.
Logs recall failures and falls back to recent history so retrieval problems do not crash the foreground turn.

Best practices

Reuse one MemoGrafterAgent for the active conversation.
Keep MemoGrafter and provider credentials on the server.
Inspect extracted memories in Studio before tuning thresholds.
Call close() during graceful shutdown.
Use MemoGrafter directly when the application must supply and reopen explicit session IDs.

Common mistakes

Creating a new agent for every message, which creates a new independent session each time.
Calling ingestText() for the same exchange after invoke().
Expecting recall on the first turn before graph memory exists.
Exposing database or provider credentials to browser code.
Assuming queued ingestion makes new memories visible immediately.