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.onMessagereports the turn as usual. Because a refused prompt is not stored on the server, it does not reappear after the conversation is reloaded with theloadThread()method. - Without a
message: the chat shows theSTREAM_ERRORerror 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.
Header
| 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 |