Skip to main content
The @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.
Zero runtime dependencies. Node 18+ (native 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.
Required body fields: 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?: AbortSignal
  • requestId?: string

list(query?)AsyncIterable<Memory>

Auto-paginating async iterator over memories matching the query.
Filter keys (all optional): 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.
See Searching memories for scoping, modes, and groups.

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.
Axes AND within a pool; pools OR. So [{ 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.
Options:
  • timeoutMs?: number — default 60_000
  • initialIntervalMs?: number — default 500
  • maxIntervalMs?: number — default 5_000
  • backoffFactor?: number — default 1.5
  • signal?: 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 of MemoryError. 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 code
  • code: 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 / logs
  • details: 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 an X-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