Skip to content
Busymate AI

Guides

Install and configure the Web SDK

Add the chat to your website with the versioned Web SDK, link signed-in customers through your own backend, and listen to typed events.

On this page

Put Busymate AI on your website with the official Web SDK distribution 0.1.0: a typed package, @busymate/ai-web, that mounts the chat, recognizes customers who are signed in to your product with a token your server signs, and reports every step as an event. Source, the configuration reference and two runnable examples live in the public repository, released as 0.1.0. The SDK pins the page side of the wire to contract v1 (bridge busymate-ai-v1), so updates to the hosted chat never change what your page sends or accepts. The release manifest pins the contract hashes.

The Web SDK is the recommended way to add the chat to a site you build. The one-line embed script keeps working; section 6 shows how to move.

1. Install the pinned version

  1. Install the packed tarball attached to the 0.1.0 release: npm install https://github.com/serebano/busymate-ai-sdk-web/releases/download/0.1.0/busymate-ai-web-0.1.0.tgz. The package is not on the npm registry.
  2. Without a bundler, download busymate-ai-web-0.1.0.iife.js from the same release, serve it from your own origin and pin it with integrity. It defines window.BusymateAIWeb.
  3. The package has no runtime dependencies, ships ESM, CommonJS and TypeScript types, and is safe to import during server rendering: nothing touches the page until mount() runs in a browser.

Read the versioned installation instructions before wiring callbacks.

2. Mount the chat

typescript
import { createBusymateChat, mintFromEndpoint } from "@busymate/ai-web";

const chat = createBusymateChat({
  assistant: "your-assistant",
  origin: "https://your-assistant.busymate.ai",
  mode: "launcher", // "launcher" | "panel" | "inline"
  // YOUR authenticated endpoint: { token, nonce } for a signed-in customer, 401 for a guest.
  getIdentity: mintFromEndpoint("https://YOUR-PRODUCT-DOMAIN/api/bmai/identity"),
});
chat.onLinkStatus(({ state, reason }) => console.debug("account link", state, reason));
chat.mount();

// Wire YOUR auth events, not your router.
auth.onSignIn(() => chat.identityChanged());
auth.onSwitchAccount(() => chat.switchAccount());
auth.onSignOut(() => chat.logout());
SettingPurpose
assistantRequired assistant slug from Console › Integration.
originThe serving origin your embed script uses: https://<assistant>.busymate.ai or your verified custom domain.
modelauncher (floating button and panel), panel (no button; open it from your UI) or inline (fills container).
getIdentityYour provider: a fresh { token, nonce } from your backend, or null for a guest.
accountOptional: your current account id, read in memory only, to catch a switch you forgot to report.
locale, themeFirst-paint language and theme; later setLocale() and setTheme().
onSignInRequest, onNavigateOptional: handle in-chat sign-in and same-site links in your own router.

Add your page's exact origin to Console › Integration › allowed origins. The chat refuses to load anywhere else, and the SDK says so (origin_not_allowed) instead of showing an empty panel. See the complete configuration reference.

Your backend mints a one-time launch token; the page never holds a key. Build one authenticated endpoint that reads { nonce, returnTo }, signs an ES256 JWT with your workspace claim, sub, the echoed nonce, a unique jti and an expiry within 120 seconds, and answers { token, nonce }. Copy a reference implementation from backend signing. mintFromEndpoint calls it with your cookies, refuses redirects and treats 401 as signed out.

Then wire your own auth events, not your router:

Your productCall
Sign-in or token rotationchat.identityChanged(): the same conversation continues, now identified.
Account switchchat.switchAccount(): the previous person's chat is withdrawn first.
Sign-outchat.logout(): the chat drops the identity and clears the transcript.
A token you already holdchat.identify({ token, nonce }) or chat.setUser(...).

When a guest taps Sign in inside the chat, the SDK sends them to your login page with return_to set to the current page and picks the token up when they return. Pass onSignInRequest to keep them on the page with your own login modal. See in-chat sign-in and the identity guide.

4. Listen to events

chat.on(name, listener) is typed. ready reports the visitor kind, open and close report the source, message mirrors every chat message for logging, navigate, signInRequest and sessionEnded report what the chat asked, and error names a refused origin or a silent frame.

chat.onLinkStatus(listener) reports the account link as { state, reason, source }. state is unlinked, linking, linked or failed. reason is a stable code such as identified, not_signed_in, mint_failed, nonce_mismatch, not_verified or origin_not_allowed. New codes can be added in later releases, so always keep a default branch. See events.

5. Content Security Policy and the frame

Add the chat origin to frame-src and connect-src, and your mint endpoint's origin to connect-src when it differs. cspHeader({ origin }) prints the line for you. The SDK loads no remote script. It injects one style element; pass your policy's nonce. Leave the frame's sandbox and allow="tools; microphone; autoplay" as the SDK sets them, and do not block microphone for the chat origin in Permissions-Policy if you offer voice. Every message is pinned to the frame and its exact origin, never *. See CSP and iframe guidance.

6. Move from the embed script

Existing embed snippets keep working, and nothing is switched off. To move a page, remove the embed script tag and create the chat with the same assistant and the script's origin. Move your getIdentity into the option, then replace identityChanged() and signedOut() with chat.identityChanged() and chat.logout(). The SDK uses the same frame and the same visitor storage, so returning visitors keep their conversations. Never run both on one page. Page tools, the floating window and push layout are not in 0.1.0 yet: keep the script on pages that use them. See the migration table and the widget page API.

Troubleshoot linking

Start from the link status your page logs:

  • not_signed_in: your provider returned null. Check that your session reached the mint endpoint.
  • mint_failed or nonce_mismatch: your endpoint failed or did not echo the nonce. The detail field has the HTTP status.
  • not_verified: the token reached the chat, but the verifier refused it. Open the conversation in the Console and read its account linking timeline. It names the cause, such as wrong issuer or audience, an unknown key id, an expired token or clock skew. Console › People › Identity health shows the same picture across customers.
  • origin_not_allowed: add the page origin to the allowed origins.

Then follow identity troubleshooting.

Verify

  1. Run the example apps (npm ci && npm run build, then node example-app/server.mjs) against a test workspace that allows http://localhost:5180; see the example-app instructions.
  2. Open the launcher as a guest: ready reports anonymous and link status stays unlinked.
  3. Sign in on your site: link status reaches linked · identified and the chat greets the customer by name.
  4. Switch account and sign out: the previous transcript disappears each time.
  5. Load the page on an origin that is not allowed: the SDK reports origin_not_allowed.

Questions

Which version should I install?

Web SDK distribution 0.1.0, the tarball or the script file attached to the release. It speaks wire contract v1, bridge busymate-ai-v1.

Do I have to replace the embed script?

No. Existing snippets keep working. The SDK is the recommended path for new integrations and for pages that need typed events or link status.

The chat received a token but refused it. The account linking timeline on the conversation in the Console names the exact reason.