Skip to main content

Installation

npm install mengram-ai

Quick Start

const { MengramClient } = require('mengram-ai');
const m = new MengramClient('om-your-api-key');

// Add memories
await m.add([
    { role: 'user', content: 'Fixed the auth bug using rate limiting.' },
]);

// Semantic search
const results = await m.search('auth issues');

// Unified search — all 3 types
const all = await m.searchAll('deployment issues');
// { semantic: [...], episodic: [...], procedural: [...] }

// Cognitive Profile
const profile = await m.getProfile('alice');
// { system_prompt: "You are talking to Alice..." }

TypeScript

import { MengramClient, MengramError, QuotaExceededError } from 'mengram-ai';

const m = new MengramClient('om-...');

const results = await m.search('preferences');
const events = await m.episodes({ query: 'deployment' });
const procs = await m.procedures({ query: 'release' });

Constructor

const m = new MengramClient('om-your-key', {
    baseUrl: 'https://mengram.io',  // default
    timeout: 30000,                  // 30s default
});

Core Methods

add(messages, options?)

Add memories from a conversation. Extracts all 3 memory types.
const result = await m.add([
    { role: 'user', content: 'We use PostgreSQL and Railway' },
    { role: 'assistant', content: 'Got it.' },
], {
    userId: 'alice',
    agentId: 'support-bot',
    appId: 'production',
    expirationDate: '2027-01-01T00:00:00Z',
    source: 'slack',                          // provenance source
    metadata: { channel: '#engineering' },     // arbitrary metadata
    agentMode: true,                           // extract from all speakers (user + assistant)
});
// { status: 'accepted', job_id: 'job-...' }

addText(text, options?)

Add memories from plain text.
await m.addText('Meeting notes: decided to use Redis for caching', {
    userId: 'alice',
    source: 'email',
    metadata: { subject: 'Weekly sync' },
});

addFile(file, options?)

Upload a file and extract structured memories. Supports PDF (vision AI), DOCX, TXT, MD. Returns immediately with job_id.
// Node.js — pass a file path
const result = await m.addFile('./meeting-notes.pdf');
// { status: 'accepted', job_id: 'job-...', file_type: 'pdf', page_count: 12 }

// Browser — pass a File object from <input type="file">
await m.addFile(fileInput.files[0]);

// Poll for completion
await m.waitForJob(result.job_id);
Options: userId, agentId, runId, appId, filename (override filename for Blob inputs). File size limits: Free 10MB, Pro 50MB, Business 100MB.

search(query, options?)

Semantic search with re-ranking.
const results = await m.search('database preferences', {
    limit: 10,
    graphDepth: 3,
    userId: 'alice',
});

searchAll(query, options?)

Unified search across all 3 memory types.
const all = await m.searchAll('deployment issues', { limit: 5 });
// { semantic: [...], episodic: [...], procedural: [...] }

getAll(options?) / getAllFull(options?)

const memories = await m.getAll({ userId: 'alice' });
const full = await m.getAllFull({ userId: 'alice' });  // with full facts

get(name, options?) / delete(name, options?)

const entity = await m.get('PostgreSQL');   // returns null if not found
const ok = await m.delete('PostgreSQL');    // returns true/false

fixEntityType(name, newType, options?)

await m.fixEntityType('React', 'technology');

stats(options?) / graph(options?)

const stats = await m.stats();
const graph = await m.graph();  // { nodes: [...], edges: [...] }

Cognitive Profile

getProfile(userId?, options?)

Generate a ready-to-use system prompt from memory.
const profile = await m.getProfile('alice', { force: true });
console.log(profile.system_prompt);
console.log(profile.facts_used);

Episodic Memory

episodes(options?)

// Search
const events = await m.episodes({ query: 'deployment', limit: 5 });

// List recent
const recent = await m.episodes({ limit: 20 });

// Time range
const jan = await m.episodes({
    after: '2026-01-01',
    before: '2026-02-01',
});

Procedural Memory

procedures(options?)

const procs = await m.procedures({ query: 'deploy' });

procedureFeedback(id, options?)

await m.procedureFeedback(procId, { success: true });
await m.procedureFeedback(procId, {
    success: false,
    context: 'Build OOM at step 3',
    failedAtStep: 3,
});

