The embed is a single deferred script under three kilobytes. It renders nothing on load — it registers an idle callback and a click target, and the widget itself is only fetched when a visitor actually opens it or after the page has been quiet for a few seconds, whichever comes first. Until then the host page pays almost nothing.
Everything the widget renders lives inside a shadow root with its own styles, so the host site’s stylesheet cannot leak in and my styles cannot leak out. This is the part that decides whether an embed is a support burden or not: without isolation, every future edit to the host site is a potential visual bug in my widget, and I would be debugging someone else’s CSS for free indefinitely.
Answers come from the client’s own content, chunked from their pages and indexed at build time, never crawled live. Each answer carries the page it came from as a visible link. When retrieval returns nothing relevant enough, the widget says it does not know and offers the handover instead — that path is not a failure state, it is the designed behaviour for roughly a third of real conversations.
Handover means the conversation so far is attached to a WhatsApp deep link or an email draft, prefilled, so the visitor does not retype their question and the business does not start from nothing. If the model service is unreachable, the widget degrades to that same handover form and shows no error, so a bad day upstream looks like a contact form and not a broken site.