Use Case: Personal Memory Assistant
August 18, 2026 ยท View on GitHub
The Scenario
Imagine an AI assistant that truly remembers you - your preferences, your notes, your habits, and how your thinking evolves over time. A personal memory assistant helps you capture thoughts, retrieve contextually relevant information, and see how your understanding has changed.
This is different from a simple note-taking app. With OpenContext's temporal memory, your assistant can:
- Remember your preferences across sessions
- Store notes with rich metadata for semantic search
- Show you what you thought about a topic in the past
- Update and correct memories as your understanding evolves
What You'll Build
A personal memory assistant that:
- Captures preferences - Theme, language, work habits, communication style
- Stores notes with metadata - Tags, categories, importance levels
- Performs semantic search - Find notes by meaning, not just keywords
- Time-travels through your thoughts - See what you believed at specific points in time
- Improves memories - Update facts and deprecate outdated information
Concepts Demonstrated
remember- Storing preferences and notes with metadatarecall- Semantic search with filteringtime-travel- Querying memory as of a specific timeimprove- Updating and correcting memoriesforget- Deprecating outdated information- Metadata filtering - Using metadata for advanced search
- Batch operations - Efficiently importing existing notes
Prerequisites
Before starting this tutorial, you should:
- Complete the Getting Started tutorial
- Understand the Four Verbs from the User Guide
- Have Node.js >= 22 installed
Implementation
Step 1: Setting Up the Assistant
Create a new file personal-memory-assistant.ts:
import { createMemoryStore, getRawMessageManager } from "@melandlabs/opencontext";
async function main() {
const store = await createMemoryStore();
const messages = await getRawMessageManager();
console.log("๐ง Personal Memory Assistant initialized");
}
Step 2: Storing User Preferences
Store user preferences with descriptive metadata:
const now = Date.now();
await messages.storeMessages([
{
messageId: `pref-theme-${now}`,
userId: "user-123",
content: "User prefers dark mode in all applications",
platform: "personal-assistant",
botId: "memory-assistant",
timestamp: now,
createdAt: now,
metadata: {
type: "preference",
category: "ui",
priority: "high",
},
},
{
messageId: `pref-language-${now}`,
userId: "user-123",
content: "User communicates in English but is learning Spanish",
platform: "personal-assistant",
botId: "memory-assistant",
timestamp: now,
createdAt: now,
metadata: {
type: "preference",
category: "language",
},
},
]);
Step 3: Creating Rich Notes with Metadata
Store notes with searchable metadata:
const noteTimestamp = now + 1000;
await messages.storeMessages([
{
messageId: `note-project-idea-${noteTimestamp}`,
userId: "user-123",
content: "Consider building a personal knowledge graph that connects ideas across domains",
platform: "personal-assistant",
botId: "memory-assistant",
timestamp: noteTimestamp,
createdAt: noteTimestamp,
metadata: {
type: "note",
category: "project-idea",
tags: ["knowledge-graph", "innovation", "long-term"],
importance: "high",
context: "shower-thought",
},
},
]);
Step 4: Semantic Search Across Memories
Use semantic search to find relevant information:
// Search for project-related notes
const projectNotes = await store.search({
userId: "user-123",
query: "What project ideas have I had?",
limit: 10,
});
console.log("\n๐ Project Notes:");
for (const hit of projectNotes.results) {
const meta = hit.metadata || {};
console.log(`- ${hit.content}`);
console.log(` Category: ${meta.category}, Importance: ${meta.importance}`);
}
// Filter by metadata type
const preferences = await store.search({
userId: "user-123",
query: "user preferences",
metadata: {
type: "preference",
},
limit: 20,
});
console.log("\nโ๏ธ User Preferences:");
for (const hit of preferences.results) {
console.log(`- ${hit.content} (${hit.metadata?.category})`);
}
Step 5: Time-Travel Queries
See what you thought at a specific point in time:
// First, let's simulate some time passing and a change of mind
const updatedTimestamp = noteTimestamp + 86400000; // 1 day later
// Store an updated view
await messages.storeMessages([
{
messageId: `note-project-update-${updatedTimestamp}`,
userId: "user-123",
content: "Personal knowledge graph should focus on temporal connections - how ideas relate and evolve over time",
platform: "personal-assistant",
botId: "memory-assistant",
timestamp: updatedTimestamp,
createdAt: updatedTimestamp,
metadata: {
type: "note",
category: "project-idea",
tags: ["knowledge-graph", "temporal", "evolution"],
importance: "high",
replaces: `note-project-idea-${noteTimestamp}`,
},
},
]);
// Query: What was I thinking before the update?
const beforeUpdate = await store.search({
userId: "user-123",
query: "knowledge graph project",
asOf: noteTimestamp + 3600000, // 1 hour after original note
});
console.log("\n๐ฐ๏ธ My thinking before the update:");
for (const hit of beforeUpdate.results) {
console.log(`- ${hit.content}`);
}
// Query: What's my current thinking?
const currentThinking = await store.search({
userId: "user-123",
query: "knowledge graph project",
});
console.log("\nโจ My current thinking:");
for (const hit of currentThinking.results) {
console.log(`- ${hit.content}`);
}
Step 6: Using Improve to Update Memories
When you learn new information that changes your understanding:
const correctionTimestamp = updatedTimestamp + 3600000;
// Store a correction (using "improve" pattern)
await messages.storeMessages([
{
messageId: `correction-project-${correctionTimestamp}`,
userId: "user-123",
content: "Correction: The temporal aspect should apply to ALL connections, not just knowledge graphs. This is a fundamental principle.",
platform: "personal-assistant",
botId: "memory-assistant",
timestamp: correctionTimestamp,
createdAt: correctionTimestamp,
metadata: {
type: "correction",
category: "principle",
deprecates: [`note-project-update-${updatedTimestamp}`],
},
},
]);
// Now when searching, the latest understanding surfaces
const latestUnderstanding = await store.search({
userId: "user-123",
query: "what are my principles for knowledge management",
});
console.log("\n๐ฏ Latest understanding:");
for (const hit of latestUnderstanding.results) {
console.log(`- ${hit.content}`);
}
Step 7: Batch Import Existing Notes
If you have existing notes from another system:
async function importExistingNotes(notes: Array<{
content: string;
category: string;
tags: string[];
createdAt: number;
}>) {
const importBatch = notes.map((note, index) => ({
messageId: `import-note-${index}-${Date.now()}`,
userId: "user-123",
content: note.content,
platform: "personal-assistant",
botId: "memory-assistant",
timestamp: note.createdAt,
createdAt: Date.now(),
metadata: {
type: "note",
category: note.category,
tags: note.tags,
imported: true,
},
}));
await messages.storeMessages(importBatch);
console.log(`โ
Imported ${importBatch.length} notes`);
}
// Example usage
const existingNotes = [
{
content: "Read about spaced repetition - could apply this to memory management",
category: "learning",
tags: ["spaced-repetition", "memory"],
createdAt: Date.now() - 86400000 * 7, // 1 week ago
},
{
content: "Investigation: How do biological memory systems handle conflicting information?",
category: "research-question",
tags: ["biology", "memory", "conflict-resolution"],
createdAt: Date.now() - 86400000 * 3, // 3 days ago
},
];
await importExistingNotes(existingNotes);
Running the Example
The complete example is available at:
examples/src/tutorials/use-cases/30-personal-memory-assistant.ts
Run it with:
cd /path/to/opencontext/examples
pnpm install
node --experimental-strip-types src/tutorials/use-cases/30-personal-memory-assistant.ts
Expected Output
๐ง Personal Memory Assistant initialized
โ
Stored 2 preferences
โ
Stored 1 note
โ
Updated with new thinking
โ
Added correction
๐ Project Notes:
- Personal knowledge graph should focus on temporal connections...
Category: project-idea, Importance: high
โ๏ธ User Preferences:
- User prefers dark mode in all applications (ui)
- User communicates in English but is learning Spanish (language)
๐ฐ๏ธ My thinking before the update:
- Consider building a personal knowledge graph...
โจ My current thinking:
- The temporal aspect should apply to ALL connections...
๐ฏ Latest understanding:
- Correction: The temporal aspect should apply to ALL connections...
โ
Imported 2 notes
Next Steps
- Customer Support Agent - See how memory scales for multi-user scenarios
- Research Knowledge Tracker - Learn advanced temporal queries for research
- Advanced Usage - Explore multi-source search and platforms
Common Patterns
Searching by Category
const workNotes = await store.search({
userId: "user-123",
query: "work tasks",
metadata: { category: "work" },
});
Finding High-Priority Items
const urgent = await store.search({
userId: "user-123",
query: "important items",
metadata: { importance: "high" },
});
Tracking Evolution
Use the asOf parameter to see how your thinking changed:
const then = await store.search({
userId: "user-123",
query: "my approach",
asOf: thirtyDaysAgo,
});
const now = await store.search({
userId: "user-123",
query: "my approach",
});
Compare the results to see your growth.