Docs/Getting Started

Examples

Real-world examples and patterns for using Recall in production applications.

Chat Applications

Stateful Conversation Management

import { Recall } from '@n3wth/recall';
import OpenAI from 'openai';

class ConversationManager {
private recall: Recall;
private openai: OpenAI;

constructor() {
this.recall = new Recall({
apiKey: process.env.MEM0_API_KEY,
cacheStrategy: 'aggressive'
});

  this.openai = new OpenAI({
    apiKey: process.env.OPENAI_API_KEY
  });

}

async chat(userId: string, message: string) {
// Retrieve conversation context
const memories = await this.recall.search({
query: message,
userId,
limit: 10
});

  // Build contextual prompt
  const context = memories
    .map(m => m.content)
    .join('\n');

  const response = await this.openai.chat.completions.create({
    model: 'gpt-4',
    messages: [
      {
        role: 'system',
        content: `Previous context:\n${context}`
      },
      {
        role: 'user',
        content: message
      }
    ]
  });

  const reply = response.choices[0].message.content;

  // Store the exchange
  await this.recall.add({
    content: `User: ${message}\nAssistant: ${reply}`,
    userId,
    metadata: {
      type: 'conversation',
      timestamp: Date.now()
    }
  });

  return reply;

}
}

Personalization Engine

User Preference Learning

TypeScript
1class PersonalizationEngine {
2 private recall: Recall;
3
4 async learnPreference(userId: string, action: any) {
5 // Extract preference signals
6 const preference = this.extractPreference(action);
7
8 // Check for existing similar preferences
9 const existing = await this.recall.search({
10 query: preference.category,
11 userId,
12 metadata_filter: { type: "preference" },
13 });
14
15 if (existing.length > 0) {
16 // Update existing preference
17 await this.recall.update(existing[0].id, {
18 content: preference.description,
19 metadata: {
20 ...existing[0].metadata,
21 weight: (existing[0].metadata.weight || 1) + 1,
22 last_updated: Date.now(),
23 },
24 });
25 } else {
26 // Add new preference
27 await this.recall.add({
28 content: preference.description,
29 userId,
30 priority: "high",
31 metadata: {
32 type: "preference",
33 category: preference.category,
34 weight: 1,
35 },
36 });
37 }
38 }
39
40 async getRecommendations(userId: string, context: string) {
41 const preferences = await this.recall.search({
42 query: context,
43 userId,
44 metadata_filter: { type: "preference" },
45 });
46
47 // Sort by weight and recency
48 return preferences
49 .sort((a, b) => {
50 const weightDiff = b.metadata.weight - a.metadata.weight;
51 if (weightDiff !== 0) return weightDiff;
52 return b.metadata.last_updated - a.metadata.last_updated;
53 })
54 .slice(0, 5);
55 }
56}

RAG (Retrieval-Augmented Generation)

Document Q&A System

TypeScript
1class DocumentQA {
2 private recall: Recall;
3 private documents: Map<string, string> = new Map();
4
5 async indexDocument(docId: string, content: string) {
6 // Split document into chunks
7 const chunks = this.chunkDocument(content, 500);
8
9 // Store each chunk with metadata
10 for (let i = 0; i < chunks.length; i++) {
11 await this.recall.add({
12 content: chunks[i],
13 userId: "system",
14 metadata: {
15 doc_id: docId,
16 chunk_index: i,
17 total_chunks: chunks.length,
18 type: "document",
19 },
20 });
21 }
22
23 this.documents.set(docId, content);
24 }
25
26 async answer(question: string) {
27 // Search for relevant chunks
28 const relevantChunks = await this.recall.search({
29 query: question,
30 userId: "system",
31 metadata_filter: { type: "document" },
32 limit: 5,
33 });
34
35 // Build context from chunks
36 const context = relevantChunks.map((chunk) => chunk.content).join("\n\n");
37
38 // Generate answer using context
39 return this.generateAnswer(question, context);
40 }
41
42 private chunkDocument(content: string, chunkSize: number): string[] {
43 const words = content.split(" ");
44 const chunks: string[] = [];
45
46 for (let i = 0; i < words.length; i += chunkSize) {
47 chunks.push(words.slice(i, i + chunkSize).join(" "));
48 }
49
50 return chunks;
51 }
52}

Multi-Agent Systems

Agent Memory Sharing

TypeScript
1class AgentMemoryPool {
2 private recall: Recall;
3 private agents: Map<string, Agent> = new Map();
4
5 constructor() {
6 this.recall = new Recall({
7 apiKey: process.env.MEM0_API_KEY,
8 cacheStrategy: "balanced",
9 });
10 }
11
12 async shareMemory(fromAgent: string, toAgent: string, memory: any) {
13 await this.recall.add({
14 content: memory.content,
15 userId: toAgent,
16 metadata: {
17 source_agent: fromAgent,
18 shared_at: Date.now(),
19 visibility: "shared",
20 ...memory.metadata,
21 },
22 });
23 }
24
25 async getSharedMemories(agentId: string) {
26 return await this.recall.search({
27 query: "",
28 userId: agentId,
29 metadata_filter: { visibility: "shared" },
30 });
31 }
32
33 async broadcastMemory(memory: any) {
34 const agents = Array.from(this.agents.keys());
35
36 await Promise.all(
37 agents.map((agentId) =>
38 this.recall.add({
39 content: memory.content,
40 userId: agentId,
41 priority: "high",
42 metadata: {
43 type: "broadcast",
44 timestamp: Date.now(),
45 },
46 }),
47 ),
48 );
49 }
50}

