Official SDK for OneBrain — the persistent AI memory layer for humans and agents.
OneBrain stores your identity, preferences, knowledge, decisions, and projects in a structured system — and delivers optimized context to any AI assistant via REST API or MCP protocol.
npm install onebrainimport { OneBrain } from 'onebrain';
const ob = new OneBrain({
apiKey: process.env.ONEBRAIN_API_KEY,
baseUrl: 'https://onebrain.rocks/api/eu', // default
});
// Write a memory
await ob.memory.create({
type: 'fact',
title: 'Prefers dark mode',
body: 'User confirmed dark mode preference in settings.',
});
// List all facts
const { items } = await ob.memory.list({ type: 'fact' });
// Search memories
const { results } = await ob.memory.search({ query: 'dark mode' });
// Get full brain context for LLM
const context = await ob.brain.context();const ob = new OneBrain({
apiKey: 'ob_your_key_here', // required
baseUrl: 'https://onebrain.rocks/api/eu', // optional (default)
timeout: 10000, // optional, ms (default: 10000)
headers: { 'X-Custom': 'value' }, // optional extra headers
});| Option | Required | Default | Description |
|---|---|---|---|
apiKey |
Yes | — | Your OneBrain API key |
baseUrl |
No | https://onebrain.rocks/api/eu |
API base URL |
timeout |
No | 10000 |
Request timeout in ms |
headers |
No | {} |
Additional HTTP headers |
For self-hosted instances, set baseUrl to your API endpoint (e.g. http://localhost:3001).
// List (with cursor pagination)
const { items, cursor, hasMore } = await ob.memory.list({
type: 'fact', // fact | preference | decision | goal | experience | skill
status: 'active', // active | candidate | archived | conflicted
search: 'keyword',
cursor: 'abc',
limit: 20,
});
// Get by ID
const memory = await ob.memory.get('memory-id');
// Create
const created = await ob.memory.create({
type: 'fact',
title: 'Short title',
body: 'Detailed content',
sourceType: 'user_input', // optional
confidence: 1.0, // optional (0-1)
});
// Update
await ob.memory.update('memory-id', { title: 'New title' });
// Delete
await ob.memory.delete('memory-id');
// Semantic search (supports hybrid, vector, and keyword modes — see DeepRecall)
const { results, searchMode } = await ob.memory.search({
query: 'dark mode preferences',
mode: 'hybrid', // 'hybrid' | 'vector' | 'keyword' (default: hybrid)
top_k: 10,
alpha: 0.5, // balance between keyword and vector (0 = keyword, 1 = vector)
});
// Extract (AI-powered memory creation)
await ob.memory.extract({ type: 'fact', title: '...', body: '...' });
// AI extract from raw text
await ob.memory.aiExtract({ text: 'Long conversation...' });
// Import bulk memories
await ob.memory.import([
{ type: 'fact', title: 'A', body: 'B' },
{ type: 'decision', title: 'C', body: 'D' },
]);
// Ingest from URL
await ob.memory.ingestUrl({ url: 'https://example.com/article' });
// Parse chat transcript
await ob.memory.parseChat({ transcript: 'User: ...\nAI: ...' });
// Find duplicates
const dupes = await ob.memory.duplicates();
// Consolidate similar memories
await ob.memory.consolidate({ type: 'fact', dryRun: true });
// Expire old memories
await ob.memory.expire({ ttlDays: 365 });// List
const { items } = await ob.entity.list({ type: 'person' });
// CRUD
const entity = await ob.entity.create({ name: 'Stripe', type: 'service', description: '...' });
await ob.entity.update('entity-id', { description: 'Updated' });
await ob.entity.delete('entity-id');
// Link entity to memory
await ob.entity.addLink('entity-id', { memoryItemId: 'mem-id', linkType: 'mentioned_in' });
await ob.entity.removeLink('entity-id', 'link-id');
// Entity graph (all entities with links)
const graph = await ob.entity.graph();
// Find duplicate entities
const dupes = await ob.entity.duplicates();
// Merge two entities
await ob.entity.merge({ keepId: 'keep-this', removeId: 'remove-this' });
// Auto-extract entities from a memory
await ob.entity.autoExtract({ memoryId: 'memory-id' });// List
const { items } = await ob.project.list({ status: 'active' });
// CRUD
const project = await ob.project.create({ name: 'App V2', status: 'active', description: '...' });
await ob.project.update('project-id', { status: 'completed' });
await ob.project.delete('project-id');
// Link project to memory
await ob.project.addMemoryLink('project-id', { memoryItemId: 'mem-id', linkType: 'related' });
await ob.project.removeMemoryLink('project-id', 'link-id');// Get brain profile
const profile = await ob.brain.profile();
// Update profile
await ob.brain.updateProfile({ summary: 'Senior developer based in Berlin' });
// Get full brain context (for LLM system prompts)
const context = await ob.brain.context();
// context.formatted — ready-to-use system prompt text
// context.structured — typed object with memories, entities, projects
// context.meta — token estimate, scope, truncation info// Get optimized LLM context by scope
const ctx = await ob.context.get('brief'); // minimal
const ctx = await ob.context.get('assistant'); // balanced
const ctx = await ob.context.get('project'); // project-focused
const ctx = await ob.context.get('deep'); // comprehensiveFor AI agents that sync automatically:
// Read brain context via connect protocol
const context = await ob.connect.read({ scope: 'deep' });
// Write-back a single memory
await ob.connect.writeMemory({ type: 'fact', title: '...', body: '...' });
// Batch write-back (up to 10)
await ob.connect.writeMemories([
{ type: 'fact', title: 'A', body: 'B' },
{ type: 'preference', title: 'C', body: 'D' },
]);
// Delta sync — get changes since timestamp
const { changes, count } = await ob.connect.delta('2026-03-28T00:00:00Z');const usage = await ob.billing.usage('monthly');
const plan = await ob.billing.plan();AI-derived skills automatically extracted from your memory patterns:
// List skills (with filtering and sorting)
const { items } = await ob.skill.list({
status: 'active', // 'candidate' | 'active' | 'archived' | 'dismissed'
minConfidence: 0.7, // filter by minimum confidence score
sortBy: 'confidence', // 'confidence' | 'usage' | 'recency'
cursor: 'abc',
limit: 20,
});
// Get a single skill
const skill = await ob.skill.get('skill-id');
// skill.title — skill name
// skill.body — detailed description
// skill.status — candidate | active | archived | dismissed
// skill.confidenceScore — 0-1 confidence rating
// skill.usageCount — how often applied
// skill.triggerConditions — when the skill is relevant
// Submit feedback on a skill
await ob.skill.feedback('skill-id', {
eventType: 'applied', // 'applied' | 'referenced' | 'dismissed'
context: { task: 'code review' }, // optional context
});Scheduled or event-triggered intelligence briefings:
// Get briefing configuration
const config = await ob.briefing.config();
// config.isEnabled — whether briefings are active
// config.timezone — user timezone
// config.quietHoursStart — no-disturb window start
// config.quietHoursEnd — no-disturb window end
// config.channels — delivery channels (e.g. 'email', 'push')
// List briefings (with filtering)
const { items } = await ob.briefing.list({
type: 'morning', // 'morning' | 'midday' | 'evening'
// | 'event_triggered' | 'weekly_health'
status: 'ready', // 'pending' | 'generating' | 'ready'
// | 'delivered' | 'failed'
cursor: 'abc',
limit: 20,
});
// Each item: { id, type, status, title, createdAt }const { items } = await ob.apiKeys.list();
const key = await ob.apiKeys.create({ name: 'My Agent' });
console.log(key.fullKey); // only shown once!
await ob.apiKeys.updateTrustLevel('key-id', 'trusted');
await ob.apiKeys.revoke('key-id');ob.memory.search() is powered by DeepRecall, which supports three search modes:
| Mode | Description |
|---|---|
hybrid |
Combines keyword (Dice/trigram) and vector similarity (default) |
vector |
Pure semantic vector search via embeddings |
keyword |
Traditional text matching via Dice coefficient |
const { results, searchMode, downgradedFrom } = await ob.memory.search({
query: 'project architecture decisions',
mode: 'hybrid', // default
top_k: 10, // max results (default: 10)
alpha: 0.5, // keyword↔vector balance (0 = keyword, 1 = vector)
});
// Each result includes both scores:
// result.score — combined relevance score
// result.diceScore — keyword/trigram match score
// result.vectorScore — semantic similarity score
// If embeddings are unavailable, hybrid/vector auto-downgrades to keyword.
// Check downgradedFrom to detect this:
if (downgradedFrom) {
console.warn(`Search downgraded from ${downgradedFrom} to ${searchMode}`);
}You can check embedding health and trigger reindexing:
// Check embedding coverage
const status = await ob.memory.embeddingStatus();
// status.totalMemories, status.embedded, status.pending,
// status.failed, status.missing, status.coverage (0-1)
// Reindex failed or missing embeddings
const result = await ob.memory.reindex({ status: 'failed', maxItems: 100 });
// result.total, result.queued, result.errorsAll list endpoints use cursor-based pagination:
let cursor: string | null = null;
do {
const page = await ob.memory.list({ cursor, limit: 20 });
for (const item of page.items) {
console.log(item.title);
}
cursor = page.hasMore ? page.cursor : null;
} while (cursor);import { OneBrainError, OneBrainTimeoutError, OneBrainNetworkError } from 'onebrain';
try {
await ob.memory.get('nonexistent');
} catch (error) {
if (error instanceof OneBrainError) {
console.error(error.code); // 'NOT_FOUND'
console.error(error.statusCode); // 404
console.error(error.message); // 'Memory item not found'
console.error(error.requestId); // 'req-abc-123'
}
if (error instanceof OneBrainTimeoutError) {
// Request timed out
}
if (error instanceof OneBrainNetworkError) {
// DNS, connection refused, etc.
}
}| Type | Description |
|---|---|
fact |
Factual information about the user |
preference |
User preferences and settings |
decision |
Decisions made by the user |
goal |
Goals and objectives |
experience |
Past experiences and learnings |
skill |
Skills and competencies |
- Node.js >= 18
- An OneBrain account with an API key (onebrain.rocks)
- onebrain-mcp — MCP server for Claude, Cursor, and Windsurf
- OneBrain Docs — Full documentation
MIT