GUM Node SDK
This page shows how to integrate GUM Memory from a Node.js backend with @steamory-agent-kit/gum: create Sessions, append conversation messages, retrieve Memory, and write user Actions.
Use the GUM API Key only from server-side code. Do not expose it in browsers, mobile apps, or public repositories.
Before you start
You need:
- Node.js 18 or later.
- A valid GUM API Key.
- A server-side runtime, such as a Node.js API route, worker backend, Express service, or queue job.
For local testing, set the API key as an environment variable:
export GUM_API_KEY="<your-gum-api-key>"Install
npm install @steamory-agent-kit/gumThe SDK ships ESM, CommonJS, and TypeScript declarations. Node.js 18+ can use the built-in fetch implementation.
Quickstart
The following example covers the shortest integration path: initialize the client, create a Session, write a few conversation messages, and retrieve relevant Memory.
import { GumClient } from "@steamory-agent-kit/gum";
const gum = new GumClient({
apiKey: process.env.GUM_API_KEY!,
});
const session = await gum.sessions.create({
user_id: "user_123",
title: "Team scheduling session",
});
await session.addMessages([
{
role: "user",
content:
"For team scheduling, use Berlin when I mention Europe and Toronto when I mention the Americas.",
},
{
role: "assistant",
content:
"Got it. I will use Berlin for Europe scheduling and Toronto for Americas scheduling.",
},
]);
const memory = await session.getMemory({
query: "which city should be used for Europe team scheduling",
});
console.log(memory.data);Checkpoint
After this code runs, you should have a Session object and a Memory result in memory.data. Use session.id as the stable identifier for adding future messages and retrieving future Memory.
Use GUM in an assistant turn
In a real agent or assistant system, use this flow:
- Receive the user input in your Node.js backend.
- Retrieve relevant Memory for the current
session.id. - Add that Memory to your model context.
- After the model replies, write the user message and assistant reply back to GUM.
import { GumClient } from "@steamory-agent-kit/gum";
const gum = new GumClient({
apiKey: process.env.GUM_API_KEY!,
});
type ModelInput = {
userContent: string;
recalledMemory: unknown;
};
async function generateAssistantReply(input: ModelInput): Promise<string> {
// Replace this function with your OpenAI, Anthropic, Gemini, or local model call.
return `I will use the recalled memory for: ${input.userContent}`;
}
export async function assistantTurn(params: {
sessionId: string;
userContent: string;
}) {
const session = gum.sessions.fromId(params.sessionId);
const memory = await session.getMemory({
query: params.userContent,
details: true,
});
const assistantReply = await generateAssistantReply({
userContent: params.userContent,
recalledMemory: memory.data,
});
await session.addMessages([
{ role: "user", content: params.userContent },
{ role: "assistant", content: assistantReply },
]);
return {
reply: assistantReply,
memory: memory.data,
};
}Checkpoint
In production, store session.id when a new conversation is created. Later requests can restore the local Session handle with gum.sessions.fromId(sessionId); this does not make a network request.
Client configuration
By default, only apiKey is required. You do not need to configure host when using the default GUM service.
import { GumClient } from "@steamory-agent-kit/gum";
const gum = new GumClient({
apiKey: process.env.GUM_API_KEY!,
});Pass additional options when you need a custom deployment or timeout behavior:
const gum = new GumClient({
apiKey: process.env.GUM_API_KEY!,
host: "gum.asix.inc",
timeoutMs: 30_000,
});| Option | Type | Default | Description |
|---|---|---|---|
| apiKey | string | Required | GUM API Key. The SDK sends Authorization: Api-Key <apiKey>. Values that already start with Api-Key are not prefixed again. |
| host | string | gum.asix.inc | GUM service host. Plain host values are normalized to HTTPS, explicit http:// and https:// URLs are preserved, and a trailing / is removed. |
| timeoutMs | number | 30000 | Default request timeout in milliseconds. Set to 0 to disable the SDK timeout. |
| fetch | FetchLike | globalThis.fetch | Fetch-compatible implementation for tests, proxies, custom runtimes, or observability wrappers. |
Health check
gum.health(options?) checks the GUM service health endpoint. Use it in startup checks, deployment verification, or monitoring probes.
const health = await gum.health();
console.log(health);Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
| options | RequestOptions | No | Per-request options. Use it to override timeout, abort signal, and headers. |
Sessions
A Session is the GUM object that holds one user conversation and its Memory retrieval context. Prefer the methods on the Session handle. Use lower-level resource methods only when passing raw Session IDs is more convenient for your application.
Create a Session
gum.sessions.create(input, options?) creates a Session and returns a Session object. user_id is required by the current GUM API.
const session = await gum.sessions.create({
user_id: "user_123",
title: "Support chat",
metadata: {
source: "web-chat",
locale: "en-US",
},
});
console.log(session.id);
console.log(session.rawResponse);Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
| input | SessionCreateRequest | Yes | Request body for creating a Session. |
| input.user_id | string | Yes | User ID from your application. GUM uses it to associate the Session with user Memory. |
| input.title | string | null | No | Session title, useful for storing a conversation topic or source label. |
| input.metadata | Record<string, unknown> | null | No | Custom metadata such as channel, locale, product area, or business trace information. |
| options | RequestOptions | No | Per-request options. |
session.rawResponse keeps the original response envelope returned by GUM when the Session was created. If GUM returns a successful response without data.session_id, the SDK throws a regular Error with the message Gum API did not return data.session_id.
Restore a Session handle
gum.sessions.fromId(sessionId) creates a local Session handle from an existing Session ID without making a network request.
const session = gum.sessions.fromId("session_123");
await session.addMessage({
role: "user",
content: "Continue with the city preference from earlier.",
});Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
| sessionId | string | Yes | Existing Session ID that was created by GUM and stored in your application. |
Add messages
session.addMessage(message, options?) writes one message.
await session.addMessage({
role: "user",
content: "For Europe planning, keep Berlin as the default city.",
metadata: {
channel: "chat",
},
});Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
| message | Message | Yes | One message to write to the current Session. |
| message.role | string | Yes | Message role, such as user, assistant, system, or a custom role from your application. |
| message.content | string | Yes | Message text. GUM uses it to build and retrieve Memory. |
| message.id | string | null | No | Message ID from your application. Use it to connect GUM writes with your message table, logs, or traces. |
| message.metadata | Record<string, unknown> | No | Message-level metadata such as channel, model name, locale, or business tags. |
| message.timestamp | string | Date | null | No | Time when the message happened. Date values are serialized to ISO strings. |
| message.created_at | string | Date | null | No | Time when the message was created. Use it when this differs from the event timestamp. |
| message.status | pending | chunked | processed | failed | No | Message processing status. |
| options | RequestOptions | No | Per-request options. |
session.addMessages(input, options?) writes multiple messages. input can be either a message array or an object with a messages field.
await session.addMessages([
{
role: "user",
content: "Use Toronto for Americas planning.",
},
{
role: "assistant",
content: "Understood. I will use Toronto for Americas planning.",
},
]);
await session.addMessages({
messages: [
{
role: "user",
content: "Keep those defaults for future scheduling tasks.",
timestamp: new Date(),
},
],
});Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
| input | Message[] | AddMessagesRequest | Yes | Message collection to write. Array input is wrapped by the SDK as { messages }. |
| input.user_id | string | null | No | Optional user ID. Usually the Session is already bound to user_id when created, so this does not need to be repeated. |
| input.messages | Message[] | Yes | Messages to write to the current Session. When using array shorthand, the SDK creates this field. |
| options | RequestOptions | No | Per-request options. |
Message Date values are serialized to ISO strings. undefined fields are removed from request bodies.
Lower-level Session methods
If you only want to pass the Session ID, call the resource methods directly.
await gum.sessions.addMessages("session_123", [
{
role: "user",
content: "Draft the next Europe team agenda.",
},
]);
const memory = await gum.sessions.getMemory("session_123", {
query: "which city should be used for Europe planning",
});gum.sessions.addMessages(sessionId, input, options?) parameters:
| Name | Type | Required | Description |
|---|---|---|---|
| sessionId | string | Yes | Session ID to write messages to. The SDK safely encodes this value in the URL. |
| input | Message[] | AddMessagesRequest | Yes | Message collection to write. |
| options | RequestOptions | No | Per-request options. |
gum.sessions.getMemory(sessionId, params?, options?) parameters:
| Name | Type | Required | Description |
|---|---|---|---|
| sessionId | string | Yes | Session ID to retrieve Memory from. The SDK safely encodes this value in the URL. |
| params | GetSessionMemoryParams | No | Memory retrieval parameters. Omit it to request default Memory for the current Session. |
| options | RequestOptions | No | Per-request options. |
Memory recall and recall_config
session.getMemory(params?, options?) retrieves Memory for the current Session. Use query to focus retrieval and details to request richer response data.
const memory = await session.getMemory({
query: "which city should be used for Europe or Americas planning",
details: true,
});Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
| params | GetSessionMemoryParams | No | Memory retrieval parameters. Omit it to use GUM's default retrieval strategy for the current Session. |
| params.query | string | No | Query text for retrieval. Prefer the current user intent instead of the full prompt. |
| params.details | boolean | No | Requests richer Memory response data. Exact fields depend on the GUM API response. |
| params.recall_config | RecallConfig | null | No | Recall configuration. When present, the SDK uses the POST context request; null sends an explicit empty configuration. |
| options | RequestOptions | No | Per-request options. |
By default, the SDK uses the GET context request. When recall_config is present, the SDK uses the POST context request and sends the recall settings in the JSON body.
const memory = await session.getMemory({
query: "which city should be used for the user's scheduling request",
details: true,
recall_config: {
message_recent_limit: 20,
message_semantic_top_k: 8,
query_router: "single_hop_parallel",
enable_long_term_recall: false,
},
});Common recall_config fields:
| Field | Type | Purpose |
|---|---|---|
| message_recent_limit | number | Controls how many recent messages can be recalled. |
| message_semantic_top_k | number | Controls how many semantically matched messages can be recalled. |
| message_semantic_min_score | number | Sets the minimum semantic score for message recall. |
| query_router | "single_hop_direct" | "single_hop_parallel" | "multi_hop_chain" | Selects the query routing strategy. |
| enable_long_term_recall | boolean | Controls whether long-term Memory recall is enabled. |
| enable_long_term_rerank | boolean | Controls whether long-term Memory reranking is enabled. |
User Actions
User Actions record important product behavior, such as page views, button clicks, tool calls, or task state changes. They are useful for building Action Memory so an Agent can understand behavioral context.
await gum.userActions.create({
user_id: "user_123",
timestamp: new Date(),
content: "User opened the Europe team scheduling page",
session_id: "session_123",
event_type: "page_view",
page: "team_scheduling",
anchors: {
region: "Europe",
city: "Berlin",
},
metadata: {
source: "assistant-api",
},
});gum.userActions.create(input, options?) parameters:
| Name | Type | Required | Description |
|---|---|---|---|
| input | ActionLogInput | Yes | Request body for a user Action event. |
| input.user_id | string | Yes | User ID from your application that triggered this Action. |
| input.timestamp | string | Date | Yes | Time when the Action happened. Date values are serialized to ISO strings. |
| input.content | string | Yes | Natural-language description of the Action. Prefer a clear statement of what the user did. |
| input.session_id | string | null | No | Related Session ID. Use it to connect behavior with conversation context. |
| input.device_id | string | null | No | Device ID, useful for multi-device behavior analysis. |
| input.app | string | null | No | Application or product area name. |
| input.platform | string | null | No | Platform such as web, ios, android, or server. |
| input.event_type | string | null | No | Event type such as page_view, click, or tool_call. |
| input.page | string | null | No | Page, route, or feature entry point. |
| input.anchors | Record<string, string> | null | No | Searchable anchors such as region, city, or document_id. |
| input.metadata | Record<string, unknown> | null | No | Custom metadata. |
| input.entities | string[] | null | No | Entity names or IDs related to the Action. |
| options | RequestOptions | No | Per-request options. |
timestamp can be an ISO string or a Date. If you pass a Date, the SDK serializes it automatically.
Runtime behavior
Request options
Every SDK method accepts request options as its final argument. Use them to override timeout, abort signal, or headers for one request.
const controller = new AbortController();
const memory = await session.getMemory(
{
query: "which scheduling city should be used",
},
{
timeoutMs: 5_000,
signal: controller.signal,
headers: {
"X-Request-Id": "request_123",
},
},
);| Option | Type | Description |
|---|---|---|
| timeoutMs | number | Overrides the timeout for one request. |
| signal | AbortSignal | External abort signal. |
| headers | HeadersInit | Additional request headers. |
Response envelope
Except for gum.sessions.create(), which returns a Session object, resource methods return the GUM response envelope.
type GumEnvelope<T = unknown> = {
data?: T;
success?: boolean;
message?: string;
error?: unknown;
[key: string]: unknown;
};For example:
session.getMemory()returnsPromise<GumEnvelope<SessionMemory>>.session.addMessages()returns the GUM response envelope.gum.userActions.create()returnsPromise<GumEnvelope<CreateActionResponse>>.
Serialization
Before sending a JSON body, the SDK applies lightweight serialization:
Datevalues become ISO strings.undefinedfields are removed from objects and arrays.nullis preserved, which is useful when you need to send an explicit empty value.
Error handling
The SDK exposes three primary error types:
import {
GumApiError,
GumConnectionError,
GumTimeoutError,
} from "@steamory-agent-kit/gum";
try {
await session.getMemory({
query: "which scheduling city should be used",
});
} catch (error) {
if (error instanceof GumApiError) {
console.error(error.status, error.detail, error.body);
} else if (error instanceof GumTimeoutError) {
console.error(`Request timed out after ${error.timeoutMs}ms`);
} else if (error instanceof GumConnectionError) {
console.error("Network or fetch failure", error.cause);
} else {
throw error;
}
}| Error | When it is thrown |
|---|---|
| GumApiError | GUM returns a non-2xx response. Includes status, statusText, headers, body, and detail. |
| GumConnectionError | The underlying fetch request fails before a response is received. |
| GumTimeoutError | A request is aborted by the SDK timeout or an external AbortSignal. Extends GumConnectionError. |
TypeScript reference
Common types are exported from the package root:
import type {
ActionLogInput,
AddMessagesRequest,
CreateActionResponse,
GumClientOptions,
GumEnvelope,
Message,
RecallConfig,
RequestOptions,
SessionMemory,
SessionCreateRequest,
} from "@steamory-agent-kit/gum";
import { GumClient, Session } from "@steamory-agent-kit/gum";Core type reference:
type QueryRouter =
| "single_hop_direct"
| "single_hop_parallel"
| "multi_hop_chain";
interface SessionCreateRequest {
user_id: string;
title?: string | null;
metadata?: Record<string, unknown> | null;
}
interface Message {
role: string;
content: string;
id?: string | null;
metadata?: Record<string, unknown>;
timestamp?: string | Date | null;
created_at?: string | Date | null;
status?: "pending" | "chunked" | "processed" | "failed";
}Troubleshooting
apiKey must not be empty
apiKey is an empty string or contains only whitespace. Confirm that GUM_API_KEY is available in the server-side runtime and that runtime-only code is not being executed unexpectedly during a build step.
const gum = new GumClient({
apiKey: process.env.GUM_API_KEY!,
});401 or 403
Check that the API Key is correct, has permission to access the target GUM service, and that requests are going to the expected host. The SDK adds the Api-Key prefix automatically, so you do not need to concatenate it yourself.
Request timeout
The default timeout is 30 seconds. You can adjust it at the client level or per request.
const gum = new GumClient({
apiKey: process.env.GUM_API_KEY!,
timeoutMs: 60_000,
});Empty Memory result
First confirm that messages were written to the same Session. Then use a query that describes the user's intent. Add recall_config only when you need more control over retrieval behavior.
Next step
Continue with GUM Overview to understand GUM's role as the Memory infrastructure layer in SAK, or read Integration Patterns to choose a production integration pattern.