JavaScript / TypeScript SDK
Zero runtime dependencies — uses the global fetch. Works in
Node ≥ 18, Bun, Deno, browsers, and edge runtimes. Ships ESM + CJS + full types.
Install#
# npm publish pending — install from source:
npm install "github:11data/longmem#workspace=sdk/js"
Constructor#
import { Longmem } from "longmem";
const mem = new Longmem({
apiKey: undefined, // default: LONGMEM_API_KEY env var
baseUrl: undefined, // default: LONGMEM_BASE_URL or https://rememberos.ai
timeout: 30000, // ms per request (AbortController)
maxRetries: 2, // retry transient failures (429/5xx/network); 0 disables
backoffBase: 500, // ms, doubles each retry (Retry-After header wins)
backoffCap: 8000,
});
Throws LongmemError if no key is available.
Automatic retries#
Transient failures — network errors and 429/500/502/
503/504 — are retried with exponential backoff, honoring a
Retry-After header when present. 4xx responses are returned
immediately (never retried). Tune with maxRetries / backoffBase /
backoffCap, or set maxRetries: 0 to disable.
Methods (all async)#
| Method | Returns |
|---|---|
add(text, { collection, importance, category, metadata, source, containerTag }) | Memory |
addMany(items, { collection, containerTag, importance, category, source }) | { created, ids }; bulk import, items are strings or objects, chunked to 100/call |
remember(content, { collection, sync = true }) | facts (sync) or {job_id} |
update(memoryId, { collection, text, importance, category, metadata }) | Memory; only set fields change |
search(query, { collection, limit, minScore, mode, category, containerTag }) | SearchHit[]; omit collection for tenant-wide |
get(memoryId, { collection }) | Memory |
listMemories({ collection, limit, offset, includeArchived }) | Memory[], newest first (pinned first) |
move(memoryId, { collection, toCollection }) | { moved }; move a memory to another collection |
delete(memoryId, { collection }) | deletes the memory (+ its files) |
deleteCollection(collection) | deletes the collection and all its memories |
forget(query, { collection, minScore, limit }) | { deleted }; semantic delete — destructive |
collections() | Collection[] |
profile(collection) | { profile, based_on } |
related(memoryId, { collection, limit, minScore }) | SearchHit[]; nearest neighbours, excludes self/archived |
dedup({ collection, threshold, dryRun }) | { clusters, deleted, dry_run } |
contradictions({ collection, limit }) | list of { current, superseded } pairs |
pin(memoryId, { collection, pinned }) | Memory; pin/unpin |
archive(memoryId, { collection, archived }) | Memory; archive/restore |
archiveStale({ collection, olderThanDays, dryRun }) | { would_archive } or { archived } |
health({ collection, staleDays }) | collection health snapshot — total, stale, expired, supersessions, needs_attention, categories |
summary({ collection, limit }) | board-report briefing — { summary, themes, based_on, generated_at } |
createConnection(provider, { name, collection, containerTag, config, credentials }) | the connection; managed connector (creds encrypted, never returned) |
listConnections() / getConnection(id) | connection objects (no credentials) |
syncConnection(id) | { synced, cursor, status } or { status: "error", error } |
connectionRuns(id, { limit }) | recent sync runs: { status, synced_count, error, created_at } |
deleteConnection(id) | removes the connection (synced memories kept) |
connectorHealth({ hours }) | admin: cross-tenant sync health [{ provider, runs, errors, last_run }] |
connectorStatus() | admin: connection counts by status [{ status, n }] — surfaces paused/erroring connectors |
adminMemoryHealth() | admin: fleet-wide memory hygiene { total, current, archived, stale, expired, supersessions, needs_attention } |
exportAccount() | full knowledge-base dump { tenant, collections, memories, … } — text-only, re-imports anywhere |
importMemories(memories, { collections, intoCollection }) | re-ingest a dump (re-embeds text); { imported, skipped, collections } |
Bulk import#
// strings, or objects for per-item fields; chunked to 100/call, retries per chunk
await mem.addMany([
"Alex prefers dark mode",
{ text: "Bianca is on the design team", containerTag: "user-42", metadata: { src: "crm" } },
], { collection: "memories" }); // -> { created: 2, ids: [...] }
Errors#
import { Longmem, LongmemError, LongmemAPIError } from "longmem";
try {
await mem.add("…");
} catch (e) {
if (e instanceof LongmemAPIError) console.error(e.status, e.message);
else if (e instanceof LongmemError) console.error("config/network:", e.message);
}
In a chat handler#
const hits = await mem.search(userMessage, {
collection: "assistant", containerTag: `user-${userId}`, limit: 5 });
const context = hits.map(h => h.text).join("\n");
// …call your model with context, then:
await mem.remember(userMessage, { collection: "assistant", sync: false });