LLMs have no memory. Every request starts fresh.
This fundamental limitation creates jarring user experiences. Your AI assistant forgets your name between sessions. Your support bot asks the same clarifying questions every time. Your coding assistant cannot remember your project conventions.
Building memory into AI systems transforms them from stateless tools into persistent collaborators.
| Memory Type | Scope | Duration | Example |
|---|
| Working memory | Current conversation | Minutes | Chat history |
| Short-term memory | Session | Hours | Session context |
| Long-term memory | User | Months/Years | Preferences, history |
| Semantic memory | Knowledge | Permanent | Facts, procedures |
| Episodic memory | Events | Variable | Past interactions |
| Type | Write Frequency | Read Frequency | Size |
|---|
| Working | Every turn | Every turn | Small (tokens) |
| Short-term | Per session | Start of session | Medium (KB) |
| Long-term | Per interaction | Per request | Large (MB) |
| Semantic | Infrequent | Frequent | Very large (GB) |
Working Memory: Conversation Context
Context Window Management
| Strategy | Implementation | Use Case |
|---|
| Full history | Send all messages | Short conversations |
| Sliding window | Last N messages | Long conversations |
| Summarization | Compress older context | Very long conversations |
| Hybrid | Recent full + older summarized | Best of both |
| Context Length | Messages (avg 100 tokens) | Strategy |
|---|
| 4K tokens | ~30 messages | Full history |
| 8K tokens | ~60 messages | Full history |
| 32K tokens | ~250 messages | Full or sliding |
| 128K tokens | ~1000 messages | Usually full |
| Approach | Quality | Cost | Latency |
|---|
| LLM summarization | High | Medium | 500ms |
| Extractive summary | Medium | Low | 50ms |
| Rolling summary | High | High | Per-turn |
| Hierarchical | Very high | High | Variable |
| Step | Action | Output |
|---|
| 1 | Keep last N messages verbatim | Recent context |
| 2 | Summarize messages N+1 to N+M | Summary block |
| 3 | On new message, update summary | Updated summary |
| 4 | Combine: summary + recent | Full context |
| Data Type | Example | Storage |
|---|
| User identity | Name, role | Session store |
| Task context | Current goal | Session store |
| Working documents | Draft, edits | Session store |
| Preferences | Format, tone | Session store |
| Component | Technology | Purpose |
|---|
| Session ID | UUID | Identify session |
| Session store | Redis | Fast access |
| TTL | 24 hours | Auto-cleanup |
| Serialization | JSON | State format |
| Field | Type | Description |
|---|
| session_id | string | Unique identifier |
| user_id | string | User reference |
| created_at | timestamp | Session start |
| last_active | timestamp | Last interaction |
| context | object | Accumulated context |
| metadata | object | Session settings |
| Category | Examples | Value |
|---|
| User preferences | Tone, format, length | Personalization |
| User facts | Name, role, company | Context |
| Interaction history | Past questions, feedback | Learning |
| User documents | Uploaded files, notes | Reference |
| Learned behaviors | Corrections, preferences | Improvement |
| Layer | Technology | Data Type |
|---|
| Relational | PostgreSQL | Structured facts |
| Vector | Pinecone/Qdrant | Semantic search |
| Document | MongoDB | Flexible objects |
| Cache | Redis | Hot data |
| Trigger | What to Retrieve | Method |
|---|
| User identified | User preferences | Direct lookup |
| Query received | Relevant memories | Semantic search |
| Context needed | Related interactions | Hybrid search |
| Step | Action | Latency |
|---|
| 1 | Extract query entities | 10ms |
| 2 | Fetch user profile | 20ms |
| 3 | Semantic search memories | 50ms |
| 4 | Rerank by relevance | 30ms |
| 5 | Inject into context | 5ms |
| Total | End-to-end | ~115ms |
| Trigger | What to Store | Priority |
|---|
| Explicit statement | "My name is..." | High |
| Inferred preference | Repeated behavior | Medium |
| Task completion | Summary, outcome | Medium |
| User feedback | Corrections | High |
| Conversation end | Session summary | Low |
| Method | Accuracy | Cost | Latency |
|---|
| Rule-based | 60% | Free | 5ms |
| NER extraction | 75% | Low | 20ms |
| LLM extraction | 90% | Medium | 300ms |
| Human review | 99% | High | Async |
| Field | Type | Description |
|---|
| memory_id | string | Unique identifier |
| user_id | string | Owner |
| type | enum | fact, preference, event |
| content | string | Memory content |
| embedding | vector | Semantic representation |
| confidence | float | Extraction confidence |
| source | string | Where it came from |
| created_at | timestamp | When stored |
| accessed_at | timestamp | Last accessed |
| access_count | integer | Usage frequency |
| Challenge | Description | Solution |
|---|
| Redundancy | Same fact stored multiple times | Deduplication |
| Contradiction | Conflicting memories | Recency preference |
| Staleness | Outdated information | TTL, versioning |
| Noise | Low-value memories | Importance scoring |
| Step | Action | Frequency |
|---|
| 1 | Identify duplicates | Daily |
| 2 | Merge similar memories | Daily |
| 3 | Resolve contradictions | On access |
| 4 | Prune low-value | Weekly |
| 5 | Update embeddings | Monthly |
| Factor | Weight | Reasoning |
|---|
| Access frequency | 30% | Used memories are valuable |
| Recency | 25% | Recent is relevant |
| Explicit statement | 25% | User told us directly |
| Source quality | 20% | Some sources more reliable |
| Level | Description | User Control |
|---|
| Ephemeral | Not stored | Default |
| Session | Stored for session | Opt-in |
| Persistent | Stored long-term | Explicit consent |
| Shared | Across contexts | Separate consent |
| Control | Implementation | UI Element |
|---|
| View memories | Display stored data | Memory viewer |
| Delete memory | Remove specific | Delete button |
| Clear all | Wipe user data | Settings |
| Export | Download data | Export button |
| Pause | Stop storing | Toggle |
| Requirement | Implementation |
|---|
| Right to access | Memory viewer |
| Right to deletion | Delete functionality |
| Right to portability | Export feature |
| Consent | Explicit opt-in |
| Minimization | Only store necessary |
| Metric | Description | Target |
|---|
| Recall accuracy | Correct memories retrieved | Over 90% |
| Precision | Relevant memories retrieved | Over 80% |
| Extraction accuracy | Correct memory stored | Over 85% |
| Freshness | Up-to-date information | Over 95% |
| Metric | Description | Target |
|---|
| Personalization score | User-rated relevance | Over 4/5 |
| Context continuity | Seamless sessions | Over 90% |
| Memory latency | Retrieval time | Under 200ms |
| False memories | Incorrect recalls | Under 2% |
| Component | Implementation |
|---|
| Working | Full conversation in context |
| Short-term | Redis session store |
| Long-term | PostgreSQL user table |
| Component | Implementation |
|---|
| Working | Summarization + recent |
| Short-term | Redis with state machine |
| Long-term | Vector DB + relational |
| Consolidation | Background jobs |
Diagram
flowchart TB
subgraph Working["Working Memory"]
W1[Current Message]
W2[Recent Context]
W3[Active Goals]
end
subgraph ShortTerm["Short-Term Memory"]
S1[Session State]
S2[Conversation History]
S3[Temporary Facts]
end
subgraph LongTerm["Long-Term Memory"]
L1[User Profile]
L2[Semantic Facts]
L3[Episodic Memories]
end
W1 --> S2
S2 --> |Consolidation| L3
S3 --> |Extraction| L2
L1 --> W2
L2 --> W2
L3 --> W2
style Working fill:#22c55e,color:#fff
style ShortTerm fill:#f59e0b,color:#fff
style LongTerm fill:#3b82f6,color:#fff
Python
from dataclasses import dataclass
from typing import List, Optional
from datetime import datetime
@dataclass
class Memory:
content: str
memory_type: str # "fact", "episode", "preference"
importance: float # 0-1
created_at: datetime
last_accessed: datetime
access_count: int
class MemorySystem:
def __init__(self, redis, vector_db, postgres):
self.working = WorkingMemory(max_tokens=4000)
self.short_term = ShortTermMemory(redis, ttl_hours=24)
self.long_term = LongTermMemory(vector_db, postgres)
async def remember(self, user_id: str, content: str, memory_type: str):
"""Store a new memory with appropriate importance scoring."""
# Calculate importance based on content analysis
importance = await self._calculate_importance(content, memory_type)
memory = Memory(
content=content,
memory_type=memory_type,
importance=importance,
created_at=datetime.now(),
last_accessed=datetime.now(),
access_count=0
)
# Store in appropriate layer based on importance
if importance > 0.8:
await self.long_term.store(user_id, memory)
else:
await self.short_term.store(user_id, memory)
async def recall(self, user_id: str, query: str, k: int = 5) -> List[Memory]:
"""Retrieve relevant memories for the current context."""
# Get from all layers
working_context = self.working.get_context()
short_term = await self.short_term.search(user_id, query, k=k)
long_term = await self.long_term.search(user_id, query, k=k)
# Combine and rank by relevance + recency + importance
all_memories = short_term + long_term
ranked = self._rank_memories(all_memories, query)
# Update access patterns
for memory in ranked[:k]:
memory.last_accessed = datetime.now()
memory.access_count += 1
return ranked[:k]
async def consolidate(self, user_id: str):
"""Background job: promote important short-term to long-term."""
# Find frequently accessed short-term memories
candidates = await self.short_term.get_high_access(user_id, min_count=3)
for memory in candidates:
# Extract durable facts
facts = await self._extract_facts(memory.content)
for fact in facts:
await self.long_term.store(user_id, Memory(
content=fact,
memory_type="fact",
importance=memory.importance,
created_at=datetime.now(),
last_accessed=datetime.now(),
access_count=0
))
# Remove from short-term
await self.short_term.delete(user_id, memory.id)
def _rank_memories(self, memories: List[Memory], query: str) -> List[Memory]:
"""Rank memories by composite score."""
def score(m: Memory) -> float:
# Recency decay
age_hours = (datetime.now() - m.last_accessed).total_seconds() / 3600
recency = 1 / (1 + age_hours / 24)
# Combine factors
return (
0.4 * m.importance +
0.3 * recency +
0.2 * min(m.access_count / 10, 1) +
0.1 * self._semantic_similarity(m.content, query)
)
return sorted(memories, key=score, reverse=True)
| Component | Implementation |
|---|
| Working | Adaptive context management |
| Short-term | Distributed cache |
| Long-term | Multi-modal memory graph |
| Consolidation | ML-based importance |
| Privacy | Full compliance suite |
- 1Memory is not one thing - Working, short-term, and long-term memory serve different purposes and need different architectures.
- 2Retrieval is as important as storage - Fast, relevant memory retrieval is what makes memory useful.
- 3Write selectively - Not everything should be remembered. Store what matters, with appropriate confidence.
- 4Consolidate regularly - Memories need maintenance. Deduplicate, resolve conflicts, and prune.
- 5Privacy is non-negotiable - Users must control their data. Build consent and deletion into the architecture.
- 6Start simple - Begin with session memory, add long-term when you have proven value.
Memory transforms AI from a tool into a relationship. Build it thoughtfully, and your users will never want to go back to stateless interactions.