Skip to content

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);

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 (GIN tsvector index)
  • 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 preferences

Retrieving 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 context

Performance Tips

  1. Limit Results:

    • Use appropriate limit (5-10 for most cases)
    • More results = slower queries
  2. Cache Embeddings:

    • Embedding generation has an in-process LRU cache
    • Tune with EMBEDDING_CACHE_SIZE (default 500)
  3. Use Context Service:

    • More efficient than multiple queries
    • Combines all memory tiers automatically
  4. 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
}

ASO Universal Consciousness System Documentation