DEV Community

Cover image for My AI Assistant Had Amnesia. So I Built It a Memory System.
Lordmanhammer
Lordmanhammer

Posted on

My AI Assistant Had Amnesia. So I Built It a Memory System.

My AI Assistant Had Amnesia. So I Built It a Memory System.

I manage food delivery operations in Qatar. For the past six months, I've been running an AI assistant as a genuine daily work tool — not as a toy, as actual infrastructure. Strategy sessions, briefings, team comms, competitive analysis, project tracking.

It worked. Until it didn't.

The problem wasn't intelligence. Claude is plenty smart. The problem was amnesia.

Every new conversation started from zero. I'd spend the first five minutes rebuilding context — who's on my team, what we're working on, what decision we made last Tuesday, what I told it about our competitive situation last week. The AI didn't forget because it was bad at its job. It forgot because statelessness is baked into how these systems work.

After months of working around this, I built a fix. It's called VyasaGraph.


The Problem With "Just Use a System Prompt"

The obvious workaround is stuffing context into your system prompt. I did this for a while. It breaks down fast:

  1. Context windows are finite. A detailed system prompt plus conversation history plus actual work = you hit limits.
  2. System prompts are static. You can't update them mid-conversation as you learn new things.
  3. Compaction kills context. When Claude (or any LLM) compresses its context window, important mid-session decisions vanish.

What I actually needed was memory that works like a human's: short-term for what's happening right now, long-term for everything else.


The Architecture: Two Layers

I ended up with a dual-layer system, and the distinction matters:

SESSION-STATE.md    →  RAM (hot, ephemeral, survives compaction)
VyasaGraph DB       →  Hard drive (permanent, semantic, cross-session)
Enter fullscreen mode Exit fullscreen mode

Layer 1: SESSION-STATE.md

A plain markdown file the agent reads at the start of every message and writes to before responding. It holds:

  • What we're working on right now
  • Decisions made this session
  • Pending actions
  • Anything that needs to survive a context reset

Because it's a file (not tokens), it survives context compaction completely. When Claude resets its window, SESSION-STATE.md is still there. The agent reads it again. Continuity restored.

Layer 2: VyasaGraph

An embedded SurrealDB knowledge graph with vector search. No server, no infrastructure — just a local .db file. This stores:

  • People (your team, contacts, relationships)
  • Projects and their current status
  • Past decisions and why they were made
  • Recurring errors and how they were resolved
  • Anything that needs to exist across sessions

The key capability is semantic search — you search by meaning, not keywords. Ask for "competitive strategy" and it finds everything about Talabat, Keeta, market position, pricing decisions — even if none of those exact words appear in your query.


How It Works in Practice

The agent's instruction file (MEMORY.md or equivalent) tells it:

  1. On every message — read SESSION-STATE.md first
  2. Before responding — write any new decisions/context to SESSION-STATE.md
  3. Search VyasaGraph for relevant entities from prior sessions
  4. When the user shares something new — write it to VyasaGraph in that same reply

The last point is critical. Most memory implementations batch writes at session end. Sessions die unexpectedly. I made writes happen inline — if you tell the agent something, it writes to the graph before it replies. No exceptions.


The Code

npm install vyasagraph
Enter fullscreen mode Exit fullscreen mode
import * as vg from 'vyasagraph/src/index.js';

await vg.init('memory.db');

// Store a person
await vg.createEntities([{
  name: 'Alice (Head of Engineering, reports to Bob)',
  entityType: 'Person',
  observations: [
    'Joined in 2023',
    'Leading the platform redesign',
    'Prefers async communication'
  ]
}]);

// Create a relationship
await vg.createRelations([{
  from: 'Alice (Head of Engineering, reports to Bob)',
  to: 'Acme Corp',
  relationType: 'works_at'
}]);

// Add a new fact inline during conversation
await vg.addObservations([{
  entityName: 'Alice (Head of Engineering, reports to Bob)',
  contents: ['Just moved to Berlin — deadline for platform launch is end of Q2']
}]);

// Search by meaning — finds Alice even if you search "engineering team Berlin deadline"
const results = await vg.smartSearch('engineering team Berlin deadline', 5);

await vg.close();
Enter fullscreen mode Exit fullscreen mode

Semantic search via smartSearch() — it generates an embedding from your query, runs HNSW cosine similarity against stored entity embeddings, and applies name boosting so entities whose names match get surfaced first.


Project Tracking Built In

Because I'm using this as an operational tool, v3 added a built-in task board:

await vg.createEntities([{
  name: 'P01 - Platform redesign',
  entityType: 'Project',
  observations: ['Modernise the customer-facing platform'],
  metadata: {
    status: 'Active',
    priority: 'High',
    category: 'Work',
    nextAction: 'Finalise wireframes by Friday'
  }
}]);

// Get formatted markdown task board
const board = await vg.formatAsVtasks();
Enter fullscreen mode Exit fullscreen mode

The agent's morning briefing pulls this automatically — active projects, blocked items, what needs attention today.


Error Tracking (Verrors)

After six months I noticed the same technical issues recurring — timeouts, cron failures, service restarts. I added a verrors system that logs errors as graph entities:

await vg.createVerror({
  subsystem: 'cron_daily_brief',
  errorType: 'timeout',
  errorMessage: 'Daily brief timed out after 30s',
  context: 'Happened during heavy VyasaGraph query',
  impact: 'User missed morning update'
});

// Weekly review surfaces patterns
const unresolved = await vg.getUnresolvedVerrors();
Enter fullscreen mode Exit fullscreen mode

When the same subsystem errors three times, you start to see patterns. Patterns lead to fixes.


The Results

Six months in, with VyasaGraph running:

  • No more context-rebuilding at session start
  • The agent knows my team, their relationships, what projects we're running
  • Past decisions stay retrievable — "what did we decide about the zone boundaries in March?" actually works
  • Recurring problems get caught before they become chronic

The best way I can describe it: before VyasaGraph, the AI was a smart temp who needed onboarding every morning. After VyasaGraph, it's a colleague who was actually there yesterday.


Stack

  • SurrealDB — embedded graph + document + vector database
  • RocksDB — storage engine (no config, works everywhere)
  • HNSW — approximate nearest-neighbour vector index
  • OpenAI text-embedding-3-small — 1536-dim embeddings
  • Node.js 18+ — ES Modules

Get It

Built in Qatar. MIT licensed. Feedback welcome.


If you've been handling agent memory differently — I'm genuinely curious. What's your approach?


Top comments (0)