Memory System
SuperMemory-inspired atomic fact storage with pgvector hybrid search and conflict resolution.
Memory System
Linea's memory system is inspired by SuperMemory and targets ~45% feature parity. It provides persistent, structured memory for AI agents across workflow runs: enabling agents to remember facts, user preferences, and past events.
Design Principles
- Atomic facts: raw text is split into the smallest self-contained statements before storing
- Semantic deduplication: new facts semantically equivalent to existing ones supersede them rather than duplicating
- Hybrid retrieval: pgvector cosine similarity + keyword search, merged with score boosting
- Temporal grounding:
eventDateis separate fromcreatedAtso facts can reference when something happened - User profiling:
scope=usermemories grouped byfactTypeform a user's behavioral profile
Schema
Ingest Pipeline
POST /workspaces/:id/memories/ingest
Extract atomic facts
Claude Haiku (claude-haiku-4-5) receives the raw content and returns a JSON array of facts:
Embed each fact
Each fact is embedded with OpenAI text-embedding-3-small (1536 dimensions).
Check for conflicts
For each embedding, query for the nearest existing memory (excluding superseded):
If similarity >= 0.88 → the new fact supersedes the old one.
Insert and supersede
- Insert the new memory row
- If superseding: set
old_memory.superseded_by_id = new_memory.id
Log the session
Record the ingest batch in memory_sessions with extracted/updated IDs.
Response
Hybrid Search
POST /workspaces/:id/memories/search
Algorithm:
- Embed the query with
text-embedding-3-small - pgvector cosine → top 20 candidates with scores
ilikekeyword search → top 20 candidates- Merge scores:
- Vector-only result: use raw cosine similarity
- Keyword match on top of vector:
score + 0.2 - Keyword-only (not in vector results):
score = 0.3
- Exclude
supersededById IS NOT NULL - Return top-K sorted by merged score
User Profile
GET /workspaces/:id/memories/profile?userId=...
Returns scope=user memories (excluding superseded) grouped by factType:
Services
EmbeddingService
Wraps OpenAI text-embedding-3-small. Zero-vector fallback if OPENAI_API_KEY is not set: useful for local dev without AI billing.
ExtractionService
Wraps Claude Haiku with a strict extraction prompt. Falls back to storing the entire input as a single fact if:
ANTHROPIC_API_KEYis not set- Claude returns non-JSON
- Any parse error occurs
Feature Parity vs SuperMemory
| Feature | SuperMemory | Linea |
|---|---|---|
| Atomic extraction | ✅ | ✅ Claude Haiku |
| Hybrid retrieval | ✅ Sub-300ms | ✅ pgvector + ilike |
| Conflict resolution | ✅ | ✅ supersededById |
| User profiles | ✅ Behavioral | ✅ grouped by factType |
| Temporal grounding | ✅ Dual-layer | ✅ eventDate column |
| Memory graph | ✅ Neo4j | ❌ Not implemented |
| Web/audio connectors | ✅ | ❌ Not implemented |
Enabling vector search requires the pgvector PostgreSQL extension. Run CREATE EXTENSION IF NOT EXISTS vector; before db:push.