AI Assistant SDK

IMPORTANT: This feature is available in private preview mode and accessible only on selected workspaces. To get access, contact your account manager or Synerise Support.

The AI Assistant SDK renders the Customer AI Assistant chat on a web page and talks to Synerise on the customer's behalf. This article is the reference of its options and API. For a step-by-step guide, see Implementing the Customer AI Assistant on your website.

Packages and delivery

The SDK is published as four npm packages that share one version number and as ready-to-use files served by Synerise.

Package For
@synerise/ai-assistant-sdk Vanilla JavaScript. Exposes the init() function and is also served as the files below.
@synerise/ai-assistant-react React 18. Exposes the AIAssistant component.
@synerise/ai-assistant-core Preact. The component the other packages build on.
@synerise/ai-assistant-ui UI primitives and the theme, for a custom chat with your own state handling.

Files served directly by Synerise:

File Format
https://web.snrbox.com/ai-shop-assistant/sdk.es.js ES module. About 155 kB initially; the Markdown renderer and other heavy parts load on demand.
https://web.snrbox.com/ai-shop-assistant/sdk.umd.js Single UMD file. About 325 kB; exposes the window.SyneriseAIShopAssistant global object

The files always serve the latest release. The npm packages let you pin a version.

ES module served by Synerise:

import { init } from "https://web.snrbox.com/ai-shop-assistant/sdk.es.js";

UMD file served by Synerise:

const chat = SyneriseAIShopAssistant.init({ rootElementId: "synerise-assistant" });

npm package:

import { init } from "@synerise/ai-assistant-sdk";

Initialization options

Renders the chat into an existing, empty element and returns an instance. The chat starts closed; call open() to show it. Initialization fetches the assistant's availability and, if the assistant is available, starts a conversation (or loads the one given in threadId).

Option Type Default Description
rootElementId string required ID of the element that hosts the chat. Must exist and be empty.
stream boolean false When true, answers are streamed (server-sent events) and appear progressively. Recommended. Streaming also enables the onStreamError and onConversationTitle callbacks.
header string "AI Assistant" Title shown in the header. For a custom element, use the slots.header.title slot.
avatar string Synerise AI icon URL of the avatar shown next to the assistant's messages.
assistantId string workspace default ID (UUID) of the assistant configuration to talk to.
context object | null null Context sent with every request, for example store and language.
additionalContextValues object | null null Extra metadata sent with every request, for example segment IDs or experiment flags.
pageContext { pageType: "product"; itemId: string } | null not set Product the customer is viewing. See Storefront page context.
autoDetectPageContext boolean false Read the product from Open Graph tags and keep it in sync with changes to the <head> element.
threadId string not set Initialize with an existing conversation loaded instead of starting a new one.
textAreaMaxRows number 3 Number of lines the message input grows to before it scrolls.
actionsLayout "inline" | "dock" "inline" Where the latest answer's buttons and suggestions render: inside the message or in a full-width row below the last message.
theme { variables: Record<string, string> } defaults Overrides of the visual variables. See Customizing the AI Assistant chat.
texts AIAssistantTranslations English Overrides of the interface texts. See Texts.
slots ChatSlots not set Replacements for parts of the interface. See Slots.
fastMode boolean false Ask for faster, less thorough answers.
apiUrl string https://api.synerise.com/agents/v1/ai-assistant Base address of the assistant API.
disableXSRFToken boolean true Authentication mode. See Authentication.
settings { assistantVisible: boolean; responseFeedbackEnabled: boolean } not set Special integrations only. Skips the availability check and uses these values. See Assistant availability.
onLoad ({ assistantVisible }) => void not set Called once when the availability is known, before the conversation starts.
onMessage (response) => void not set Called after every successful answer with the response body. See Response shape.
onStreamError ({ message, type, stage }) => void not set Called when the assistant refuses a streamed exchange. See Refused responses.
onConversationTitle ({ threadId, title }) => void not set Called when Synerise generates the conversation's title (streaming only).

Instance methods