Analytics & Insights

User Behavior Tracking

TypeScript
1class BehaviorAnalytics {
2 private recall: Recall;
3
4 async trackEvent(userId: string, event: any) {
5 await this.recall.add({
6 content: JSON.stringify(event),
7 userId,
8 metadata: {
9 type: "event",
10 category: event.category,
11 action: event.action,
12 timestamp: Date.now(),
13 },
14 });
15 }
16
17 async getUserJourney(userId: string, timeRange: number) {
18 const endTime = Date.now();
19 const startTime = endTime - timeRange;
20
21 const events = await this.recall.search({
22 query: "",
23 userId,
24 metadata_filter: {
25 type: "event",
26 timestamp: { $gte: startTime, $lte: endTime },
27 },
28 limit: 100,
29 });
30
31 return events
32 .sort((a, b) => a.metadata.timestamp - b.metadata.timestamp)
33 .map((e) => JSON.parse(e.content));
34 }
35
36 async getInsights(userId: string) {
37 const journey = await this.getUserJourney(
38 userId,
39 7 * 24 * 60 * 60 * 1000, // Last 7 days
40 );
41
42 return {
43 total_events: journey.length,
44 most_common_action: this.getMostCommon(journey, "action"),
45 peak_activity_hour: this.getPeakHour(journey),
46 engagement_score: this.calculateEngagement(journey),
47 };
48 }
49}

Performance Patterns

Cache Warming

TypeScript
1class CacheWarmer {
2 private recall: Recall;
3
4 async warmCache(userIds: string[]) {
5 const results = await Promise.allSettled(
6 userIds.map(async userId => {
7 // Get user's most accessed memories
8 const memories = await this.recall.get_all_memories({
9 user_id: userId
10 });
11
12 // Sort by access count
13 const topMemories = memories
14 .sort((a, b) => b.access_count - a.access_count)
15 .slice(0, 100);
16
17 // Force cache population
18 return Promise.all(
19 topMemories.map(m =>
20 this.recall.get(m.id)
21 )
22 );
23 })
24 );
25
26 const successful = results.filter(r => r.status === 'fulfilled').length;
27 console.log(\`Warmed cache for \${successful}/\${userIds.length} users\`);
28 }
29
30 async scheduleWarmup() {
31 // Run every 5 minutes
32 setInterval(() => {
33 this.warmActiveUsers();
34 }, 5 * 60 * 1000);
35 }
36
37 private async warmActiveUsers() {
38 // Get active users from your system
39 const activeUsers = await this.getActiveUsers();
40 await this.warmCache(activeUsers);
41 }
42}

Error Handling

Resilient Memory Operations

TypeScript
1class ResilientRecall {
2 private recall: Recall;
3 private fallbackStore: Map<string, any> = new Map();
4
5 async safeAdd(params: any, maxRetries = 3) {
6 for (let i = 0; i < maxRetries; i++) {
7 try {
8 return await this.recall.add(params);
9 } catch (error) {
10 if (i === maxRetries - 1) {
11 // Final attempt failed, use fallback
12 return this.addToFallback(params);
13 }
14
15 // Exponential backoff
16 await this.sleep(Math.pow(2, i) * 1000);
17 }
18 }
19 }
20
21 async safeSearch(params: any) {
22 try {
23 return await this.recall.search(params);
24 } catch (error) {
25 // Try fallback store
26 return this.searchFallback(params);
27 }
28 }
29
30 private addToFallback(params: any) {
31 const id = \`fallback_\${Date.now()}\`;
32 this.fallbackStore.set(id, params);
33
34 // Schedule retry
35 setTimeout(() => {
36 this.syncFallback(id);
37 }, 60000);
38
39 return { id, status: 'fallback' };
40 }
41
42 private async syncFallback(id: string) {
43 const params = this.fallbackStore.get(id);
44 if (!params) return;
45
46 try {
47 await this.recall.add(params);
48 this.fallbackStore.delete(id);
49 } catch (error) {
50 // Retry later
51 setTimeout(() => this.syncFallback(id), 300000);
52 }
53 }
54}

Testing Patterns

Memory Mocking for Tests

TypeScript
1class MockRecall {
2 private memories: Map<string, any> = new Map();
3
4 async add(params: any) {
5 const id = \`mock_\${Date.now()}\`;
6 this.memories.set(id, params);
7 return { id, status: 'completed' };
8 }
9
10 async search(params: any) {
11 const results = Array.from(this.memories.values())
12 .filter(m => m.userId === params.user_id)
13 .filter(m => m.content.includes(params.query))
14 .slice(0, params.limit || 10);
15
16 return {
17 memories: results,
18 source: 'mock'
19 };
20 }
21
22 async clear() {
23 this.memories.clear();
24 }
25}
26
27// Usage in tests
28describe('ConversationManager', () => {
29 let manager: ConversationManager;
30 let mockRecall: MockRecall;
31
32 beforeEach(() => {
33 mockRecall = new MockRecall();
34 manager = new ConversationManager(mockRecall as any);
35 });
36
37 afterEach(() => {
38 mockRecall.clear();
39 });
40
41 it('should remember context', async () => {
42 await manager.chat('user123', 'My name is Alice');
43 const response = await manager.chat('user123', 'What is my name?');
44 expect(response).toContain('Alice');
45 });
46});