Enable request logging
The TypeScript client emits a typed event stream around every HTTP
exchange via the logger constructor option. Hook this into your
favourite logger (Pino, Winston, console) for tracing, request-id
correlation, and ops dashboards.
Prerequisites: a configured MemoryClient and an application logger.
Procedure
-
Pass a
loggercallback when constructing the client. -
Make a supported read and inspect the emitted event fields below.
-
Redact query values and service error text before exporting logs; retain a request id when supplied.
Basic usage
import { MemoryClient, type LogEvent } from "@neo4j-labs/agent-memory";
const client = new MemoryClient({
logger: (event: LogEvent) => {
console.log(JSON.stringify(event));
},
});
You’ll see two events per successful call:
{ "kind": "request", "method": "create_conversation", "url": "...", "httpMethod": "POST" }
{ "kind": "response", "method": "create_conversation", "url": "...", "status": 200,
"requestId": "req-abc", "durationMs": 142 }
Recognized HTTP failures emit request then error:
{ "kind": "request", "method": "create_conversation", "url": "...", "httpMethod": "POST" }
{ "kind": "error", "method": "create_conversation", "url": "...", "status": 500,
"requestId": "req-abc", "durationMs": 87, "message": "..." }
Event shape
type LogEvent =
| { kind: "request"; method: string; url: string; httpMethod?: string }
| { kind: "response"; method: string; url: string; status: number;
requestId?: string; durationMs: number }
| { kind: "error"; method: string; url: string; status?: number;
requestId?: string; durationMs: number; message: string };
method is the snake_case bridge method name
(create_conversation, search_entities, record_step, …). httpMethod
is the HTTP verb (POST, GET, …).
Bodies are never logged by default
The logger does not receive separate request or response body fields. URLs can contain search query values, and error messages can include server-provided text. Apply redaction before exporting events; absence of body fields is not a guarantee that events contain no sensitive data. If you need bodies during development, log them yourself by wrapping the call:
const msg = await client.shortTerm.addMessage(conv.id, "user", "hi");
console.debug("addMessage result:", msg);
Logger exceptions are swallowed
If your logger throws, the SDK catches the error and continues. This means a misbehaving logger can’t take down your application — but it also means logging is best-effort. Wrap calls into your structured logger in your own try/catch if you care.
User-Agent customization
The client sends a default User-Agent like
@neo4j-labs/agent-memory/0.5.0 (node/22.5.0; darwin). To override,
pass your own:
new MemoryClient({
headers: { "User-Agent": "my-app/2.1 (CI runner)" },
});
Wrapping SDKs should append their own identifier (e.g.,
@neo4j-labs/agent-memory/0.5.0 my-wrapper/1.0) so server-side metrics
can break the population down.
Request-id correlation
SDK errors built from a response may carry error.requestId. It is absent
when the service supplied no recognized header or no response was captured.
Pre-request validation/unsupported operations do not emit an HTTP event pair;
raw aborts, parsing or token-provider failures may also lack an error event.
See handle errors.
Verify the integration
Make one successful read and inspect its request/response pair. With an
offline HTTP stub returning 500, check the request/error pair and optional
request id. Also test a client-side validation failure: it need not emit HTTP
events. The SDK’s observability and docs-contract integration tests cover these
contracts without sending data to an external logging service.