TypeScript SDK API reference

The shape of the public surface of @neo4j-labs/agent-memory, with deep links into the auto-generated TypeDoc reference for each symbol.

This map describes the released @neo4j-labs/[email protected] package. Where the repository source already behaves differently, the affected entry says so. The SDK shares a memory model with the Python SDK, but method availability differs by backend and language. The normal TypeScript application uses hosted REST; the optional bridge transport exists for development and TCK conformance. A bridge method’s presence does not establish a hosted endpoint. See backend capabilities.

A source manifest or a generated page does not prove that an API has shipped in an npm artifact. Verify the installed package’s exports/types before adopting new APIs. Source-checkout tutorials build the in-tree SDK explicitly.

Full method-level reference is bundled with these docs as the TypeDoc-generated site at the TypeDoc API reference. It has every parameter, every property, every overload. This page is the map — what the SDK exposes and which TypeDoc symbol to open.

The TypeDoc pages are regenerated into docs/modules/ROOT/attachments/api/typescript/ on every push to main that touches typescript/src/** (see .github/workflows/docs-typedoc.yml).

Installation

npm install @neo4j-labs/[email protected]
# pnpm add @neo4j-labs/[email protected]
# bun add @neo4j-labs/[email protected]

Requires Node.js 22+. The core REST transport uses fetch; pass credentials explicitly where environment access differs. Framework adapters retain their own runtime and peer requirements.

MemoryClient

The root class. Holds six subclients (shortTerm, longTerm, reasoning, query, auth, ontology) and the underlying Transport.

import { MemoryClient } from "@neo4j-labs/agent-memory";

// Zero-config: reads MEMORY_API_KEY from environment, targets hosted NAMS.
const memory = new MemoryClient();

// Alternatively, construct a client with options.
const configuredMemory = new MemoryClient({
  endpoint: "https://memory.neo4jlabs.com/v1",
  apiKey: process.env.MEMORY_API_KEY,
  timeout: 30_000,
  headers: { "X-Trace-Id": "example-trace-id" },
  logger: (event) => console.log(event),
});

new MemoryClient(options) selects a transport; a supplied Transport is also accepted for tests/adapters. Construction makes no HTTP request. Ordinary calls connect lazily; await client.connect() performs an optional explicit probe. await client.close() closes client resources and does not delete stored data.

MemoryClientOptions

Field Type Description Default

endpoint

string

The NAMS REST endpoint. Auto-selects REST when the endpoint contains a version path matching /\/v\d+\b/; otherwise selects the bridge protocol.

https://memory.neo4jlabs.com/v1

apiKey

string

Bearer token for Authorization header.

process.env.MEMORY_API_KEY

workspaceId

string

NAMS workspace id, sent as the X-Workspace-Id header on every request. Use when the deployment requires an explicit workspace header. The selected workspace, not a conversation user id, defines tenancy. An explicit X-Workspace-Id entry in headers overrides it.

process.env.MEMORY_WORKSPACE_ID

tokenProvider

() ⇒ string | Promise<string>

Dynamic token source (OAuth refresh, AWS STS, etc.). Overrides apiKey.

—

transport

"auto" | "bridge" | "rest"

Force the wire protocol. "auto" selects based on endpoint shape.

"auto"

timeout

number

Per-request timeout in milliseconds.

30000

headers

Record<string, string>

Extra request headers (User-Agent, trace headers, etc.).

—

namespace

string

Accepted but currently unused; does not scope requests or isolate entities.

—

logger

(event: LogEvent) ⇒ void

Receives request / response / error events for observability.

—

client.shortTerm — short-term memory

Conversations, messages, three-tier context. On REST, create a conversation first and reuse its returned id. userId is metadata and a supported list filter, not a substitute for a conversation id or an authorization policy.

Method Purpose

addMessage(sessionId, role, content, options?)

Append a message to a conversation. Returns the persisted Message.

getConversation(sessionId, options?)

Fetch a conversation by id, with its messages oldest first. On REST these are at most the newest 200 messages; the service lists them newest first and the client reverses them.

searchMessages(query, options?)

Semantic + filter search within the required sessionId (alias conversationId) on REST; sessionId wins if both are supplied.

listSessions(options?)

Enumerate session ids (with message counts and timestamps).

deleteMessage(messageId)

Bridge only. REST raises NotSupportedError; use conversation deletion when appropriate.

clearSession(sessionId, options?)

Delete the whole conversation.

createConversation(options) (hosted)

Create a conversation with required userId and optional metadata. Workspace selection comes from credentials/headers, not this options object.

listConversations(options?) (hosted)

Enumerate full conversation objects, most recently updated first. The service serves at most 200 per page; the client follows its next_cursor until limit are collected.

getConversationMetadata(conversationId) (hosted)

Conversation header without the message list.

deleteConversation(conversationId) (hosted)

Delete an entire conversation.

getContext(conversationId) (hosted)

Three-tier window: reflections, observations, recent messages — designed to be dropped into an LLM prompt.

bulkAddMessages(conversationId, messages) (hosted)

Persist up to 100 messages in one HTTP round-trip. More than 100 raises a plain Error before sending a request.

getObservations(conversationId, options?) (hosted)

Inline observations extracted from the conversation so far.

getReflections(conversationId) (hosted)

Higher-level reflections generated when accumulated context crosses the compression threshold.

Options and scope: addMessage accepts metadata; getConversation accepts limit, which REST sends as 200 when omitted and clamps to 200 (the service’s maximum). Both, and clearSession, accept an options conversationId alias when the positional sessionId is undefined; the positional id wins if both exist. Missing both raises ValidationError. searchMessages accepts sessionId / conversationId, limit (10) and threshold (0.7). On REST, missing both ids raises a pre-request TransportError for the required path parameter. listSessions defaults its limit to 100. listConversations accepts userId and limit (default 100; REST pages past 200); getObservations accepts limit, with an omitted value left to the server.

Returned types: Message, Conversation, ConversationContext, SessionInfo, Observation, Reflection.

Hosted vs bridge: methods marked (hosted) require a NAMS REST endpoint (default). The bridge transport (for TCK conformance) raises NotSupportedError for these.

TypeDoc: ShortTermMemory

client.longTerm — long-term memory

Entities and graph views on REST. The compatibility operations marked bridge only raise NotSupportedError on REST. They are not substitutes for hosted entity APIs.

Method Purpose

addEntity(name, entityType, options?)

Create an entity. On the hosted service, a sufficiently similar existing entity can cause the create to auto-merge onto it instead of creating a new record; the returned Entity is then the canonical merged-into entity, whose name and type can differ from the arguments (see below).

addPreference(category, preference, options?) (bridge only)

Record a preference (food, communication, dietary, etc.).

addFact(subject, predicate, object) (bridge only)

Store a typed subject-predicate-object triple.

searchEntities(query, options?)

Semantic search over entities, with optional type and limit (default 10).

searchPreferences(query, options?) (bridge only)

Semantic search over preferences, with optional category filter.

getEntityByName(name) (bridge only)

Look up an entity by exact name (returns null if not found).

getRelatedEntities(entityId, options?) (bridge only)

Walk relationships outward from a given entity.

addRelationship(sourceId, targetId, relationshipType, options?) (bridge only)

Create a typed relationship between two entities.

mergeDuplicateEntities(sourceId, targetId, options?) (bridge only)

Merge source into target; aliases the source name onto target.

listEntities(options?) (hosted)

Enumerate entities with optional type and limit; an omitted limit is left to the server. No cursor/offset option is exposed.

getEntity(entityId) (hosted)

Fetch an entity by id.

updateEntity(entityId, options) (hosted)

Patch an entity’s name and/or description. Type and metadata are not update options.

deleteEntity(entityId) (hosted)

Remove an entity.

setEntityFeedback(entityId, options) (hosted)

Record positive/negative feedback that signals dedup/merge intent.

getEntityHistory(entityId) (hosted)

Audit log of changes to an entity.

mergeEntities(sourceId, targetId) (hosted)

Server-side merge with conflict resolution.

getEntityGraph() (hosted)

Snapshot of the workspace entity graph (nodes + edges) for visualization.

expandGraph(nodeId, loadedIds?) (hosted)

Expand around a graph node, excluding already loaded ids (default []). Returns ExpandedGraph. Fixed to work over REST in 0.5.0 — earlier releases nested the request payload under a literal body key, so every call failed with nodeId is required.

waitForExtraction(options)

Poll searchEntities for a predicate, exact expected names, or a minimum result count. See readiness constraints below.

Hosted entity auto-merge: NAMS resolves-before-create. When the name passed to addEntity is a sufficiently close match to an existing entity, the hosted service responds {id, resolution: "merged", merged_into, confidence} instead of a full entity record — with no name/type at all. The client detects resolution === "merged" and follows up with GET /entities/{id} (using merged_into, falling back to the response’s own id) to fetch the canonical merged-into entity, and that is what addEntity returns — so the resulting name and type can differ from what was passed in. If that follow-up GET 404s, or comes back with no name, the client falls back to a locally constructed Entity (the request’s name, a lowercased entityType, and a client-generated createdAt); other transport errors propagate, and a malformed canonical response (a missing id/type, or a field of the wrong shape) throws ValidationError. Either way, Entity.metadata (Record<string, unknown>) gains an added nams_resolution object:

Field Meaning

resolution

Always "merged" when this key is present.

merged_into

Id of the canonical entity the create resolved onto.

merge_confidence

Present only when the service reported a match confidence. Does not populate Entity.confidence, which reflects extraction confidence instead.

fallback

true when the canonical GET 404’d or came back incomplete and the client constructed the entity locally.

Null normalization: optional fields that arrive over the wire as null — on Entity, EntityRelationshipRef, Preference, Fact and EntityMention — are normalized to undefined, so every optional property is T | undefined at runtime, matching its declared type.

Returned types: Entity, Preference, Fact, Relationship, EntityHistory, EntityGraph.

Readiness options for waitForExtraction:

Option Type Default/constraint

query

string

First expected name when omitted; empty string for a predicate-only check.

expectedNames

string[]

Case-insensitive names that must all appear.

predicate

(entities: Entity[]) ⇒ boolean

Takes precedence over expected names/count when supplied.

minResults

number

1; used when neither a predicate nor expected names is supplied.

limit

number

10; effective search limit is at least the minimum count and expected-name count.

timeoutMs

number

30,000; bounded polling returns false at the deadline.

intervalMs

number

1,000 between unsuccessful polls.

waitForExtraction requires query, expectedNames or predicate. Defaults are 30,000 ms timeout, 1,000 ms interval and minResults: 1; the search limit defaults to 10 and is raised to at least minResults and the number of expected names. Prefer a predicate or case-insensitive expectedNames for this ingestion: unrelated nearest-neighbor results can satisfy a mere count. Returns false on timeout; validation and transport failures propagate. Both this helper and graph expansion ship in 0.5.0.

Entity types: hosted service uses lowercase strings — "person", "organization", "location", "concept", "tool", "custom". The bridge protocol uses POLE+O uppercase — "PERSON", "ORGANIZATION", "LOCATION", "EVENT", "OBJECT". The SDK normalizes both directions.

TypeDoc: LongTermMemory

client.reasoning — reasoning memory

Reasoning traces, steps, tool calls.

Method Purpose

startTrace(sessionId, task) (bridge only)

Begin a reasoning trace. Returns a ReasoningTrace with an id.

addStep(traceId, options?) (bridge only)

Add a step (thought / action / observation) to a trace.

recordToolCall(stepId, toolName, args, options?)

Persist a tool call: name, arguments, result, status, duration.

completeTrace(traceId, options?) (bridge only)

Mark the trace finished with an outcome and success: boolean.

getTraceWithSteps(traceId) (bridge only)

Fetch a trace including its steps and tool calls.

listTraces(options?) (bridge only)

Enumerate traces with sessionId and limit (default 100); no success/time-range filters.

getToolStats(toolName?) (bridge only)

Per-tool aggregate stats: success rate, average duration.

getSimilarTraces(task, options?) (bridge only)

"What did I do last time I tried something like this?" Semantic search over past traces.

recordStep(input) (hosted)

Record a "step" event for the hosted agent-trace surface.

listSteps(conversationId) (hosted)

All steps recorded against a conversation.

explainStep(stepId) (hosted)

Read the recorded step together with its tool calls and influenced entities. This is a provenance view, not hidden model reasoning.

getTraceByConversation(conversationId) (hosted)

Pull the full reasoning trace tied to a conversation.

getEntityProvenance(entityId) (hosted)

"Which reasoning steps touched this entity?" — audit query.

Returned types: ReasoningTrace, ReasoningStep, ToolCall, ToolStats, AgentStep, ConversationTrace, EntityProvenance.

Status values for ToolCall: "pending", "success", "failure", "error", "timeout", "cancelled".

TypeDoc: ReasoningMemory

client.query — read-only Cypher (hosted only)

Method Purpose

cypher({ cypher, params? })

Run a read-only Cypher query against the NAMS-managed graph. Returns { columns, rows, stats? }. Write queries are rejected server-side.

TypeDoc: QueryConsole

client.auth — API key + OAuth (hosted only)

Method Purpose

listApiKeys(workspaceId)

Enumerate keys in a workspace.

createApiKey(input)

Mint a new key. The plaintext key is only returned at creation — store it then.

revokeApiKey(keyId)

Permanently revoke a key.

revealApiKey(keyId, workspaceId)

Request plaintext for a stored key in the workspace, where authorized by the service.

rotateApiKey(keyId)

Mint a replacement key and revoke the old one.

refreshAccessToken(refreshToken)

Exchange a refresh token for a fresh access token pair.

TypeDoc: AuthClient

client.ontology — domain ontologies (hosted only)

Typed, versioned, validated domain schemas. See Ontology API and Use ontologies.

Method Purpose

list()

System templates + workspace-owned ontologies (active flagged).

get(id)

One ontology with its full revision history.

getActive()

Active parsed document plus ontologyId / versionId / revision / validationMode. In 0.5.0 that metadata is composed from a list() / get() lookup and can name the latest revision rather than the bound one; read GET /ontologies/active directly for a rollback target (see active binding in the released SDKs). The repository source, not yet released, reads the metadata from the active response’s bound version and adds schemaHash.

clone(templateName)

Editable workspace copy of a system template (rev 1).

create({ name, schema, validationMode? })

New workspace ontology from a schema document.

update({ id, schema, validationMode? })

New immutable revision.

activate(versionId)

Bind the version to the workspace. Validation enforcement is a service behavior, separate from successful activation.

delete(id)

Delete a workspace-owned ontology.

import({ content?, url?, format? })

Convert an external graph/ontology document into a non-persisted draft (OntologyImportResult).

diff(id, fromRevision, toRevision)

Structural diff between two revisions (OntologyDiff).

migrate(id, { fromVersionId, toVersionId, typeMappings, dryRun? })

Enqueue an async label-rename migration; returns a MigrationJob.

getMigration(jobId)

Poll a migration job’s status/progress.

Errors

The classes below describe SDK errors. Not all thrown values extend MemoryError: client guards, token providers, response parsing and fetch aborts can throw ordinary errors. A server correlation id is optional and appears only when captured from a response header.

Class Current REST behavior

MemoryError

Base class of the SDK’s named errors; does not cover every failure.

ConnectionError

Wraps fetch TypeError failures. Explicit connect() also wraps timeouts and HTTP 5xx.

AuthenticationError

HTTP 401 or 403.

TransportError

Other non-success statuses, including 400, 404, 429 and 5xx on ordinary requests; carries statusCode, responseBody and optional requestId. Also used for missing route parameters before HTTP.

ValidationError

Selected client-side argument checks. Has no details field.

NotFoundError

Exported compatibility class; ordinary REST 404 responses use TransportError.

NotSupportedError

No implementation on the selected transport; raised before HTTP.

The client makes one attempt per ordinary request. It does not automatically retry, expose RateLimitError, or honor Retry-After for retries. A normal request timeout can propagate a DOMException named TimeoutError; it is not always a ConnectionError. See handling errors for a bounded retry of an idempotent read.

import { MemoryClient, AuthenticationError, MemoryError, TransportError } from "@neo4j-labs/agent-memory";

const client = new MemoryClient();
try {
  await client.shortTerm.listConversations({ limit: 5 });
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error("Check credentials and workspace access", error.requestId);
  } else if (error instanceof TransportError) {
    console.error("HTTP failure", error.statusCode, error.requestId);
  } else if (error instanceof MemoryError) {
    console.error(error.message, error.requestId);
  }
  throw error; // Preserve non-SDK errors too.
} finally {
  await client.close();
}

TypeDoc: MemoryError and subclasses

Subpath exports

The package exposes seven subpath exports beyond the root. Each is independently importable to keep tree-shaking honest on edge runtimes.

Import Exports Use it for

@neo4j-labs/agent-memory

MemoryClient, types, errors, VERSION

Standard application code.

@neo4j-labs/agent-memory/middleware/vercel-ai

agentMemoryMiddleware, AgentMemoryLanguageModelMiddleware

Wire memory into a Vercel AI SDK generateText / streamText call. Implements specification v4 (ai 7.x). Requires the optional @ai-sdk/provider peer for its exported types. See Vercel AI SDK middleware.

@neo4j-labs/agent-memory/mcp

createMemoryTools, handleMemoryToolCall, McpToolDefinition, McpToolAnnotations, READ_ONLY_MEMORY_TOOLS, memoryToolAnnotations

The 12-tool memory surface as JSON Schema plus a dispatcher, for the low-level MCP Server API. See MCP tools.

@neo4j-labs/agent-memory/mcp/register

registerMemoryTools, memoryToolShapes, RegisterMemoryToolsOptions, MemoryToolCallAudit

Register the same 12 tools on a high-level McpServer (Zod input schemas, annotations, optional allow-list and audit hook). Requires the optional zod and @modelcontextprotocol/sdk peers.

@neo4j-labs/agent-memory/integrations/langchain

Neo4jChatMessageHistory, Neo4jEntityRetriever

LangChain JS — duck-typed against BaseChatMessageHistory and BaseRetriever. See LangChain JS.

@neo4j-labs/agent-memory/integrations/mastra

Neo4jMastraMemory

A thin thread-and-message-history adapter in Mastra’s vocabulary — not a Mastra Memory or storage adapter. See Mastra.

@neo4j-labs/agent-memory/integrations/strands

Neo4jSessionStorage, Neo4jConversationManager, registerReasoningHooks, connectMemoryToAgent, Neo4jMemoryStore

AWS Strands Agents SDK (JS). Requires the optional @strands-agents/sdk peer. See Strands.

@neo4j-labs/agent-memory/testing

BridgeTransport, BridgeTransportOptions

TCK conformance testing against a local bridge server. Production code should not import from here.

TypeDoc: each subpath’s exports are listed under the matching module in the TypeDoc module index.

Related package: @neo4j-labs/nams-ai-provider is a separate npm package, not a subpath of this one, that wraps this SDK for the Vercel AI SDK with additional retrieval and persistence policies — cross-session search, graph expansion, explicit memory tools, and lifecycle hooks across four selectable modes. See its API reference.

Observability

The logger constructor option receives typed `LogEvent`s for supported HTTP calls. Pre-request validation and some raw failures have no complete event pair:

import { MemoryClient, type LogEvent } from "@neo4j-labs/agent-memory";

const memory = new MemoryClient({
  logger: (event: LogEvent) => {
    if (event.kind === "error") {
      console.error("memory.error", event);
    }
  },
});
event.kind Fields

"request"

method, url, httpMethod?

"response"

method, url, status, requestId?, durationMs

"error"

method, url, status?, requestId?, durationMs, message

See enable request logging for the full pattern including OpenTelemetry forwarding.

Versioning

The SDK has its own package version; NAMS itself is continuously shipped and /v1 is the service API path. The current release is 0.5.0 (2026-09-22). Release tags are namespaced per package: typescript-v<X.Y.Z> publishes @neo4j-labs/agent-memory itself, separately from Python’s python-v* tags; nams-ai-provider-v<X.Y.Z> publishes the separate @neo4j-labs/nams-ai-provider package. The source manifest and changelog record repository development; an [Unreleased] entry does not prove an npm release — verify the installed package before treating it as shipped. This Neo4j Labs project provides no backward-compatibility or scheduled-deprecation guarantee.

See also