MemLibMemLib

Session-Aware Agents

Use diff() to brief your agent on changes between sessions

The Problem

Your agent talks to a user, learns their preferences, then the session ends. Next time the user returns, the agent has no idea what changed since the last session — did the user update their preferences? Did they mention new goals?

prepare() gives you relevant context, but it doesn't tell you what changed. That's what diff() is for.


The Pattern

Track the last session timestamp, and at the start of each new session, call diff() to get a changelog:

import { MemLib } from "memlib";

const mem = new MemLib({
  apiKey: process.env.MEMLIB_API_KEY!,
  namespace: "my-app",
});

async function startSession(userId: string, lastSessionEnd: string) {
  const entity = `user-${userId}`;

  // 1. What changed since the last session?
  const diff = await mem.diff({
    since: lastSessionEnd,
    entity,
  });

  // 2. Get current context
  const { context } = await mem.prepare({
    messages: [{ role: "system", content: "New session starting" }],
    entity,
  });

  // 3. Build a session-aware system prompt
  let systemPrompt = "You are a helpful assistant with memory.\n\n";

  if (context) {
    systemPrompt += `About this user:\n${context}\n\n`;
  }

  if (diff.changeCount > 0) {
    systemPrompt += `Changes since last session (${diff.summary}):\n`;
    systemPrompt += formatDiff(diff);
  }

  return systemPrompt;
}

Formatting the Diff

The diff result has four arrays — format them into something your LLM can understand:

import type { DiffResult } from "memlib";

function formatDiff(diff: DiffResult): string {
  const lines: string[] = [];

  for (const r of diff.replaced) {
    lines.push(`• Changed: "${r.oldContent}" → "${r.newContent}"`);
  }

  for (const c of diff.created) {
    lines.push(`• New: ${c.content}`);
  }

  for (const u of diff.updated) {
    lines.push(`• Updated: "${u.previousContent}" → "${u.content}"`);
  }

  for (const d of diff.deleted) {
    lines.push(`• Removed: ${d.content}`);
  }

  return lines.join("\n");
}

Example Output

Changes since last session (1 new, 1 replaced):
• Changed: "Uses VS Code" → "Uses Cursor (switched from VS Code)"
• New: Team does sprint planning on Thursdays

Tracking Session Timestamps

You need to store when each session ended. A simple approach:

// At the end of each session, save the timestamp
async function endSession(userId: string) {
  const timestamp = new Date().toISOString();

  // Store in your app's database, Redis, or even in MemLib itself
  await saveLastSessionTime(userId, timestamp);
}

// At the start of the next session, retrieve it
async function getLastSessionTime(userId: string): Promise<string> {
  const timestamp = await loadLastSessionTime(userId);

  // Fallback: 24 hours ago if no previous session
  return timestamp ?? new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
}

What Diff Reports

ArrayWhat It ContainsExample
createdNew memories added since the timestampUser mentioned a new hobby
updatedMemories that were refined or merged"Uses TypeScript" → "Uses TypeScript, especially for backend"
replacedContradiction pairs — old fact superseded by new"Lives in NYC" → "Moved to Berlin"
deletedMemories that were removedExpired or manually deleted

The replaced array is the most interesting for session awareness — it tells your agent exactly what preferences changed.


Full Example: Chat with Session Awareness

import { MemLib } from "memlib";
import type { DiffResult } from "memlib";

const mem = new MemLib({
  apiKey: process.env.MEMLIB_API_KEY!,
  namespace: "chatbot",
});

function formatDiff(diff: DiffResult): string {
  const lines: string[] = [];
  for (const r of diff.replaced) {
    lines.push(`• Changed: "${r.oldContent}" → "${r.newContent}"`);
  }
  for (const c of diff.created) {
    lines.push(`• New: ${c.content}`);
  }
  for (const u of diff.updated) {
    lines.push(`• Updated: "${u.previousContent}" → "${u.content}"`);
  }
  return lines.join("\n");
}

async function chat(
  userId: string,
  userMessage: string,
  conversationHistory: Array<{ role: "user" | "assistant"; content: string }>,
  lastSessionEnd: string,
) {
  const entity = `user-${userId}`;

  // Store the message
  await mem.store({ content: userMessage, entity });

  // Build context
  const messages = [
    ...conversationHistory,
    { role: "user" as const, content: userMessage },
  ];

  const [{ context }, diff] = await Promise.all([
    mem.prepare({
      messages: messages.map((m) => ({
        role: m.role,
        content: m.content,
      })),
      entity,
    }),
    mem.diff({ since: lastSessionEnd, entity }),
  ]);

  // Build system prompt
  let systemPrompt = "You are a helpful assistant with memory.\n\n";

  if (context) {
    systemPrompt += `About this user:\n${context}\n\n`;
  }

  if (diff.changeCount > 0) {
    systemPrompt += `Recent changes:\n${formatDiff(diff)}\n\n`;
    systemPrompt += "Acknowledge relevant changes naturally in conversation.";
  }

  // Pass to your LLM
  return callYourLLM(systemPrompt, messages);
}

Performance

diff() makes zero LLM calls — it's a pure SQL query on the memory_events audit trail. Typical response time is under 20ms. Safe to call at the start of every session.

On this page