The chat widget
Install the widget, sign users in, the JavaScript API, events, customisation and conversations in the widget.
The widget is a single script that renders a chat launcher on any website and connects it to an app.
#Install
Copy the snippet from App → Install. It looks like this:
<script src="https://<widget host>/widget.js"
data-app-id="app_xxxxxxxxxxxxxxxxxxxxxxxx"
data-api-url="https://<api host>/api"
async></script>data-app-id is the app's public id; data-api-url is the AgentRow API base URL.
Optional attributes: data-identity-token (a JWT already available at page load) and
data-open="true" to open the panel immediately.
#Signing users in
Call AgentRow.identify(token) after your user logs in, with a JWT your backend signs
using the app secret. Under "require verified" enforcement the widget shows a sign-in
gate until it is called. Call AgentRow.logout() when the user signs out.
#JavaScript API
AgentRow.init(options) starts the widget with options such as appId, apiUrl,
identityToken, autoOpen, container (mount inline in an element), mode
(floating or inline), theme, css, renderers, strings, showToolActivity and
showConversations.
Methods: identify, logout, open, close, send(text), newConversation,
openConversation(id), listConversations, showConversations, decideApproval
(approve or reject the tool call a run is waiting on), answerQuestion and
declineQuestion (the question card a run is waiting on), onEvent and
respondToEvent (chat window events, Tools), registerClientAction, setTheme
(change the design tokens at runtime), on, once, off, waitFor(event, options),
getClient (headless client), destroy, createClient (build your own UI on the
client), and version.
#Events
The widget emits events your page can react to: ready, open, close,
session:started, session:ended, identity:required, conversations:loaded,
conversation:loaded, conversation:opened, conversation:new,
conversation:created, message:sent, message:failed, message:delta (streamed
text), message:received, run:queued, run:started, run:completed, run:failed,
tool:started, tool:delta, tool:completed, tool:failed, approval:requested,
approval:decided, question:asked, question:answered, question:refused,
intake:submitted, intake:refused, event:<name> (an event tool fired <name> in
this chat window), client_action:started, client_action:completed,
client_action:failed, client_action:deferred, stream:state and error. Handlers
can filter by tool name, so a page can react when a specific tool completes, for example
to refresh an order panel after the assistant looked it up. The client_action: events
report a step a tool asked the chat window to do in the visitor's browser, such as a
change to a Shopify cart (Shopify store assistant) or an event your page answers (Tools).
#Customisation
- From the dashboard (no redeploy): placeholder, welcome message, suggested prompts, accent colour, light or dark theme, position, launcher label and icon, branding, and whether built-in tool activity is shown — and the look: a header logo, the font and its size, the panel's width, height and corner radius, and the colours of the user, assistant and support bubbles and of the header, with a live preview on the Install tab.
- From the page: theme tokens (colours, radius, panel width), extra CSS inside the widget, host CSS through shadow parts (launcher, panel, header, messages, composer, footer), custom renderers for messages and other parts, custom copy for every string, inline mounting, and a headless client for a fully custom UI.
- Tool activity: per tool, choose whether end users see nothing, a status line ("Looking up your order…") or full detail, and give the tool its own icon and label for that line. Built-in tools follow the app-level setting.
#The form at the start of a chat
The Install tab can ask the visitor a short form before the first message — name and email by default; fields of type name, email, phone, text or choice, each required or not — once per visitor or at the start of every conversation. A signed-in user is not asked what their identity token already says. The answers travel with the conversation as the end user's details: agents see them in their auth context and the Inbox shows them on the conversation.
#Questions the agent asks
When the toolbox node's Ask the user is on, the agent has the built-in ask_user
tool: it can put a card to the person with one or several questions (up to the node's
limit per call), each with options, one it recommends, a free answer where it allows
it, and several picks where it allows that. The run pauses until the card is answered.
The card shows one question at a time with arrows between them, and Cancel and Submit;
a lone question with options only is answered by the pick. The answers go back to the
agent as the tool's result — they are never a message of the conversation — and the
card gives way to an "Answered · …" line; Cancel tells the agent the person chose not
to answer, as does nobody answering within the node's wait. The builder's test chat
shows the same card. The tool is bound only where someone can answer: the widget and
the test chat, never Slack, webhooks or server runs.
#Events the page answers
A Chat window event tool (Tools) lets the agent ask your page to do something
and read the result: register AgentRow.onEvent("book_demo", async (input) => …) on
the page, and the tool binds on that page. Async events answer later with
AgentRow.respondToEvent(id, result), or from your server with the app secret.
#Conversations in the widget
End users see their conversation list, can start a new conversation and switch between earlier ones. Conversations are tied to the end user, so a signed-in user sees the same history on every device; an anonymous visitor's history stays with their browser until they sign in and it is merged.
#When a person takes over
On support apps the widget tells the end user when the conversation was handed to your team ("You're now talking to Billing…"), keeps the composer open, shows each team reply with the person's name, and notes when the team resolved the conversation (sending a message reopens it).
Updated 30 September 2026