Skip to content

Repository files navigation

RecallrAI Node.js SDK

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.

Installation

Install the SDK via npm or yarn:

npm install recallrai
# or
yarn add recallrai

Initialization

Create 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});

User Management

Create a User

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}`);}}

Get a User

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});

List Users

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("---");}

Update a User

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}`);}}

Refresh User Instance

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}`);}}

Delete a User

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}`);}}

Session Management

Create a Session

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}`);}}

Get an Existing Session

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});

Trusted IDs - Skip Validation Lookups

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.

Update a Session

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}`);}}

Refresh a Session

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}`);}}

Delete a Session

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}`);}}

List Sessions

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}`);}}

Session – Adding Messages

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}`);}}

Session – Retrieving Context

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}`);}}

Session – Streaming Context

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}`);}}

Session – Process Session

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}`);}}

Session – List Messages

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}`);}}

User Memories

List User Memories (with optional category filters)

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}`);}}

User Messages

Get Last N Messages

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}`);}}

Merge Conflict Management

List Merge Conflicts

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}`);}}

Get a Specific Merge Conflict

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}`);}}

Resolve a Merge Conflict

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}`);}}

Refresh Merge Conflict Data

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}`);}}

Example Usage with LLMs

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}`);});

Exception Handling

The RecallrAI SDK implements a comprehensive exception hierarchy to help you handle different error scenarios gracefully.

Available Exceptions

  • 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

Importing Exceptions

import{UserNotFoundError,SessionNotFoundError,InvalidCategoriesError,MergeConflictNotFoundError,MergeConflictAlreadyResolvedError,}from"recallrai";

Best Practices for Error Handling

try{// SDK operation}catch(error){if(errorinstanceofUserNotFoundError){// Specific handling}elseif(errorinstanceofRecallrAIError){// General fallback}}

Conclusion

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.

About

Official Node.js SDK for RecallrAI - Revolutionary contextual memory system that enables AI assistants to form meaningful connections between conversations, just like human memory."

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages