# 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.