code

TypeScript Client

Lightweight TypeScript REST client for the Rekall API. A thin, fully-typed wrapper with no local storage -- ideal for server-side services, scripts, and dashboards.

@rekall/client~8 KB

Installation

npm install @rekall/client

No native dependencies

The client has zero native dependencies. It uses the standard fetch API and works in Node.js 18+, Deno, Bun, and edge runtimes like Cloudflare Workers.

Initialization

client.ts
import { RekallClient } from '@rekall/client';
const client = new RekallClient({
apiKey: process.env.REKALL_API_KEY!,
baseUrl: 'https://api.rekall.ai/v1', // Default
timeout: 30_000, // Request timeout in ms
retries: 3, // Automatic retries on 5xx
});

The client is stateless. Each method call maps directly to a single API request. There is no local caching, sync, or background processing.

Memories

Full CRUD operations for memories. Each method returns typed response objects.

Create a memory
const memory = await client.memories.create({
type: 'episodic',
content: 'User completed onboarding flow successfully.',
agentId: 'onboarding-agent',
context: 'user',
importance: 0.7,
metadata: {
userId: 'user_123',
step: 'complete',
duration: 45,
},
});
console.log(memory.id); // 'mem_abc123...'
Read, update, and delete
// Get a single memory
const memory = await client.memories.get('mem_abc123');
// Update a memory
const updated = await client.memories.update('mem_abc123', {
content: 'Updated content for this memory.',
importance: 0.9,
metadata: { ...memory.metadata, reviewed: true },
});
// Delete a memory
await client.memories.delete('mem_abc123');
// List memories with filters
const list = await client.memories.list({
agentId: 'onboarding-agent',
type: 'episodic',
context: 'user',
limit: 25,
offset: 0,
});
console.log(list.data); // Memory[]
console.log(list.total); // Total count
console.log(list.hasMore); // Pagination flag

Semantic search across memories using vector embeddings. Filter by type, context, metadata, and time range.

const results = await client.memories.search({
query: 'customer onboarding issues',
agentId: 'support-agent',
type: 'episodic',
limit: 10,
threshold: 0.7,
filters: {
createdAfter: '2024-06-01T00:00:00Z',
tags: { contains: 'support' },
},
});
for (const result of results.data) {
console.log(result.memory.content);
console.log(result.score); // Similarity score 0.0 - 1.0
}

Entities

Create, read, update, and delete entities in the knowledge graph.

// Create an entity
const entity = await client.entities.create({
name: 'Acme Corp',
type: 'organization',
agentId: 'research-agent',
attributes: {
industry: 'Technology',
employees: 5000,
},
});
// Get an entity
const fetched = await client.entities.get(entity.id);
// Update an entity
await client.entities.update(entity.id, {
attributes: { employees: 5200 },
});
// Delete an entity
await client.entities.delete(entity.id);
// List entities
const entities = await client.entities.list({
agentId: 'research-agent',
type: 'organization',
limit: 50,
});

Relationships

// Create a relationship
const rel = await client.relationships.create({
sourceEntityId: 'ent_abc',
targetEntityId: 'ent_def',
type: 'acquired',
attributes: { date: '2024-03-15', amount: '2.5B' },
});
// List relationships for an entity
const rels = await client.relationships.list({
entityId: 'ent_abc',
type: 'acquired',
direction: 'outgoing', // 'incoming' | 'outgoing' | 'both'
});
// Query the knowledge graph
const graph = await client.entities.graph({
rootId: 'ent_abc',
depth: 3,
relationshipTypes: ['acquired', 'partner_of'],
});

Agents

Manage agent registrations and query agent state through the API.

// Register an agent
const agent = await client.agents.create({
agentId: 'support-agent',
name: 'Support Assistant',
description: 'Handles customer support tickets',
config: {
model: 'claude-3-opus',
systemPrompt: 'You are a support assistant...',
},
});
// Get agent details
const details = await client.agents.get('support-agent');
// List all agents
const agents = await client.agents.list({ limit: 50 });
// Update agent configuration
await client.agents.update('support-agent', {
config: { model: 'claude-3-5-sonnet' },
});
// Delete an agent
await client.agents.delete('support-agent');

Hives

Hives are shared memory contexts for groups of agents. Manage hive membership and shared memories.

// Create a hive
const hive = await client.hives.create({
name: 'Research Team',
description: 'Shared knowledge base for research agents',
});
// Add agents to a hive
await client.hives.addMember(hive.id, {
agentId: 'research-agent-1',
role: 'contributor', // 'viewer' | 'contributor' | 'admin'
});
await client.hives.addMember(hive.id, {
agentId: 'research-agent-2',
role: 'contributor',
});
// List hive members
const members = await client.hives.listMembers(hive.id);
// Remove an agent from a hive
await client.hives.removeMember(hive.id, 'research-agent-1');
// List hives
const hives = await client.hives.list({ limit: 25 });

