@mnemo-ai/client-ts
v3.6.2
Published
Typed TypeScript SDK for the Mnemosyne cognitive memory HTTP API. Drop-in alternative to direct library import when consumers prefer RPC over coupling.
Maintainers
Readme
@mnemo-ai/client-ts
AI pointer: Typed TypeScript HTTP client SDK for the Mnemosyne server. No runtime deps beyond fetch.
Depends on: nothing (uses native fetch)
Exposes: MnemosyneClient (typed methods matching the HTTP API surface)
Status: STABLE
See also: CLAUDE.md · docs/INDEX.md · docs/architecture/API.md
Zero runtime dependencies. Works in Node 20+, Bun, Deno, Cloudflare Workers, and modern browsers. Drop-in alternative to @mnemo-ai/core when you'd rather talk to a centralized memory server than embed the engine in your app.
Install
pnpm add @mnemo-ai/client-ts
# or
npm i @mnemo-ai/client-ts30-second start
import { MnemosyneClient } from "@mnemo-ai/client-ts";
const memory = new MnemosyneClient({
url: "https://memory.example.com",
apiKey: process.env.MNEMOSYNE_API_KEY!,
});
const { hits } = await memory.recall({ query: "user email preferences" });
console.log(hits);Examples
1. Basic recall
const result = await memory.recall({
query: "Acme's preferred communication language",
topK: 5,
});
for (const hit of result.hits) {
console.log(`${hit.score.toFixed(2)} — ${hit.content}`);
}2. Recall with a pre-embedded vector
Useful when you already have the query vector from a shared embedding cache, or you want to use a non-default embedding model. The server skips its own embedding pass when you pass vector.
import OpenAI from "openai";
const openai = new OpenAI();
const { data } = await openai.embeddings.create({
model: "text-embedding-3-small",
input: "billing escalation policy",
});
const result = await memory.recall({
query: "billing escalation policy",
vector: data[0].embedding,
topK: 10,
});3. Create a fact
createFact is idempotent via content-hash on the server — re-sending the same content won't duplicate. The response is the created Fact (including its assigned id).
const result = await memory.createFact({
content: "Acme prefers communication in Spanish.",
attribution: { source: "user_stated" },
tags: ["client:acme"],
});
console.log("stored fact:", result.id);4. Time-travel recall with asOf
Ask what memory knew at a past instant — useful for replaying historical agent decisions and for audit trails.
const snapshot = await memory.recall({
query: "team escalation owner",
asOf: "2026-01-15T00:00:00Z",
topK: 3,
});
// `snapshot.hits` reflects facts as they existed on Jan 15, 2026.5. Error handling
The SDK throws a typed error hierarchy. Branch on the class — not the message — for resilient retry/UX logic.
import {
MnemosyneAPIError,
MnemosyneNetworkError,
MnemosyneTimeoutError,
} from "@mnemo-ai/client-ts";
try {
await memory.recall({ query: "anything" });
} catch (err) {
if (err instanceof MnemosyneTimeoutError) {
// Server is alive but slow — degrade gracefully.
} else if (err instanceof MnemosyneAPIError && err.status === 401) {
// Rotate API key.
} else if (err instanceof MnemosyneNetworkError) {
// DNS / TLS / connection refused. Retry or fail open.
} else if (err instanceof MnemosyneAPIError) {
console.error(`Mnemosyne ${err.status} [${err.code}] ${err.requestId}`);
throw err;
}
}Configuration
new MnemosyneClient({
url: "https://memory.example.com",
apiKey: process.env.MNEMOSYNE_API_KEY!,
// Inject a custom fetch (defaults to global fetch). Useful in tests
// or when wrapping for tracing.
fetch: undici.fetch,
// Per-request timeout in milliseconds. Default 30_000.
timeout: 10_000,
// Retry policy for transient failures (5xx + network errors).
// Default: 3 attempts, exponential backoff with full jitter (200ms,
// 400ms, 800ms). 4xx errors and timeouts are NOT retried by default.
retry: {
attempts: 5,
initialDelayMs: 100,
shouldRetry: (err, attempt) => attempt < 5,
},
// Optional User-Agent suffix to distinguish traffic in server logs.
userAgent: "my-app/1.2.3",
});API
| Method | HTTP | Description |
| ----------------------------------- | -------------------------------------- | -------------------------------------------- |
| recall(input) | POST /recall | Top-K relevant facts |
| createFact(input) | POST /facts | Persist a new fact (idempotent) |
| getFact(id) | GET /facts/:id | Fetch one fact |
| pinFact(id) / unpinFact(id) | POST /facts/:id/pin ({ pinned: true/false }) | Protect from auto-prune; recall boost |
| forgetFact(id) | DELETE /facts/:id | Soft-delete (bitemporal close) |
| timeline(input) | GET /timeline | Recent fact activity |
| health() | GET /health | Liveness + per-component readiness |
When to use this vs. @mnemo-ai/core
| Pick @mnemo-ai/client-ts if… | Pick @mnemo-ai/core directly if… |
| -------------------------------------------------------------------- | --------------------------------------------------------------- |
| You're talking to a shared memory server from many apps | You want sub-millisecond in-process recall |
| Your runtime can't host Postgres / pgvector / Drizzle | You already have a Postgres pool and want to reuse it |
| You need a stable wire contract across engine refactors | You want the full hookable internals (extraction, consolidation) |
License
Apache-2.0 © Lucas Mailland
