How to Query Memories
Last Updated: 2026-02-06
Content-Type: How-to
Audience: Developers
Overview
This guide shows you how to query memory context using chunked hybrid retrieval (vector + keyword) with a safe fallback to legacy memories vector retrieval.
Prerequisites
- Access to the Memory Service and Embedding Service
- User ID for filtering
- Understanding of vector similarity search
Steps
1. Generate Query Embedding
First, convert your query text to an embedding vector:
typescript
import { generateEmbedding } from '../services/embedding.service';
const queryText = "What does the user like?";
const queryEmbedding = await generateEmbedding(queryText);2. Query Memory Context (Recommended)
Use the embedding to search for similar memories:
The simplest way is to call gatherFullContext() (what production uses):
typescript
import { gatherFullContext } from '../services/aso/context.service';
const ctx = await gatherFullContext(
playerUserId,
npcUserId,
userInput, // the user’s message
protocolContext, // optional
conversationId // optional (enables continuity boost in chunk retrieval)
);
// Three-tiered memory sections (already clamped for prompts)
console.log(ctx.memoryContext.worldContext);
console.log(ctx.memoryContext.asoContext);
console.log(ctx.memoryContext.personalContext);3. Process Results
The results are ordered by similarity (most relevant first):
typescript
memories.forEach(memory => {
console.log(`Memory: ${memory.content}`);
console.log(`Similarity: ${memory.similarity}`);
console.log(`Source: ${memory.source}`);
});Chunk Retrieval Controls
Chunk retrieval is enabled by default. To disable (force legacy memories retrieval), set:
USE_MEMORY_CHUNKS=false
When enabled, the system uses:
- vector similarity on
memory_chunks.embedding - keyword search on
memory_chunks.content(GINtsvectorindex) - tier/time/conversation weighting
Filtering by Source
Query specific memory types:
typescript
// Get only shared memories
const sharedMemories = await queryMemoriesByEmbedding(
queryEmbedding,
10,
userId
);
const filtered = sharedMemories.filter(m => m.source === 'shared');Query Examples
Finding User Preferences
typescript
const query = "What are the user's preferences?";
const embedding = await generateEmbedding(query);
const memories = await queryMemoriesByEmbedding(embedding, 5, userId);
// Results will include memories about user preferencesRetrieving World Knowledge
typescript
const query = "What are the game world rules?";
const embedding = await generateEmbedding(query);
const memories = await queryMemoriesByEmbedding(embedding, 10, 0); // userId 0 for world
const worldMemories = memories.filter(m => m.source === 'world');Getting Conversation Context
typescript
const query = userMessage; // Current user message
const embedding = await generateEmbedding(query);
const context = await gatherFullContext(userId, npcUserId, conversationId);
// Use context.memories for conversation contextPerformance Tips
Limit Results:
- Use appropriate limit (5-10 for most cases)
- More results = slower queries
Cache Embeddings:
- Embedding generation has an in-process LRU cache
- Tune with
EMBEDDING_CACHE_SIZE(default 500)
Use Context Service:
- More efficient than multiple queries
- Combines all memory tiers automatically
Filter Early:
- Filter by source after query if needed
- Avoid querying unnecessary memory types
Error Handling
typescript
try {
const ctx = await gatherFullContext(playerUserId, npcUserId, userMessage, protocolContext, conversationId);
if (!ctx.memoryContext.personalContext.trim()) {
console.log('No personal context retrieved');
}
} catch (error) {
console.error('Query failed:', error);
// Fallback to empty context or default behavior
}Related Documentation
- API Reference - Complete function documentation
- Add Memory - How to add new memories
- Architecture - System design details