Method Returns Description
open() void Shows the chat.
close() void Hides the chat without removing it. The conversation is kept.
message(text) void Sends a message as if the customer had typed it.
unmount() void Removes the chat from the page and empties the container.
setContext(value) void Replaces context for the following requests.
setAdditionalContextValues(value) void Replaces additionalContextValues for the following requests.
setPageContext(value) void Sets or clears (null) the product the customer is viewing.
loadThread(threadId) Promise<void> Replaces the current conversation with an existing one.
getConversations() Promise<AIAssistantConversation[]> Lists the customer's conversations.

Response shape

onMessage receives the body of each successful response:

type Response = {
  data: {
    messages: Array<HumanMessage | AIMessage>;
    context: Context | null;
    additionalContextValues: AdditionalContextValues | null;
  };
  meta: { threadId: string };
};

messages is the full conversation so far, made of the elements described in Message elements.

Conversations

type AIAssistantConversation = {
  threadId: string;
  agentType: string;
  realm: string;
  businessProfileId: number;
  userId?: number | null;
  clientId?: string | null;
  createdAt: string;          // ISO timestamp
  title?: string | null;      // generated by Synerise
  summary?: string | null;    // generated by Synerise
  meta?: Record<string, unknown> | null;
};

If loadThread() or initialization with threadId hits a conversation that does not exist (HTTP 404), the chat enters the THREAD_NOT_FOUND error state and shows a Start new conversation button that starts a fresh conversation.

Authentication

Mode disableXSRFToken How requests are authenticated
Tracking code (default) true The SDK reads the tracker key (SR.auth.trackerKey()) and the customer's UUID (SyneriseTC.uuid) from the Synerise Web SDK on the page and sends them with each request. The tracking code must be loaded and initialized first.
Cookie and XSRF token false Requests are sent with credentials and the XSRF-TOKEN cookie is mirrored into the X-XSRF-TOKEN header. For tenants configured for session-based authentication.

Assistant availability

Before the conversation starts, the SDK fetches the assistant's public settings:

type AIAssistantPublicSettings = {
  assistantVisible: boolean;          // false: the chat renders nothing
  responseFeedbackEnabled: boolean;   // true: answers get the rating toolbar
};

assistantVisible: false means the assistant is disabled for the workspace or the credits are exhausted. The chat then renders nothing and no conversation starts. If the settings request fails, both flags fall back to false and the chat renders nothing. onLoad is called exactly once with the result; the flag is not re-checked during the session.

The settings option replaces the fetch with fixed values. Use it only for integrations that must not depend on the workspace settings, such as a read-only preview. Everywhere else leave it unset.

Storefront page context

type StorefrontPageContext = { pageType: "product"; itemId: string };

The product is sent with every request under the additionalContextValues.page_context key. Three ways set it: the pageContext option, autoDetectPageContext: true, and the setPageContext() method. Once any of them is used, it takes precedence over a page_context key placed in additionalContextValues directly: setPageContext(null) removes the key even if it is still present there.

Automatic detection reads the og:type tag (product or product.item; product.group is ignored) and the product:retailer_part_no tag. The tags are read synchronously during initialization, so the first request already carries the product, and <head> is observed for changes afterwards.

The detection is also available as a function:

import { detectPageContextFromMeta } from "https://web.snrbox.com/ai-shop-assistant/sdk.es.js";

const detected = detectPageContextFromMeta(); // StorefrontPageContext | null

Refused responses

In streaming mode Synerise can refuse an exchange instead of answering it, most often because guardrails rejected the prompt. The SDK handles both forms:

  • With a message: the text is shown as the assistant's answer and the conversation continues. onMessage reports the turn as usual. Because a refused prompt is not stored on the server, it does not reappear after the conversation is reloaded with the loadThread() method.
  • Without a message: the chat shows the STREAM_ERROR error state with a Try Again button; the customer's message stays in the conversation.

onStreamError is called in both cases with the raw payload:

type AIAssistantStreamError = {
  message?: string;   // user-facing copy, when provided
  type?: string;      // e.g. "validation_failed"
  stage?: string;     // e.g. "input" or "output"
  [key: string]: unknown;
};

An exception thrown inside the callback is contained and does not affect the chat.

Texts

