Skip to main content
MemoryClient is the primary interface for reading and writing memories in your application. It wraps the memory provider of your choice (AtomicMemory Core, Mem0, or a custom implementation) and exposes a consistent set of operations directly on the client instance. Every operation requires a scope that routes the request to the correct memory partition — see the Scope page for details.

Initialization

Construct a MemoryClient by passing a providers object that specifies at least one backend, then call initialize() before making any other calls. The initialize() call establishes the provider connection and is required — calls made before it will throw.
import { MemoryClient } from '@atomicmemory/sdk';

const memory = new MemoryClient({
  providers: {
    atomicmemory: {
      apiUrl: process.env.ATOMICMEMORY_URL!,
      apiKey: process.env.ATOMICMEMORY_KEY!,
    },
  },
});

await memory.initialize();
providers
object
required
An object with at least one provider key. Supported keys are atomicmemory and mem0. See Providers for full configuration options.
providers.atomicmemory.apiUrl
string
The base URL of your AtomicMemory Core instance, e.g. http://127.0.0.1:17350.
providers.atomicmemory.apiKey
string
The bearer token to authenticate with the Core API. Corresponds to CORE_API_KEY on the server.

memory.ingest()

Full ingest runs LLM-powered extraction on the provided messages, applies AUDN-SC mutation decisions (Add, Update, Delete, No-op, Supersede, Clarify), and versions claims with temporal lineage. Duplicate and contradicting claims are automatically detected and handled — you do not need to deduplicate before calling ingest. The mode field selects the input shape: 'messages' for structured chat turns, 'text' for raw transcript or document content, and 'verbatim' to bypass LLM extraction and store content as a single memory record.
await memory.ingest({
  mode: 'messages',
  messages: [
    { role: 'user', content: 'I prefer dark mode and TypeScript.' },
    { role: 'assistant', content: 'Noted!' },
  ],
  scope: { user: 'alice' },
});
mode
'messages' | 'text' | 'verbatim'
required
Input shape selector. Use 'messages' for chat turn arrays, 'text' for a raw content string, or 'verbatim' to store content as-is without LLM extraction.
messages
Message[]
Required when mode is 'messages'. An array of conversation messages to extract memories from. Each message has a role ('user' | 'assistant' | 'system' | 'tool') and a content string.
content
string
Required when mode is 'text' or 'verbatim'. The raw text or verbatim content to store.
scope
Scope
required
The routing key for this ingest operation. At least one scope field must be set. See Scope.
Full ingest calls your configured LLM provider for each request. Use it when the accuracy of claim extraction and contradiction detection matters — for example, when processing a completed conversation turn.
Semantic search retrieves the most relevant memories for a natural-language query using hybrid retrieval (vector similarity + BM25/FTS with RRF fusion). Results are ranked by relevance score.
const result = await memory.search({
  query: "What are Alice's editor preferences?",
  scope: { user: 'alice' },
  limit: 5,
});

for (const item of result.results) {
  console.log(`[${item.score.toFixed(2)}] ${item.memory.content}`);
}
query
string
required
A natural-language question or phrase to search for.
scope
Scope
required
Only memories that match this scope are searched.
limit
number
Maximum number of results to return. Defaults to the server-configured maximum.
results
SearchResult[]
Ranked array of matching memories. Each entry includes memory (with id, content, createdAt, and updatedAt), score, and optional similarity and relevance fields.

memory.get()

Retrieve a single memory by its ID. The scope must match the scope under which the memory was stored.
const mem = await memory.get({
  id: 'mem_abc123',
  scope: { user: 'alice' },
});

console.log(mem?.content, mem?.createdAt);
id
string
required
The memory ID, returned by ingest, search, or list.
scope
Scope
required
Must match the scope the memory was stored under. Mismatched scope returns a not-found error.

memory.delete()

Soft-deletes a memory. The memory is marked as deleted and excluded from future search and list results, but its versioning history is retained for audit purposes.
await memory.delete({
  id: 'mem_abc123',
  scope: { user: 'alice' },
});
id
string
required
The ID of the memory to delete.
scope
Scope
required
Must match the scope the memory was stored under.

memory.package()

Packages the most relevant memories for a query into a ready-to-use context string, trimmed to a token budget. Use this to inject memory into a prompt without manually formatting or truncating results.
const pkg = await memory.package({
  query: "Alice's preferences",
  scope: { user: 'alice' },
  tokenBudget: 1200,
});

// Inject into your prompt
const systemPrompt = `${pkg.text}\n\nYou are a helpful assistant.`;
console.log(pkg.text);
query
string
required
The query used to select which memories to include.
scope
Scope
required
Only memories matching this scope are considered.
tokenBudget
number
Approximate maximum number of tokens the returned text string should consume. The server applies tiered L0/L1/L2 compression to fit within the budget.
text
string
A formatted, token-budgeted string suitable for direct inclusion in a system prompt or context window.
memory.package() is the recommended way to inject memory into prompts. It handles ranking, formatting, and compression for you — you only need to specify what you are looking for and how many tokens you can afford.

memory.list()

Lists memories for a given scope, with optional pagination. Useful for inspection, admin tooling, and export workflows.
const list = await memory.list({
  scope: { user: 'alice' },
  limit: 20,
});

for (const mem of list.memories) {
  console.log(mem.id, mem.content);
}
scope
Scope
required
Only memories matching this scope are returned.
limit
number
Maximum number of memories to return per page.
cursor
string
Pagination cursor from a previous response. Pass this to retrieve the next page of results.
A valid scope is required on every operation — ingest, search, get, delete, package, and list. The SDK rejects requests without at least one populated scope field. See Scope for a full explanation of how scope routing works.