Use the memory API
In shortStore, search, and manage long-term memories across agent conversations with the 10xGraph TypeScript client.
- 6 min read
- 12 sections
- Updated
- v0.10.0
- Markdown
The memory API lets you store facts, preferences, and conversation history that persists across threads and sessions. Agents can search this long-term context during conversation to provide personalized, informed responses. This guide shows you how to build agents that learn and remember.
Why memory matters
Without memory, each thread starts fresh: the agent sees no history, no preferences, no facts about the user. With memory, you can:
- Personalize responses based on learned user preferences.
- Accumulate context that grows richer over time.
- Build continuity across separate conversations and days.
- Let agents refer to prior decisions and past interactions.
The memory API handles the storage and retrieval; you control what to remember and how to use it.
Prerequisites
- A configured
TenxGraphClient. See create the client. - The API server running with a memory store configured in
10xgraph.json.
Store a memory
Use storeMemory() to save any piece of information. Each memory has a type (semantic, episodic, etc.) and a category (like “preferences” or “history”).
import { MemoryType } from '10xgraph-client';
const response = await client.storeMemory({
content: 'User works in healthcare and prefers technical explanations.',
memory_type: MemoryType.SEMANTIC,
category: 'user_profile',
metadata: { source: 'inferred', confidence: 0.9 },
});
const memoryId = response.data.memory_id;
console.log('Stored memory with ID:', memoryId);The response includes memory_id, which you can use later to update or delete the memory. Save it if you need to reference the memory later.
Search memories to build context
Vector similarity search finds memories that relate to your current query, even if the wording differs. This is the core value of the memory API: you ask a question, and the store returns relevant past facts.
import { MemoryType, RetrievalStrategy } from '10xgraph-client';
const results = await client.searchMemory({
query: 'What is the user\'s background?',
memory_type: MemoryType.SEMANTIC,
category: 'user_profile',
limit: 3,
score_threshold: 0.6,
retrieval_strategy: RetrievalStrategy.SIMILARITY,
});
for (const result of results.data.results) {
console.log(`Match (score ${result.score.toFixed(2)}): ${result.content}`);
}Each result carries a score; higher means a closer match. The score_threshold filters out low-scoring matches. Score scale depends on your store backend and distance metric.
Build an agent that uses memory
The full pattern is: search for relevant memories, build a system prompt with them, then invoke the agent. This way, the agent always has context.
import { TenxGraphClient, Message, MemoryType, RetrievalStrategy } from '10xgraph-client';
const client = new TenxGraphClient({ baseUrl: 'http://localhost:8000' });
const THREAD_ID = 'user-session-123';
async function respondWithMemory(userQuestion: string) {
// 1. Search for relevant memories
const memories = await client.searchMemory({
query: userQuestion,
memory_type: MemoryType.SEMANTIC,
limit: 5,
score_threshold: 0.65,
});
// 2. Build context from the top matches
const context = memories.data.results
.map(r => `- ${r.content}`)
.join('\n');
const systemPrompt = context
? `You are a helpful assistant with knowledge of the user:\n${context}`
: 'You are a helpful assistant.';
// 3. Invoke the agent with memory context
const response = await client.invoke(
[
Message.text_message(systemPrompt, 'system'),
Message.text_message(userQuestion),
],
{
config: { thread_id: THREAD_ID },
response_granularity: 'low',
}
);
// 4. Store this interaction for future reference
const last = response.messages[response.messages.length - 1];
const answer = last.content
.filter((b) => b.type === 'text')
.map((b) => (b as { text: string }).text)
.join('');
await client.storeMemory({
content: `User asked: "${userQuestion}". Agent responded with: "${answer}"`,
memory_type: MemoryType.EPISODIC,
category: 'conversations',
metadata: { timestamp: new Date().toISOString(), thread_id: THREAD_ID },
});
return response;
}
// Use it
const result = await respondWithMemory('How should I approach this project?');
console.log(result.messages);This pattern ensures every conversation is stored for learning, and every new question is informed by past context.
Organize memories with types and categories
Choosing the right MemoryType makes searches more precise. See memory reference for the full list, but here are the main types:
- Semantic: Facts, preferences, knowledge. Best for agent learning.
- Episodic: Specific conversations, events, interactions. Builds a history.
- Procedural: How-to workflows, recurring processes.
- Entity: Information about people, places, or things.
- Relationship, Declarative and Custom are also available.
Use categories to group related memories (like "user_profile", "conversations", "work_history"). When searching, you can filter by category to avoid irrelevant results.
// Store different types
await client.storeMemory({
content: 'User is a software engineer interested in Rust.',
memory_type: MemoryType.SEMANTIC,
category: 'user_profile',
});
await client.storeMemory({
content: 'Discussed deployment architecture for microservices.',
memory_type: MemoryType.EPISODIC,
category: 'conversations',
});
// Search only semantic memories in the profile
const facts = await client.searchMemory({
query: 'What does the user do?',
memory_type: MemoryType.SEMANTIC,
category: 'user_profile',
limit: 3,
});Retrieve and update a specific memory
If you have a memory_id, you can fetch a single memory by ID:
const memory = await client.getMemory(memoryId);
console.log('Content:', memory.data.memory.content);
console.log('Type:', memory.data.memory.memory_type);
console.log('Stored at:', memory.data.memory.timestamp);To update a memory’s content or metadata:
await client.updateMemory(
memoryId,
'User works in healthcare, prefers technical explanations, and uses Python daily.',
{
metadata: { updated_at: new Date().toISOString(), reason: 'user_correction' },
}
);Advanced search options
The memory API supports multiple retrieval strategies and distance metrics. Most use cases work well with the defaults (similarity and cosine distance), but for specialized scenarios, you have options.
For detailed tables of retrieval strategies and distance metrics, see memory reference and distance metric reference.
Common advanced patterns:
// Temporal retrieval: get the most recent memories
const recent = await client.searchMemory({
query: 'recent activity',
limit: 10,
retrieval_strategy: RetrievalStrategy.TEMPORAL,
});
// Hybrid search: combined retrieval approaches
const hybrid = await client.searchMemory({
query: 'user preferences',
limit: 5,
retrieval_strategy: RetrievalStrategy.HYBRID,
score_threshold: 0.5,
});
// Cap results by tokens to avoid oversized context
const limited = await client.searchMemory({
query: 'project history',
limit: 20,
max_tokens: 2000, // Cap the total tokens of returned results
});List and manage memory lifecycle
List all stored memories:
const response = await client.listMemories({ limit: 100 });
console.log(`Total memories: ${response.data.memories.length}`);
for (const mem of response.data.memories) {
console.log(`[${mem.memory_type}] ${mem.content.slice(0, 60)}`);
}Delete a single memory by ID:
await client.deleteMemory(memoryId);
console.log('Memory deleted');Bulk-delete memories matching a filter (more efficient than deleting one by one):
// Clear all session-temporary memories
await client.forgetMemories({
memory_type: MemoryType.EPISODIC,
category: 'session_temp',
});
// Clear memories with a custom filter
await client.forgetMemories({
filters: { archived: true },
});Common errors and fixes
| Problem | Cause | Solution |
|---|---|---|
TenxGraphError status 404 on getMemory() |
Memory ID not found or deleted. | Verify the ID is correct. Use listMemories() to check what exists. |
TenxGraphError status 503 |
Store not configured or unreachable. | Check the store field in 10xgraph.json and ensure the store backend is running. |
| Empty search results | Score threshold too high, or no memories match the type/category. | Lower score_threshold, remove the type filter, or store more memories. |
| Irrelevant search results | Query is too vague, or memories are poorly written. | Use specific queries. Store memories with clear, descriptive content. |
What you learned
- Use
storeMemory()to save facts, preferences, and interactions with a type and category. searchMemory()finds related memories using vector similarity; higher scores mean stronger matches.- Build agent context by searching memories before invoking the agent.
- Store agent interactions as episodic memories to build a conversation history.
- Organize memories with types and categories to make searches more precise.
- Use
updateMemory(),deleteMemory(), andforgetMemories()to manage the memory lifecycle.
Next step
See files and multimodal to learn how to upload and reference images, audio, and documents in your agents.