Memory SDK
AI memory SDK with semantic search, knowledge graphs, and context management.
Installation
Install the Memory SDK using your preferred package manager:
npm install @usetransactional/memorypnpm add @usetransactional/memoryyarn add @usetransactional/memoryQuick Start
import { MemoryClient } from '@usetransactional/memory';
const client = new MemoryClient({
apiKey: 'your-api-key',
});
// Add a memory
await client.add({
content: 'User prefers dark mode and compact layouts.',
userId: 'user-123',
type: 'preference',
});
// Search memories
const results = await client.search({
query: 'UI preferences',
userId: 'user-123',
strategy: 'semantic',
});
// Get context for an LLM prompt
const context = await client.getContext({
userId: 'user-123',
query: 'Help the user customize their dashboard',
maxTokens: 2000,
includeProfile: true,
includeFacts: true,
includePreferences: true,
});Configuration
Create a client instance with your API key and optional configuration:
import { MemoryClient } from '@usetransactional/memory';
const client = new MemoryClient({
apiKey: 'your-api-key',
baseUrl: 'https://api.usetransactional.com',
timeout: 30000,
maxRetries: 3,
headers: {
'X-Custom-Header': 'value',
},
});| Option | Type | Required | Default | Description |
|---|---|---|---|---|
apiKey | string | Yes | - | Your Transactional API key |
baseUrl | string | No | https://api.usetransactional.com | API base URL |
timeout | number | No | 30000 | Request timeout in milliseconds |
maxRetries | number | No | 3 | Maximum number of retry attempts for failed requests |
headers | Record<string, string> | No | - | Additional HTTP headers to include in every request |
Memory Operations
add()
Store a new memory associated with a user:
const memory = await client.add({
content: 'User mentioned they work at Acme Corp as a senior engineer.',
userId: 'user-123',
sessionId: 'session-abc',
type: 'fact',
metadata: {
source: 'chat',
confidence: 0.95,
},
});
console.log(memory.id); // 'mem_abc123'| Parameter | Type | Required | Description |
|---|---|---|---|
content | string | Yes | The memory content to store |
userId | string | Yes | User ID to associate the memory with |
sessionId | string | No | Session ID for grouping related memories |
type | string | No | Memory type (e.g., 'fact', 'preference', 'event') |
metadata | Record<string, unknown> | No | Arbitrary metadata to attach |
search()
Search memories using keyword, semantic, or hybrid strategies:
const results = await client.search({
query: 'work experience and company',
userId: 'user-123',
types: ['fact', 'entity'],
strategy: 'hybrid',
threshold: 0.7,
limit: 10,
includeRelated: true,
});
for (const result of results) {
console.log(result.content, result.score);
}| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search query |
userId | string | Yes | User ID to search within |
types | string[] | No | Filter by memory types |
strategy | 'auto' | 'keyword' | 'semantic' | 'hybrid' | No | Search strategy. Defaults to 'auto' |
threshold | number | No | Minimum relevance score (0 to 1) |
limit | number | No | Maximum number of results |
includeRelated | boolean | No | Include related memories via knowledge graph connections |
Search strategies:
| Strategy | Description |
|---|---|
auto | Automatically selects the best strategy based on the query |
keyword | Traditional keyword matching, best for exact terms |
semantic | Vector similarity search, best for conceptual queries |
hybrid | Combines keyword and semantic search for balanced results |
get()
Retrieve a specific memory by session and memory ID:
const memory = await client.get('session-abc', 'mem_abc123');
console.log(memory.content);update()
Update an existing memory's name or properties:
await client.update('session-abc', 'mem_abc123', {
name: 'Work Info',
properties: {
verified: true,
lastConfirmed: '2025-01-15',
},
});delete()
Delete a specific memory:
await client.delete('session-abc', 'mem_abc123');getContext()
Generate a formatted context string optimized for LLM system prompts. This method aggregates relevant memories, profile data, facts, and preferences into a single context block:
const context = await client.getContext({
userId: 'user-123',
sessionId: 'session-abc',
query: 'Help the user with their project settings',
maxTokens: 2000,
includeProfile: true,
includeFacts: true,
includePreferences: true,
});
// Use the context in an LLM system prompt
const systemPrompt = `You are a helpful assistant. Here is what you know about the user:
${context.text}
Use this context to personalize your responses.`;| Parameter | Type | Required | Description |
|---|---|---|---|
userId | string | Yes | User ID to generate context for |
sessionId | string | No | Limit context to a specific session |
query | string | No | Relevance query to prioritize related memories |
maxTokens | number | No | Maximum token budget for the context |
includeProfile | boolean | No | Include user profile information |
includeFacts | boolean | No | Include stored facts about the user |
includePreferences | boolean | No | Include user preferences |
getJobStatus()
Check the status of an asynchronous job (e.g., content ingestion):
const status = await client.getJobStatus('job_xyz789');
console.log(status.state); // 'pending' | 'processing' | 'completed' | 'failed'Sessions
Sessions group related memories and conversations together. They support auto-extraction and auto-summarization of memories from conversation messages.
sessions.create()
const session = await client.sessions.create({
userId: 'user-123',
agentId: 'support-bot',
ttl: 86400, // 24 hours in seconds
config: {
autoExtract: true,
autoSummarize: true,
},
});
console.log(session.id); // 'ses_abc123'| Parameter | Type | Required | Description |
|---|---|---|---|
userId | string | Yes | User ID to associate the session with |
agentId | string | No | Agent or bot identifier |
ttl | number | No | Time-to-live in seconds before the session expires |
config.autoExtract | boolean | No | Automatically extract memories from messages |
config.autoSummarize | boolean | No | Automatically generate session summaries |
sessions.get()
const session = await client.sessions.get('ses_abc123');sessions.list()
import { MemorySessionStatus } from '@usetransactional/memory';
const sessions = await client.sessions.list({
userId: 'user-123',
status: MemorySessionStatus.ACTIVE,
page: 1,
limit: 20,
});| Parameter | Type | Required | Description |
|---|---|---|---|
userId | string | No | Filter sessions by user ID |
status | MemorySessionStatus | No | Filter by session status |
page | number | No | Page number for pagination |
limit | number | No | Results per page |
sessions.update()
await client.sessions.update('ses_abc123', {
ttl: 172800, // Extend to 48 hours
});sessions.delete()
await client.sessions.delete('ses_abc123');Profiles
Profiles store persistent facts and preferences about a user that span across sessions.
profiles.get()
const profile = await client.profiles.get('user-123');
console.log(profile.staticFacts); // e.g., { name: 'Jane', role: 'Engineer' }
console.log(profile.dynamicFacts); // e.g., { currentProject: 'Dashboard Redesign' }profiles.upsert()
Create or update a user profile with static and dynamic facts:
await client.profiles.upsert('user-123', {
staticFacts: {
name: 'Jane Doe',
company: 'Acme Corp',
role: 'Senior Engineer',
},
dynamicFacts: {
currentProject: 'Dashboard Redesign',
preferredLanguage: 'TypeScript',
timezone: 'America/New_York',
},
});Static facts are permanent attributes that rarely change (name, company, role). Dynamic facts are contextual information that may change over time (current project, recent activity).
profiles.delete()
await client.profiles.delete('user-123');Knowledge Graph
The knowledge graph connects memories through entity relationships, enabling traversal and discovery of related information.
graph.get()
Retrieve the knowledge graph for a session:
const graph = await client.graph.get({
sessionId: 'ses_abc123',
depth: 2,
entityTypes: ['entity', 'topic', 'relationship'],
limit: 50,
});
for (const node of graph.nodes) {
console.log(node.name, node.type, node.properties);
}
for (const edge of graph.edges) {
console.log(edge.source, '->', edge.target, `[${edge.label}]`);
}| Parameter | Type | Required | Description |
|---|---|---|---|
sessionId | string | Yes | Session to retrieve the graph for |
depth | number | No | Maximum traversal depth from root nodes |
entityTypes | string[] | No | Filter by entity types |
limit | number | No | Maximum number of nodes to return |
graph.traverse()
Traverse the graph starting from a specific entity:
const subgraph = await client.graph.traverse({
startEntityId: 'ent_abc123',
depth: 3,
direction: 'outbound',
});| Parameter | Type | Required | Description |
|---|---|---|---|
startEntityId | string | Yes | Entity ID to start traversal from |
depth | number | No | Maximum traversal depth |
direction | 'outbound' | 'inbound' | 'both' | No | Traversal direction. Defaults to 'both' |
Content Ingestion
Ingest external content to automatically extract memories, entities, and embeddings.
ingest.url()
Ingest content from a URL:
const job = await client.ingest.url({
url: 'https://example.com/docs/getting-started',
userId: 'user-123',
sessionId: 'ses_abc123',
options: {
extractEntities: true,
generateEmbeddings: true,
},
});
// Check ingestion progress
const status = await client.getJobStatus(job.jobId);ingest.pdf()
Ingest content from a PDF file:
import { readFileSync } from 'fs';
const pdfBuffer = readFileSync('/path/to/document.pdf');
const job = await client.ingest.pdf({
file: pdfBuffer,
filename: 'document.pdf',
userId: 'user-123',
options: {
extractEntities: true,
generateEmbeddings: true,
},
});| Parameter | Type | Required | Description |
|---|---|---|---|
file | Buffer | Yes | PDF file contents as a Buffer |
filename | string | Yes | Original filename |
userId | string | Yes | User ID to associate extracted memories with |
options.extractEntities | boolean | No | Extract named entities from the document |
options.generateEmbeddings | boolean | No | Generate vector embeddings for semantic search |
ingest.text()
Ingest raw text content:
const job = await client.ingest.text({
content: '# Project Notes\n\nThe dashboard redesign uses React 19...',
contentType: 'markdown',
sessionId: 'ses_abc123',
});| Parameter | Type | Required | Description |
|---|---|---|---|
content | string | Yes | Text content to ingest |
contentType | 'markdown' | 'text' | 'code' | Yes | Content format for optimal parsing |
sessionId | string | No | Session to associate the content with |
Enums
The SDK exports enums for type-safe usage across all operations:
import {
MemoryEntityType,
MemorySessionStatus,
MemoryMessageRole,
} from '@usetransactional/memory';MemoryEntityType
| Value | Description |
|---|---|
USER | A user identity |
FACT | A verified piece of information |
TOPIC | A subject or theme |
PREFERENCE | A user preference or setting |
EVENT | A time-bound occurrence |
MESSAGE | A conversation message |
SUMMARY | An auto-generated summary |
ORGANIZATION | An organization or group |
MemorySessionStatus
| Value | Description |
|---|---|
ACTIVE | Session is currently active |
EXPIRED | Session has expired based on TTL |
DELETED | Session has been deleted |
MemoryMessageRole
| Value | Description |
|---|---|
USER | Message from the user |
ASSISTANT | Message from the AI assistant |
SYSTEM | System-level message |
Error Handling
The SDK throws typed errors for different failure scenarios. All errors extend the base MemoryError class:
import {
MemoryError,
AuthenticationError,
ValidationError,
NotFoundError,
RateLimitError,
} from '@usetransactional/memory';
try {
const results = await client.search({
query: 'user preferences',
userId: 'user-123',
});
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Invalid API key. Check your credentials.');
} else if (error instanceof ValidationError) {
console.error('Invalid request parameters:', error.message);
} else if (error instanceof NotFoundError) {
console.error('Resource not found:', error.message);
} else if (error instanceof RateLimitError) {
console.error(`Rate limited. Retry after ${error.retryAfter} seconds.`);
} else if (error instanceof MemoryError) {
console.error('Memory API error:', error.message);
}
}| Error Class | Description |
|---|---|
MemoryError | Base error class for all SDK errors |
AuthenticationError | Invalid or missing API key |
ValidationError | Invalid request parameters |
NotFoundError | Requested resource does not exist |
RateLimitError | Too many requests. Includes retryAfter property (seconds until retry is safe) |
TypeScript Types
The SDK exports all types for full type safety:
import type {
Memory,
Session,
SearchResult,
ContextResult,
MemoryEntityType,
} from '@usetransactional/memory';| Type | Description |
|---|---|
Memory | A stored memory with id, content, type, userId, metadata, createdAt, and updatedAt |
Session | A session with id, userId, status, config, ttl, createdAt, and updatedAt |
SearchResult | A search result with memory, score, and highlights |
ContextResult | Generated context with text, tokenCount, memoryCount, and sources |
MemoryEntityType | Enum of all memory entity types |
On This Page
- Installation
- Quick Start
- Configuration
- Memory Operations
- add()
- search()
- get()
- update()
- delete()
- getContext()
- getJobStatus()
- Sessions
- sessions.create()
- sessions.get()
- sessions.list()
- sessions.update()
- sessions.delete()
- Profiles
- profiles.get()
- profiles.upsert()
- profiles.delete()
- Knowledge Graph
- graph.get()
- graph.traverse()
- Content Ingestion
- ingest.url()
- ingest.pdf()
- ingest.text()
- Enums
- MemoryEntityType
- MemorySessionStatus
- MemoryMessageRole
- Error Handling
- TypeScript Types