type AIAssistantTranslations = Partial<{
  loadingMessage: string;
  tryAgain: string;
  startNewConversation: string;
  rating: Partial<{ commentPlaceholder: string; cancel: string; submit: string; thanks: string }>;
  errorMessage: Partial<Record<AIAssistantErrorType, string>>;
}>;

type AIAssistantErrorType =
  | "UNKNOWN_ERROR"
  | "NETWORK_ERROR"      // offline, blocked request, CORS, timeout
  | "SERVER_ERROR"       // HTTP 5xx
  | "CLIENT_ERROR"       // HTTP 4xx
  | "THREAD_NOT_FOUND"   // the requested conversation does not exist
  | "STREAM_ERROR";      // refused exchange without user-facing copy

In the React and Preact packages every text also accepts a React node. Defaults and usage are listed in Customizing the AI Assistant chat.

Message elements

Messages returned in response.data.messages and passed to message slots:

type HumanMessage = {
  type: "HUMAN";
  content: { type: "BUBBLE_TEXT"; content: string };
  actionParams?: Record<string, unknown>;
};

type AIMessage = {
  type: "AI";
  seqNo?: number | null;      // position of the answer in the conversation; null for the greeting
  feedback?: { vote: "POSITIVE" | "NEGATIVE"; comment?: string };
  isHighlighted: boolean;
  content: MessageElement[];
};

type MessageElement =
  | { type: "TEXT"; content: string }                           // Markdown
  | { type: "BUBBLE_TEXT"; content: string; productLinks?: ProductLink[] }
  | { type: "OL" | "UL"; items: Array<{ content: string; nestedList?: MessageElement }> }
  | { type: "BUTTON"; content: string; action: ChatAction; iconLeft?: IconName; iconRight?: IconName;
      tooltip?: { title: string; description?: string }; disabled?: boolean }
  | { type: "SUGGESTION"; content: { title: string; description: string }; action: ChatAction; disabled?: boolean }
  | { type: "CAROUSEL"; content: ProductItem[] };               // rendered as product cards

type ProductItem = {
  itemId?: string;            // absent on items that cannot be attributed; such items emit no click events
  img: string;
  title: string;
  description: string;
  meta: string[];             // additional lines, HTML allowed
  action: ChatAction;
  attributes: Record<string, unknown>;
  correlationId?: string | null;
  campaignId?: string | null;
  searchCorrelationId?: string | null;
};

type ProductLink = { url: string; itemId: string; correlationId?: string | null;
  campaignId?: string | null; searchCorrelationId?: string | null };

Clicks on product cards and on inline product links are reported to Synerise as assistant.click events automatically; see Measuring the AI Assistant.

Chat actions

Every button, suggestion, and product card carries an action:

type ChatAction =
  | { type: "MESSAGE"; content: string; params?: object }   // sends a message to the assistant
  | { type: "REDIRECT"; url: string }                        // opens a page
  | { type: "CUSTOM"; name: string; params?: object };      // handled by the host application

CUSTOM actions are produced by Custom action tools of the assistant configuration. The React and Preact packages deliver them to the onCustomAction callback as an object with the actionName and params fields. The vanilla init() does not expose this callback in the current version.

Icon names

Used by iconLeft and iconRight on buttons:

AngleLeftM | AngleRightM | ArrowRightM | AttachmentsM | CloseM |
CopyClipboardM | FileTypeImage | InfoFillM | InfoM | LinkM |
OptionVerticalM | PauseM | RefreshM | SearchM | StepBackM |
StepForwardM | StopM | WarningFillM | WarningM

Slots

A slot is a function that returns a DOM element (or a React node in the framework packages). The chat calls it where the default element would render and uses the result instead. Return null to hide the element, undefined to keep the default.

Slot Parameters Replaces
header.title none The title.
header.closeButton { onClose } The close button. Call onClose() to close the chat.
header.extraActions none An extra area before the close button.

Messages

