Skip to content
Back to skills

Memory Patterns

ASecurity

SQLite and memory system patterns specific to the @reactive-agents/memory package. Use when working on the memory layer, database operations, FTS5 search, Zettelkasten, or sqlite-vec KNN.

  • 28 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
ai-agentstypescriptsqlreactapidatabase

Works with

  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tylerjrbuell/reactive-agents-ts --skill memory-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Memory Patterns?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Memory Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tylerjrbuell-memory-patterns/badge)](https://www.skillsdirectory.com/skills/tylerjrbuell-memory-patterns)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: memory-patterns
description: SQLite and memory system patterns specific to the @reactive-agents/memory package. Use when working on the memory layer, database operations, FTS5 search, Zettelkasten, or sqlite-vec KNN.
user-invocable: false
---

# Memory System Patterns

## Architecture

```
.reactive-agents/memory/{agentId}/
├── memory.db      ← Source of truth (bun:sqlite, WAL mode)
└── memory.md      ← Human-readable projection (200-line cap, regenerated on flush)
```

SQLite is the source of truth. Markdown files are projections only.

## Four Memory Types

| Type         | Storage                               | Usage                                                   |
| ------------ | ------------------------------------- | ------------------------------------------------------- |
| `semantic`   | SQLite + memory.md                    | Long-term knowledge, bootstrapped at session start      |
| `episodic`   | SQLite                                | Daily logs + session snapshots                          |
| `procedural` | SQLite                                | Learned workflows and patterns                          |
| `working`    | In-process `Ref<WorkingMemoryItem[]>` | Capacity 7, FIFO/LRU/importance eviction, NOT persisted |

## Two Tiers

| Feature       | Tier 1                   | Tier 2                   |
| ------------- | ------------------------ | ------------------------ |
| Factory       | `createMemoryLayer("1")` | `createMemoryLayer("2")` |
| Search        | FTS5 BM25 only           | FTS5 + sqlite-vec KNN    |
| Embeddings    | None                     | Via `LLMService.embed()` |
| External deps | Zero                     | `sqlite-vec` npm package |

## Database Setup (bun:sqlite)

```typescript
import { Database } from "bun:sqlite";

// ─── Database creation with WAL mode ─────────────────────────────
export const MemoryDatabaseLive = Layer.scoped(
  MemoryDatabase,
  Effect.acquireRelease(
    Effect.sync(() => {
      const db = new Database(dbPath, { create: true });
      db.exec("PRAGMA journal_mode=WAL");
      db.exec("PRAGMA synchronous=NORMAL");
      db.exec("PRAGMA foreign_keys=ON");
      return db;
    }),
    (db) => Effect.sync(() => db.close()),
  ).pipe(
    Effect.map((db) => ({
      query: db.query.bind(db),
      exec: db.exec.bind(db),
      prepare: db.prepare.bind(db),
    })),
  ),
);
```

**Critical rules:**

- ALWAYS use `Effect.sync()` for bun:sqlite operations (they are synchronous)
- ALWAYS enable WAL mode
- ALWAYS use `Layer.scoped` + `Effect.acquireRelease` for DB lifecycle
- NEVER use `Effect.tryPromise` for SQLite (it's not async)

## FTS5 Setup

```sql
-- Create FTS5 virtual table for full-text search
CREATE VIRTUAL TABLE IF NOT EXISTS semantic_fts
USING fts5(content, summary, tags, tokenize='porter unicode61');

-- Insert into FTS (must mirror inserts to main table)
INSERT INTO semantic_fts(rowid, content, summary, tags) VALUES (?, ?, ?, ?);

-- Search with BM25 ranking
SELECT rowid, rank FROM semantic_fts
WHERE semantic_fts MATCH ?
ORDER BY rank
LIMIT ?;
```

## sqlite-vec KNN (Tier 2 Only)

```sql
-- Create vec0 virtual table (Tier 2)
CREATE VIRTUAL TABLE IF NOT EXISTS semantic_vec
USING vec0(embedding float[1536]);

-- Insert vector
INSERT INTO semantic_vec(rowid, embedding) VALUES (?, ?);

-- KNN search
SELECT rowid, distance FROM semantic_vec
WHERE embedding MATCH ?
ORDER BY distance
LIMIT ?;
```

**Tier 2 rules:**

- Embeddings come ONLY from `LLMService.embed()` — never from an independent embedding service
- `sqlite-vec` is an optional npm dependency
- Vector dimensions MUST match `EmbeddingConfig.dimensions` (default: 1536)
- `createMemoryLayer("2")` requires `LLMService` in the layer context

## Working Memory (Ref-based)

```typescript
export const WorkingMemoryServiceLive = Layer.effect(
  WorkingMemoryService,
  Effect.gen(function* () {
    const items = yield* Ref.make<readonly WorkingMemoryItem[]>([]);
    const capacity = 7; // Miller's number

    return {
      add: (item) =>
        Ref.update(items, (current) => {
          const updated = [...current, item];
          // Evict oldest if over capacity
          return updated.length > capacity ? updated.slice(-capacity) : updated;
        }),
      get: () => Ref.get(items),
      clear: () => Ref.set(items, []),
      size: () => Ref.get(items).pipe(Effect.map((i) => i.length)),
    };
  }),
);
```

## Memory Service Lifecycle

```
bootstrap(agentId) → loads memory.md into working memory
                   → rehydrates semantic index from SQLite
                   → returns MemoryBootstrapResult

flush()            → persists working memory to appropriate stores
                   → regenerates memory.md from SQLite
                   → runs compaction if needed
                   → applies auto-decay (decayFactor) to memory entries
                   → runs MemoryConsolidatorService when configured via .withMemoryConsolidation()

snapshot()         → creates episodic session snapshot
                   → saves to SQLite episodic table
```

## Zettelkasten (Link Graph)

```sql
-- Stored in SQLite, NOT a separate system
CREATE TABLE IF NOT EXISTS zettel_links (
  source_id TEXT NOT NULL,
  target_id TEXT NOT NULL,
  relation TEXT NOT NULL,  -- "relates-to", "contradicts", "supports", "extends"
  strength REAL DEFAULT 1.0,
  created_at TEXT DEFAULT (datetime('now')),
  PRIMARY KEY (source_id, target_id, relation),
  FOREIGN KEY (source_id) REFERENCES semantic_entries(id),
  FOREIGN KEY (target_id) REFERENCES semantic_entries(id)
);
```

Zettelkasten is included in Tier 1 (Phase 1). It uses FTS5 for similarity, not embeddings.

## Common Memory Mistakes

1. **Using LanceDB** — removed. Use bun:sqlite only.
2. **Using `EmbeddingProvider` service** — removed. Use `LLMService.embed()` only.
3. **Using Nomic API** — removed. Use OpenAI or Ollama for embeddings.
4. **Making memory.md the source of truth** — wrong. SQLite is source of truth.
5. **Using `Effect.tryPromise` for SQLite** — wrong. bun:sqlite is synchronous, use `Effect.sync`.
6. **Calling `embed()` in Tier 1** — wrong. Tier 1 has no embeddings.
7. **Creating separate embedding service** — wrong. `LLMService.embed()` is the sole source.

## SQLite Services Beyond Memory

Several packages use SQLite for persistence beyond the memory layer:

| Service | Package | Table | Purpose |
|---------|---------|-------|---------|
| SessionStoreService | memory | agent_sessions | SQLite-backed chat session persistence |
| DebriefStore | runtime | agent_debriefs | Persists run artifacts from DebriefSynthesizer |
| PlanStoreService | memory | agent_plans | SQLite plan persistence for plan-execute strategy |
| ExperienceStore | memory | agent_experiences | Cross-agent learning store |
| CalibrationStore | reactive-intelligence | (in-memory) | Entropy calibration data per model |

All follow the same bun:sqlite WAL pattern. See each service's source for schema.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.