procedureHistory(id) / procedureEvolution(id)

const history = await m.procedureHistory(procId);
const evolution = await m.procedureEvolution(procId);

Timeline

timeline(options?)

const facts = await m.timeline({
    after: '2026-01-01',
    before: '2026-02-01',
    limit: 20,
});

Agents

runAgents(options?)

await m.runAgents({ agent: 'curator' });
await m.runAgents();  // runs all agents

agentHistory(options?) / agentStatus(options?)

const history = await m.agentHistory({ limit: 5 });
const status = await m.agentStatus();

Insights & Reflections

await m.reflect();
const insights = await m.insights();
const refs = await m.reflections({ scope: 'cross' });

Memory Management

await m.dedup();                           // merge duplicate entities
await m.dedupAll();                        // dedup facts across all entities
await m.dedupEntity('PostgreSQL');         // dedup one entity
await m.merge('React.js', 'React');        // merge entities
await m.mergeUser();                       // merge "User" into primary
await m.archiveFact('Entity', 'old fact'); // archive a fact
await m.reindex();                         // re-embed all entities

feed(options?)

const feed = await m.feed({ limit: 20 });

Webhooks

await m.createWebhook({
    url: 'https://your-app.com/hook',
    eventTypes: ['memory_add', 'memory_update'],
    secret: 'hmac-secret',
});
const hooks = await m.listWebhooks();
await m.updateWebhook(1, { active: false });
await m.deleteWebhook(1);

Teams

const team = await m.createTeam('Engineering', 'Shared memory');
await m.joinTeam('invite-code');
const teams = await m.listTeams();
const members = await m.teamMembers(teamId);

await m.shareMemory('PostgreSQL', teamId);
await m.unshareMemory('PostgreSQL', teamId);
await m.leaveTeam(teamId);
await m.deleteTeam(teamId);  // owner only

Smart Triggers

const triggers = await m.getTriggers('alice', { includeFired: true });
await m.processTriggers();
await m.dismissTrigger(triggerId);
await m.detectTriggers('alice');

API Keys

const keys = await m.listKeys();
const newKey = await m.createKey('production');
await m.renameKey(keyId, 'staging');
await m.revokeKey(keyId);

Billing

const billing = await m.getBilling();
const checkout = await m.createCheckout('pro');
const portal = await m.createPortal();

Jobs

const status = await m.jobStatus('job-abc');
const result = await m.waitForJob('job-abc', {
    pollInterval: 1000,
    maxWait: 60000,
});

Import Data

// ChatGPT export (requires jszip)
await m.importChatgpt('~/Downloads/chatgpt-export.zip', {
    chunkSize: 20,
    onProgress: (current, total, title) => console.log(`${current}/${total}: ${title}`),
});

// Obsidian vault
await m.importObsidian('~/Documents/MyVault');

// Text/markdown files
await m.importFiles(['notes.md', 'journal.txt']);

Multi-User Isolation

// Each userId gets its own memory space
await m.add([{ role: 'user', content: 'I prefer dark mode' }], { userId: 'alice' });
await m.add([{ role: 'user', content: 'I prefer light mode' }], { userId: 'bob' });

const alice = await m.searchAll('preferences', { userId: 'alice' });
// Only Alice's memories

Error Handling

const { MengramClient, MengramError, QuotaExceededError } = require('mengram-ai');

try {
    await m.add(messages);
} catch (e) {
    if (e instanceof QuotaExceededError) {
        console.log('Upgrade your plan:', e.message);
    } else if (e instanceof MengramError) {
        console.log(`API error ${e.statusCode}: ${e.message}`);
    }
}

Quota Usage

After any API call, check your current quota usage via the .quota property:
await m.search('test');
console.log(m.quota);
// { add: { used: 5, limit: 30 }, search: { used: 12, limit: 100 } }

// Check before hitting the wall
const { search } = m.quota;
if (search && search.used >= search.limit * 0.8) {
    console.warn('Warning: approaching search quota limit');
}
The quota is read from response headers (X-Quota-Add-Used, X-Quota-Add-Limit, X-Quota-Search-Used, X-Quota-Search-Limit) and reflects usage at the time of the last API call.