Slot Parameters Replaces
messages.avatar { src } The avatar next to the assistant's messages.
messages.loader { avatar, message } The typing indicator row.
messages.error { code, message, tryAgainMessage, onRetry } The error row with the retry button.
messages.toolbar { seqNo, isLastMessage, feedback, submitFeedback } The rating toolbar under an answer. Rendered only when rating is enabled and the answer can be rated.
messages.type.text { type: "text", content } A Markdown text element.
messages.type.bubbleText { type: "bubble-text", content, productLinks, onItemClick } A short text bubble. Call onItemClick(itemId) when a product link is clicked to keep click tracking.
messages.type.button { type: "button", content, iconLeft, iconRight, tooltip, disabled, action, onClick } A button.
messages.type.suggestion { type: "suggestion", content: { title, description }, action, disabled } A suggestion card.
messages.type.list { type: "ordered-list" | "unordered-list", items } A list.
messages.type.products.container { type: "products", content: ProductItem[], onItemClick } The wrapper around the product cards.
messages.type.products.item ProductItem & { onItemClick } A single product card. Call onItemClick() on click to keep click tracking.
messages.type.custom[name] data An element of a type the SDK does not render itself.

Message input

Slot Parameters Replaces
textArea.input { value, onChange, disabled, placeholder, ref, state } The text field. Assign the element to the ref.current property.
textArea.submitButton { onSubmit, disabled, icon, state } The send button.

Markdown

Slot Parameters Replaces
markdown[tagName] the element's data The renderer of one HTML tag in Markdown answers, for example the a, code, or table tag.

React and Preact packages

npm install @synerise/ai-assistant-react preact

@synerise/ai-assistant-react wraps the Preact component for React 18 applications. The chat itself is rendered with Preact, so preact must be installed next to the react and react-dom packages.

import { useRef } from "react";
import { AIAssistant, type AIAssistantRef } from "@synerise/ai-assistant-react";

export function AssistantPanel() {
  const chatRef = useRef<AIAssistantRef>(null);

  return (
    <AIAssistant
      ref={chatRef}
      apiUrl="https://api.synerise.com/agents/v1/ai-assistant"
      displayMode="bordered"
      stream
      disableXSRFToken
      authParams={{ code: SR.auth.trackerKey(), clientUUID: SyneriseTC.uuid }}
      onPromptSuccess={(response) => console.log(response.meta.threadId)}
      onCustomAction={({ actionName, params }) => console.log(actionName, params)}
    />
  );
}

Differences from init():

Prop Description
apiUrl Required. Base address of the assistant API.
onPromptSuccess Required. The equivalent of the onMessage option.
displayMode "drawer" or "bordered" - the layout of the window.
isOpen Controls whether the chat is shown; open() and close() do not exist.
authParams { code, clientUUID } for tracking-code authentication; the React package does not read them from the page by itself.
onCustomAction Receives CUSTOM actions.
onError Receives every error as an object with the errorType, operation, and error fields.
header, avatar, texts Accept React nodes in addition to strings.

The component is a forwardRef; the ref exposes the loadThread(threadId) and getConversations() methods. The usePageContext({ autoDetect, initial }) hook returns [pageContext, setPageContext]; merge the value into additionalContextValues.page_context yourself. The API helpers are available without rendering anything as assistantApi (initChat, sendChatMessage, getConversations, and others).

Render the component on the client only. In server-side rendered applications (Next.js, Remix), load it dynamically with SSR disabled or mount it inside an effect.

@synerise/ai-assistant-core exposes the same AIAssistant component for Preact applications. @synerise/ai-assistant-ui exposes the chat primitives (ChatBase, message elements, Icon, the theme) for a chat with custom state handling.

Endpoints used by the SDK

All requests go to the address in apiUrl (by default https://api.synerise.com/agents/v1/ai-assistant). Allow this host and web.snrbox.com in your Content Security Policy.

Request Purpose
GET /public-settings Assistant availability and feature flags
POST /chat Starts a conversation and returns the greeting
POST /chat/{threadId}/messages Sends a customer's message
GET /chat/{threadId}/messages Loads the messages of an existing conversation
GET /chat/conversations Lists the customer's conversations
PUT /chat/{threadId}/messages/rating Records a rating of an answer
POST /chat/{threadId}/events/click Records a click on a product

Canonical URL: https://hub.synerise.com/developers/web/ai-assistant-sdk