Enterprise-grade TypeScript SDK for the RecallBricks API. Build intelligent memory systems with semantic search, graph relationships, and persistent context.
- Full TypeScript Support: Complete type definitions for all API operations
- Retry Logic: Automatic exponential backoff for transient failures
- Error Handling: Comprehensive error types with detailed context
- Timeout Configuration: Configurable request timeouts
- Production Ready: 40+ tests covering unit, integration, edge cases, and security
- Zero Dependencies: Only axios for HTTP requests
- Autonomous Agent Features: Working memory, prospective memory, metacognition, and more
npm install recallbricksOr with yarn:
yarn add recallbricksimport { RecallBricks } from 'recallbricks';
// Initialize the client
const client = new RecallBricks({
apiKey: 'your-api-key',
baseUrl: 'http://localhost:10002/api/v1', // Optional, defaults to localhost
timeout: 30000, // Optional, defaults to 30s
maxRetries: 3, // Optional, defaults to 3
});
// Create a memory
const memory = await client.createMemory('User prefers dark mode', {
tags: ['preference', 'ui'],
metadata: { userId: '123', source: 'settings' }
});
console.log(`Created memory: ${memory.id}`);interface RecallBricksConfig {
apiKey: string; // Required: Your API key
baseUrl?: string; // Optional: API base URL
timeout?: number; // Optional: Request timeout in ms (default: 30000)
maxRetries?: number; // Optional: Max retry attempts (default: 3)
retryDelay?: number; // Optional: Initial retry delay in ms (default: 1000)
maxRetryDelay?: number; // Optional: Max retry delay in ms (default: 10000)
}Create a new memory with optional metadata and tags.
const memory = await client.createMemory('Important information', {
tags: ['important', 'work'],
metadata: {
userId: '123',
category: 'business'
},
timestamp: '2025-01-01T12:00:00Z' // Optional
});Parameters:
text(string): The content of the memoryoptions(object, optional):tags(string[]): Array of tags for categorizationmetadata(object): Key-value pairs for additional contexttimestamp(string): ISO 8601 timestamp
Returns: Promise<Memory>
List memories with filtering and pagination.
const result = await client.listMemories({
limit: 10,
offset: 0,
tags: ['important'],
metadata: { userId: '123' },
sort: 'desc',
sortBy: 'created_at'
});
console.log(`Found ${result.total} memories`);
result.memories.forEach(memory => {
console.log(`- ${memory.text}`);
});Parameters:
options(object, optional):limit(number): Max number of resultsoffset(number): Pagination offsettags(string[]): Filter by tagsmetadata(object): Filter by metadatasort('asc' | 'desc'): Sort ordersortBy(string): Field to sort by
Returns: Promise<ListMemoriesResponse>
Semantic search across memories.
const results = await client.search('user preferences', {
limit: 5,
threshold: 0.7,
tags: ['preference'],
metadata: { userId: '123' }
});
results.results.forEach(result => {
console.log(`[${result.score.toFixed(2)}] ${result.memory.text}`);
});Parameters:
query(string): Search queryoptions(object, optional):limit(number): Max results to returnthreshold(number): Minimum similarity score (0-1)tags(string[]): Filter by tagsmetadata(object): Filter by metadata
Returns: Promise<SearchResponse>
Get all relationships (incoming and outgoing) for a memory.
const relationships = await client.getRelationships('mem-123');
console.log(`Outgoing: ${relationships.outgoing.length}`);
relationships.outgoing.forEach(rel => {
console.log(` -> ${rel.target_id} (${rel.type}, strength: ${rel.strength})`);
});
console.log(`Incoming: ${relationships.incoming.length}`);
relationships.incoming.forEach(rel => {
console.log(` <- ${rel.source_id} (${rel.type}, strength: ${rel.strength})`);
});Parameters:
memoryId(string): ID of the memory
Returns: Promise<RelationshipsResponse>
Get the graph context around a memory up to a specified depth.
const graph = await client.getGraphContext('mem-123', 3);
console.log(`Root: ${graph.root_id}`);
console.log(`Total nodes: ${graph.total_nodes}`);
graph.nodes.forEach(node => {
console.log(`[Depth ${node.depth}] ${node.memory.text}`);
console.log(` Relationships: ${node.relationships.length}`);
});Parameters:
memoryId(string): Root memory IDdepth(number, optional): Max traversal depth (1-10, default: 2)
Returns: Promise<GraphContextResponse>
Update an existing memory.
const updated = await client.updateMemory('mem-123', {
text: 'Updated text',
tags: ['updated', 'important'],
metadata: { version: 2 }
});
console.log(`Updated at: ${updated.updated_at}`);Parameters:
memoryId(string): ID of the memory to updateupdates(object): Fields to updatetext(string, optional): New text contenttags(string[], optional): New tagsmetadata(object, optional): New metadata
Returns: Promise<Memory>
Delete a memory by ID.
await client.deleteMemory('mem-123');
console.log('Memory deleted successfully');Parameters:
memoryId(string): ID of the memory to delete
Returns: Promise<boolean>
import { RecallBricks } from 'recallbricks';
const client = new RecallBricks({ apiKey: process.env.RECALLBRICKS_API_KEY! });
// Store user preferences
async function savePreference(userId: string, preference: string, value: any) {
return await client.createMemory(
`User ${userId} set ${preference} to ${value}`,
{
tags: ['preference', preference],
metadata: { userId, preference, value: String(value) }
}
);
}
// Retrieve user preferences
async function getUserPreferences(userId: string) {
const results = await client.listMemories({
tags: ['preference'],
metadata: { userId },
limit: 100
});
return results.memories;
}
// Find similar preferences across users
async function findSimilarPreferences(preferenceDescription: string) {
const results = await client.search(preferenceDescription, {
tags: ['preference'],
threshold: 0.8,
limit: 10
});
return results.results;
}// Store conversation turns
async function saveConversation(conversationId: string, role: string, content: string) {
return await client.createMemory(content, {
tags: ['conversation', role],
metadata: {
conversationId,
role,
timestamp: new Date().toISOString()
}
});
}
// Retrieve conversation history
async function getConversationHistory(conversationId: string) {
const results = await client.listMemories({
tags: ['conversation'],
metadata: { conversationId },
sort: 'asc',
sortBy: 'created_at'
});
return results.memories;
}
// Find relevant context from past conversations
async function findRelevantContext(query: string, conversationId: string) {
return await client.search(query, {
tags: ['conversation'],
metadata: { conversationId },
threshold: 0.7,
limit: 5
});
}// Create interconnected memories
async function buildKnowledgeGraph() {
const concept1 = await client.createMemory('Machine learning is a subset of AI', {
tags: ['concept', 'ml', 'ai']
});
const concept2 = await client.createMemory('Deep learning uses neural networks', {
tags: ['concept', 'deep-learning']
});
const concept3 = await client.createMemory('Neural networks mimic brain structure', {
tags: ['concept', 'neural-networks']
});
return [concept1, concept2, concept3];
}
// Explore relationships
async function exploreRelationships(memoryId: string) {
// Get immediate relationships
const relationships = await client.getRelationships(memoryId);
// Get broader context
const graph = await client.getGraphContext(memoryId, 3);
return { relationships, graph };
}async function getAllMemories() {
const allMemories = [];
let offset = 0;
const limit = 100;
let hasMore = true;
while (hasMore) {
const result = await client.listMemories({ limit, offset });
allMemories.push(...result.memories);
offset += limit;
hasMore = result.memories.length === limit;
}
return allMemories;
}The SDK includes specialized clients for building autonomous AI agents with human-like memory systems.
Attention-based active memory with limited capacity, like human working memory.
// Create a working memory session
const session = await client.workingMemory.createSession({
namespace: 'task-planning',
capacity: 7, // Miller's magic number
ttlSeconds: 3600,
agentId: 'agent-001'
});
// Add memories to working memory
await client.workingMemory.addMemory(session.id, 'mem-456', {
priority: 8,
relevanceScore: 0.95,
tags: ['current-task', 'important']
});
// Promote important items
await client.workingMemory.promote('item-789');
// Auto-manage (evict low-priority, promote relevant)
const result = await client.workingMemory.autoManage(session.id);
console.log(`Evicted: ${result.summary.itemsEvicted}`);"Remember to remember" - set intentions triggered by future events.
// Create an intention to be triggered later
const intention = await client.prospectiveMemory.create({
namespace: 'reminders',
description: 'Remind about project deadline when user mentions "status"',
triggers: [
{ type: 'keyword', value: 'status' },
{ type: 'time', value: '2025-01-15T09:00:00Z' }
],
action: {
type: 'inject_context',
parameters: { memoryIds: ['mem-deadline'] }
},
priority: 8
});
// Check for triggered intentions
const result = await client.prospectiveMemory.checkTriggers({
currentText: 'What is the project status?'
});
if (result.triggered.length > 0) {
// Handle triggered intentions
for (const intent of result.triggered) {
await client.prospectiveMemory.complete(intent.id);
}
}Three types of human-like memory for different kinds of knowledge.
// Episodic: Specific events and experiences
const episode = await client.memoryTypes.createEpisodic({
namespace: 'conversations',
content: 'User asked about weather in Paris',
entities: ['user-123', 'Paris', 'weather'],
emotionalValence: 0.3,
importance: 0.7
});
// Semantic: Facts and concepts
const fact = await client.memoryTypes.createSemantic({
namespace: 'knowledge',
content: 'Paris is the capital of France',
category: 'geography',
confidence: 1.0,
relatedConcepts: ['France', 'Europe', 'capitals']
});
// Procedural: Skills and how-to knowledge
const procedure = await client.memoryTypes.createProcedural({
namespace: 'workflows',
name: 'Handle API Errors',
description: 'Steps to handle API error responses',
steps: [
{ order: 1, description: 'Log the error with context' },
{ order: 2, description: 'Determine if retryable' },
{ order: 3, description: 'Retry with backoff or return fallback' }
],
triggers: ['API error', 'network failure']
});
// Query by type
const recentEpisodes = await client.memoryTypes.getEpisodic({
entities: ['user-123'],
minImportance: 0.5,
limit: 10
});Self-assessment and performance tracking for agents.
// Assess quality of agent output
const assessment = await client.metacognition.assess({
agentId: 'agent-001',
content: 'The capital of France is Paris',
contentType: 'response',
selfScore: 0.95,
confidence: 0.9,
reasoning: 'Well-known factual information'
});
console.log(`Quality: ${assessment.qualityScore}`);
console.log(`Calibration: ${assessment.calibrationScore}`);
// Get performance metrics
const performance = await client.metacognition.getPerformance('agent-001', {
days: 30
});
console.log(`Overall score: ${performance.overallScore}`);
console.log(`Confidence correlation: ${performance.confidenceCorrelation}`);
// Get actionable insights
const insights = await client.metacognition.getInsights('agent-001', {
minImportance: 7
});Hierarchical objective tracking with milestones.
// Create a goal with milestones
const goal = await client.goals.create({
namespace: 'project-alpha',
title: 'Implement User Authentication',
description: 'Add secure auth with OAuth support',
type: 'achievement',
priority: 9,
milestones: [
{ description: 'Design auth flow' },
{ description: 'Implement OAuth provider' },
{ description: 'Add session management' },
{ description: 'Write tests' }
],
successCriteria: ['All tests pass', 'Security review complete']
});
// Track progress
const result = await client.goals.advance(goal.id, {
action: 'Completed OAuth integration',
milestoneId: 'milestone-2',
progressDelta: 25
});
if (result.goalCompleted) {
console.log('Goal achieved!');
}
// Get active goals
const activeGoals = await client.goals.getActive('project-alpha');Know what you don't know - critical for autonomous decision-making.
// Quantify uncertainty
const result = await client.uncertainty.quantify({
agentId: 'agent-001',
content: 'Sales will increase 15% next quarter',
contentType: 'prediction',
selfConfidence: 0.75,
knownUnknowns: ['Market conditions', 'Competitor actions'],
assumptions: ['Economic stability', 'No major disruptions'],
evidence: [
{ source: 'historical-data', strength: 0.8, description: '3 years of data' }
]
});
console.log(`Uncertainty: ${result.uncertaintyScore}`);
console.log(`Reliability: ${result.reliability}`);
console.log(`Epistemic: ${result.epistemicUncertainty}`);
console.log(`Aleatoric: ${result.aleatoricUncertainty}`);
if (result.deferAction) {
console.log('Too uncertain - gather more information');
console.log('Suggested queries:', result.suggestedQueries);
}Maintain memory quality by identifying stale content.
// Find stale memories
const stale = await client.health.getStale('knowledge-base', 30, {
minImportance: 0.5
});
// Refresh memories that need updating
for (const memory of stale.filter(m => m.recommendation === 'refresh')) {
await client.health.refresh(memory.id, 'scheduled-review');
}
// Get comprehensive health report
const report = await client.health.getReport('production');
console.log(`Health Score: ${report.metrics.healthScore}/100`);
console.log(`Trend: ${report.trend.direction}`);Intelligently assemble context from multiple sources.
// Build context for a query
const context = await client.context.build({
namespace: 'customer-support',
query: 'Help user with billing issue',
maxTokens: 8000,
sources: [
{ type: 'working_memory', config: { sessionId: 'current' }, weight: 2.0 },
{ type: 'semantic', config: { category: 'billing' }, weight: 1.5 },
{ type: 'episodic', config: { entities: ['user-123'] }, maxItems: 5 },
{ type: 'procedural', config: { trigger: 'billing' } }
],
includeProspective: true,
includeGoals: true
});
console.log(`Quality: ${context.qualityScore}`);
console.log(`Tokens: ${context.totalTokens}/${context.totalTokens + context.tokensRemaining}`);
// Use the formatted context
const formattedContext = context.formattedContext;Advanced search combining semantic, keyword, graph, and recency signals.
const results = await client.hybridSearch.hybrid('payment processing error', {
namespace: 'support-tickets',
memoryTypes: ['episodic', 'semantic'],
semanticWeight: 0.5,
keywordWeight: 0.2,
graphWeight: 0.15,
recencyWeight: 0.15,
includeRelationships: true,
expandQuery: true,
rerank: true
});
console.log(`Found ${results.totalFound} results in ${results.searchDurationMs}ms`);
results.results.forEach(r => {
console.log(`[${r.score.toFixed(3)}] ${r.content}`);
console.log(` Semantic: ${r.componentScores.semantic.toFixed(2)}`);
console.log(` Keyword: ${r.componentScores.keyword.toFixed(2)}`);
});The SDK uses a custom RecallBricksError class for all API errors:
import { RecallBricksError } from 'recallbricks';
try {
const memory = await client.createMemory('test');
} catch (error) {
if (error instanceof RecallBricksError) {
console.error(`Error ${error.statusCode}: ${error.message}`);
console.error(`Code: ${error.code}`);
console.error(`Details:`, error.details);
} else {
console.error('Unexpected error:', error);
}
}message(string): Human-readable error messagestatusCode(number): HTTP status codecode(string): Error code from APIdetails(unknown): Additional error details
The SDK automatically retries failed requests with exponential backoff for:
- Network errors (connection refused, timeout, etc.)
- 429 (Rate Limit Exceeded)
- 500+ (Server errors)
Non-retryable errors (fail immediately):
- 400 (Bad Request)
- 401 (Unauthorized)
- 403 (Forbidden)
- 404 (Not Found)
Configure retry behavior:
const client = new RecallBricks({
apiKey: 'your-api-key',
maxRetries: 5, // Max number of retry attempts
retryDelay: 500, // Initial delay in ms
maxRetryDelay: 30000, // Max delay in ms (caps exponential backoff)
});All types are exported from the main module:
import {
RecallBricks,
RecallBricksConfig,
RecallBricksError,
Memory,
CreateMemoryOptions,
ListMemoriesOptions,
ListMemoriesResponse,
SearchOptions,
SearchResponse,
SearchResult,
Relationship,
RelationshipsResponse,
GraphNode,
GraphContextResponse,
UpdateMemoryOptions,
MemoryMetadata,
} from 'recallbricks';# Install dependencies
npm install
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Build
npm run build
# Lint
npm run lintThe SDK includes comprehensive test coverage:
- Unit Tests: Client initialization, configuration, and individual methods
- Integration Tests: Full workflows and real-world scenarios
- Edge Case Tests: Boundary conditions, malformed data, and error scenarios
- Security Tests: Input validation, injection prevention, and data protection
Run tests:
npm testView coverage report:
npm run test:coverage- Node.js 16.0.0 or higher
- TypeScript 5.0+ (for development)
MIT
For issues and feature requests, please file an issue on the project repository.
Contributions are welcome! Please ensure all tests pass and coverage remains high:
npm test
npm run test:coverage