# Delete Memory
Source: https://docs.recallrai.com/api-reference/memories/delete-memory
https://api.recallrai.com/api/openapi.json delete /api/v1/users/{custom_user_id}/memory/{memory_id}
Delete any version in the memory version history.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user
- `memory_id` (str): Memory UUID (can be any version in the chain)
**Query Parameters:**
- `delete_previous_versions` (bool): Delete this version + all previous (true) or just this version (false). Default: false
**Returns:**
- HTTP 204 No Content on success
**Deletion Modes:**
**Mode 1: Single Version Deletion (delete_previous_versions=false, default)**
- Deletes only the specified version (can be any version in the chain)
- If deleting latest version: previous version becomes new latest (resurrected)
- If deleting middle version: next version links to previous version (relinks chain)
- If deleting first version with no next: complete deletion
- Connections on latest version are preserved/transferred appropriately
**Mode 2: Delete Version + All Previous (delete_previous_versions=true)**
- Deletes the specified version AND all its previous versions
- If deleting latest: deletes entire history
- If deleting middle version N: deletes N and all versions before it (N-1, N-2, etc.)
- Version N+1 becomes orphaned (prev_version_id = None)
**Examples:**
```
Chain: v1 ← v2 ← v3 ← v4 (latest)
Delete v4 (latest) with delete_previous_versions=false:
Result: v1 ← v2 ← v3 (latest, resurrected)
Delete v2 (middle) with delete_previous_versions=false:
Result: v1 ← v3 ← v4 (latest) [v2 removed from chain]
Delete v2 (middle) with delete_previous_versions=true:
Result: v3 ← v4 (latest) [v1 and v2 deleted, v3 orphaned]
```
# Get Memory
Source: https://docs.recallrai.com/api-reference/memories/get-memory
https://api.recallrai.com/api/openapi.json get /api/v1/users/{custom_user_id}/memory/{memory_id}
Retrieve a specific memory by ID with version history and relationships.
Get complete details for a single memory including its content, categories, version history,
and connected memories. Accepts any version of a memory ID, including older expired versions.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user
- `memory_id` (str): Memory UUID to retrieve
**Query Parameters:**
- `include_previous_versions` (bool): Include full version history for this memory. Default: true
- `include_connected_memories` (bool): Include related memories via relationships. Default: true
**Returns:**
- UserMemoryItem: Complete memory object with all metadata, categories, and optional version/relationship data
# List User Memories
Source: https://docs.recallrai.com/api-reference/memories/list-user-memories
https://api.recallrai.com/api/openapi.json get /api/v1/users/{custom_user_id}/memories
List all memories for a user with version history and relationships.
Retrieve extracted memories with support for category filtering, session filtering, and metadata queries.
Always returns only current (latest) versions of memories. Optionally includes version history
and connected memory relationships.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user
**Query Parameters:**
- `categories` (List[str]): Filter by memory categories. Optional
- `offset` (int): Number of records to skip for pagination. Default: 0
- `limit` (int): Maximum records to return. Range: 1-200. Default: 20
- `session_id_filter` (List[str]): Filter by specific session IDs. Optional
- `session_metadata_filter` (str): JSON string filter for session metadata (supports nested JSON matching). Optional
- `include_previous_versions` (bool): Include full version history for each memory. Default: true
- `include_connected_memories` (bool): Include related memories via relationships. Default: true
**Returns:**
- `items` (List[UserMemoryItem]): List of memory objects with categories, versions, and relationships
- `total` (int): Total number of memories matching the filters
- `has_more` (bool): Whether more memories are available beyond the current page
# Get Merge Conflict
Source: https://docs.recallrai.com/api-reference/merge-conflicts/get-merge-conflict
https://api.recallrai.com/api/openapi.json get /api/v1/users/{custom_user_id}/merge-conflicts/{conflict_id}
Retrieve detailed information about a specific merge conflict.
Get complete details about a memory merge conflict including the proposed memory content,
conflicting existing memories, and clarifying questions to help resolve the conflict.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user owning the merge conflict
- `conflict_id` (UUID): Merge conflict UUID to retrieve
**Returns:**
- `conflict` (MergeConflictInfo): Conflict details with proposed_memory_content, conflicting_memories, clarifying_questions, status, and timestamps
# List Merge Conflicts
Source: https://docs.recallrai.com/api-reference/merge-conflicts/list-merge-conflicts
https://api.recallrai.com/api/openapi.json get /api/v1/users/{custom_user_id}/merge-conflicts
List memory merge conflicts for a user with filtering and sorting.
When the system detects conflicting or contradictory memories, it creates merge conflicts that
require user resolution. This endpoint retrieves all such conflicts with filtering options.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user
**Query Parameters:**
- `offset` (int): Number of records to skip for pagination. Default: 0
- `limit` (int): Maximum records to return. Range: 1-100. Default: 10
- `status` (MemoryMergeConflictStatus): Filter by status (PENDING, PROCESSING, PROCESSED, IN_QUEUE). Optional
- `sort_by` (str): Sort field. Options: created_at, resolved_at. Default: created_at
- `sort_order` (str): Sort order. Options: asc, desc. Default: desc
**Returns:**
- `conflicts` (List[MergeConflictInfo]): List of merge conflicts with clarifying questions and conflicting memory details
- `total` (int): Total number of conflicts matching the filters
- `has_more` (bool): Whether more conflicts are available beyond the current page
# Resolve Merge Conflict
Source: https://docs.recallrai.com/api-reference/merge-conflicts/resolve-merge-conflict
https://api.recallrai.com/api/openapi.json post /api/v1/users/{custom_user_id}/merge-conflicts/{conflict_id}/resolve
Resolve a memory merge conflict by answering clarifying questions.
Submit answers to the AI-generated clarifying questions to resolve memory conflicts.
The system will use your answers to determine how to merge or update the conflicting memories.
After resolution, the conflict status changes to IN_QUEUE for processing.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user owning the merge conflict
- `conflict_id` (UUID): Merge conflict UUID to resolve
**Body Parameters:**
- `answers` (UserResponseMergeConflictQuestionAnswers): List of question-answer pairs matching the clarifying questions
**Returns:**
- `conflict` (MergeConflictInfo): Updated conflict with resolution_data, IN_QUEUE status, and resolved_at timestamp
# Add Message
Source: https://docs.recallrai.com/api-reference/sessions/add-message
https://api.recallrai.com/api/openapi.json post /api/v1/users/{custom_user_id}/sessions/{session_id}/add-message
Add a message to an active session.
Append a new message to the session's conversation history. The session must be in PENDING status.
Adding a message resets the auto-process timer, keeping the session active.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user
- `session_id` (UUID): Session UUID to add message to
**Body Parameters:**
- `message` (str): Message content text
- `role` (str): Message role (user, assistant)
**Returns:**
- `detail` (str): Success confirmation message
# Create Session
Source: https://docs.recallrai.com/api-reference/sessions/create-session
https://api.recallrai.com/api/openapi.json post /api/v1/users/{custom_user_id}/sessions
Create a new conversation session for a user.
Sessions track conversation history and are used for memory extraction. Messages added to a session
will be processed to extract and store long-term memories when the session is finalized.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user
**Body Parameters:**
- `auto_process_after_seconds` (int): Seconds of inactivity before session auto-processes. Must be >= 600. Default: 600
- `metadata` (Dict[str, Any]): Optional JSON metadata to attach to the session
- `custom_created_at_utc` (datetime): Optional custom timestamp for when the session was created. Must be UTC timezone-aware. Useful for benchmarking or importing historical data. Default: current time
**Returns:**
- `session` (SessionInfo): Created session with ID, status, creation timestamp, and metadata
# Delete Session
Source: https://docs.recallrai.com/api-reference/sessions/delete-session
https://api.recallrai.com/api/openapi.json delete /api/v1/users/{custom_user_id}/sessions/{session_id}
Delete a session and all associated data.
Permanently deletes a session along with its messages (from MongoDB), vector embeddings
(from Milvus), and any memories, memory connections, memory categories, and merge conflicts
that were created from this session.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user owning the session
- `session_id` (UUID): Session UUID to delete
**Returns:**
- 204 No Content on success
# Get Context
Source: https://docs.recallrai.com/api-reference/sessions/get-context
https://api.recallrai.com/api/openapi.json get /api/v1/users/{custom_user_id}/sessions/{session_id}/context
Retrieve AI context including relevant memories and recent conversations.
Generate context for LLM prompts by retrieving the most relevant memories and recent messages
for a user. Use this to manually inject memory context into your AI applications.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user
- `session_id` (UUID): Session UUID to get context from
**Query Parameters:**
- `recall_strategy` (RecallStrategy): Memory retrieval strategy. Options: low_latency, balanced, agentic and auto. Default: balanced
- `min_top_k` (int): Minimum number of memories to return. Range: 5-50. Default: 15
- `max_top_k` (int): Maximum number of memories to return. Range: 10-100. Default: 50
- `memories_threshold` (float): Similarity threshold for memories. Range: 0.2-0.8. Default: 0.6
- `summaries_threshold` (float): Similarity threshold for session summaries. Range: 0.2-0.8. Default: 0.5
- `last_n_messages` (int): Number of last messages to include in context. Range: 1-100. Optional
- `last_n_summaries` (int): Number of last summaries to include in context. Range: 1-20. Optional
- `timezone` (str): Timezone for formatting timestamps (e.g., 'America/New_York'). Default: UTC
- `include_system_prompt` (bool): Whether to include the default system prompt. Default: true
- `stream` (bool): Whether to stream status updates via Server-Sent Events. Default: false
**Returns:**
- When `stream=false`: JSON `GetContextResponse` with `is_final=true` and `context` field
- When `stream=true`: SSE stream of `GetContextResponse` events with progress updates, ending with a final event containing the context
# Get Messages
Source: https://docs.recallrai.com/api-reference/sessions/get-messages
https://api.recallrai.com/api/openapi.json get /api/v1/users/{custom_user_id}/sessions/{session_id}/messages
Retrieve all messages from a session conversation.
Get the complete conversation history for a session with pagination support.
Messages are returned in chronological order.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user
- `session_id` (UUID): Session UUID to get messages from
**Query Parameters:**
- `offset` (int): Number of messages to skip for pagination. Default: 0
- `limit` (int): Maximum messages to return. Range: 1-500. Default: 50
**Returns:**
- `messages` (List[Message]): List of message objects with role, content, and timestamp
- `total` (int): Total number of messages in the session
- `has_more` (bool): Whether more messages are available beyond the current page
# Get Session
Source: https://docs.recallrai.com/api-reference/sessions/get-session
https://api.recallrai.com/api/openapi.json get /api/v1/users/{custom_user_id}/sessions/{session_id}
Retrieve a specific session by ID.
Get detailed information about a conversation session including its status, creation time,
and custom metadata.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user
- `session_id` (UUID): Session UUID to retrieve
**Query Parameters:**
- `include_summary` (bool): Whether to include session summary in the response. Default: false
- `include_memories` (bool): Whether to include memories created in this session. Default: false
**Returns:**
- `session` (SessionInfo): Session details with ID, status, creation timestamp, metadata, and optionally summary and memories
# List Sessions
Source: https://docs.recallrai.com/api-reference/sessions/list-sessions
https://api.recallrai.com/api/openapi.json get /api/v1/users/{custom_user_id}/sessions
List all sessions for a user with pagination and filtering.
Retrieve conversation sessions with support for filtering by status and custom metadata.
Results are sorted by creation date (newest first).
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user
**Query Parameters:**
- `offset` (int): Number of records to skip for pagination. Default: 0
- `limit` (int): Maximum records to return. Range: 1-100. Default: 10
- `metadata_filter` (str): JSON string filter for session metadata (supports nested JSON matching)
- `status_filter` (List[ProjectUserSessionStatus]): Filter by session status (pending, processing, processed, insufficient_balance)
- `include_summary` (bool): Whether to include session summaries in the response. Default: false
- `include_memories` (bool): Whether to include memories created in each session. Default: false
**Returns:**
- `sessions` (List[SessionInfo]): List of session objects (optionally with summaries and memories)
- `total` (int): Total number of sessions matching the filters
- `has_more` (bool): Whether more sessions are available beyond the current page
# Process Session
Source: https://docs.recallrai.com/api-reference/sessions/process-session
https://api.recallrai.com/api/openapi.json post /api/v1/users/{custom_user_id}/sessions/{session_id}/process
Manually trigger session processing to extract memories.
Force immediate processing of a session to extract long-term memories from the conversation history.
The session must be in PENDING status. Processing analyzes messages, extracts key facts,
and stores them as searchable memories.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user
- `session_id` (UUID): Session UUID to process
**Returns:**
- `detail` (str): Success confirmation message. Session status changes to PROCESSING, then PROCESSED when complete.
# Update Session
Source: https://docs.recallrai.com/api-reference/sessions/update-session
https://api.recallrai.com/api/openapi.json put /api/v1/users/{custom_user_id}/sessions/{session_id}
Update session metadata.
Replace the entire metadata object for a session. Use this to attach custom attributes
like conversation topics, tags, or application-specific data to your sessions.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user owning the session
- `session_id` (UUID): Session UUID to update
**Body Parameters:**
- `new_metadata` (Dict[str, Any]): New metadata JSON object (replaces existing metadata completely)
**Returns:**
- `session` (SessionInfo): Updated session with new metadata
# Get System Prompt
Source: https://docs.recallrai.com/api-reference/system-prompt/get-system-prompt
https://api.recallrai.com/api/openapi.json get /api/v1/system-prompt
Retrieve the global system prompt used by Recallr AI.
**Headers:**
- `X-Recallr-Project-Id` (UUID): Your project ID.
- `X-Recallr-Api-Key` (str): Your API key.
**Query Parameters:**
- `recall_strategy`: The recall strategy you are using.
**Returns:**
- `system_prompt` (str): The full global system prompt text.
# Create User
Source: https://docs.recallrai.com/api-reference/users/create-user
https://api.recallrai.com/api/openapi.json post /api/v1/users
Create a new user in your project.
Register a new user to start tracking their memories and sessions. Each user is identified
by a unique custom_user_id that you provide from your application.
**Body Parameters:**
- `custom_user_id` (str): Your unique identifier for this user
- `metadata` (Dict[str, Any]): Optional JSON metadata to attach (e.g., name, email, preferences)
**Returns:**
- `user` (UserInfo): Created user object with custom_user_id, metadata, and timestamps
# Delete User
Source: https://docs.recallrai.com/api-reference/users/delete-user
https://api.recallrai.com/api/openapi.json delete /api/v1/users/{custom_user_id}
Permanently delete a user and all associated data.
Remove a user from your project. This deletes all their sessions, messages, memories, and related data.
This action cannot be undone.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user to delete
**Returns:**
- HTTP 204 No Content on success
# Get User
Source: https://docs.recallrai.com/api-reference/users/get-user
https://api.recallrai.com/api/openapi.json get /api/v1/users/{custom_user_id}
Retrieve detailed information for a specific user.
Get user profile including metadata, creation date, and last activity timestamp.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user
**Returns:**
- `user` (UserInfo): User object with custom_user_id, metadata, created_at, and last_active_at
# Get User Messages
Source: https://docs.recallrai.com/api-reference/users/get-user-messages
https://api.recallrai.com/api/openapi.json get /api/v1/users/{custom_user_id}/messages
Get recent conversation messages across all user sessions.
Retrieve the most recent N messages for a user from across all their sessions, sorted chronologically.
Useful for displaying conversation history or providing chat context.
**Path Parameters:**
- `custom_user_id` (str): Unique identifier for the user
**Query Parameters:**
- `limit` (int): Number of recent messages to retrieve. Range: 1-100. Default: 10
**Returns:**
- `messages` (List[UserMessage]): List of message objects with role, content, timestamp, and session_id
# List Users
Source: https://docs.recallrai.com/api-reference/users/list-users
https://api.recallrai.com/api/openapi.json get /api/v1/users
List all users in your project with pagination and filtering.
Retrieve all registered users with support for metadata-based filtering and partial user ID search.
Results include user activity timestamps and custom metadata.
**Query Parameters:**
- `offset` (int): Number of records to skip for pagination. Default: 0
- `limit` (int): Maximum records to return. Range: 1-100. Default: 10
- `metadata_filter` (str): JSON string filter for user metadata (supports nested JSON matching)
- `partial_user_id` (str): Partial user ID to search for (case-insensitive)
**Returns:**
- `users` (List[UserInfo]): List of user objects
- `total` (int): Total number of users matching the filters
- `has_more` (bool): Whether more users are available beyond the current page
# Update User
Source: https://docs.recallrai.com/api-reference/users/update-user
https://api.recallrai.com/api/openapi.json put /api/v1/users/{custom_user_id}
Update user metadata or change user identifier.
Modify user attributes including custom metadata and the custom_user_id itself. When changing
the custom_user_id, the new ID must not already exist in the project.
**Path Parameters:**
- `custom_user_id` (str): Current unique identifier for the user
**Body Parameters:**
- `new_custom_user_id` (str): New user identifier to replace current one. Optional
- `new_metadata` (Dict[str, Any]): New metadata JSON object to replace current metadata. Optional
**Returns:**
- `user` (UserInfo): Updated user object with new values
# Memories
Source: https://docs.recallrai.com/concepts/memories
Understanding memories - the extracted facts and knowledge from conversations
## What are Memories?
Memories are the facts, preferences, and knowledge that Recallr automatically extracts from your conversations. Think of them as the key takeaways from each session - the important information worth remembering for future interactions.
## Memory Categories
Memory categories help you organize and filter memories based on their type or domain. Categories make it easier to retrieve relevant memories and maintain clean, structured knowledge about your users.
### Managing Categories
Categories are configured through the [Recallr Dashboard](https://app.recallrai.com) for each project. You can create custom categories that match your application's needs.
Navigate to your project settings in the Recallr Dashboard.
Add a new category with a descriptive name and optional description.
Use descriptive, lowercase names with underscores (e.g., `food_preferences`, `medical_history`).
Optional description explaining what this category contains.
Once created, Recallr will automatically assign memories to appropriate categories during extraction, and you can filter memories by category when retrieving them.
Create categories that align with your application's domain. For a healthcare app, you might use categories like `medical_history`, `medications`, and `allergies`. For an e-commerce app, consider `product_preferences`, `shopping_habits`, and `size_information`.
**Important category considerations:**
* Deleting a category does not delete memories - existing memories will remain in the system but will no longer be associated with that category
* Categories are not retroactive - only new memories extracted after a category is created will be assigned to it. Existing memories will not be automatically recategorized
## Customizing Memory Extraction
Recallr provides powerful customization options to tailor the memory extraction process to your specific needs. Configure these settings through the **Dashboard** to control how memories are generated from conversations.
### Generation Preferences
Custom instructions to guide what aspects should be included in generated memories.
List of specific instructions to emphasize certain aspects during memory extraction.
```json theme={null}
[
"Always capture specific product names and brands mentioned",
"Include temporal context for events (when something happened)",
"Extract numerical measurements and quantities precisely"
]
```
Examples of well-formatted, high-quality memories to guide the extraction model.
Short examples demonstrating the desired memory format and content.
```json theme={null}
[
"User prefers Nike running shoes in size 10",
"User's birthday is March 15, 1990",
"User works as a software engineer at TechCorp since 2020"
]
```
Provide 3-5 positive examples that represent the ideal structure and detail level for your use case.
Instructions to prevent certain types of information from being stored as memories.
Specific guidelines for what to avoid capturing as memories.
```json theme={null}
[
"Do not store temporary session-specific information",
"Exclude casual greetings and pleasantries",
"Ignore hypothetical scenarios or 'what-if' discussions"
]
```
Use exclusion instructions to avoid storing sensitive information, temporary data, or noise that doesn't provide long-term value.
Examples of poor-quality memories that should be avoided.
Short examples showing what NOT to extract as memories.
```json theme={null}
[
"User said hello",
"The weather was discussed",
"User asked a question"
]
```
Memories that were incorrectly extracted when they shouldn't have been (actual negative, predicted positive).
Examples where the system incorrectly created a memory. Use these to fine-tune extraction precision.
Help the model learn from past mistakes by showing examples of information that was extracted but shouldn't have been.
Important information that was missed during extraction (actual positive, predicted negative).
Examples where the system failed to create a memory that should have been created. Use these to improve extraction recall.
Teach the model to catch important information it previously missed.
Control how Recallr checks for redundant memories during generation.
Number of existing memories to check for similarity before creating a new memory. Range: 10-50.
Higher values provide more thorough redundancy checking but increase processing time.
Recallr uses LLM-based similarity checking to avoid creating duplicate or highly similar memories. This parameter controls how many existing memories are evaluated for each new memory candidate.
Configure whether the system should raise merge conflicts for ambiguous situations.
When `true`, Recallr will create merge conflicts when it detects potentially contradictory or ambiguous information. When `false`, it will automatically resolve conflicts using its best judgment.
Enable merge conflicts for critical applications where you need human review of ambiguous updates. Disable for faster processing when automated resolution is acceptable.
## Customizing Memory Recall
The recall system determines which memories are retrieved when you call `getContext()`. Customize recall behavior through the **Dashboard** to optimize for your specific use case.
### Recall Strategies
Recallr offers three recall strategies with different performance characteristics:
Fastest retrieval with basic semantic search. Best for real-time applications where speed is critical.
Combines multiple retrieval techniques for better accuracy with reasonable performance. **Recommended for most use cases.**
Most comprehensive search using subqueries, keywords, and semantic similarity. Best when accuracy is paramount.
### Recall Preferences
Configure these settings for **Balanced** and **Agentic** recall strategies:
Guide the subquery and keyword generation process with specific instructions.
Instructions to help generate better search queries and keywords from user messages.
```json theme={null}
[
"Focus on extracting the user's intent and goal",
"Include domain-specific terminology in keywords",
"Consider temporal context when generating subqueries"
]
```
Control how subquery-based recall contributes to memory retrieval.
Weight for memories retrieved via subquery matching. Range: 0.0-1.0.
Higher values give more importance to memories found through generated subqueries.
Example subqueries to guide the generation process.
```json theme={null}
[
"What are the user's dietary restrictions?",
"Has the user mentioned any health conditions?",
"What products has the user purchased before?"
]
```
Control how keyword-based recall contributes to memory retrieval.
Weight for memories retrieved via keyword matching. Range: 0.0-1.0.
Higher values give more importance to memories found through keyword extraction.
Example keywords to guide the extraction process.
```json theme={null}
[
"allergy, peanuts, shellfish",
"preference, vegetarian, organic",
"medical, diabetes, medication"
]
```
Guide how the system generates questions for searching session summaries.
Example questions that help retrieve relevant session summaries.
```json theme={null}
[
"What did the user say about their preferences?",
"What problems or issues has the user mentioned?",
"What are the user's goals and objectives?"
]
```
Fine-tune recall weights based on your testing. Start with equal weights (0.5 for both subqueries and keywords) and adjust based on which retrieval method performs better for your use case.
## Memory Versioning
Recallr maintains a complete version history for each memory, allowing you to track how information evolves over time and understand why changes occurred.
### How Versioning Works
When information about a user is updated, Recallr doesn't simply overwrite the old memory. Instead, it creates a new version and preserves the previous one with metadata explaining why it changed.
First version is created during session processing.
```
Version 1: "User prefers contact by email"
Created: 2024-01-15 10:00:00
Status: Current
```
During a later session, contradictory or updated information appears.
```
User: "Actually, I prefer text messages now instead of email"
```
Recallr creates version 2 and expires version 1.
```
Version 1: "User prefers contact by email"
Created: 2024-01-15 10:00:00
Expired: 2024-02-20 14:30:00
Expiration Reason: "updated"
Version 2: "User prefers contact by text message"
Created: 2024-02-20 14:30:00
Status: Current
```
### Version Creation Reasons
Each memory version includes an `expiration_reason` field that explains why a new version was created:
Indicates why this version was superseded by a new one.
**`updated`**\
The memory was updated with new information that supersedes the old content. This is the most common reason - used when user preferences change, facts are corrected, or information is refined.
* "User prefers tea" -> "User prefers coffee now"
* "User lives in New York" -> "User moved to San Francisco"
**`merged`**\
Multiple related memories were combined into a single, more comprehensive memory during a merge conflict resolution or deduplication process.
* "User likes Italian food" + "User enjoys pasta dishes" -> "User enjoys Italian cuisine, especially pasta"
**`invalidated`**\
The memory was determined to be incorrect, outdated, or no longer relevant based on new information.
* "User is planning a trip to Japan" (invalidated after trip completed)
* "User is interested in buying a car" (invalidated after purchase)
**`conflict_resolved`**\
A new version was created as the result of resolving a merge conflict, where multiple contradictory pieces of information were reconciled.
**`system_correction`**\
The memory was automatically corrected by the system due to detected errors or inconsistencies in the extraction process.
### Accessing Version History
```python theme={null}
from recallrai import RecallrAI
client = RecallrAI(api_key="rai_yourapikey", project_id="your-project-id")
user = client.get_user("user123")
# Retrieve memories with full version history
memories = user.list_memories(
include_previous_versions=True,
limit=20
)
for memory in memories.items:
print(f"Current Memory: {memory.content}")
print(f"Version {memory.version_number} of {memory.total_versions}")
# Access version history
if memory.previous_versions:
print("\nVersion History:")
for version in memory.previous_versions:
print(f" Version {version.version_number}:")
print(f" Content: {version.content}")
print(f" Created: {version.created_at}")
print(f" Expired: {version.expired_at}")
print(f" Reason: {version.expiration_reason}")
```
```typescript theme={null}
import { RecallrAI } from "recallrai";
const client = new RecallrAI({
apiKey: "rai_yourapikey",
projectId: "your-project-id",
});
const user = await client.getUser("user123");
// Retrieve memories with full version history
const memories = await user.listMemories({
includePreviousVersions: true,
limit: 20,
});
for (const memory of memories.items) {
console.log(`Current Memory: ${memory.content}`);
console.log(`Version ${memory.versionNumber} of ${memory.totalVersions}`);
// Access version history
if (memory.previousVersions) {
console.log("\nVersion History:");
for (const version of memory.previousVersions) {
console.log(` Version ${version.versionNumber}:`);
console.log(` Content: ${version.content}`);
console.log(` Created: ${version.createdAt}`);
console.log(` Expired: ${version.expiredAt}`);
console.log(` Reason: ${version.expirationReason}`);
}
}
}
```
Version history is included by default when listing memories. Set `include_previous_versions=False` (Python) or `includePreviousVersions: false` (Node.js) to retrieve only current versions for improved performance.
### Benefits of Versioning
Track how user information changes over time with complete history and reasons for each change.
Understand the context of merge conflicts by reviewing what information existed before the contradiction emerged.
Access previous versions if new information turns out to be incorrect or if you need to analyze past states.
Investigate issues in memory extraction by examining the full evolution of a memory and why versions changed.
Memory versions are immutable once created. While you can see the full history, individual versions cannot be modified or deleted - only new versions can be created.
# Core Concepts Overview
Source: https://docs.recallrai.com/concepts/overview
Understand the fundamental building blocks of Recallr AI
## Understanding Recallr AI
Recallr AI is built around a few core concepts that work together to provide persistent memory for AI applications. This page introduces these concepts and shows how they relate to each other.
## The Four Main Components
Individual people using your application, each with isolated memory
Conversations or interactions that contain messages
Extracted facts and knowledge stored long-term
Intelligent handling of contradictory information
## How They Work Together
Think of Recallr AI like a personal assistant's notebook:
```mermaid theme={null}
graph TB
A[User] --> B[Has Many Sessions]
B --> C[Session 1: Monday Chat]
B --> D[Session 2: Wednesday Chat]
B --> E[Session 3: Friday Chat]
C --> F[Process]
D --> F
E --> F
F --> G[Memories Extracted]
G --> H[User Memory Graph]
H --> I[Used for Future Context]
```
Each individual using your app (customer, player, student, etc.) is a **User**. They have:
* A unique ID (you provide this)
* Metadata (name, email, preferences, etc.)
* A collection of memories (automatically extracted from conversation **sessions**)
* Can have multiple sessions over time
When a User interacts with your app, it happens in a **Session**. A session:
* Contains messages (back-and-forth dialogue)
* Has a status (pending, processing, processed)
* Will be processed to extract memories
* Represents one conversation or interaction
When you process a session, Recallr AI analyzes the conversation and creates **Memories**:
* Structured facts about the user
* Categorized automatically
* Versioned (track changes over time)
* Semantically searchable
Sometimes new information conflicts with existing memories, creating **Merge Conflicts**:
* Detect contradictions automatically (e.g., "I love coffee" vs. "I hate coffee")
* **Disabled by default** - must be enabled in project settings
* When enabled, generates clarifying questions sent via webhooks
* You provide answers to resolve conflicts and update memories
* Preserves accuracy by requiring human clarification for contradictions
## Real-World Analogy
Imagine you're a human assistant taking notes about your clients:
| Recallr AI Concept | Real-World Equivalent |
| ------------------ | ---------------------------------------------------------------- |
| **User** | A specific client you work with |
| **Session** | One meeting or phone call with that client |
| **Messages** | The back-and-forth conversation during the meeting |
| **Memories** | Important facts you write in your notebook about the client |
| **Merge Conflict** | When the client says something that contradicts your notes |
| **Process** | After the meeting, reviewing your notes and updating them |
| **Get Context** | Before a meeting, reviewing your notes to remember what you know |
## FAQs
### Users
Create a user when:
* A new person signs up for your app
* A first-time visitor starts a conversation
* You need to track someone's preferences
Example: E-commerce customer, game player, student
Good user IDs are:
* Unique and stable (don't change over time)
* From your existing system (database ID, email, UUID)
* Easy to retrieve when needed
✅ Good: `user_12345`, `john@example.com`, `player_uuid_...`
❌ Bad: Changing usernames, timestamps, random numbers
### Sessions
Start a session when:
* User opens a chat window
* User begins a new conversation
* Significant time has passed since last interaction
Example: New customer support ticket, new game level, new tutoring session
Process a session when:
* Chat window is closed
* Extended period of inactivity
### Memories
Recallr AI automatically extracts:
* User preferences and dislikes
* Personal information shared
* Goals and plans
* Factual statements about the user
* Important context from conversations
Example memories:
* "User's birthday is March 15th"
* "User is learning Python"
...
### Merge Conflicts
Conflicts occur when:
* New information contradicts existing memories
* User changes their mind or preferences
* Ambiguous or unclear statements are made
**Example conflict:**
* Existing memory: "User is vegetarian"
* New message: "I ate chicken last night"
* -> Merge Conflict created!
Conflicts are resolved through webhook notifications:
1. **Enable merge conflicts** in your project settings
2. **Add webhook URL** to receive conflict events
3. **Receive webhook** with conflict details and clarifying questions
4. **Provide answers** via API to resolve the conflict
5. **Memories update** automatically based on your answers
See the [Merge Conflicts guide](/concepts/merge-conflicts) for implementation details.
Merge conflicts require webhook setup and human intervention, so they're disabled by default to:
* Keep the default experience simple
* Avoid overwhelming new users with complexity
* Allow gradual adoption as your use case requires it
Enable them when accuracy is critical and you can handle webhook responses.
## Architecture Diagram
Here's how data flows through Recallr AI:
```mermaid theme={null}
sequenceDiagram
participant App as Your Application
participant SDK as Recallr AI SDK
participant API as Recallr AI API
participant LLM as Your LLM
App->>SDK: Create user
SDK->>API: POST /users
API-->>SDK: User created
App->>SDK: Start session
SDK->>API: POST /sessions
API-->>SDK: Session created
App->>SDK: Add message
SDK->>API: POST /messages
App->>SDK: Get context
SDK->>API: GET /context
API-->>SDK: Relevant memories
SDK-->>App: Context text
App->>LLM: Generate response with context
LLM-->>App: Personalized response
App->>SDK: Process session
SDK->>API: POST /process
API-->>SDK: Memories extracted
```
## Next Steps
Now that you understand the core concepts, dive deeper into each component:
Learn about user management and metadata
Understand session lifecycle and states
Explore memory structure and versioning
Handle contradictory information
Optimize memory retrieval
Get notified of events
# Anthropic Integration
Source: https://docs.recallrai.com/integrations/anthropic
Add persistent memory to your Anthropic Claude applications using Recallr's forward proxy
Recallr seamlessly integrates with Anthropic by acting as a forward proxy. Simply point your Anthropic client to our base URL and we'll inject relevant context from user memory into each request.
## Quick Start
```python theme={null}
from anthropic import Anthropic
client = Anthropic(
base_url='https://api.recallrai.com/api/v1/forward/https://api.anthropic.com',
api_key='sk-ant-...', # Your Anthropic API key
default_headers={
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'your-project-id',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600', # Optional
}
)
# Use normally - memory is automatically injected
response = client.messages.create(
model="claude-4-5-sonnet",
messages=[{"role": "user", "content": "My name is Alice"}],
extra_headers={
'X-Recallr-User-Id': 'alice-123',
'X-Recallr-Recall-Strategy': 'low_latency', # Optional
}
)
print(response.content[0].text)
```
## Supported APIs
Anthropic's Messages API with streaming and non-streaming support
## Required Headers
These headers must be included with every request:
Your Recallr API key. Get it from the [dashboard](https://app.recallrai.com).
Your Recallr Project ID. Get it from the [dashboard](https://app.recallrai.com).
Unique identifier for the user. Used to maintain separate memory graphs per user.
Can also be passed as `user` field in the request body for OpenAI compatibility.
## Optional Headers
### Session Management
Automatically create a new user if the specified User-ID doesn't exist. Set to `true` to avoid errors for new users.
Inactivity period (in seconds) before creating a new session. Minimum value is 600 (10 minutes).
Messages within a session are always passed directly to the LLM. Only memories from previous sessions are retrieved and injected as context.
### Recall Configuration
Controls the recall method used for retrieving memories. Affects latency and accuracy.
**Best for:** Voice agents and real-time applications
* Fastest response time
* Retrieves more memories to compensate for reduced accuracy
* Use when sub-second latency is critical
**Best for:** Standard chatbots and applications
* Good balance between speed and accuracy
* Default strategy for most use cases
* Recommended for general applications
**Best for:** Complex queries requiring comprehensive context
* Runs agents to browse the knowledge graph
* Most accurate but slowest
* Use for questions like "What do you know about my preferences?"
Minimum number of memories to retrieve from the knowledge graph.
Maximum number of memories to retrieve from the knowledge graph.
Similarity threshold for retrieving individual memories (0.0 to 1.0). Lower values retrieve more memories.
Similarity threshold for retrieving session summaries (0.0 to 1.0). Lower values retrieve more summaries.
Include last N messages from past sessions when building context.
Include last N session summaries when building context.
User's timezone for formatting timestamps in memory context (e.g., "America/New\_York", "Europe/London"). Defaults to UTC if not specified.
Providing the user's timezone improves temporal context by showing memories with locally-formatted timestamps.
Whether to include Recallr AI's system prompt (\~ 3k tokens) in the context. This prompt includes instructions for how to use the injected memories. Set to `false` if you already have those instructions in your system prompt.
## Response Headers
Recallr returns these headers in the response for debugging and session tracking:
The internal session ID used by Recallr. Use this to continue the same session in future requests.
Unique identifier for the user. Matches the `X-Recallr-User-Id` sent in the request.
Unique identifier for this request. Use for debugging and tracing.
Time taken to process the request on Recallr's side (in milliseconds).
## Examples
### Messages API - Non-Streaming
```python Python theme={null}
from anthropic import Anthropic
client = Anthropic(
base_url='https://api.recallrai.com/api/v1/forward/https://api.anthropic.com',
api_key='sk-ant-...', # Your Anthropic API key
default_headers={
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'project-id',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600', # Optional
}
)
response = client.messages.with_raw_response.create(
model="claude-4-5-sonnet",
system="You are a helpful assistant.",
messages=[
{"role": "user", "content": "My name is Alice and I love Python programming."}
],
extra_headers={
'X-Recallr-User-Id': 'alice-123',
'X-Recallr-Recall-Strategy': 'low_latency', # Optional
}
)
# Access headers
session_id = raw_response.headers.get('X-Recallr-Session-Id')
request_id = raw_response.headers.get('X-Recallr-Request-Id')
# Parse response
response = raw_response.parse()
print(response.content[0].text)
```
```javascript Node.js theme={null}
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
baseURL: 'https://api.recallrai.com/api/v1/forward/https://api.anthropic.com',
apiKey: 'sk-ant-...', // Your Anthropic API key
defaultHeaders: {
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'project-id',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600', // Optional
},
});
const response = await client.messages.create({
model: 'claude-4-5-sonnet',
system: 'You are a helpful assistant.',
messages: [
{ role: 'user', content: 'My name is Alice and I love Python programming.' }
],
extraHeaders: {
'X-Recallr-User-Id': 'alice-123',
'X-Recallr-Recall-Strategy': 'low_latency', // Optional
}
});
console.log(response.content[0].text);
```
### Messages API - Streaming
```python Python theme={null}
from anthropic import Anthropic
client = Anthropic(
base_url='https://api.recallrai.com/api/v1/forward/https://api.anthropic.com',
api_key='sk-ant-...', # Your Anthropic API key
default_headers={
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'project-id',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600', # Optional
}
)
with client.messages.stream(
model="claude-4-5-sonnet",
system="You are a helpful assistant.",
messages=[
{"role": "user", "content": "What do you know about me and my interests?"}
],
extra_headers={
'X-Recallr-User-Id': 'alice-123',
'X-Recallr-Recall-Strategy': 'low_latency', # Optional
}
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
```
```javascript Node.js theme={null}
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
baseURL: 'https://api.recallrai.com/api/v1/forward/https://api.anthropic.com',
apiKey: 'sk-ant-...', // Your Anthropic API key
defaultHeaders: {
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'project-id',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600', // Optional
},
});
const stream = client.messages.stream({
model: 'claude-4-5-sonnet',
system: 'You are a helpful assistant.',
messages: [
{ role: 'user', content: 'What do you know about me and my interests?' }
],
});
for await (const chunk of stream) {
if (chunk.type === 'content_block_delta' && chunk.delta?.type === 'text_delta') {
process.stdout.write(chunk.delta.text);
}
}
```
## How It Works
```mermaid theme={null}
sequenceDiagram
participant Client
participant Recallr
participant Anthropic
Client->>Recallr: Request with X-Recallr headers
Recallr->>Recallr: Validate API Key + Project ID
Recallr->>Recallr: Resolve User ID (create if allowed)
Recallr->>Recallr: Retrieve relevant memories from knowledge graph
Recallr->>Recallr: Inject context into request
Recallr->>Anthropic: Forward enhanced request
Anthropic->>Recallr: Response stream
Recallr->>Recallr: Store conversation in knowledge graph
Recallr->>Client: Return response with Recallr headers
```
Contact our support team for assistance with Anthropic integration
# Google Gemini Integration
Source: https://docs.recallrai.com/integrations/gemini
Add persistent memory to your Google Gemini applications using Recallr's forward proxy
Recallr seamlessly integrates with Google Gemini by acting as a forward proxy. Configure your Gemini client to use our proxy URL and we'll inject relevant context from user memory into each request.
## Quick Start
```python theme={null}
from google import genai
from google.genai import types
client = genai.Client(
api_key='YOUR_GEMINI_API_KEY', # Your Google Gemini API key
http_options={
'api_version': 'v1beta',
'base_url': 'https://api.recallrai.com/api/v1/forward/https://generativelanguage.googleapis.com',
'headers': {
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'your-project-id',
'X-Recallr-User-Id': 'user-123',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600',
'X-Recallr-Recall-Strategy': 'low_latency', # Optional
}
}
)
# Use normally - memory is automatically injected
response = client.models.generate_content(
model='gemini-2.5-pro',
contents='My name is Alice',
config=types.GenerateContentConfig(
system_instruction='You are a helpful assistant.',
)
)
print(response.text)
```
## Supported APIs
Standard text generation with non-streaming support
Real-time streaming responses for interactive experiences
## Required Headers
These headers must be included via the `http_options` configuration:
Your Recallr API key. Get it from the [dashboard](https://app.recallrai.com).
Your Recallr Project ID. Get it from the [dashboard](https://app.recallrai.com).
Unique identifier for the user. Used to maintain separate memory graphs per user.
Must be passed in the headers configuration when initializing the Gemini client.
## Optional Headers
### Session Management
Automatically create a new user if the specified User-ID doesn't exist. Set to `true` to avoid errors for new users.
Inactivity period (in seconds) before creating a new session. Minimum value is 600 (10 minutes).
Messages within a session are always passed directly to the LLM. Only memories from previous sessions are retrieved and injected as context.
### Recall Configuration
Controls the recall method used for retrieving memories. Affects latency and accuracy.
**Best for:** Voice agents and real-time applications
* Fastest response time
* Retrieves more memories to compensate for reduced accuracy
* Use when sub-second latency is critical
**Best for:** Standard chatbots and applications
* Good balance between speed and accuracy
* Default strategy for most use cases
* Recommended for general applications
**Best for:** Complex queries requiring comprehensive context
* Runs agents to browse the knowledge graph
* Most accurate but slowest
* Use for questions like "What do you know about my preferences?"
Minimum number of memories to retrieve from the knowledge graph.
Maximum number of memories to retrieve from the knowledge graph.
Similarity threshold for retrieving individual memories (0.0 to 1.0). Lower values retrieve more memories.
Similarity threshold for retrieving session summaries (0.0 to 1.0). Lower values retrieve more summaries.
Include last N messages from past sessions when building context.
Include last N session summaries when building context.
User's timezone for formatting timestamps in memory context (e.g., "America/New\_York", "Europe/London"). Defaults to UTC if not specified.
Providing the user's timezone improves temporal context by showing memories with locally-formatted timestamps.
Whether to include Recallr AI's system prompt (\~ 3k tokens) in the context. This prompt includes instructions for how to use the injected memories. Set to `false` if you already have those instructions in your system prompt.
## Response Headers
Recallr returns these headers in the response for debugging and session tracking:
The internal session ID used by Recallr. Use this to continue the same session in future requests.
Unique identifier for the user. Matches the `X-Recallr-User-Id` sent in the request.
Unique identifier for this request. Use for debugging and tracing.
Time taken to process the request on Recallr's side (in milliseconds).
## Examples
### Generate Content - Non-Streaming
```python Python theme={null}
from google import genai
from google.genai import types
client = genai.Client(
api_key='YOUR_GEMINI_API_KEY', # Your Google Gemini API key
http_options={
'api_version': 'v1beta',
'base_url': 'https://api.recallrai.com/api/v1/forward/https://generativelanguage.googleapis.com',
'headers': {
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'project-id',
'X-Recallr-User-Id': 'alice-123',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600',
'X-Recallr-Recall-Strategy': 'low_latency', # Optional
}
}
)
# Store user information in memory
response = client.models.generate_content(
model='gemini-2.5-pro',
contents='My name is Alice and I love Python programming.',
config=types.GenerateContentConfig(
system_instruction='You are a helpful assistant.',
)
)
print(response.text)
```
```javascript Node.js theme={null}
import { GoogleGenAI } from '@google/genai';
// Create custom fetch to proxy through RecallrAI
const createRecallrFetch = (recallrConfig) => {
return async (url, options = {}) => {
const proxiedUrl = url.replace(
'https://generativelanguage.googleapis.com',
'https://api.recallrai.com/api/v1/forward/https://generativelanguage.googleapis.com'
);
const headers = {
...options.headers,
'X-Recallr-API-Key': recallrConfig.apiKey,
'X-Recallr-Project-Id': recallrConfig.projectId,
'X-Recallr-User-Id': recallrConfig.userId,
'X-Recallr-Allow-New-User-Creation': recallrConfig.allowNewUserCreation || 'true',
'X-Recallr-Session-Timeout-Seconds': recallrConfig.sessionTimeout || '600',
};
if (recallrConfig.recallStrategy) {
headers['X-Recallr-Recall-Strategy'] = recallrConfig.recallStrategy;
}
return fetch(proxiedUrl, { ...options, headers });
};
};
// Initialize with RecallrAI proxy
const customFetch = createRecallrFetch({
apiKey: 'rai-...',
projectId: 'project-id',
userId: 'alice-123',
recallStrategy: 'low_latency', // Optional
});
const ai = new GoogleGenAI({
apiKey: 'YOUR_GEMINI_API_KEY', // Your Google Gemini API key
fetch: customFetch,
});
// Store user information in memory
const response = await ai.models.generateContent({
model: 'gemini-2.5-pro',
contents: 'My name is Alice and I love Python programming.',
config: {
systemInstruction: 'You are a helpful assistant.',
}
});
console.log(response.text);
```
### Generate Content - Streaming
```python Python theme={null}
from google import genai
from google.genai import types
client = genai.Client(
api_key='YOUR_GEMINI_API_KEY', # Your Google Gemini API key
http_options={
'api_version': 'v1beta',
'base_url': 'https://api.recallrai.com/api/v1/forward/https://generativelanguage.googleapis.com',
'headers': {
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'project-id',
'X-Recallr-User-Id': 'alice-123',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600',
'X-Recallr-Recall-Strategy': 'low_latency', # Optional
}
}
)
# Recall stored information about the user with streaming
response = client.models.generate_content_stream(
model='gemini-2.5-pro',
contents='What do you know about me and my interests?',
config=types.GenerateContentConfig(
system_instruction='You are a helpful assistant.',
)
)
for chunk in response:
if chunk.text:
print(chunk.text, end='', flush=True)
```
```javascript Node.js theme={null}
import { GoogleGenAI } from '@google/genai';
// Create custom fetch to proxy through RecallrAI
const createRecallrFetch = (recallrConfig) => {
return async (url, options = {}) => {
const proxiedUrl = url.replace(
'https://generativelanguage.googleapis.com',
'https://api.recallrai.com/api/v1/forward/https://generativelanguage.googleapis.com'
);
const headers = {
...options.headers,
'X-Recallr-API-Key': recallrConfig.apiKey,
'X-Recallr-Project-Id': recallrConfig.projectId,
'X-Recallr-User-Id': recallrConfig.userId,
'X-Recallr-Allow-New-User-Creation': recallrConfig.allowNewUserCreation || 'true',
'X-Recallr-Session-Timeout-Seconds': recallrConfig.sessionTimeout || '600',
};
if (recallrConfig.recallStrategy) {
headers['X-Recallr-Recall-Strategy'] = recallrConfig.recallStrategy;
}
return fetch(proxiedUrl, { ...options, headers });
};
};
// Initialize with RecallrAI proxy
const customFetch = createRecallrFetch({
apiKey: 'rai-...',
projectId: 'project-id',
userId: 'alice-123',
recallStrategy: 'low_latency', // Optional
});
const ai = new GoogleGenAI({
apiKey: 'YOUR_GEMINI_API_KEY', // Your Google Gemini API key
fetch: customFetch,
});
// Recall stored information about the user with streaming
const response = await ai.models.generateContentStream({
model: 'gemini-2.5-pro',
contents: 'What do you know about me and my interests?',
config: {
systemInstruction: 'You are a helpful assistant.',
}
});
for await (const chunk of response) {
if (chunk.text) {
process.stdout.write(chunk.text);
}
}
```
## How It Works
```mermaid theme={null}
sequenceDiagram
participant Client
participant Recallr
participant Gemini
Client->>Recallr: Request with X-Recallr headers
Recallr->>Recallr: Validate API Key + Project ID
Recallr->>Recallr: Resolve User ID (create if allowed)
Recallr->>Recallr: Retrieve relevant memories from knowledge graph
Recallr->>Recallr: Inject context into request
Recallr->>Gemini: Forward enhanced request
Gemini->>Recallr: Response stream
Recallr->>Recallr: Store conversation in knowledge graph
Recallr->>Client: Return response with Recallr headers
```
Contact our support team for assistance with Gemini integration
# OpenAI Integration
Source: https://docs.recallrai.com/integrations/openai
Add persistent memory to your OpenAI applications using Recallr's forward proxy
Recallr seamlessly integrates with OpenAI by acting as a forward proxy. Simply point your OpenAI client to our base URL and we'll inject relevant context from user memory into each request.
## Quick Start
```python theme={null}
from openai import OpenAI
client = OpenAI(
base_url='https://api.recallrai.com/api/v1/forward/https://api.openai.com/v1',
api_key='sk-...', # Your OpenAI API key
default_headers={
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'your-project-id',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600',
}
)
# Use normally - memory is automatically injected
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "My name is Alice"}],
extra_headers={
'X-Recallr-User-Id': 'user-123',
'X-Recallr-Recall-Strategy': 'low_latency', # Optional
}
)
print(response.choices[0].message.content)
```
## Supported APIs
Standard conversational API with streaming and non-streaming support
OpenAI's new Responses API with streaming and non-streaming support
## Required Headers
These headers must be included with every request:
Your Recallr API key. Get it from the [dashboard](https://app.recallrai.com).
Your Recallr Project ID. Get it from the [dashboard](https://app.recallrai.com).
Unique identifier for the user. Used to maintain separate memory graphs per user.
Can also be passed as `user` field in the request body for OpenAI compatibility.
## Optional Headers
### Session Management
Automatically create a new user if the specified User-ID doesn't exist. Set to `true` to avoid errors for new users.
Inactivity period (in seconds) before creating a new session. Minimum value is 600 (10 minutes).
Messages within a session are always passed directly to the LLM. Only memories from previous sessions are retrieved and injected as context.
### Recall Configuration
Controls the recall method used for retrieving memories. Affects latency and accuracy.
**Best for:** Voice agents and real-time applications
* Fastest response time
* Retrieves more memories to compensate for reduced accuracy
* Use when sub-second latency is critical
**Best for:** Standard chatbots and applications
* Good balance between speed and accuracy
* Default strategy for most use cases
* Recommended for general applications
**Best for:** Complex queries requiring comprehensive context
* Runs agents to browse the knowledge graph
* Most accurate but slowest
* Use for questions like "What do you know about my preferences?"
Minimum number of memories to retrieve from the knowledge graph.
Maximum number of memories to retrieve from the knowledge graph.
Similarity threshold for retrieving individual memories (0.0 to 1.0). Lower values retrieve more memories.
Similarity threshold for retrieving session summaries (0.0 to 1.0). Lower values retrieve more summaries.
Include last N messages from past sessions when building context.
Include last N session summaries when building context.
User's timezone for formatting timestamps in memory context (e.g., "America/New\_York", "Europe/London"). Defaults to UTC if not specified.
Providing the user's timezone improves temporal context by showing memories with locally-formatted timestamps.
Whether to include Recallr AI's system prompt (\~ 3k tokens) in the context. This prompt includes instructions for how to use the injected memories. Set to `false` if you already have those instructions in your system prompt.
## Response Headers
Recallr returns these headers in the response for debugging and session tracking:
The internal session ID used by Recallr. Use this to continue the same session in future requests.
Unique identifier for the user. Matches the `X-Recallr-User-Id` sent in the request.
Unique identifier for this request. Use for debugging and tracing.
Time taken to process the request on Recallr's side (in milliseconds).
## Examples
### Chat Completions - Non-Streaming
```python Python theme={null}
from openai import OpenAI
client = OpenAI(
base_url='https://api.recallrai.com/api/v1/forward/https://api.openai.com/v1',
api_key='sk-...',
default_headers={
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'project-id',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600',
}
)
# Get raw response with headers
raw_response = client.chat.completions.with_raw_response.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "My name is Alice and I love Python programming."}
],
extra_headers={
'X-Recallr-User-Id': 'alice-123',
'X-Recallr-Recall-Strategy': 'low_latency', # Optional
}
)
# Access headers
session_id = raw_response.headers.get('X-Recallr-Session-Id')
request_id = raw_response.headers.get('X-Recallr-Request-Id')
# Parse response
response = raw_response.parse()
print(response.choices[0].message.content)
```
```javascript Node.js theme={null}
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://api.recallrai.com/api/v1/forward/https://api.openai.com/v1',
apiKey: 'sk-...',
defaultHeaders: {
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'project-id',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600', // Optional
},
});
const response = await client.chat.completions.create({
model: 'gpt-4o-mini',
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'My name is Alice and I love Python programming.' }
],
}, {
headers: {
'X-Recallr-User-Id': 'alice-123',
'X-Recallr-Recall-Strategy': 'low_latency', // Optional
}
});
console.log(response.choices[0].message.content);
```
### Chat Completions - Streaming
```python Python theme={null}
from openai import OpenAI
client = OpenAI(
base_url='https://api.recallrai.com/api/v1/forward/https://api.openai.com/v1',
api_key='sk-...',
default_headers={
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'project-id',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600', # Optional
}
)
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": "What do you know about me and my interests?"}
],
stream=True,
extra_headers={
'X-Recallr-User-Id': 'alice-123',
'X-Recallr-Recall-Strategy': 'low_latency',
}
)
for chunk in response:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end='', flush=True)
```
```javascript Node.js theme={null}
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://api.recallrai.com/api/v1/forward/https://api.openai.com/v1',
apiKey: 'sk-...',
defaultHeaders: {
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'project-id',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600', // Optional
},
});
const stream = await client.chat.completions.create({
model: 'gpt-4o-mini',
messages: [
{ role: 'user', content: 'What do you know about me and my interests?' }
],
stream: true,
}, {
headers: {
'X-Recallr-User-Id': 'alice-123',
'X-Recallr-Recall-Strategy': 'low_latency', // Optional
}
});
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content;
if (content) process.stdout.write(content);
}
```
### Responses API - Non-Streaming
```python Python theme={null}
from openai import OpenAI
client = OpenAI(
base_url='https://api.recallrai.com/api/v1/forward/https://api.openai.com/v1',
api_key='sk-...',
default_headers={
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'project-id',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600', # Optional
}
)
response = client.responses.create(
model="gpt-4o-mini",
input="I'm allergic to peanuts and love Italian food",
max_output_tokens=150,
extra_headers={
'X-Recallr-User-Id': 'alice-123',
'X-Recallr-Recall-Strategy': 'low_latency',
}
)
print(response.output[0].content[0].text)
```
```javascript Node.js theme={null}
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://api.recallrai.com/api/v1/forward/https://api.openai.com/v1',
apiKey: 'sk-...',
defaultHeaders: {
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'project-id',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600', // Optional
},
});
const response = await client.responses.create({
model: 'gpt-4o-mini',
input: "I'm allergic to peanuts and love Italian food",
max_output_tokens: 150,
}, {
headers: {
'X-Recallr-User-Id': 'alice-123',
'X-Recallr-Recall-Strategy': 'low_latency', // Optional
}
});
console.log(response.output[0].content[0].text);
```
### Responses API - Streaming
```python Python theme={null}
from openai import OpenAI
client = OpenAI(
base_url='https://api.recallrai.com/api/v1/forward/https://api.openai.com/v1',
api_key='sk-...',
default_headers={
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'project-id',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600', # Optional
}
)
response = client.responses.create(
model="gpt-4o-mini",
input="What are my food preferences?",
stream=True,
extra_headers={
'X-Recallr-User-Id': 'alice-123',
'X-Recallr-Recall-Strategy': 'low_latency',
}
)
for event in response:
if event.type == 'response.output_text.delta':
print(event.delta, end='', flush=True)
```
```javascript Node.js theme={null}
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://api.recallrai.com/api/v1/forward/https://api.openai.com/v1',
apiKey: 'sk-...',
defaultHeaders: {
'X-Recallr-API-Key': 'rai-...',
'X-Recallr-Project-Id': 'project-id',
'X-Recallr-Allow-New-User-Creation': 'true',
'X-Recallr-Session-Timeout-Seconds': '600', // Optional
},
});
const stream = await client.responses.create({
model: 'gpt-4o-mini',
input: 'What are my food preferences?',
stream: true,
}, {
headers: {
'X-Recallr-User-Id': 'alice-123',
'X-Recallr-Recall-Strategy': 'low_latency', // Optional
}
});
for await (const event of stream) {
if (event.type === 'response.output_text.delta') {
process.stdout.write(event.delta);
}
}
```
## How It Works
```mermaid theme={null}
sequenceDiagram
participant Client
participant Recallr
participant OpenAI
Client->>Recallr: Request with X-Recallr headers
Recallr->>Recallr: Validate API Key + Project ID
Recallr->>Recallr: Resolve User ID (create if allowed)
Recallr->>Recallr: Retrieve relevant memories from knowledge graph
Recallr->>Recallr: Inject context into request
Recallr->>OpenAI: Forward enhanced request
OpenAI->>Recallr: Response stream
Recallr->>Recallr: Store conversation in knowledge graph
Recallr->>Client: Return response with Recallr headers
```
Contact our support team for assistance with OpenAI integration
# RecallrAI Client
Source: https://docs.recallrai.com/sdks/nodejs/client
Main client class for interacting with RecallrAI
## Overview
The `RecallrAI` client is the entry point for all SDK operations. It manages authentication and provides methods for user management.
## Initialization
```typescript theme={null}
import { RecallrAI } from "recallrai";
const client = new RecallrAI({
apiKey: "rai_yourapikey",
projectId: "project-uuid",
baseUrl: "https://api.recallrai.com",
timeout: 60,
});
```
## Methods
### createUser()
```typescript theme={null}
import { UserAlreadyExistsError } from "recallrai";
try {
const user = await client.createUser("user123", { name: "John Doe", role: "admin" });
console.log(`Created user: ${user.userId}`);
} catch (error) {
if (error instanceof UserAlreadyExistsError) {
console.log(`Error: ${error.message}`);
}
}
```
Unique identifier for the user. Must be unique within your project.
Optional metadata to associate with the user.
**Returns:** `User`
**Raises:** `UserAlreadyExistsError`
***
### getUser()
```typescript theme={null}
import { UserNotFoundError } from "recallrai";
try {
const user = await client.getUser("user123");
console.log(`User metadata:`, user.metadata);
} catch (error) {
if (error instanceof UserNotFoundError) {
console.log(`Error: ${error.message}`);
}
}
```
The ID of the user to retrieve.
Whether to validate user existence via API before creating the instance. Set `false` only when `userId` is already trusted.
**Returns:** `User`
**Raises:** `UserNotFoundError`
Set `{ validate: false }` to skip the SDK lookup request (`GET /api/v1/users/{userId}`) when the user ID is already trusted by your system.
When `{ validate: false }` is used, fields that require an API lookup (for example `createdAt`, `lastActiveAt`, and `metadata`) are set to `UNAVAILABLE` until you call `refresh()`.
Import `UNAVAILABLE` from `recallrai` when checking these values.
***
### listUsers()
```typescript theme={null}
const userList = await client.listUsers({
offset: 0,
limit: 10,
metadataFilter: { role: "admin" },
});
console.log(`Total users: ${userList.total}`);
console.log(`Has more: ${userList.hasMore}`);
```
Number of users to skip. Default: `0`
Maximum number of users to return. Default: `10`
Filter users by metadata fields.
**Returns:** `UserList` with `users`, `total`, and `hasMore`.
# Exception Handling
Source: https://docs.recallrai.com/sdks/nodejs/exceptions
Comprehensive guide to SDK exceptions and error handling
## Overview
The RecallrAI SDK implements a consistent exception hierarchy to help you handle errors gracefully. All SDK exceptions inherit from `RecallrAIError`.
## Importing Exceptions
```typescript theme={null}
import {
RecallrAIError,
AuthenticationError,
TimeoutError,
ConnectionError,
InternalServerError,
RateLimitError,
UserNotFoundError,
UserAlreadyExistsError,
SessionNotFoundError,
InvalidSessionStateError,
MergeConflictNotFoundError,
} from "recallrai";
```
## Base Exception
```typescript theme={null}
try {
await client.getUser("user123");
} catch (error) {
if (error instanceof RecallrAIError) {
console.log(`RecallrAI error: ${error.message}`);
}
}
```
## Common Errors
* `AuthenticationError`: Invalid API key or project ID
* `TimeoutError`: Request timed out
* `ConnectionError`: Network connectivity issues
* `InternalServerError`: API returned a 5xx error
* `RateLimitError`: Too many requests
* `UserNotFoundError`: User does not exist
* `SessionNotFoundError`: Session does not exist
* `InvalidSessionStateError`: Invalid session status for operation
* `MergeConflictNotFoundError`: Merge conflict was not found
# Installation
Source: https://docs.recallrai.com/sdks/nodejs/installation
Install the RecallrAI Node.js SDK using npm, yarn, or pnpm
## Installation Methods
Install the RecallrAI Node.js SDK with your preferred package manager.
```bash theme={null}
npm install recallrai
```
```bash theme={null}
yarn add recallrai
```
```bash theme={null}
pnpm add recallrai
```
## Verify Installation
```typescript theme={null}
import { RecallrAI } from "recallrai";
const client = new RecallrAI({
apiKey: "rai_yourapikey",
projectId: "project-uuid",
});
console.log("RecallrAI client initialized:", Boolean(client));
```
## Get Your API Credentials
Create an account at [RecallrAI Dashboard](https://app.recallrai.com).
Navigate to your project API keys section and create an API key. It starts with `rai_`.
Copy your Project UUID from the dashboard.
Keep your API key secure and never commit it to version control.
## Next Steps
Get started with the Node.js SDK in minutes
Learn about the RecallrAI client class
Manage users, sessions, and memories
Visit the SDK repository for examples and source code
# Merge Conflict Resolution
Source: https://docs.recallrai.com/sdks/nodejs/merge-conflicts
Handle and resolve memory merge conflicts
## Overview
When RecallrAI processes sessions, it may detect conflicts between new memories and existing ones. The SDK provides tools to handle these merge conflicts through clarifying questions.
## List Merge Conflicts
```typescript theme={null}
import { MergeConflictStatus } from "recallrai";
const user = await client.getUser("user123");
const conflicts = await user.listMergeConflicts({
offset: 0,
limit: 10,
status: MergeConflictStatus.PENDING,
sortBy: "created_at",
sortOrder: "desc",
});
console.log(`Total conflicts: ${conflicts.total}`);
```
Filter by status: `PENDING`, `IN_QUEUE`, `RESOLVING`, `RESOLVED`, or `FAILED`.
## Resolve a Merge Conflict
```typescript theme={null}
import { MergeConflictAnswer } from "recallrai";
const conflict = await user.getMergeConflict("conflict-uuid");
const answers: MergeConflictAnswer[] = conflict.clarifyingQuestions.map((q) => ({
question: q.question,
answer: q.options[0],
message: "User prefers this option based on recent conversation",
}));
await conflict.resolve(answers);
```
**Raises:** `MergeConflictNotFoundError`, `MergeConflictAlreadyResolvedError`, `MergeConflictInvalidQuestionsError`, `MergeConflictMissingAnswersError`, `MergeConflictInvalidAnswerError`.
## MergeConflict Object Fields
Each conflict object contains:
* `id`: Unique conflict identifier
* `projectUserSessionId`: Session that triggered the conflict
* `proposedMemoryContent`: The proposed memory content that caused the conflict (optional)
* `conflictingMemories`: Array of existing memories that conflict, each containing:
* `memoryId`: ID of the conflicting memory
* `content`: Memory content
* `reason`: Why this memory conflicts with the new one
* `eventDateStart`: UTC `Date` when the event started
* `eventDateEnd`: UTC `Date` when the event ended
* `createdAt`: UTC `Date` when the memory was recorded
* `clarifyingQuestions`: Array of questions to help resolve the conflict, each containing:
* `question`: The question text
* `options`: Array of possible answer strings
* `status`: Current conflict status (`PENDING`, `IN_QUEUE`, `RESOLVING`, `RESOLVED`, `FAILED`)
* `createdAt`: UTC `Date` when the conflict was created
* `resolvedAt`: UTC `Date` when resolved (optional)
# Quickstart
Source: https://docs.recallrai.com/sdks/nodejs/quickstart
Get started with the RecallrAI Node.js SDK in minutes
## Installation
Install the SDK via npm, yarn, or pnpm:
```bash npm theme={null}
npm install recallrai
```
```bash yarn theme={null}
yarn add recallrai
```
```bash pnpm theme={null}
pnpm add recallrai
```
## Initialize Client
```typescript theme={null}
import { RecallrAI } from "recallrai";
const client = new RecallrAI({
apiKey: "rai_yourapikey",
projectId: "project-uuid",
baseUrl: "https://api.recallrai.com",
timeout: 60,
});
```
All datetime objects returned by the SDK are JavaScript Date instances in UTC.
## Parameters
Your RecallrAI API key. Must start with `rai_`.
Your project UUID from the RecallrAI dashboard.
Custom API endpoint. Default: `https://api.recallrai.com`
Request timeout in seconds. Default: `30`
When user and session IDs are already trusted in your system, you can skip SDK lookup calls by setting `validate: false` on `getUser()` and `getSession()`.
# Session Class
Source: https://docs.recallrai.com/sdks/nodejs/session
Manage conversation sessions, messages, and context retrieval
## Overview
The `Session` class represents a conversation session. It provides methods for adding messages, retrieving context, and processing sessions.
## Properties
Unique identifier for the session.
Current session status: `PENDING`, `PROCESSING`, `PROCESSED`, or `FAILED`.
Session metadata as an object.
UTC timestamp when the session was created.
## Session Management Methods
### delete()
Delete this session and all associated data permanently.
```typescript theme={null}
import { UserNotFoundError, SessionNotFoundError } from "recallrai";
try {
const session = await user.getSession("session-uuid");
await session.delete();
console.log("Session deleted successfully");
} catch (error) {
if (error instanceof SessionNotFoundError) {
console.log(`Session not found: ${error.message}`);
} else if (error instanceof UserNotFoundError) {
console.log(`User not found: ${error.message}`);
}
}
```
This action is irreversible. Deleting a session permanently removes its messages, memories, memory connections, memory categories, and merge conflicts that were created from it.
**Returns:** `Promise`
**Throws:** `UserNotFoundError`, `SessionNotFoundError`
## Message Methods
### addMessage()
```typescript theme={null}
import { MessageRole } from "recallrai";
await session.addMessage(MessageRole.USER, "Hello! How are you?");
await session.addMessage(MessageRole.ASSISTANT, "I am doing well, thanks!");
```
Message role: `USER` or `ASSISTANT`.
Message content text.
## Context Retrieval
### getContext()
```typescript theme={null}
import { RecallStrategy } from "recallrai";
const response = await session.getContext({
recallStrategy: RecallStrategy.BALANCED,
minTopK: 10,
maxTopK: 100,
memoriesThreshold: 0.6,
summariesThreshold: 0.5,
lastNMessages: 20,
lastNSummaries: 5,
timezone: "America/New_York",
includeMetadataIds: true
});
console.log(response.context);
if (response.metadata) {
console.log("Memory IDs:", response.metadata.memoryIds);
console.log("Session IDs:", response.metadata.sessionIds);
}
```
### Trusted IDs Fast Path
If your system already trusts the IDs, you can skip SDK pre-validation calls and go directly to context retrieval:
```typescript theme={null}
const trustedUser = await client.getUser("user123", { validate: false });
const trustedSession = await trustedUser.getSession("session-uuid", { validate: false });
const response = await trustedSession.getContext();
console.log(response.context);
```
This skips SDK lookup requests only. It removes extra latency from `getUser()` and `getSession()` when IDs are already validated in your own system.
Use this only with trusted IDs. The context endpoint still performs server-side validation and can still return `UserNotFoundError` or `SessionNotFoundError`.
Strategy for memory retrieval: `LOW_LATENCY`, `BALANCED`, `AGENTIC`, or `AUTO`.
Minimum number of memories to return. Range: 5-50.
Maximum number of memories to return. Range: 10-100.
Similarity threshold for memories. Range: 0.2-0.8.
Similarity threshold for summaries. Range: 0.2-0.8.
Number of last messages to include in context. Range: 1-100.
Number of last summaries to include in context. Range: 1-20.
Timezone for formatting timestamps (e.g., "America/New\_York").
Whether to include the default RecallrAI system prompt.
Whether to include memory IDs and session IDs that contributed to the context.
Enable this to track which specific memories and sessions were used to generate the context, useful for debugging, auditing, or building UI features that show sources.
**Returns:** `ContextResponse` object with:
Always `true` for non-streaming responses.
The formatted context string containing relevant memories and conversation history.
Only present when `includeMetadataIds=true`. Contains:
* `memoryIds`: Array of memory IDs that contributed to the context
* `sessionIds`: Array of session IDs that contributed to the context
* `agentReasoning`: (Optional) Agent's reasoning process, only populated when using agentic recall strategy
* `vectorSearchQueries`: (Optional) Vector search queries generated for recall
* `keywords`: (Optional) Keywords extracted for recall
* `sessionSummariesSearchQueries`: (Optional) Queries used to search session summaries
* `dateRangeFilters`: (Optional) Date range filters extracted from the query (balanced recall only)
When using the **agentic recall strategy**, the `agentReasoning` field will contain a step-by-step summary of the agent's exploration through your knowledge graph, showing how it arrived at the final context.
### getContextStream()
Stream context events with status updates and structured metadata.
```typescript theme={null}
for await (const event of session.getContextStream({
recallStrategy: RecallStrategy.BALANCED,
timezone: "America/New_York",
includeMetadataIds: true
})) {
if (event.statusUpdateMessage) {
console.log("Status:", event.statusUpdateMessage);
}
if (event.isFinal) {
if (event.errorMessage) {
console.log("Error:", event.errorMessage);
} else {
console.log("Final context:", event.context);
if (event.metadata) {
console.log("Memory IDs:", event.metadata.memoryIds);
console.log("Session IDs:", event.metadata.sessionIds);
console.log("Vector Queries:", event.metadata.vectorSearchQueries);
console.log("Keywords:", event.metadata.keywords);
console.log("Summary Queries:", event.metadata.sessionSummariesSearchQueries);
console.log("Date Filters:", event.metadata.dateRangeFilters);
}
}
}
if (event.metadata?.agentReasoning) {
console.log("Agent Reasoning:", event.metadata.agentReasoning);
}
}
```
Whether to include context metadata (IDs, queries, filters, and agent reasoning in status events) in the response.
**Yields:** `ContextResponse` objects with the following fields:
Indicates whether this is the final event or a status update.
Human-readable status update message (only present when `isFinal` is `false`).
Error message if an error occurred during context generation.
The formatted context string (only present when `isFinal` is `true`).
Only present when `includeMetadataIds=true` and `isFinal=true`. Contains:
* `memoryIds`: Array of memory IDs that contributed to the context
* `sessionIds`: Array of session IDs that contributed to the context
* `agentReasoning`: (Optional) Agent's reasoning process, only populated when using agentic recall strategy
* `vectorSearchQueries`: (Optional) Vector search queries generated for recall
* `keywords`: (Optional) Keywords extracted for recall
* `sessionSummariesSearchQueries`: (Optional) Queries used to search session summaries
* `dateRangeFilters`: (Optional) Date range filters extracted from the query (balanced recall only)
# User Class
Source: https://docs.recallrai.com/sdks/nodejs/user
Manage users and their sessions, memories, and messages
## Overview
The `User` class represents a user in your RecallrAI project. It provides methods for managing sessions, memories, messages, and merge conflicts.
## Properties
Unique identifier for the user.
User metadata as an object.
Per-user merge conflict override. `true` = always raise merge conflicts for this user. `false` = never raise. `undefined` = inherit the project-level setting.
UTC timestamp when the user was created.
UTC timestamp of the user's last activity.
## User Management Methods
### update()
```typescript theme={null}
import { UserAlreadyExistsError } from "recallrai";
try {
const user = await client.getUser("user123");
await user.update({
newMetadata: { name: "John Doe", role: "admin" },
newUserId: "john_doe",
mergeConflictEnabled: true, // optional: override merge conflict behaviour
});
console.log(`Updated user ID: ${user.userId}`);
} catch (error) {
if (error instanceof UserAlreadyExistsError) {
console.log(`New user ID already exists: ${error.message}`);
}
}
```
New metadata to replace the existing metadata.
Optional new user ID. Must be unique within your project.
Per-user merge conflict override. `true` = always raise merge conflicts for this user. `false` = never raise. Set `undefined` to reset to the project-level default (omit the field from the call).
**Returns:** `void`
**Raises:** `UserNotFoundError`, `UserAlreadyExistsError`
***
### refresh()
```typescript theme={null}
const user = await client.getUser("john_doe");
await user.refresh();
console.log(`Latest metadata:`, user.metadata);
```
**Returns:** `void`
**Raises:** `UserNotFoundError`
***
### delete()
```typescript theme={null}
const user = await client.getUser("john_doe");
await user.delete();
```
This permanently deletes the user and all associated sessions, memories, and messages.
**Returns:** `void`
**Raises:** `UserNotFoundError`
## Session Management Methods
### createSession()
```typescript theme={null}
const user = await client.getUser("user123");
const session = await user.createSession({
autoProcessAfterSeconds: 600,
metadata: { type: "chat", channel: "web" },
});
console.log(`Created session: ${session.sessionId}`);
```
Seconds of inactivity before auto-processing. Default: `600`.
Optional metadata for the session.
### getSession()
```typescript theme={null}
import { SessionNotFoundError } from "recallrai";
try {
const user = await client.getUser("user123");
const session = await user.getSession("session-uuid");
console.log(`Session status: ${session.status}`);
} catch (error) {
if (error instanceof SessionNotFoundError) {
console.log(`Error: ${error.message}`);
}
}
```
The UUID of the session to retrieve.
Whether to validate session existence via API before creating the instance. Set `false` only when `userId` and `sessionId` are already trusted.
**Returns:** `Session`
**Raises:** `UserNotFoundError`, `SessionNotFoundError`
Set `{ validate: false }` to skip the SDK lookup request (`GET /api/v1/users/{userId}/sessions/{sessionId}`) when IDs are already trusted.
When `{ validate: false }` is used, fields that require an API lookup (for example `status`, `createdAt`, and `metadata`) are set to `UNAVAILABLE` until you call `refresh()`.
Import `UNAVAILABLE` from `recallrai` when checking these values.
## Memory Management Methods
### listMemories()
List user memories with optional filtering.
```typescript theme={null}
import { UserNotFoundError, InvalidCategoriesError } from "recallrai";
try {
const user = await client.getUser("user123");
const memories = await user.listMemories({
categories: ["food_preferences", "allergies"],
sessionIdFilter: ["session-uuid-1", "session-uuid-2"],
sessionMetadataFilter: { environment: "production" },
offset: 0,
limit: 20,
includePreviousVersions: true,
includeConnectedMemories: true,
});
for (const mem of memories.items) {
console.log(`Memory: ${mem.content}`);
console.log(`Categories: ${mem.categories}`);
console.log(`Version: ${mem.versionNumber} of ${mem.totalVersions}`);
console.log(`Event occurred: ${mem.eventDateStart} to ${mem.eventDateEnd}`);
console.log(`Recorded at: ${mem.createdAt}`);
}
} catch (error) {
if (error instanceof InvalidCategoriesError) {
console.log(`Invalid categories: ${error.invalidCategories}`);
}
}
```
Filter by memory categories. Only memories matching these categories are returned.
Filter by specific session IDs.
Filter by session metadata.
Number of memories to skip. Default: `0`
Maximum number of memories to return. Range: 1-200. Default: `20`
Include version history for each memory. Default: `true`
Include related memories. Default: `true`
**Returns:** `UserMemoriesList` object
**Raises:** `UserNotFoundError`, `InvalidCategoriesError`
***
### getMemory()
Retrieve a single memory by its ID.
```typescript theme={null}
import { RecallrAIError } from "recallrai";
try {
const user = await client.getUser("user123");
const memory = await user.getMemory("memory-uuid", {
includePreviousVersions: true,
includeConnectedMemories: true,
});
console.log(`Content: ${memory.content}`);
console.log(`Categories: ${memory.categories}`);
console.log(`Version: ${memory.versionNumber} of ${memory.totalVersions}`);
} catch (error) {
if (error instanceof RecallrAIError) {
console.log(`Error: ${error.message}`);
}
}
```
UUID of the memory to retrieve.
Include version history for the memory. Default: `true`
Include related memories. Default: `true`
**Returns:** `UserMemoryItem`
**Raises:** `RecallrAIError`
***
### deleteMemory()
Delete a specific memory version, with an option to also remove all previous versions in the chain.
```typescript theme={null}
import { RecallrAIError } from "recallrai";
try {
const user = await client.getUser("user123");
// Delete only the specified memory version
await user.deleteMemory("memory-uuid");
// Delete the specified version and all previous versions
await user.deleteMemory("memory-uuid", true);
} catch (error) {
if (error instanceof RecallrAIError) {
console.log(`Error: ${error.message}`);
}
}
```
UUID of the memory to delete. Can be any version in the version chain.
If `true`, deletes the specified version and all previous versions in the chain. If `false` (default), deletes only the specified version.
Deletion is permanent and cannot be undone. When `deletePreviousVersions` is `true`, the entire version history up to and including the specified version is removed.
**Returns:** `void`
**Raises:** `RecallrAIError`
### UserMemoryItem Fields
Each memory item contains:
* `memoryId`: Unique identifier for the current version
* `categories`: Array of category strings
* `content`: Current version's content text
* `eventDateStart`: UTC `Date` when the event started (actual event time, not when it was recorded)
* `eventDateEnd`: UTC `Date` when the event ended (actual event time, not when it was recorded)
* `createdAt`: UTC `Date` when this memory version was created (when it was recorded in the system)
* `expiredAt`: UTC `Date` when this version expired — only set when viewing an expired/previous version
* `expirationReason`: Why this version was superseded (`MERGE_CONFLICT`, `ADDITION_TO_EXISTING_MEMORY`, `TEMPORAL_CONFLICT`) — only set for expired versions
* `sessionId`: ID of the session that created this version
* `versionNumber`: Current version number
* `totalVersions`: Total number of versions
* `hasPreviousVersions`: Boolean indicating multiple versions exist
* `previousVersions`: Array of `MemoryVersionInfo` objects (optional)
* `connectedMemories`: Array of `MemoryRelationship` objects (optional)
* `mergeConflictInProgress`: Boolean indicating an active (unresolved) conflict on this memory
* `mergeConflictId`: ID of the merge conflict that caused this memory to expire — only set when `expirationReason` is `MERGE_CONFLICT` and a conflict record exists (manually resolved conflicts only)
Each `MemoryVersionInfo` object in `previousVersions` contains:
* `memoryId`: ID of that specific version (can be passed to `getMemory()` for full details)
* `versionNumber`: Version number (1 = oldest)
* `content`: Content of that version
* `eventDateStart` / `eventDateEnd`: Event timestamps for that version
* `createdAt`: When that version was created
* `expiredAt`: When that version expired
* `expirationReason`: Why it was superseded
* `mergeConflictId`: Conflict that caused expiration, if applicable
The difference between `eventDateStart`/`eventDateEnd` and `createdAt`:
* **Event dates** represent when the event actually occurred in the real world (e.g., "I met John on Monday")
* **Created at** represents when the memory was extracted and stored in the system
This distinction allows for better temporal reasoning when extracting memories from past conversations.
# RecallrAI Client
Source: https://docs.recallrai.com/sdks/python/client
Main client class for interacting with RecallrAI
## Overview
The `RecallrAI` client is the entry point for all SDK operations. It manages authentication and provides methods for user management.
## Initialization
```python theme={null}
from recallrai import RecallrAI
client = RecallrAI(
api_key="rai_yourapikey",
project_id="project-uuid",
base_url="https://api.recallrai.com", # optional
timeout=60, # optional
)
```
## Methods
### create\_user()
Create a new user in your project.
```python theme={null}
from recallrai.exceptions import UserAlreadyExistsError
try:
user = client.create_user(
user_id="user123",
metadata={"name": "John Doe", "role": "admin"}
)
print(f"Created user: {user.user_id}")
except UserAlreadyExistsError as e:
print(f"Error: {e}")
```
Unique identifier for the user. Must be unique within your project.
Optional metadata to associate with the user. Can contain any JSON-serializable data.
**Returns:** `User` object
**Raises:** `UserAlreadyExistsError` if user\_id already exists
***
### get\_user()
Retrieve an existing user by ID.
```python theme={null}
from recallrai.exceptions import UserNotFoundError
try:
user = client.get_user("user123")
print(f"User metadata: {user.metadata}")
except UserNotFoundError as e:
print(f"Error: {e}")
```
The ID of the user to retrieve.
Whether to validate user existence via API before creating the instance. Set `False` only when `user_id` is already trusted.
**Returns:** `User` object
**Raises:** `UserNotFoundError` if user doesn't exist
Set `validate=False` to skip the SDK lookup request (`GET /api/v1/users/{user_id}`) when the user ID is already trusted by your system.
When `validate=False`, fields that require an API lookup (for example `created_at`, `last_active_at`, and `metadata`) are set to `UNAVAILABLE` until you call `refresh()`.
Import `UNAVAILABLE` from `recallrai.models` when checking these values.
***
### list\_users()
List all users in your project with optional filtering and pagination.
```python theme={null}
user_list = client.list_users(
offset=0,
limit=10,
metadata_filter={"role": "admin"}
)
print(f"Total users: {user_list.total}")
print(f"Has more: {user_list.has_more}")
for user in user_list.users:
print(f"User ID: {user.user_id}")
print(f"Metadata: {user.metadata}")
```
Number of users to skip. Default: `0`
Maximum number of users to return. Default: `10`
Filter users by metadata fields. Only users matching all specified fields are returned.
**Returns:** `UserList` object with:
* `users`: List of `User` objects
* `total`: Total number of users matching the filter
* `has_more`: Boolean indicating if more results are available
## Async Client
For async applications, use `AsyncRecallrAI`:
```python theme={null}
from recallrai import AsyncRecallrAI
client = AsyncRecallrAI(
api_key="rai_yourapikey",
project_id="project-uuid"
)
# All methods are the same, just use await
user = await client.create_user("user123")
user = await client.get_user("user123")
user_list = await client.list_users(limit=20)
```
# Exception Handling
Source: https://docs.recallrai.com/sdks/python/exceptions
Comprehensive guide to SDK exceptions and error handling
## Overview
The RecallrAI SDK implements a comprehensive exception hierarchy to help you handle different error scenarios gracefully. All SDK exceptions inherit from the base `RecallrAIError` class.
## Exception Hierarchy
```mermaid theme={null}
flowchart LR
Exception[Exception]
RecallrAIError[RecallrAIError]
AuthenticationError[AuthenticationError]
NetworkError[NetworkError]
ServerError[ServerError]
UserError[UserError]
SessionError[SessionError]
MergeConflictError[MergeConflictError]
ValidationError[ValidationError]
TimeoutError[TimeoutError]
ConnectionError[ConnectionError]
InternalServerError[InternalServerError]
RateLimitError[RateLimitError]
UserNotFoundError[UserNotFoundError]
UserAlreadyExistsError[UserAlreadyExistsError]
InvalidCategoriesError[InvalidCategoriesError]
InvalidSessionStateError[InvalidSessionStateError]
SessionNotFoundError[SessionNotFoundError]
MergeConflictNotFoundError[MergeConflictNotFoundError]
MergeConflictAlreadyResolvedError[MergeConflictAlreadyResolvedError]
MergeConflictInvalidQuestionsError[MergeConflictInvalidQuestionsError]
MergeConflictMissingAnswersError[MergeConflictMissingAnswersError]
MergeConflictInvalidAnswerError[MergeConflictInvalidAnswerError]
Exception --> RecallrAIError
RecallrAIError --> AuthenticationError
RecallrAIError --> NetworkError
RecallrAIError --> ServerError
RecallrAIError --> UserError
RecallrAIError --> SessionError
RecallrAIError --> MergeConflictError
RecallrAIError --> ValidationError
NetworkError --> TimeoutError
NetworkError --> ConnectionError
ServerError --> InternalServerError
ServerError --> RateLimitError
UserError --> UserNotFoundError
UserError --> UserAlreadyExistsError
UserError --> InvalidCategoriesError
SessionError --> InvalidSessionStateError
SessionError --> SessionNotFoundError
MergeConflictError --> MergeConflictNotFoundError
MergeConflictError --> MergeConflictAlreadyResolvedError
MergeConflictError --> MergeConflictInvalidQuestionsError
MergeConflictError --> MergeConflictMissingAnswersError
MergeConflictError --> MergeConflictInvalidAnswerError
```
## Importing Exceptions
Import exceptions from the `recallrai.exceptions` module:
```python theme={null}
# Import specific exceptions
from recallrai.exceptions import (
UserNotFoundError,
SessionNotFoundError,
InvalidCategoriesError,
MergeConflictNotFoundError,
)
# Import all exceptions
from recallrai.exceptions import (
RecallrAIError,
AuthenticationError,
TimeoutError,
ConnectionError,
InternalServerError,
RateLimitError,
UserNotFoundError,
UserAlreadyExistsError,
InvalidCategoriesError,
SessionNotFoundError,
InvalidSessionStateError,
ValidationError,
MergeConflictError,
MergeConflictNotFoundError,
MergeConflictAlreadyResolvedError,
MergeConflictInvalidQuestionsError,
MergeConflictMissingAnswersError,
MergeConflictInvalidAnswerError,
)
```
## Base Exception
### RecallrAIError
The base exception class for all SDK-specific errors.
```python theme={null}
from recallrai.exceptions import RecallrAIError
try:
# SDK operation
user = client.get_user("user123")
except RecallrAIError as e:
print(f"RecallrAI error occurred: {e}")
```
Catch `RecallrAIError` to handle all SDK-specific exceptions in one place.
## Authentication Errors
### AuthenticationError
Raised when there's an issue with your API key or project ID authentication.
```python theme={null}
from recallrai.exceptions import AuthenticationError
try:
client = RecallrAI(api_key="invalid_key", project_id="project-uuid")
user = client.get_user("user123")
except AuthenticationError as e:
print(f"Authentication failed: {e}")
# Prompt user to check their API credentials
```
**Common causes:**
* Invalid or expired API key
* Incorrect project ID
* Missing authentication headers
## Network Errors
### TimeoutError
Occurs when a request takes too long to complete.
```python theme={null}
from recallrai.exceptions import TimeoutError
try:
user = client.get_user("user123")
except TimeoutError as e:
print(f"Request timed out: {e}")
# Implement retry logic or increase timeout
```
### ConnectionError
Happens when the SDK cannot establish a connection to the RecallrAI API.
```python theme={null}
from recallrai.exceptions import ConnectionError
try:
user = client.get_user("user123")
except ConnectionError as e:
print(f"Connection failed: {e}")
# Check network connectivity
```
## Server Errors
### InternalServerError
Raised when the RecallrAI API returns a 5xx error code.
```python theme={null}
from recallrai.exceptions import InternalServerError
try:
user = client.create_user("user123")
except InternalServerError as e:
print(f"Server error: {e}")
# Retry after a delay or contact support
```
### RateLimitError
Raised when the API rate limit has been exceeded (HTTP 429).
```python theme={null}
from recallrai.exceptions import RateLimitError
try:
users = client.list_users(limit=100)
except RateLimitError as e:
print(f"Rate limit exceeded: {e}")
if hasattr(e, 'retry_after'):
print(f"Retry after {e.retry_after} seconds")
# Wait and retry
```
When available, the `retry_after` value indicates how long to wait before retrying the request.
## User Errors
### UserNotFoundError
Raised when attempting to access a user that doesn't exist.
```python theme={null}
from recallrai.exceptions import UserNotFoundError
try:
user = client.get_user("nonexistent_user")
except UserNotFoundError as e:
print(f"User not found: {e}")
# Create the user or handle gracefully
```
### UserAlreadyExistsError
Occurs when creating a user with an ID that already exists.
```python theme={null}
from recallrai.exceptions import UserAlreadyExistsError
try:
user = client.create_user("user123")
except UserAlreadyExistsError as e:
print(f"User already exists: {e}")
# Get the existing user instead
user = client.get_user("user123")
```
### InvalidCategoriesError
Raised when filtering user memories by categories that don't exist in the project.
```python theme={null}
from recallrai.exceptions import InvalidCategoriesError
try:
user = client.get_user("user123")
memories = user.list_memories(categories=["invalid_category"])
except InvalidCategoriesError as e:
print(f"Invalid categories: {e.invalid_categories}")
# Use valid categories from your project
```
The exception contains the list of invalid categories in the `invalid_categories` attribute.
## Session Errors
### SessionNotFoundError
Raised when attempting to access a non-existent session.
```python theme={null}
from recallrai.exceptions import SessionNotFoundError
try:
user = client.get_user("user123")
session = user.get_session("nonexistent_session")
except SessionNotFoundError as e:
print(f"Session not found: {e}")
# Create a new session
```
### InvalidSessionStateError
Occurs when performing an operation that's not valid for the current session state.
```python theme={null}
from recallrai.exceptions import InvalidSessionStateError
from recallrai.models import MessageRole
try:
user = client.get_user("user123")
session = user.get_session("session-uuid")
# Trying to add a message to a processed session
session.add_message(role=MessageRole.USER, content="Hello")
except InvalidSessionStateError as e:
print(f"Invalid session state: {e}")
# Create a new session for new messages
```
You cannot add messages to a session that has already been processed.
## Merge Conflict Errors
### MergeConflictNotFoundError
Raised when attempting to access a merge conflict that doesn't exist.
```python theme={null}
from recallrai.exceptions import MergeConflictNotFoundError
try:
user = client.get_user("user123")
conflict = user.get_merge_conflict("nonexistent_conflict")
except MergeConflictNotFoundError as e:
print(f"Merge conflict not found: {e}")
```
### MergeConflictAlreadyResolvedError
Occurs when trying to resolve a merge conflict that has already been processed.
```python theme={null}
from recallrai.exceptions import MergeConflictAlreadyResolvedError
try:
conflict.resolve(answers)
except MergeConflictAlreadyResolvedError as e:
print(f"Conflict already resolved: {e}")
# Refresh to get latest status
conflict.refresh()
```
### MergeConflictInvalidQuestionsError
Raised when the provided questions don't match the original clarifying questions.
```python theme={null}
from recallrai.exceptions import MergeConflictInvalidQuestionsError
try:
conflict.resolve(answers)
except MergeConflictInvalidQuestionsError as e:
print(f"Invalid questions: {e}")
if e.invalid_questions:
print(f"These questions are invalid: {e.invalid_questions}")
```
### MergeConflictMissingAnswersError
Occurs when not all required clarifying questions have been answered.
```python theme={null}
from recallrai.exceptions import MergeConflictMissingAnswersError
try:
conflict.resolve(answers)
except MergeConflictMissingAnswersError as e:
print(f"Missing answers: {e}")
if e.missing_questions:
print(f"Missing answers for: {e.missing_questions}")
```
### MergeConflictInvalidAnswerError
Raised when an answer is not one of the valid options for a question.
```python theme={null}
from recallrai.exceptions import MergeConflictInvalidAnswerError
try:
conflict.resolve(answers)
except MergeConflictInvalidAnswerError as e:
print(f"Invalid answer: {e}")
if e.question and e.valid_options:
print(f"Question: {e.question}")
print(f"Valid options: {e.valid_options}")
```
## Validation Errors
### ValidationError
Raised when provided data doesn't meet the required format or constraints.
```python theme={null}
from recallrai.exceptions import ValidationError
try:
# Invalid parameter value
context = session.get_context(min_top_k=200) # Out of range
except ValidationError as e:
print(f"Validation error: {e}")
```
## Best Practices
### 1. Handle Specific Exceptions First
Catch more specific exceptions before general ones:
```python theme={null}
from recallrai.exceptions import UserNotFoundError, RecallrAIError
try:
user = client.get_user("user123")
except UserNotFoundError as e:
# Handle specific case
print(f"Creating new user...")
user = client.create_user("user123")
except RecallrAIError as e:
# General fallback
print(f"SDK error: {e}")
```
### 2. Implement Retry Logic for Transient Errors
Network and timeout errors might be temporary:
```python theme={null}
import time
from recallrai.exceptions import TimeoutError, ConnectionError, RateLimitError
def get_user_with_retry(client, user_id, max_retries=3):
for attempt in range(max_retries):
try:
return client.get_user(user_id)
except (TimeoutError, ConnectionError) as e:
if attempt < max_retries - 1:
wait_time = 2 ** attempt # Exponential backoff
print(f"Retry in {wait_time}s...")
time.sleep(wait_time)
else:
raise
except RateLimitError as e:
if hasattr(e, 'retry_after'):
time.sleep(e.retry_after)
else:
time.sleep(60)
```
### 3. Log Detailed Error Information
Exceptions contain useful information for debugging:
```python theme={null}
import logging
from recallrai.exceptions import RecallrAIError
logger = logging.getLogger(__name__)
try:
user = client.get_user("user123")
except RecallrAIError as e:
logger.error(f"RecallrAI error: {type(e).__name__} - {e}")
# Re-raise or handle appropriately
```
### 4. Handle Common User Flows
Check if resources exist before operations:
```python theme={null}
from recallrai.exceptions import UserNotFoundError
def get_or_create_user(client, user_id, metadata=None):
try:
return client.get_user(user_id)
except UserNotFoundError:
return client.create_user(user_id, metadata=metadata)
```
### 5. Graceful Degradation
Provide fallback behavior when errors occur:
```python theme={null}
from recallrai.exceptions import SessionNotFoundError
def get_conversation_context(user, session_id=None):
if session_id:
try:
session = user.get_session(session_id)
return session.get_context()
except SessionNotFoundError:
# Fallback: create new session
pass
# Default behavior
session = user.create_session()
return session.get_context()
```
## Complete Example
Here's a comprehensive example showing proper exception handling:
```python theme={null}
from recallrai import RecallrAI
from recallrai.exceptions import (
AuthenticationError,
UserNotFoundError,
UserAlreadyExistsError,
SessionNotFoundError,
InvalidSessionStateError,
TimeoutError,
RecallrAIError,
)
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def safe_chat_operation(api_key, project_id, user_id, session_id=None):
try:
# Initialize client
client = RecallrAI(api_key=api_key, project_id=project_id)
# Get or create user
try:
user = client.get_user(user_id)
logger.info(f"Retrieved user: {user_id}")
except UserNotFoundError:
user = client.create_user(user_id)
logger.info(f"Created new user: {user_id}")
# Get or create session
if session_id:
try:
session = user.get_session(session_id)
logger.info(f"Retrieved session: {session_id}")
except SessionNotFoundError:
session = user.create_session()
logger.info(f"Created new session: {session.session_id}")
else:
session = user.create_session()
logger.info(f"Created new session: {session.session_id}")
# Add message
try:
session.add_message(role=MessageRole.USER, content="Hello")
logger.info("Added message to session")
except InvalidSessionStateError:
logger.warning("Session already processed, creating new one")
session = user.create_session()
session.add_message(role=MessageRole.USER, content="Hello")
# Get context
context = session.get_context()
return session, context
except AuthenticationError as e:
logger.error(f"Authentication failed: {e}")
raise
except TimeoutError as e:
logger.error(f"Request timed out: {e}")
# Could implement retry logic here
raise
except RecallrAIError as e:
logger.error(f"RecallrAI error: {type(e).__name__} - {e}")
raise
except Exception as e:
logger.error(f"Unexpected error: {e}")
raise
```
# Installation
Source: https://docs.recallrai.com/sdks/python/installation
Install the RecallrAI Python SDK using pip, Poetry, or uv
## Installation Methods
The RecallrAI Python SDK can be installed using your preferred Python package manager.
```bash theme={null}
pip install recallrai
```
```bash theme={null}
poetry add recallrai
```
```bash theme={null}
uv add recallrai
```
## Verify Installation
After installation, verify that the SDK is properly installed:
```python theme={null}
import recallrai
print(f"RecallrAI SDK version: {recallrai.__version__}")
```
## Get Your API Credentials
Create an account at [RecallrAI Dashboard](https://app.recallrai.com) if you haven't already.
Navigate to your project api keys section and create an API key. It will start with `rai_`.
Copy your Project UUID from the dashboard.
Keep your API key secure and never commit it to version control. Use environment variables or a secrets manager.
## Next Steps
Get started with the Python SDK in minutes
Learn about the RecallrAI client class
Manage users, sessions, and memories
Visit our GitHub repository for examples and source code
# Merge Conflict Resolution
Source: https://docs.recallrai.com/sdks/python/merge-conflicts
Handle and resolve memory merge conflicts
## Overview
When RecallrAI processes sessions, it may detect conflicts between new memories and existing ones. The SDK provides comprehensive tools to handle these merge conflicts through clarifying questions.
## MergeConflict Class
The `MergeConflict` class represents a conflict between memories that requires resolution.
### Properties
Unique identifier for the merge conflict.
ID of the user this conflict belongs to.
Current status: `PENDING`, `IN_QUEUE`, `RESOLVING`, `RESOLVED`, or `FAILED`
Content of the proposed memory that conflicts with existing ones.
List of existing memories that conflict with the new memory. Each contains:
* `content`: Memory content
* `reason`: Explanation of why it conflicts
List of questions to help resolve the conflict. Each contains:
* `question`: The question text
* `options`: List of possible answers
UTC timestamp when the conflict was created.
UTC timestamp when resolved, or None if not yet resolved.
Additional data about the resolution, or None if not resolved.
## List Merge Conflicts
List merge conflicts for a user with optional filtering.
```python theme={null}
from recallrai.models import MergeConflictStatus
user = client.get_user("user123")
conflicts = user.list_merge_conflicts(
offset=0,
limit=10,
status=MergeConflictStatus.PENDING,
sort_by="created_at",
sort_order="desc"
)
print(f"Total conflicts: {conflicts.total}")
print(f"Has more: {conflicts.has_more}")
for conf in conflicts.conflicts:
print(f"Conflict ID: {conf.conflict_id}")
print(f"Status: {conf.status}")
print(f"New memory: {conf.proposed_memory_content}")
print(f"Conflicting memories: {len(conf.conflicting_memories)}")
print(f"Questions: {len(conf.clarifying_questions)}")
```
Number of conflicts to skip. Default: `0`
Maximum number of conflicts to return. Default: `10`
Filter by status. Options:
* `PENDING`: Conflict detected and waiting for resolution
* `IN_QUEUE`: Queued for automated processing
* `RESOLVING`: Being processed
* `RESOLVED`: Successfully resolved
* `FAILED`: Resolution failed
Sort field: `created_at` or `resolved_at`. Default: `created_at`
Sort order: `asc` or `desc`. Default: `desc`
**Returns:** `MergeConflictList` object with `conflicts`, `total`, and `has_more` fields
## Get a Specific Merge Conflict
Retrieve detailed information about a specific merge conflict.
```python theme={null}
from recallrai.exceptions import MergeConflictNotFoundError
try:
user = client.get_user("user123")
conflict = user.get_merge_conflict("conflict-uuid")
print(f"Status: {conflict.status.value}")
print(f"New memory: {conflict.proposed_memory_content}")
# Examine conflicting memories
print("\nConflicting memories:")
for mem in conflict.conflicting_memories:
print(f" Content: {mem.content}")
print(f" Reason: {mem.reason}")
# View clarifying questions
print("\nClarifying questions:")
for ques in conflict.clarifying_questions:
print(f" Question: {ques.question}")
print(f" Options: {ques.options}")
except MergeConflictNotFoundError as e:
print(f"Error: {e}")
```
The UUID of the merge conflict to retrieve.
**Returns:** `MergeConflict` object
**Raises:** `UserNotFoundError`, `MergeConflictNotFoundError`
## Resolve a Merge Conflict
Resolve a merge conflict by answering the clarifying questions.
```python theme={null}
from recallrai.exceptions import (
MergeConflictNotFoundError,
MergeConflictAlreadyResolvedError,
MergeConflictInvalidQuestionsError,
MergeConflictMissingAnswersError,
MergeConflictInvalidAnswerError,
)
from recallrai.models import MergeConflictAnswer
try:
user = client.get_user("user123")
conflict = user.get_merge_conflict("conflict-uuid")
# Prepare answers to the clarifying questions
answers = []
for ques in conflict.clarifying_questions:
print(f"Question: {ques.question}")
print(f"Options: {ques.options}")
# Select an option (in this example, we select the first one)
answer = MergeConflictAnswer(
question=ques.question,
answer=ques.options[0],
message="User prefers this option based on recent conversation"
)
answers.append(answer)
# Resolve the conflict
conflict.resolve(answers)
print(f"Conflict resolved! Status: {conflict.status}")
print(f"Resolved at: {conflict.resolved_at}")
if conflict.resolution_data:
print(f"Resolution data: {conflict.resolution_data}")
except MergeConflictNotFoundError as e:
print(f"Conflict not found: {e}")
except MergeConflictAlreadyResolvedError as e:
print(f"Conflict already resolved: {e}")
except MergeConflictInvalidQuestionsError as e:
print(f"Invalid questions provided: {e}")
if e.invalid_questions:
print(f"Invalid questions: {e.invalid_questions}")
except MergeConflictMissingAnswersError as e:
print(f"Missing answers: {e}")
if e.missing_questions:
print(f"Missing answers for: {e.missing_questions}")
except MergeConflictInvalidAnswerError as e:
print(f"Invalid answer: {e}")
if e.question and e.valid_options:
print(f"Question: {e.question}")
print(f"Valid options: {e.valid_options}")
```
### resolve() Method
List of answers to the clarifying questions. Each answer must include:
* `question`: The question text (must match exactly)
* `answer`: Selected option (must be one of the valid options)
* `message`: Optional explanation for the choice
**Returns:** None (updates the instance in place)
**Raises:**
* `MergeConflictNotFoundError`: Conflict doesn't exist
* `MergeConflictAlreadyResolvedError`: Conflict already processed
* `MergeConflictInvalidQuestionsError`: Questions don't match original questions
* `MergeConflictMissingAnswersError`: Not all questions have been answered
* `MergeConflictInvalidAnswerError`: Answer is not a valid option
All clarifying questions must be answered, and each answer must match one of the provided options exactly.
## Refresh Merge Conflict
Refresh the merge conflict instance to get the latest status from the server.
```python theme={null}
user = client.get_user("user123")
conflict = user.get_merge_conflict("conflict-uuid")
# Refresh to get latest status
conflict.refresh()
print(f"Current status: {conflict.status}")
print(f"Resolved at: {conflict.resolved_at}")
```
**Returns:** None (updates the instance in place)
**Raises:** `UserNotFoundError`, `MergeConflictNotFoundError`
## MergeConflictAnswer Model
When resolving conflicts, you need to create `MergeConflictAnswer` objects:
```python theme={null}
from recallrai.models import MergeConflictAnswer
answer = MergeConflictAnswer(
question="Which food preference is correct?",
answer="User prefers vegetarian meals",
message="User explicitly mentioned being vegetarian in last conversation"
)
```
The exact question text from the conflict's clarifying questions.
The selected option. Must be one of the valid options from the question.
Optional explanation for why this answer was selected.
## Merge Conflict Statuses
Conflict has been detected and is waiting for resolution. You can call `resolve()` to provide answers.
Conflict is queued for automated processing by the system.
Conflict is currently being processed.
Conflict has been successfully resolved. The memories have been updated accordingly.
Conflict resolution failed. You may need to contact support or try resolving again.
## Async Merge Conflicts
For async applications, all merge conflict methods support async/await:
```python theme={null}
from recallrai import AsyncRecallrAI
client = AsyncRecallrAI(api_key="rai_yourapikey", project_id="project-uuid")
user = await client.get_user("user123")
# All methods are the same, just use await
conflicts = await user.list_merge_conflicts(status=MergeConflictStatus.PENDING)
conflict = await user.get_merge_conflict("conflict-uuid")
await conflict.resolve(answers)
await conflict.refresh()
```
## Best Practices
**Regular Monitoring**: Check for pending merge conflicts regularly, especially after processing sessions with important conversations.
**Contextual Answers**: When resolving conflicts, use the `message` field to provide context about why you selected a particular answer. This helps improve the accuracy of future memory updates.
**Error Handling**: Always handle the specific merge conflict exceptions to provide appropriate user feedback and recovery options.
# Quickstart
Source: https://docs.recallrai.com/sdks/python/quickstart
Get started with the RecallrAI Python SDK in minutes
## Installation
Install the SDK via Poetry or pip:
```bash Poetry theme={null}
poetry add recallrai
```
```bash pip theme={null}
pip install recallrai
```
## Initialize Client
Create a client instance with your API key and project ID:
```python theme={null}
from recallrai import RecallrAI
client = RecallrAI(
api_key="rai_yourapikey",
project_id="project-uuid",
base_url="https://api.recallrai.com", # optional: custom endpoint
timeout=60, # optional: timeout in seconds (default: 60)
)
```
All datetime objects returned by the SDK are in UTC timezone.
## Parameters
Your RecallrAI API key. Must start with `rai_`.
Your project UUID from the RecallrAI dashboard.
Custom API endpoint. Default: `https://api.recallrai.com`
Request timeout in seconds. Default: `60`
## Async Support
The SDK provides full async/await support for all operations. Use `AsyncRecallrAI`, `AsyncUser`, and `AsyncSession` for async applications:
```python theme={null}
from recallrai import AsyncRecallrAI
client = AsyncRecallrAI(
api_key="rai_yourapikey",
project_id="project-uuid"
)
# All usage patterns are identical, just with await keywords
user = await client.create_user(user_id="user123")
```
All async classes have the same API as their sync counterparts - just add `await` before method calls.
When user and session IDs are already trusted in your system, you can skip SDK lookup calls by setting `validate=False` on `get_user()` and `get_session()`.
# Session Class
Source: https://docs.recallrai.com/sdks/python/session
Manage conversation sessions, messages, and context retrieval
## Overview
The `Session` class represents a conversation session. It provides methods for adding messages, retrieving context, and processing sessions to update user memories.
## Properties
Unique identifier for the session.
ID of the user this session belongs to.
Current session status: `PENDING`, `PROCESSING`, `PROCESSED`, or `FAILED`
Session metadata as a dictionary.
UTC timestamp when the session was created. Can be customized using `custom_created_at_utc` during session creation for benchmarking or importing historical data.
UTC timestamp when the session was processed, or None if not yet processed.
Seconds of inactivity before auto-processing, or None if disabled.
## Session Management Methods
### update()
Update the session metadata.
```python theme={null}
from recallrai.exceptions import SessionNotFoundError
try:
user = client.get_user("user123")
session = user.get_session("session-uuid")
session.update(new_metadata={"type": "support_chat", "priority": "high"})
print(f"Updated metadata: {session.metadata}")
except SessionNotFoundError as e:
print(f"Error: {e}")
```
New metadata to replace the existing metadata. Completely replaces the old metadata.
**Returns:** None (mutates the instance in place)
**Raises:** `UserNotFoundError`, `SessionNotFoundError`
***
### refresh()
Refresh the session instance with the latest data from the server.
```python theme={null}
session = user.get_session("session-uuid")
session.refresh()
print(f"Current status: {session.status}")
print(f"Processed at: {session.processed_at}")
```
**Returns:** None (updates the instance in place)
**Raises:** `UserNotFoundError`, `SessionNotFoundError`
***
### delete()
Delete this session and all associated data permanently.
```python theme={null}
from recallrai.exceptions import UserNotFoundError, SessionNotFoundError
try:
session = user.get_session("session-uuid")
session.delete()
print("Session deleted successfully")
except SessionNotFoundError as e:
print(f"Session not found: {e}")
except UserNotFoundError as e:
print(f"User not found: {e}")
```
This action is irreversible. Deleting a session permanently removes its messages, memories, memory connections, memory categories, and merge conflicts that were created from it.
**Returns:** None
**Raises:** `UserNotFoundError`, `SessionNotFoundError`
## Message Methods
### add\_message()
Add a message to the session.
```python theme={null}
from recallrai.models import MessageRole
from recallrai.exceptions import InvalidSessionStateError
try:
session = user.get_session("session-uuid")
# Add a user message
session.add_message(
role=MessageRole.USER,
content="Hello! How are you?"
)
# Add an assistant message
session.add_message(
role=MessageRole.ASSISTANT,
content="I'm doing well, thank you! How can I help you today?"
)
except InvalidSessionStateError as e:
print(f"Cannot add messages to a processed session: {e}")
```
Message role: `MessageRole.USER` or `MessageRole.ASSISTANT`
The message content text.
**MessageRole.USER**: Messages from the user/human\
**MessageRole.ASSISTANT**: Messages from the AI assistant
**Returns:** None
**Raises:** `UserNotFoundError`, `SessionNotFoundError`, `InvalidSessionStateError`
You cannot add messages to a session that has already been processed.
***
### get\_messages()
Retrieve messages from the session with pagination.
```python theme={null}
session = user.get_session("session-uuid")
messages = session.get_messages(offset=0, limit=50)
print(f"Total messages: {messages.total}")
print(f"Has more: {messages.has_more}")
for msg in messages.messages:
print(f"{msg.role.value.upper()} (at {msg.timestamp}): {msg.content}")
```
Number of messages to skip. Default: `0`
Maximum number of messages to return. Default: `50`
**Returns:** `MessageList` object with:
* `messages`: List of message objects with `role`, `content`, and `timestamp` fields
* `total`: Total number of messages in the session
* `has_more`: Boolean indicating if more messages are available
**Raises:** `UserNotFoundError`, `SessionNotFoundError`
## Context Retrieval
### get\_context()
Retrieve contextual information for the session based on user memories and conversation history.
```python theme={null}
from recallrai.models import RecallStrategy
# Get context with default parameters
context_response = session.get_context()
print(f"Context: {context_response.context}")
# Get context with memory and session IDs
context_response = session.get_context(
include_metadata_ids=True
)
if context_response.metadata:
print(f"Memory IDs: {context_response.metadata.memory_ids}")
print(f"Session IDs: {context_response.metadata.session_ids}")
# Get context with specific recall strategy
context_response = session.get_context(recall_strategy=RecallStrategy.LOW_LATENCY)
# Get context with custom parameters
context_response = session.get_context(
recall_strategy=RecallStrategy.BALANCED,
min_top_k=10,
max_top_k=100,
memories_threshold=0.6,
summaries_threshold=0.5,
last_n_messages=20,
last_n_summaries=5,
timezone="America/New_York",
include_system_prompt=True,
include_metadata_ids=True
)
```
### Trusted IDs Fast Path
If your system already trusts the IDs, you can skip SDK pre-validation calls and go directly to context retrieval:
```python theme={null}
trusted_user = client.get_user("user123", validate=False)
trusted_session = trusted_user.get_session(session_id="session-uuid", validate=False)
context_response = trusted_session.get_context()
print(context_response.context)
```
This skips SDK lookup requests only. It removes extra latency from `get_user()` and `get_session()` when IDs are already validated in your own system.
Use this only with trusted IDs. The context endpoint still performs server-side validation and can still return `UserNotFoundError` or `SessionNotFoundError`.
### get\_context\_stream()
Stream context events with status updates and structured metadata.
```python theme={null}
from recallrai.models import RecallStrategy
for event in session.get_context_stream(
recall_strategy=RecallStrategy.BALANCED,
timezone="America/New_York",
include_metadata_ids=True
):
if event.status_update_message:
print("Status:", event.status_update_message)
if event.is_final:
if event.error_message:
print("Error:", event.error_message)
else:
print("Final context:", event.context)
if event.metadata:
print("Memory IDs:", event.metadata.memory_ids)
print("Session IDs:", event.metadata.session_ids)
print("Vector Queries:", event.metadata.vector_search_queries)
print("Keywords:", event.metadata.keywords)
print("Summary Queries:", event.metadata.session_summaries_search_queries)
print("Date Filters:", event.metadata.date_range_filters)
if event.metadata.agent_reasoning:
print("Agent Reasoning:", event.metadata.agent_reasoning)
```
Strategy for memory retrieval: `LOW_LATENCY`, `BALANCED`, `AGENTIC`, or `AUTO`.
Timezone for formatting timestamps (e.g., `America/New_York`).
Whether to include context metadata (IDs, queries, filters, and agent reasoning in status events) in the response.
**Yields:** `ContextResponse` objects with the following fields:
Strategy for memory retrieval:
* `LOW_LATENCY`: Fast retrieval with basic relevance
* `BALANCED`: Good balance of speed and quality (default)
* `AGENTIC`: Agentic exploration for complex queries
Minimum number of memories to return. Range: 5-50. Default: `15`
Maximum number of memories to return. Range: 10-100. Default: `50`
Similarity threshold for memories. Range: 0.2-0.8. Default: `0.6`
Similarity threshold for summaries. Range: 0.2-0.8. Default: `0.5`
Number of last messages to include in context. Range: 1-100. Optional.
Number of last summaries to include in context. Range: 1-20. Optional.
Timezone for formatting timestamps in the context (e.g., "America/New\_York", "Europe/London", "Asia/Tokyo"). All timestamps in the retrieved memories and summaries will be formatted according to this timezone. Defaults to UTC.
Use the user's local timezone for better temporal context. For example, showing "Today at 2:30 PM" is more meaningful than a UTC timestamp.
Whether to include the default RecallrAI system prompt. Default: `True`
Whether to include context metadata. When `True`, the response includes a `metadata` field with IDs, queries, filters, and agent reasoning when available.
Enable this to track which specific memories and sessions were used to generate the context, useful for debugging, auditing, or building UI features that show sources.
Timestamps in the context are formatted using the specified `timezone` parameter (defaults to UTC). This ensures temporal information like "Last updated on Monday, January 6th at 3:45 PM EST" is presented in a user-friendly, localized format.
**Returns:** `ContextResponse` object with the following fields:
Always `True` for non-streaming responses.
The formatted context string containing relevant memories and conversation history.
Only present when `include_metadata_ids=True`. Contains:
* `memory_ids`: List of memory IDs that contributed to the context
* `session_ids`: List of session IDs that contributed to the context
* `agent_reasoning`: (Optional) Agent's reasoning process, only populated when using agentic recall strategy
* `vector_search_queries`: (Optional) Vector search queries generated for recall
* `keywords`: (Optional) Keywords extracted for recall
* `session_summaries_search_queries`: (Optional) Queries used to search session summaries
* `date_range_filters`: (Optional) Date range filters extracted from the query (balanced recall only)
When using the **agentic recall strategy**, the `agent_reasoning` field will contain a step-by-step summary of the agent's exploration through your knowledge graph, showing how it arrived at the final context.
**Raises:** `UserNotFoundError`, `SessionNotFoundError`
Use the context string as part of your system prompt when calling your LLM. This provides the AI with relevant memories and conversation history.
## Processing
### process()
Process the session to update user memories.
```python theme={null}
from recallrai.exceptions import InvalidSessionStateError
try:
session = user.get_session("session-uuid")
session.process()
print("Session processing started")
# Check status later
session.refresh()
print(f"Status: {session.status}")
except InvalidSessionStateError as e:
print(f"Cannot process session: {e}")
```
Processing extracts memories from the conversation and updates the user's memory store. This is an asynchronous operation - the session status will change to `PROCESSING` and then `PROCESSED` when complete.
**Returns:** None
**Raises:** `UserNotFoundError`, `SessionNotFoundError`, `InvalidSessionStateError`
You can only process a session once. After processing, you cannot add more messages to the session.
## Usage Example with LLM
Here's how to use sessions with an LLM like OpenAI:
```python theme={null}
import openai
from recallrai import RecallrAI
from recallrai.models import MessageRole
# Initialize clients
rai_client = RecallrAI(api_key="rai_yourapikey", project_id="project-uuid")
oai_client = openai.OpenAI(api_key="your-openai-api-key")
# Get user and create session
user = rai_client.get_user("user123")
session = user.create_session(auto_process_after_seconds=1800)
# Get user input
user_message = input("You: ")
# Add to RecallrAI
session.add_message(role=MessageRole.USER, content=user_message)
# Get context from RecallrAI
context_response = session.get_context()
# Create system prompt with context
system_prompt = "You are a helpful assistant" + context_response.context
# Get conversation history
messages = session.get_messages(limit=50)
previous_messages = [
{"role": msg.role, "content": msg.content}
for msg in messages.messages
]
# Call LLM
response = oai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system_prompt},
*previous_messages,
]
)
assistant_message = response.choices[0].message.content
print(f"Assistant: {assistant_message}")
# Add assistant response to RecallrAI
session.add_message(role=MessageRole.ASSISTANT, content=assistant_message)
# Process session when conversation ends
session.process()
```
## Async Session
For async applications, use `AsyncSession`:
```python theme={null}
from recallrai import AsyncRecallrAI
from recallrai.models import MessageRole
client = AsyncRecallrAI(api_key="rai_yourapikey", project_id="project-uuid")
user = await client.get_user("user123")
session = await user.create_session()
# All methods are the same, just use await
await session.add_message(role=MessageRole.USER, content="Hello")
context = await session.get_context()
messages = await session.get_messages(limit=10)
await session.process()
```
# User Class
Source: https://docs.recallrai.com/sdks/python/user
Manage users and their sessions, memories, and messages
## Overview
The `User` class represents a user in your RecallrAI project. It provides methods for managing sessions, memories, messages, and merge conflicts.
## Properties
Unique identifier for the user.
User metadata as a dictionary.
Per-user merge conflict override. `True` = always raise merge conflicts for this user. `False` = never raise. `None` = inherit the project-level setting.
UTC timestamp when the user was created.
UTC timestamp of the user's last activity.
## User Management Methods
### update()
Update the user's metadata or ID.
```python theme={null}
from recallrai.exceptions import UserNotFoundError, UserAlreadyExistsError
try:
user = client.get_user("user123")
user.update(
new_metadata={"name": "John Doe", "role": "admin"},
new_user_id="john_doe", # optional: change user ID
merge_conflict_enabled=True # optional: override merge conflict behaviour
)
print(f"Updated user ID: {user.user_id}")
except UserAlreadyExistsError as e:
print(f"New user ID already exists: {e}")
```
New metadata to replace the existing metadata. Completely replaces the old metadata.
Optional new user ID. Must be unique within your project.
Per-user merge conflict override. `True` = always raise merge conflicts for this user. `False` = never raise. Pass `None` explicitly to reset to the project-level default.
**Returns:** None (mutates the instance in place)
**Raises:** `UserNotFoundError`, `UserAlreadyExistsError`
***
### refresh()
Refresh the user instance with the latest data from the server.
```python theme={null}
user = client.get_user("john_doe")
user.refresh()
print(f"Latest metadata: {user.metadata}")
```
**Returns:** None (updates the instance in place)
**Raises:** `UserNotFoundError`
***
### delete()
Delete the user and all associated data.
```python theme={null}
from recallrai.exceptions import UserNotFoundError
try:
user = client.get_user("john_doe")
user.delete()
print("User deleted successfully")
except UserNotFoundError as e:
print(f"Error: {e}")
```
This permanently deletes the user and all associated sessions, memories, and messages. This action cannot be undone.
**Returns:** None
**Raises:** `UserNotFoundError`
## Session Management Methods
### create\_session()
Create a new session for the user.
```python theme={null}
from recallrai.exceptions import UserNotFoundError
try:
user = client.get_user("user123")
session = user.create_session(
auto_process_after_seconds=600,
metadata={"type": "chat", "channel": "web"}
)
print(f"Created session: {session.session_id}")
except UserNotFoundError as e:
print(f"Error: {e}")
```
Automatically process the session after this many seconds of inactivity. Optional.
Optional metadata to associate with the session.
Optional custom timestamp for when the session was created. Must be a timezone-aware datetime in UTC. Useful for benchmarking or importing historical data.
**Returns:** `Session` object
**Raises:** `UserNotFoundError`, `ValueError` (if timestamp is not UTC)
The `custom_created_at_utc` parameter is particularly useful when:
* Importing historical conversation data and preserving original timestamps
* Running benchmarks with controlled temporal context
* Migrating data from another system with existing timestamps
#### Example with Custom Timestamp
```python theme={null}
from datetime import datetime, timezone
user = client.get_user("user123")
# Create session with historical timestamp
historical_time = datetime(2025, 1, 1, 12, 0, 0, tzinfo=timezone.utc)
session = user.create_session(
custom_created_at_utc=historical_time,
metadata={"imported": True, "source": "legacy_system"}
)
print(f"Session created with timestamp: {session.created_at}")
```
The timestamp must be timezone-aware and in UTC. Naive datetime objects or non-UTC timezones will raise a `ValueError`.
***
### get\_session()
Retrieve an existing session by ID.
```python theme={null}
from recallrai.exceptions import SessionNotFoundError
try:
user = client.get_user("user123")
session = user.get_session(session_id="session-uuid")
print(f"Session status: {session.status}")
except SessionNotFoundError as e:
print(f"Error: {e}")
```
The UUID of the session to retrieve.
Whether to validate session existence via API before creating the instance. Set `False` only when `user_id` and `session_id` are already trusted.
**Returns:** `Session` object
**Raises:** `UserNotFoundError`, `SessionNotFoundError`
Set `validate=False` to skip the SDK lookup request (`GET /api/v1/users/{user_id}/sessions/{session_id}`) when IDs are already trusted.
When `validate=False`, fields that require an API lookup (for example `status`, `created_at`, and `metadata`) are set to `UNAVAILABLE` until you call `refresh()`.
Import `UNAVAILABLE` from `recallrai.models` when checking these values.
***
### list\_sessions()
List all sessions for the user with optional filtering.
```python theme={null}
from recallrai.models import SessionStatus
user = client.get_user("user123")
session_list = user.list_sessions(
offset=0,
limit=10,
metadata_filter={"type": "chat"},
status_filter=[SessionStatus.PENDING, SessionStatus.PROCESSING]
)
print(f"Total sessions: {session_list.total}")
for session in session_list.sessions:
print(f"{session.session_id}: {session.status}")
```
Number of sessions to skip. Default: `0`
Maximum number of sessions to return. Default: `10`
Filter sessions by metadata fields.
Filter by session status. Available statuses: `PENDING`, `PROCESSING`, `PROCESSED`, `FAILED`
**Returns:** `SessionList` object with `sessions`, `total`, and `has_more` fields
## Memory Management Methods
### list\_memories()
List user memories with optional filtering.
```python theme={null}
from recallrai.exceptions import InvalidCategoriesError
try:
user = client.get_user("user123")
memories = user.list_memories(
categories=["food_preferences", "allergies"],
session_id_filter=["session-uuid-1", "session-uuid-2"],
session_metadata_filter={"environment": "production"},
offset=0,
limit=20,
include_previous_versions=True,
include_connected_memories=True
)
for mem in memories.items:
print(f"Memory: {mem.content}")
print(f"Categories: {mem.categories}")
print(f"Version: {mem.version_number} of {mem.total_versions}")
print(f"Event occurred: {mem.event_date_start} to {mem.event_date_end}")
print(f"Recorded at: {mem.created_at}")
except InvalidCategoriesError as e:
print(f"Invalid categories: {e.invalid_categories}")
```
Filter by memory categories. Only memories matching these categories are returned.
Filter by specific session IDs.
Filter by session metadata.
Number of memories to skip. Default: `0`
Maximum number of memories to return. Range: 1-200. Default: `20`
Include version history for each memory. Default: `True`
Include related memories. Default: `True`
**Returns:** `MemoryList` object
**Raises:** `UserNotFoundError`, `InvalidCategoriesError`
***
### get\_memory()
Retrieve a single memory by its ID.
```python theme={null}
from recallrai.exceptions import RecallrAIError
try:
user = client.get_user("user123")
memory = user.get_memory(
memory_id="memory-uuid",
include_previous_versions=True,
include_connected_memories=True,
)
print(f"Content: {memory.content}")
print(f"Categories: {memory.categories}")
print(f"Version: {memory.version_number} of {memory.total_versions}")
except RecallrAIError as e:
print(f"Error: {e}")
```
UUID of the memory to retrieve.
Include version history for the memory. Default: `True`
Include related memories. Default: `True`
**Returns:** `UserMemoryItem` object
**Raises:** `RecallrAIError`
***
### delete\_memory()
Delete a specific memory version, with an option to also remove all previous versions in the chain.
```python theme={null}
from recallrai.exceptions import RecallrAIError
try:
user = client.get_user("user123")
# Delete only the specified memory version
user.delete_memory(memory_id="memory-uuid")
# Delete the specified version and all previous versions
user.delete_memory(memory_id="memory-uuid", delete_previous_versions=True)
except RecallrAIError as e:
print(f"Error: {e}")
```
UUID of the memory to delete. Can be any version in the version chain.
If `True`, deletes the specified version and all previous versions in the chain. If `False` (default), deletes only the specified version.
Deletion is permanent and cannot be undone. When `delete_previous_versions=True`, the entire version history up to and including the specified version is removed.
**Returns:** `None`
**Raises:** `RecallrAIError`
### Memory Item Fields
Each memory item contains:
* `memory_id`: Unique identifier for the current version
* `categories`: List of category strings
* `content`: Current version's content text
* `event_date_start`: UTC timestamp when the event started (actual event time, not when it was recorded)
* `event_date_end`: UTC timestamp when the event ended (actual event time, not when it was recorded)
* `created_at`: UTC timestamp when this memory version was created (when it was recorded in the system)
* `expired_at`: UTC timestamp when this version expired — only set when viewing an expired/previous version
* `expiration_reason`: Why this version was superseded (`MERGE_CONFLICT`, `ADDITION_TO_EXISTING_MEMORY`, `TEMPORAL_CONFLICT`) — only set for expired versions
* `session_id`: ID of the session that created this version
* `version_number`: Current version number
* `total_versions`: Total number of versions
* `has_previous_versions`: Boolean indicating multiple versions exist
* `previous_versions`: List of `MemoryVersionInfo` objects (optional)
* `connected_memories`: List of `MemoryRelationship` objects (optional)
* `merge_conflict_in_progress`: Boolean indicating an active (unresolved) conflict on this memory
* `merge_conflict_id`: ID of the merge conflict that caused this memory to expire — only set when `expiration_reason` is `MERGE_CONFLICT` and a conflict record exists (manually resolved conflicts only)
Each `MemoryVersionInfo` object in `previous_versions` contains:
* `memory_id`: ID of that specific version (can be passed to `get_memory()` for full details)
* `version_number`: Version number (1 = oldest)
* `content`: Content of that version
* `event_date_start` / `event_date_end`: Event timestamps for that version
* `created_at`: When that version was created
* `expired_at`: When that version expired
* `expiration_reason`: Why it was superseded
* `merge_conflict_id`: Conflict that caused expiration, if applicable
The difference between `event_date_start`/`event_date_end` and `created_at`:
* **Event dates** represent when the event actually occurred in the real world (e.g., "I met John on Monday")
* **Created at** represents when the memory was extracted and stored in the system
This distinction allows for better temporal reasoning when extracting memories from past conversations.
## Message Methods
### get\_last\_n\_messages()
Retrieve the most recent messages for the user across all sessions.
```python theme={null}
user = client.get_user("user123")
messages = user.get_last_n_messages(n=5)
for msg in messages.messages:
print(f"Session: {msg.session_id}")
print(f"{msg.role.upper()}: {msg.content}")
```
Number of recent messages to retrieve.
This is useful for chatbot applications where you need conversation context, such as WhatsApp bots where you want the last few messages to understand the ongoing conversation.
**Returns:** `MessageList` object with `messages` field
**Raises:** `UserNotFoundError`
## Merge Conflict Methods
### list\_merge\_conflicts()
List merge conflicts for the user.
```python theme={null}
from recallrai.models import MergeConflictStatus
user = client.get_user("user123")
conflicts = user.list_merge_conflicts(
offset=0,
limit=10,
status=MergeConflictStatus.PENDING,
sort_by="created_at",
sort_order="desc"
)
print(f"Total conflicts: {conflicts.total}")
for conflict in conflicts.conflicts:
print(f"Conflict ID: {conflict.conflict_id}")
print(f"Status: {conflict.status}")
```
Number of conflicts to skip. Default: `0`
Maximum number of conflicts to return. Default: `10`
Filter by status: `PENDING`, `IN_QUEUE`, `RESOLVING`, `RESOLVED`, `FAILED`
Sort field: `created_at` or `resolved_at`. Default: `created_at`
Sort order: `asc` or `desc`. Default: `desc`
**Returns:** `MergeConflictList` object
***
### get\_merge\_conflict()
Get a specific merge conflict by ID.
```python theme={null}
from recallrai.exceptions import MergeConflictNotFoundError
try:
user = client.get_user("user123")
conflict = user.get_merge_conflict("conflict-uuid")
print(f"Status: {conflict.status}")
print(f"Clarifying questions: {len(conflict.clarifying_questions)}")
except MergeConflictNotFoundError as e:
print(f"Error: {e}")
```
The UUID of the merge conflict to retrieve.
**Returns:** `MergeConflict` object
**Raises:** `UserNotFoundError`, `MergeConflictNotFoundError`
## Async User
For async applications, use `AsyncUser`:
```python theme={null}
from recallrai import AsyncRecallrAI
client = AsyncRecallrAI(api_key="rai_yourapikey", project_id="project-uuid")
user = await client.get_user("user123")
# All methods are the same, just use await
await user.update(new_metadata={"name": "Jane"})
await user.refresh()
session = await user.create_session()
memories = await user.list_memories(limit=10)
```
## Working with Historical Data
When importing historical data or running benchmarks, you can preserve original timestamps:
```python theme={null}
from datetime import datetime, timezone
from recallrai import RecallrAI
from recallrai.models import MessageRole
client = RecallrAI(api_key="rai_yourapikey", project_id="project-uuid")
user = client.get_user("user123")
# Create session with historical timestamp
historical_timestamp = datetime(2024, 12, 25, 14, 30, 0, tzinfo=timezone.utc)
session = user.create_session(
custom_created_at_utc=historical_timestamp,
metadata={"source": "import", "original_platform": "legacy_system"}
)
# Add messages from historical conversation
session.add_message(role=MessageRole.USER, content="What's the weather?")
session.add_message(role=MessageRole.ASSISTANT, content="It's sunny today!")
# Process the session - memories will use the historical timestamp for temporal context
session.process()
```
When sessions are processed with custom timestamps, the memory extraction and context retrieval use that timestamp instead of the current time. This ensures accurate temporal context for benchmarking and historical data analysis.