@xtraceai/memory package is the primary supported client. It’s a hand-written wrapper over the HTTP API with idiomatic TypeScript types, an exponential-backoff polling helper, async-iterator pagination, and a typed error hierarchy.
fetch). Works in the browser too.
MemoryClient
The entry point. One client serves the whole org.
Constructor options
client.memories
All memory operations live here. Returns a Memories instance.
ingest(body, options?)
Submit conversation messages for extraction. Returns an IngestJob.
messages, user_id, conv_id. Optional: agent_id, app_id, group_ids (tag the extracted memories to groups), timestamp_format, extract_artifacts (defaults to true — pass false to skip the artifact-extraction stage).
Options:
wait?: boolean— if true, the server holds the connection up to 30s and returns a terminal job inline. Falls back to async if extraction is still running at 30s.signal?: AbortSignalrequestId?: string
list(query?) → AsyncIterable<Memory>
Auto-paginating async iterator over memories matching the query.
user_id, agent_id, conv_id, app_id, type, limit, order, include.
listPage(query?) → Promise<ListEnvelope<Memory>>
Single-page version of list. Use when you need cursor-level control.
get(id) → Promise<Memory>
Fetch a single memory by id. Returns the full row, including details.full_content for artifacts.
delete(id) → Promise<void>
Hard delete. Removes the point outright — afterwards get 404s, it’s gone from list/search, and a second delete 404s (idempotent by absence). There is no update method: corrections flow through ingest (re-ingesting the corrected statement supersedes the old one).
search(body) → Promise<SearchListEnvelope>
Vector search, scoped by what you pass (user_id / group_ids / agent_id / app_id — all AND-narrow; at least one required). mode defaults to compose.
retrieve(body) → Promise<SearchListEnvelope>
Sugar over search that forces mode: 'compose' — the response’s context carries the LLM-assembled, ready-to-inject prompt.
recall(params, options?) → Promise<RecallResult>
Personal + shared (group) read in one call. Fans out a search per scope, dedupes by id, and renders a single prompt sectioned by Personal + group name (shared lines attributed to their author). This is the combined read that AND-scoping can’t express in a single search.
[{ user_id }, { app_id: 'product-kb' }] reads “alice’s memories OR the product KB,” while { user_id, app_id } in one pool would AND them.
Params: query (required) and pools (≥1 pool — each a ScopePool of { user_id?, group_ids?, agent_id?, app_id? }); optional mode (default compose), limit (default 10).
Options: template? (override the prompt format — see PromptTemplate), render? (supply your own renderer), signal?, requestId?.
renderMemoriesPrompt(memories, opts?) is also exported standalone if you want to format a memory list yourself.
client.memories.jobs
get(jobId) → Promise<IngestJob>
Poll a single ingest job. Use pollUntilDone instead for normal flows.
pollUntilDone(jobId, options?) → Promise<IngestJob>
Polls a job until it reaches succeeded or failed. Exponential backoff starting at 500ms, capped at 5s, default 60s timeout.
timeoutMs?: number— default 60_000initialIntervalMs?: number— default 500maxIntervalMs?: number— default 5_000backoffFactor?: number— default 1.5signal?: AbortSignal
client.groups
Register and manage groups — shared tagging targets. Register a group, then pass its id in ingest({ group_ids }) and read it back with search/recall. See the Groups guide.
Error classes
Every API failure is a subclass ofMemoryError. Match on the class for HTTP-status handling and on .code for stable machine-readable error codes from the server.
Common fields on every error:
status: number— HTTP status codecode: string— stable machine-readable error code (e.g.memory_not_found,org_mismatch)errorType: string— category (e.g.invalid_request_error)requestId: string | undefined— propagate to support / logsdetails: Record<string, unknown> | undefined— error-specific extras
Type exports
The full set of exported types:renderMemoriesPrompt and DEFAULT_PROMPT_TEMPLATE are exported as values (not types):
Memory is a discriminated union — m.type === 'fact' narrows m.details to FactDetails, etc.
Retries and timeouts
Network errors on idempotent methods also retry.
Request ids
Every request carries anX-Request-Id header (auto-generated req_<uuid> by default). The server echoes it; the SDK surfaces it on errors via err.requestId. Use it when filing support tickets — it pins down the exact request in our logs.
See also
- Quickstart — install and run end-to-end
- Authentication — credentials, headers, environment selection
- Ingesting memories — async/sync, polling, group tagging
- Searching memories — scoping, modes,
recall - Groups — share memory across users
- API Reference tab — the underlying HTTP endpoints