RecipesSupport agent

Support agent with memory

A reference architecture for the most-asked-about use case: a chat support agent that gets smarter with every interaction.

Goals

  • Recall per-customer history at the start of every session.
  • Remember stable preferences (tier, language, recurring issues).
  • Track resolution outcome so future sessions favour what worked.
  • Never duplicate effort: the bot shouldn’t ask “what’s your email?” twice.

Per-customer workspace ID

const workspaceId = `tenant:${tenantId}:customer:${customerId}`;

Each customer gets their own RLS-isolated namespace. Even if your agent code mishandles a request, PostgreSQL won’t let workspace A read workspace B.

On every message, recall first

async function answer(userMessage: string) {
  const hits = await mnemo.recall({
    query: userMessage,
    topK: 5,
    types: ["fact", "decision", "strategy"],
    includeGraph: true,
  });
 
  const systemPrompt = buildSystemPrompt({
    persona: "support",
    knownFacts: hits.hits,
  });
 
  const response = await llm.chat([
    { role: "system", content: systemPrompt },
    { role: "user", content: userMessage },
  ]);
 
  return response;
}

Remember durable observations

// When the user states a stable preference:
if (extractedPreference) {
  await mnemo.facts.create({
    content: extractedPreference,
    type: "fact",
    tags: ["preference"],
    confidence: 0.9,
  });
}
 
// When the agent solves a class of problem:
if (resolutionStrategy) {
  await mnemo.facts.create({
    content: resolutionStrategy,
    type: "strategy",
    tags: ["resolution"],
    confidence: 0.7,
  });
}

Capture outcome at session end

async function onSessionEnd({ ticketId, status }: SessionEnd) {
  // Record what happened
  await mnemo.events.create({
    name: status === "resolved" ? "ticket.resolved" : "ticket.escalated",
    description: `Ticket ${ticketId} closed with status ${status}`,
    metadata: { ticketId, status },
  });
 
  // Feed Memory Worth so successful strategies float up over time
  await mnemo.governance.recordOutcome({
    sessionId,
    score: status === "resolved" ? 1.0 : 0.3,
    source: "explicit",
  });
}

What this looks like after 100 sessions

  • The support agent recognises returning customers and skips re-introduction.
  • Strategies that consistently resolve tickets float to the top via Memory Worth.
  • Strategies that lead to escalation get demoted automatically.
  • Predictive anticipation pre-loads the customer’s last 3 issues at the start of every session — the LLM never has to ask “have we talked before?”.

This pattern is what Orchester (the project that built Mnemosyne) uses for its own support agents. The code in examples/support-agent/ is the same code we run in production.