Skip to main content

Memory & Knowledge Graph

Query the character's persistent memory system to retrieve facts, relationships, and conversation history across sessions.

Overview​

Estuary characters remember things about users across conversations. The memory system stores facts, relationships, and context as a knowledge graph. The SDK provides a MemoryClient accessible via client.memory that lets you query this data through the REST API.

Memory is scoped to a specific character-player pair -- each player has their own memory with each character.

For more details on how memory works, see the Memory System platform documentation.

Authentication​

The MemoryClient authenticates using the same API key configured on the EstuaryClient. No additional setup is required:

const client = new EstuaryClient({
serverUrl: 'https://api.estuary-ai.com',
apiKey: 'est_your_api_key',
characterId: 'your-character-uuid',
playerId: 'user-123',
});

// client.memory is ready to use immediately -- no need to call connect() first
const facts = await client.memory.getCoreFacts();
info

The memory API uses REST endpoints, not the WebSocket connection. You can query memory without calling client.connect().

Every memory request carries your API key plus an X-Estuary-Client: estuary-ts-sdk/<version> header identifying the SDK and its version (see Client identification). The header goes on REST requests only, never on the WebSocket connection.

Reads need a key with the memories:read scope and edits need memories:write. A key that lacks the scope a call needs gets a 403, surfaced as described in Error Handling.

Listing Memories​

Retrieve a paginated list of memories with optional filtering:

const result = await client.memory.getMemories({
status: 'active',
limit: 20,
offset: 0,
});

console.log(`Total memories: ${result.total}`);
for (const memory of result.memories) {
console.log(memory);
}

Filter Options​

OptionTypeDescription
memoryTypestringFilter by memory type
statusstringFilter by status (e.g., 'active')
limitnumberMax results to return
offsetnumberPagination offset
sortBystringDeprecated. Accepted for compatibility, but ignored: it is no longer sent and no route ever honored it
sortOrderstringDeprecated. Accepted for compatibility, but ignored: it is no longer sent and no route ever honored it
note

Memories come back in the server's default order. Sort client side if you need a specific order.

Core Facts​

Core facts are high-confidence, stable pieces of information the character has learned about the player -- things like their name, preferences, or important details:

const result = await client.memory.getCoreFacts();

for (const fact of result.coreFacts) {
console.log(fact);
}

Knowledge Graph​

The knowledge graph represents memories as a network of entities and relationships:

const graph = await client.memory.getGraph({
includeEntities: true,
includeCharacterMemories: true,
});

console.log('Nodes:', graph.nodes.length);
console.log('Edges:', graph.edges.length);
console.log('Stats:', graph.stats);

Graph Options​

OptionTypeDefaultDescription
includeEntitiesbooleanfalseInclude entity nodes in the graph
includeCharacterMemoriesbooleanfalseInclude the character's own memories

Searching Memories​

Search across all memories using natural language:

// Optional second argument: result limit, 1 to 50 (server default 10)
const results = await client.memory.search('likes pizza', 5);

console.log(`Found ${results.total} results for "${results.query}"`);
for (const result of results.results) {
console.log(`[${result.similarity.toFixed(2)}] ${result.content} (${result.memoryId})`);
}

Search uses semantic similarity, so the query does not need to match the stored text exactly.

Each hit is a MemorySearchResult with three fields: memoryId, similarity, and content. It is not a full memory object, so if you need the other fields, match memoryId against the results of getMemories().

:::note Search works from this release onward Earlier SDK versions sent the search request in a form the server rejected, so search() could never return results. Upgrade to the current version to use it. For the request and response shapes, see Search Memories in the REST reference. :::

Timeline​

View memories organized chronologically:

const timeline = await client.memory.getTimeline({
groupBy: 'week',
});

console.log(`Total memories: ${timeline.totalMemories}`);
for (const group of timeline.timeline) {
console.log(`${group.date}: ${group.memories.length} memories`);
}

Timeline Options​

OptionTypeDescription
startDatestringISO date string for range start
endDatestringISO date string for range end
groupBystring'day', 'week', or 'month'

Statistics​

Get aggregate statistics about the character's memory for this player:

const stats = await client.memory.getStats();
console.log(stats);

Example: Memory Dashboard​

import { EstuaryClient } from '@estuary-ai/sdk';

const client = new EstuaryClient({
serverUrl: 'https://api.estuary-ai.com',
apiKey: 'est_your_api_key',
characterId: 'your-character-uuid',
playerId: 'user-123',
});

async function showMemoryDashboard() {
// Fetch everything in parallel
const [facts, graph, stats, timeline] = await Promise.all([
client.memory.getCoreFacts(),
client.memory.getGraph({ includeEntities: true }),
client.memory.getStats(),
client.memory.getTimeline({ groupBy: 'week' }),
]);

console.log('=== Core Facts ===');
for (const fact of facts.coreFacts) {
console.log('-', fact);
}

console.log('\n=== Knowledge Graph ===');
console.log(`${graph.nodes.length} nodes, ${graph.edges.length} edges`);

console.log('\n=== Stats ===');
console.log(stats);

console.log('\n=== Timeline ===');
for (const group of timeline.timeline) {
console.log(`${group.date}: ${group.memories.length} memories`);
}
}

showMemoryDashboard().catch(console.error);

Real-Time Memory Events​

By default, memory extraction happens silently in the background. If you want to be notified when new memories are extracted during a conversation, enable realtimeMemory in your client config:

const client = new EstuaryClient({
serverUrl: 'https://api.estuary-ai.com',
apiKey: 'est_your_api_key',
characterId: 'your-character-uuid',
playerId: 'user-123',
realtimeMemory: true,
});

client.on('memoryUpdated', (event) => {
console.log(`Extracted ${event.memoriesExtracted} memories, ${event.factsExtracted} facts`);

for (const memory of event.newMemories) {
console.log(`[${memory.memoryType}] ${memory.content} (confidence: ${memory.confidence})`);
}
});

await client.connect();

The memoryUpdated event fires after each bot response when the server finishes extracting memories from the conversation turn. The event includes:

FieldTypeDescription
agentIdstringCharacter (agent) ID
playerIdstringPlayer ID
memoriesExtractednumberNumber of memories extracted this turn
factsExtractednumberNumber of core facts extracted
conversationIdstringConversation ID
newMemoriesMemoryData[]Array of newly extracted memory objects
timestampstringISO timestamp
tip

Real-time memory events are useful for building UIs that show the user what the character has learned, or for triggering application logic based on extracted facts.

Next Steps​