Skip to main content
The chat widget adds a floating chat button to your site. Clicking it opens a panel where visitors type to the same agent that answers your calls — same prompt, same knowledge base, same tools.
The widget renders inside a Shadow DOM, so your site’s CSS cannot break it and its styles cannot leak into your page. It works on sites using Tailwind, Bootstrap, aggressive CSS resets, and strict Content Security Policies.

Quick start

Paste this before the closing </body> tag of any page:
A chat button appears in the bottom-right corner of the page. The dashboard generates this snippet pre-filled under any agent’s Widget tab.
The package is scoped@openmic/openmic-chat-widget. The unscoped name openmic-chat-widget has no published versions, so a script URL without the @openmic/ prefix will 404.
The chat widget identifies agents with bot-uid, while the voice widget uses assistant-id. Both take the same agent UID — only the attribute name differs.

Complete working page

Attributes

Every attribute also accepts a data- prefix (data-bot-uid, data-public-api-key, and so on) for stricter HTML validators. The unprefixed form takes precedence when both are present.
subtitle and primary-color are not supported by the current build. They appear in the package README and in the dashboard’s generated snippet, but the widget never reads them — setting either has no effect.
Unlike the voice widget, the chat widget has no demo fallback. If bot-uid and bot-id are both missing it logs Missing bot-uid or bot-id attribute and disables itself rather than connecting to something unexpected.

Using it in React

The chat widget watches the DOM for elements being added and removed, so it initializes correctly in React and other SPAs with no extra work. Render the script and the element together:
Re-loading the script is a no-op and multiple widgets on one page work independently, so you do not need to coordinate mounting the way the voice widget requires. When the element unmounts, the widget tears down its listeners and cancels in-flight requests automatically.

TypeScript

Behaviour worth knowing

The active chat session is persisted in localStorage, so a visitor who reloads or navigates keeps their conversation. Sessions that have expired server-side recover gracefully with a “session expired” message rather than failing silently.
Transient network errors and 5xx responses are retried up to three times with exponential backoff (250ms, 500ms, 1000ms). 4xx responses — bad key, wrong agent UID — fail immediately without retrying. Closing the panel aborts any in-flight request, so a message the visitor never sees is not billed.
The chat panel’s DOM is only built the first time a visitor clicks the launcher, so pages where nobody opens chat pay almost nothing for having the widget present.
Chrome 89+, Firefox 85+, Safari 14+, Edge 89+. The widget checks at load time for fetch, ReadableStream, MutationObserver, AbortController, and Shadow DOM; if any are missing it logs a clear error and disables itself instead of half-working.
To point the widget at a backend running on your machine, set api-base:
Unlike the voice widget, the chat widget works normally when served from localhost.

Troubleshooting

All widget logs are prefixed with [openmic-chat-widget], so filtering the console by that string shows exactly what happened.