Your First Memory
A hands-on tutorial walking through the complete memory lifecycle. You will create a memory, search for it, update it, and delete it -- all with detailed code examples and example responses.
Overview
Every memory in Rekall follows the same lifecycle: Create, Read (search or retrieve), Update, and Delete. This tutorial walks through each operation step by step, using realistic examples.
We will create an episodic memory capturing a user interaction, search for it with natural language, update it with new information, and finally clean it up. By the end, you will understand how memories flow through the system.
Prerequisites
This tutorial assumes you have already installed the SDK and configured your API key. If not, complete the Quickstart first.
Create a Memory
Choosing a Memory Type
Rekall supports 7 memory types. For this tutorial, we will use episodic memory, which captures events with context -- perfect for recording interactions, decisions, and observations. Here is a quick reference for when to use each type:
| Type | Best For |
|---|---|
| episodic | Events, interactions, decisions, observations |
| semantic | Facts, entities, relationships, domain knowledge |
| procedural | Workflows, recipes, step-by-step processes |
| long_term | Consolidated knowledge, accumulated insights |
| short_term | Current session context, working state |
| execution | Agent task state, checkpoints, progress tracking |
| preferences | Learned user preferences and settings |
Create Request
Let's create an episodic memory that records a user conversation where they described their project requirements.
import { RekallClient } from '@rekall/agent-sdk';const rekall = new RekallClient({apiKey: process.env.REKALL_API_KEY,});const memory = await rekall.memories.create({type: 'episodic',content: `User described their project: building a multi-agent system forcustomer support. They need agents to remember conversation history,track open tickets, and learn from resolved issues. The system servesapproximately 10,000 customers and handles 500 tickets per day.`,metadata: {source: 'project-planning-session',userId: 'user_abc123',agentId: 'agent_planner_01',tags: ['project-requirements', 'customer-support', 'multi-agent'],importance: 'high',},context: 'personal',});console.log('Memory created:', memory.id);console.log('Type:', memory.type);console.log('Strength:', memory.strength);
Example response:
{"id": "mem_9c4f2a1e8b3d7f6a5e0c9d8b","type": "episodic","content": "User described their project: building a multi-agent system for customer support...","context": "personal","metadata": {"source": "project-planning-session","userId": "user_abc123","agentId": "agent_planner_01","tags": ["project-requirements", "customer-support", "multi-agent"],"importance": "high"},"strength": 1.0,"embedding": null,"createdAt": "2025-01-15T14:22:00.000Z","updatedAt": "2025-01-15T14:22:00.000Z","lastAccessedAt": "2025-01-15T14:22:00.000Z","accessCount": 0}
Embeddings are generated automatically
You do not need to provide embeddings. Rekall automatically generates vector embeddings from the content using a high-quality embedding model. The embedding field appears as null in the response for brevity, but the vectors are stored and indexed for semantic search.
Search for Memories
Rekall supports two primary search modes: semantic search (natural language queries matched against vector embeddings) and filtered search (using metadata fields, tags, and memory types).
Semantic Search
Search with a natural language query. Rekall converts your query into an embedding and finds the most similar memories using cosine similarity.
const results = await rekall.memories.search({query: 'what are the customer support project requirements?',limit: 5,threshold: 0.7,});for (const result of results) {console.log(`Score: ${result.score.toFixed(3)}`);console.log(`Type: ${result.memory.type}`);console.log(`Content: ${result.memory.content.substring(0, 100)}...`);console.log('---');}
Example response:
{"results": [{"score": 0.952,"memory": {"id": "mem_9c4f2a1e8b3d7f6a5e0c9d8b","type": "episodic","content": "User described their project: building a multi-agent system for customer support...","context": "personal","strength": 1.0,"metadata": {"source": "project-planning-session","tags": ["project-requirements", "customer-support", "multi-agent"]},"createdAt": "2025-01-15T14:22:00.000Z"}}],"total": 1,"query": "what are the customer support project requirements?"}
Filtered Search
Combine semantic search with metadata filters for precise results. You can filter by memory type, tags, date ranges, context, and custom metadata fields.
const results = await rekall.memories.search({query: 'project requirements',type: 'episodic',filters: {tags: { contains: 'customer-support' },'metadata.importance': 'high',createdAfter: '2025-01-01T00:00:00Z',},limit: 10,});console.log(`Found ${results.length} matching memories`);
Update a Memory
Memories evolve as new information becomes available. Rekall supports both partial updates (patch specific fields) and full replacements.
Partial Update
Use a partial update to modify specific fields without affecting others. This is the most common way to update memories -- for example, appending new context or changing tags.
const updated = await rekall.memories.update('mem_9c4f2a1e8b3d7f6a5e0c9d8b',{content: `User described their project: building a multi-agent system forcustomer support. They need agents to remember conversation history,track open tickets, and learn from resolved issues. The system servesapproximately 10,000 customers and handles 500 tickets per day.UPDATE: User confirmed they want to use Rekall for long-term memoryand preferences. Budget approved for Pro plan. Timeline is Q2 launch.`,metadata: {source: 'project-planning-session',userId: 'user_abc123',agentId: 'agent_planner_01',tags: ['project-requirements', 'customer-support', 'multi-agent', 'approved'],importance: 'high',status: 'approved',},});console.log('Updated at:', updated.updatedAt);
Example response:
{"id": "mem_9c4f2a1e8b3d7f6a5e0c9d8b","type": "episodic","content": "User described their project: building a multi-agent system for customer support... UPDATE: User confirmed they want to use Rekall for long-term memory and preferences. Budget approved for Pro plan. Timeline is Q2 launch.","context": "personal","metadata": {"source": "project-planning-session","userId": "user_abc123","agentId": "agent_planner_01","tags": ["project-requirements", "customer-support", "multi-agent", "approved"],"importance": "high","status": "approved"},"strength": 1.0,"createdAt": "2025-01-15T14:22:00.000Z","updatedAt": "2025-01-15T15:45:00.000Z","lastAccessedAt": "2025-01-15T15:45:00.000Z","accessCount": 2}
Re-embedding on content change
When you update a memory's content, Rekall automatically regenerates the vector embedding to reflect the new text. This ensures semantic search results remain accurate after updates. Metadata-only updates do not trigger re-embedding.
Full Replacement
Use a PUT request to completely replace a memory. All fields not included in the request will be reset to their defaults. This is useful when you want to rewrite a memory entirely.
const replaced = await rekall.memories.replace('mem_9c4f2a1e8b3d7f6a5e0c9d8b',{type: 'episodic',content: 'Project requirements finalized: multi-agent customer support system using Rekall. Pro plan approved, Q2 launch target.',metadata: {source: 'project-planning-session',userId: 'user_abc123',tags: ['project-requirements', 'finalized'],status: 'finalized',},context: 'personal',});
PUT replaces the entire memory
A PUT (replace) operation replaces the entire memory object. Any fields you omit will be reset. For most use cases, prefer PATCH (partial update) to avoid accidentally losing metadata.
Delete a Memory
Delete a memory permanently by its ID. This is irreversible -- the memory, its embedding, and all associated metadata will be removed.
await rekall.memories.delete('mem_9c4f2a1e8b3d7f6a5e0c9d8b');console.log('Memory deleted successfully.');// Attempting to retrieve it will throw a 404 errortry {await rekall.memories.get('mem_9c4f2a1e8b3d7f6a5e0c9d8b');} catch (error) {console.log(error.status); // => 404console.log(error.message); // => Memory not found}
Deletion is permanent
There is no undo for memory deletion. If you need to preserve memories for audit purposes, consider using soft-delete by updating the metadata with a deleted: true flag instead. Alternatively, create a snapshot before deleting.
Lifecycle Summary
Here is a recap of the full memory CRUD lifecycle and the corresponding HTTP methods:
| Operation | Method | Endpoint | Description |
|---|---|---|---|
| Create | POST | /v1/memories | Store a new memory with content and metadata |
| Read | GET | /v1/memories/:id | Retrieve a memory by ID (also strengthens it) |
| Search | POST | /v1/memories/search | Semantic or filtered search across memories |
| Update | PATCH | /v1/memories/:id | Partially update specific fields |
| Replace | PUT | /v1/memories/:id | Fully replace a memory |
| Delete | DELETE | /v1/memories/:id | Permanently remove a memory |
Next Steps
You now understand the complete memory lifecycle. Here is where to go deeper:
