Official Node.js SDK for RecallrAI – a revolutionary contextual memory system that enables AI assistants to form meaningful connections between conversations, just like human memory.
Note: All datetime objects returned by the SDK are JavaScript Date objects in UTC timezone.
Install the SDK via npm or yarn:
npm install recallrai
# or
yarn add recallraiCreate a client instance with your API key and project ID:
import{RecallrAI}from"recallrai";constclient=newRecallrAI({apiKey: "rai_yourapikey",projectId: "project-uuid",baseUrl: "https://api.recallrai.com",// custom endpoint if applicabletimeout: 60,// seconds});import{UserAlreadyExistsError}from"recallrai";try{constuser=awaitclient.createUser("user123",{name: "John Doe"});console.log(`Created user: ${user.userId}`);console.log(`User metadata:`,user.metadata);console.log(`Created at: ${user.createdAt}`);}catch(error){if(errorinstanceofUserAlreadyExistsError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError}from"recallrai";try{constuser=awaitclient.getUser("user123");console.log(`User metadata:`,user.metadata);console.log(`Last active: ${user.lastActiveAt}`);}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}}If userId is already trusted, you can skip the lookup request:
constuser=awaitclient.getUser("user123",{validate: false});constuserList=awaitclient.listUsers({offset: 0,limit: 10,metadataFilter: {role: "admin"},});console.log(`Total users: ${userList.total}`);console.log(`Has more users: ${userList.hasMore}`);console.log("---");for(constuofuserList.users){console.log(`User ID: ${u.userId}`);console.log(`Metadata:`,u.metadata);console.log(`Created at: ${u.createdAt}`);console.log(`Last active: ${u.lastActiveAt}`);console.log("---");}import{UserNotFoundError,UserAlreadyExistsError}from"recallrai";try{constuser=awaitclient.getUser("user123");awaituser.update({newMetadata: {name: "John Doe",role: "admin"},newUserId: "john_doe",mergeConflictEnabled: true,// override: always raise merge conflicts for this user});console.log(`Updated user ID: ${user.userId}`);console.log(`Updated metadata:`,user.metadata);console.log(`Merge conflict enabled: ${user.mergeConflictEnabled}`);console.log(`Last active: ${user.lastActiveAt}`);}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofUserAlreadyExistsError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError}from"recallrai";try{constuser=awaitclient.getUser("john_doe");awaituser.refresh();console.log(`Refreshed user metadata:`,user.metadata);console.log(`Last active: ${user.lastActiveAt}`);}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError}from"recallrai";try{constuser=awaitclient.getUser("john_doe");awaituser.delete();console.log("User deleted successfully");}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError}from"recallrai";try{constuser=awaitclient.getUser("user123");constsession=awaituser.createSession({autoProcessAfterSeconds: 600,metadata: {type: "chat"},});console.log("Created session id:",session.sessionId);}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError,SessionNotFoundError}from"recallrai";try{constuser=awaitclient.getUser("user123");constsession=awaituser.getSession("session-uuid");console.log("Session status:",session.status);console.log("Session metadata:",session.metadata);}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofSessionNotFoundError){console.log(`Error: ${error.message}`);}}If sessionId is trusted, you can skip this lookup request:
constsession=awaituser.getSession("session-uuid",{validate: false});import{RecallStrategy}from"recallrai";// Skips GET /api/v1/users/{userId}constuser=awaitclient.getUser("user123",{validate: false});// Skips GET /api/v1/users/{userId}/sessions/{sessionId}constsession=awaituser.getSession("session-uuid",{validate: false});// Goes directly to context retrievalconstcontext=awaitsession.getContext({recallStrategy: RecallStrategy.LOW_LATENCY,});console.log(context.context);Use this only when IDs are already trusted by your system. This optimization skips SDK pre-validation calls.
When validate: false is used, unknown reference fields are set to UNAVAILABLE until you call refresh().
Import it from recallrai when you need to check for this sentinel.
import{UserNotFoundError,SessionNotFoundError}from"recallrai";try{constuser=awaitclient.getUser("user123");constsession=awaituser.getSession("session-uuid");awaitsession.update({type: "support_chat"});console.log("Updated session metadata:",session.metadata);}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofSessionNotFoundError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError,SessionNotFoundError}from"recallrai";try{constuser=awaitclient.getUser("user123");constsession=awaituser.getSession("session-uuid");awaitsession.refresh();console.log("Session status:",session.status);console.log("Refreshed session metadata:",session.metadata);}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofSessionNotFoundError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError,SessionNotFoundError}from"recallrai";try{constuser=awaitclient.getUser("user123");constsession=awaituser.getSession("session-uuid");awaitsession.delete();console.log("Session deleted successfully");}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofSessionNotFoundError){console.log(`Error: ${error.message}`);}}import{SessionStatus,UserNotFoundError}from"recallrai";try{constuser=awaitclient.getUser("user123");constsessionList=awaituser.listSessions({offset: 0,limit: 10,metadataFilter: {type: "chat"},statusFilter: [SessionStatus.PENDING,SessionStatus.PROCESSING],});console.log(`Total sessions: ${sessionList.total}`);console.log(`Has more sessions: ${sessionList.hasMore}`);for(constsofsessionList.sessions){console.log(s.sessionId,s.status,s.metadata);}}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError,SessionNotFoundError,InvalidSessionStateError,MessageRole}from"recallrai";try{awaitsession.addMessage(MessageRole.USER,"Hello! How are you?");awaitsession.addMessage(MessageRole.ASSISTANT,"I'm an assistant. How can I help you?");}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofSessionNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofInvalidSessionStateError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError,SessionNotFoundError,RecallStrategy}from"recallrai";try{letcontext=awaitsession.getContext();console.log("Context:",context.context);context=awaitsession.getContext({recallStrategy: RecallStrategy.LOW_LATENCY,});console.log("Context:",context.context);context=awaitsession.getContext({recallStrategy: RecallStrategy.BALANCED,minTopK: 10,maxTopK: 100,memoriesThreshold: 0.6,summariesThreshold: 0.5,lastNMessages: 20,lastNSummaries: 5,timezone: "America/Los_Angeles",});console.log("Context:",context.context);context=awaitsession.getContext({includeMetadataIds: true});if(context.metadata){console.log("Memory IDs:",context.metadata.memoryIds);console.log("Session IDs:",context.metadata.sessionIds);console.log("Vector Queries:",context.metadata.vectorSearchQueries);console.log("Keywords:",context.metadata.keywords);console.log("Summary Queries:",context.metadata.sessionSummariesSearchQueries);console.log("Date Filters:",context.metadata.dateRangeFilters);console.log("Agent Reasoning:",context.metadata.agentReasoning);}}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofSessionNotFoundError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError,SessionNotFoundError,RecallStrategy}from"recallrai";try{forawait(consteventofsession.getContextStream({recallStrategy: RecallStrategy.BALANCED,timezone: "America/Los_Angeles",})){if(event.statusUpdateMessage){console.log("Status:",event.statusUpdateMessage);}if(event.metadata){console.log("Metadata:",event.metadata);}if(event.isFinal){if(event.errorMessage){console.log("Error:",event.errorMessage);}else{console.log("Final context:",event.context);}}}}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofSessionNotFoundError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError,SessionNotFoundError,InvalidSessionStateError}from"recallrai";try{awaitsession.process();}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofSessionNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofInvalidSessionStateError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError,SessionNotFoundError}from"recallrai";try{constmessages=awaitsession.getMessages(0,50);for(constmsgofmessages.messages){console.log(`${msg.role.toUpperCase()} (at ${msg.timestamp}): ${msg.content}`);}console.log(`Has more?: ${messages.hasMore}`);console.log(`Total messages: ${messages.total}`);}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofSessionNotFoundError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError,InvalidCategoriesError}from"recallrai";try{constuser=awaitclient.getUser("user123");constmemories=awaituser.listMemories({categories: ["food_preferences","allergies"],sessionIdFilter: ["session-uuid-1","session-uuid-2"],// optional: filter by specific sessionssessionMetadataFilter: {environment: "production"},// optional: filter by session metadataoffset: 0,limit: 20,includePreviousVersions: true,includeConnectedMemories: true,});for(constmemofmemories.items){console.log(`Memory ID: ${mem.memoryId}`);console.log(`Categories: ${mem.categories}`);console.log(`Content: ${mem.content}`);console.log(`Created at: ${mem.createdAt}`);console.log(`Session ID: ${mem.sessionId}`);console.log(`Version: ${mem.versionNumber} of ${mem.totalVersions}`);console.log(`Has previous versions: ${mem.hasPreviousVersions}`);if(mem.previousVersions){console.log(`Previous versions: ${mem.previousVersions.length}`);for(constversionofmem.previousVersions){console.log(` - Version ${version.versionNumber}: ${version.content}`);console.log(` Created: ${version.createdAt}, Expired: ${version.expiredAt}`);console.log(` Expiration reason: ${version.expirationReason}`);}}if(mem.connectedMemories){console.log(`Connected memories: ${mem.connectedMemories.length}`);for(constconnectedofmem.connectedMemories){console.log(` - ${connected.memoryId}: ${connected.content}`);}}console.log(`Merge conflict in progress: ${mem.mergeConflictInProgress}`);console.log("---");}console.log(`Has more?: ${memories.hasMore}`);console.log(`Total memories: ${memories.total}`);}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofInvalidCategoriesError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError}from"recallrai";try{constuser=awaitclient.getUser("user123");constmessages=awaituser.getLastNMessages(5);for(constmsgofmessages.messages){console.log(`Session ID: ${msg.sessionId}`);console.log(`${msg.role.toUpperCase()} (at ${msg.timestamp}): ${msg.content}`);console.log("---");}}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError,MergeConflictStatus}from"recallrai";try{constuser=awaitclient.getUser("user123");constconflicts=awaituser.listMergeConflicts({offset: 0,limit: 10,status: MergeConflictStatus.PENDING,sortBy: "created_at",sortOrder: "desc",});console.log(`Total conflicts: ${conflicts.total}`);console.log(`Has more: ${conflicts.hasMore}`);for(constconfofconflicts.conflicts){console.log(`Conflict ID: ${conf.conflictId}`);console.log(`Status: ${conf.status}`);console.log(`New memory: ${conf.proposedMemoryContent}`);console.log(`Conflicting memories: ${conf.conflictingMemories.length}`);console.log(`Questions: ${conf.clarifyingQuestions.length}`);console.log(`Created at: ${conf.createdAt}`);console.log("---");}}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError,MergeConflictNotFoundError}from"recallrai";try{constuser=awaitclient.getUser("user123");constconflict=awaituser.getMergeConflict("conflict-uuid");console.log(`Conflict ID: ${conflict.conflictId}`);console.log(`Status: ${conflict.status}`);console.log(`New memory content: ${conflict.proposedMemoryContent}`);console.log("\nConflicting memories:");for(constmemofconflict.conflictingMemories){console.log(` Content: ${mem.content}`);console.log(` Reason: ${mem.reason}`);console.log();}console.log("Clarifying questions:");for(constquesofconflict.clarifyingQuestions){console.log(` Question: ${ques.question}`);console.log(` Options: ${ques.options}`);console.log();}}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofMergeConflictNotFoundError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError,MergeConflictNotFoundError,MergeConflictAlreadyResolvedError,MergeConflictInvalidQuestionsError,MergeConflictMissingAnswersError,MergeConflictInvalidAnswerError,ValidationError,}from"recallrai";try{constuser=awaitclient.getUser("user123");constconflict=awaituser.getMergeConflict("conflict-uuid");constanswers=[];for(constquesofconflict.clarifyingQuestions){console.log(` Question: ${ques.question}`);console.log(` Options: ${ques.options}`);console.log();answers.push({question: ques.question,answer: ques.options[0],message: "User prefers this option based on recent conversation",});}awaitconflict.resolve(answers);console.log(`Conflict resolved! Status: ${conflict.status}`);console.log(`Resolved at: ${conflict.resolvedAt}`);if(conflict.resolutionData){console.log(`Resolution data:`,conflict.resolutionData);}}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofMergeConflictNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofMergeConflictAlreadyResolvedError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofMergeConflictInvalidQuestionsError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofMergeConflictMissingAnswersError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofMergeConflictInvalidAnswerError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofValidationError){console.log(`Error: ${error.message}`);}}import{UserNotFoundError,MergeConflictNotFoundError}from"recallrai";try{constuser=awaitclient.getUser("user123");constconflict=awaituser.getMergeConflict("conflict-uuid");awaitconflict.refresh();console.log(`Current status: ${conflict.status}`);console.log(`Last updated: ${conflict.resolvedAt}`);}catch(error){if(errorinstanceofUserNotFoundError){console.log(`Error: ${error.message}`);}elseif(errorinstanceofMergeConflictNotFoundError){console.log(`Error: ${error.message}`);}}importOpenAIfrom"openai";import{RecallrAI,UserNotFoundError,MessageRole}from"recallrai";constraiClient=newRecallrAI({apiKey: "rai_yourapikey",projectId: "your-project-uuid",});constoaiClient=newOpenAI({apiKey: "your-openai-api-key",});asyncfunctionchatWithMemory(userId: string,sessionId?: string){letuser;try{user=awaitraiClient.getUser(userId);}catch(error){if(errorinstanceofUserNotFoundError){user=awaitraiClient.createUser(userId);}else{throwerror;}}letsession;if(sessionId){session=awaituser.getSession(sessionId);}else{session=awaituser.createSession({autoProcessAfterSeconds: 1800});console.log(`Created new session: ${session.sessionId}`);}console.log("Chat session started. Type 'exit' to end the conversation.");constreadline=require("readline");constrl=readline.createInterface({input: process.stdin,output: process.stdout,});constaskQuestion=(query: string): Promise<string>=>{returnnewPromise((resolve)=>rl.question(query,resolve));};while(true){constuserMessage=awaitaskQuestion("You: ");if(userMessage.toLowerCase()==="exit"){break;}awaitsession.addMessage(MessageRole.USER,userMessage);constcontext=awaitsession.getContext();constsystemPrompt="You are a helpful assistant"+context.context;constmessagesData=awaitsession.getMessages(0,50);constpreviousMessages=messagesData.messages.map((message)=>({role: message.role,content: message.content,}));constresponse=awaitoaiClient.chat.completions.create({model: "gpt-4o-mini",messages: [{role: "system",content: systemPrompt}, ...previousMessages],temperature: 0.7,});constassistantMessage=response.choices[0].message.content||"";console.log(`Assistant: ${assistantMessage}`);awaitsession.addMessage(MessageRole.ASSISTANT,assistantMessage);}rl.close();console.log("Processing session to update memory...");awaitsession.process();console.log(`Session ended. Session ID: ${session.sessionId}`);returnsession.sessionId;}chatWithMemory("user123").then((sessionId)=>{console.log(`To continue this conversation later, use session ID: ${sessionId}`);});The RecallrAI SDK implements a comprehensive exception hierarchy to help you handle different error scenarios gracefully.
- RecallrAIError: Base exception for all SDK-specific errors
- AuthenticationError: Authentication issues with API key or project ID
- TimeoutError: Request timeout
- ConnectionError: Connection issues to the API
- InternalServerError: API returns 5xx error
- RateLimitError: API rate limit exceeded
- UserNotFoundError: User doesn't exist
- UserAlreadyExistsError: User creation with existing ID
- InvalidCategoriesError: Invalid memory categories
- SessionNotFoundError: Session doesn't exist
- InvalidSessionStateError: Invalid operation for session state
- MergeConflictNotFoundError: Merge conflict doesn't exist
- MergeConflictAlreadyResolvedError: Conflict already processed
- MergeConflictInvalidQuestionsError: Invalid clarifying questions
- MergeConflictMissingAnswersError: Missing required answers
- MergeConflictInvalidAnswerError: Invalid answer option
- ValidationError: Request validation failure
import{UserNotFoundError,SessionNotFoundError,InvalidCategoriesError,MergeConflictNotFoundError,MergeConflictAlreadyResolvedError,}from"recallrai";try{// SDK operation}catch(error){if(errorinstanceofUserNotFoundError){// Specific handling}elseif(errorinstanceofRecallrAIError){// General fallback}}This README outlines the basic usage of the RecallrAI SDK functions for user and session management. For additional documentation and advanced usage, please see the official documentation or the source code repository on GitHub.