Workflows & Execution

Create workflows and manage execution state, including checkpoints, pause, and resume.

// Create a workflow
const workflow = await client.workflows.create({
name: 'Data Pipeline',
agentId: 'pipeline-agent',
steps: [
{ id: 'fetch', name: 'Fetch Data', type: 'action' },
{ id: 'transform', name: 'Transform', type: 'action' },
{ id: 'validate', name: 'Validate', type: 'decision' },
{ id: 'store', name: 'Store Results', type: 'action' },
],
});
// Start an execution
const execution = await client.executions.create({
workflowId: workflow.id,
input: { source: 'https://data.example.com/feed.json' },
});
// Get execution status
const status = await client.executions.get(execution.id);
console.log(status.state); // 'running' | 'paused' | 'completed' | 'failed'
console.log(status.currentStep);
// Checkpoint an execution
await client.executions.checkpoint(execution.id, {
state: { processedRows: 1500 },
});
// Pause and resume
await client.executions.pause(execution.id);
await client.executions.resume(execution.id);
// List executions
const executions = await client.executions.list({
workflowId: workflow.id,
state: 'running',
});

Error Handling

The client throws typed errors for all failure cases. Every error includes the HTTP status code, error code, and a human-readable message.

import { RekallClient, RekallError, RekallNotFoundError, RekallRateLimitError } from '@rekall/client';
try {
const memory = await client.memories.get('mem_nonexistent');
} catch (error) {
if (error instanceof RekallNotFoundError) {
console.log('Memory not found:', error.resourceId);
} else if (error instanceof RekallRateLimitError) {
console.log('Rate limited. Retry after:', error.retryAfterMs, 'ms');
} else if (error instanceof RekallError) {
console.log('API error:', error.status, error.code, error.message);
} else {
throw error; // Re-throw unexpected errors
}
}
// Error types exported by the client:
// - RekallError (base class, any API error)
// - RekallAuthError (401 - invalid or expired API key)
// - RekallForbiddenError (403 - insufficient permissions)
// - RekallNotFoundError (404 - resource not found)
// - RekallValidationError (422 - invalid request body)
// - RekallRateLimitError (429 - rate limit exceeded)
// - RekallServerError (500+ - server error, auto-retried)

Pagination

All list endpoints return paginated results. The client includes helpers for iterating through pages.

// Manual pagination
let offset = 0;
const limit = 50;
let hasMore = true;
while (hasMore) {
const page = await client.memories.list({
agentId: 'my-agent',
limit,
offset,
});
for (const memory of page.data) {
console.log(memory.id);
}
hasMore = page.hasMore;
offset += limit;
}
// Automatic pagination with async iterator
for await (const memory of client.memories.iterate({
agentId: 'my-agent',
type: 'episodic',
})) {
console.log(memory.id);
// Automatically fetches next page when needed
}
// Collect all results into an array
const allMemories = await client.memories.all({
agentId: 'my-agent',
type: 'episodic',
});

Type Definitions

The client exports all request and response types for full IntelliSense and type safety.

Exported types
import type {
// Memory types
Memory,
MemoryType,
MemoryContext,
MemoryCreateInput,
MemoryUpdateInput,
MemoryListInput,
MemorySearchInput,
MemorySearchResult,
// Entity types
Entity,
EntityCreateInput,
EntityUpdateInput,
// Relationship types
Relationship,
RelationshipCreateInput,
GraphQueryInput,
GraphQueryResult,
// Agent types
Agent,
AgentCreateInput,
AgentUpdateInput,
// Hive types
Hive,
HiveCreateInput,
HiveMember,
// Workflow and Execution types
Workflow,
WorkflowCreateInput,
Execution,
ExecutionCreateInput,
ExecutionState,
// Pagination
PaginatedResponse,
ListParams,
// Errors
RekallError,
RekallErrorCode,
} from '@rekall/client';
Paginated response shape
interface PaginatedResponse<T> {
data: T[];
total: number;
limit: number;
offset: number;
hasMore: boolean;
}

Progressive Disclosure

The lightweight client supports progressive disclosure via the search-index and batch endpoints for token-efficient memory retrieval.

// Step 1: Get lightweight search index
const index = await client.post('/v1/memories/search-index', {
query: 'project requirements',
token_budget: 2000,
limit: 50,
});
// Step 2: Review snippets and select relevant IDs
const relevantIds = index.data.index
.filter((e: any) => e.score > 0.7)
.map((e: any) => e.id);
// Step 3: Load full content for selected memories only
const memories = await client.post('/v1/memories/batch', {
ids: relevantIds,
});
Rekall
rekall