# AI Assistant — full corpus > Every English page of the site as Markdown, in llms.txt order. Per-page twins: append `.md` to any page URL. --- title: "AI Assistant — Busy day? You’ve got a mate." description: "An AI assistant that learns from your website, answers questions, helps customers choose and hands the hot ones to your team — under your own name, on your own web address, day and night." last_updated: "2026-10-08T17:27:06+03:00" --- # AI Assistant — Busy day? You’ve got a mate. Source: https://busymate.ai/ Last modified: 2026-10-08T17:27:06+03:00 An AI assistant that learns from your website, answers questions, helps customers choose and hands the hot ones to your team — under your own name, on your own web address, day and night. ## In this section - [How the platform works](https://busymate.ai/platform.md): How the platform works — everything is a setting you control - [WebMCP: make your website something an assistant can use](https://busymate.ai/webmcp.md): WebMCP — your website tells assistants what it can do; what changes for customers and how to enable it - [Agent Ready v1: the web standard an AI agent reads](https://busymate.ai/agent-ready.md): The AI Assistant Agent Ready v1 standard — six scored sections, ten requirements, and the evidence each check records - [Meet the assistant your website could have](https://busymate.ai/try.md): Shareable standalone assistant preview for any public website - [Security and protocols](https://busymate.ai/security.md): How data is kept separate, how sign-in is checked, how changes are confirmed - [Who runs on AI Assistant](https://busymate.ai/customers.md): Businesses running on it today, with addresses you can open - [Pricing](https://busymate.ai/pricing.md): Platform pricing per workspace; the Shopify app plans - [About AI Assistant](https://busymate.ai/about.md): Who builds it and what it is - [Contact](https://busymate.ai/contact.md): Talk to the team - [Solutions — support, sales, help in your app, everyday tasks](https://busymate.ai/solutions.md): Customer support, sales and onboarding, help inside your app, everyday tasks, what customers keep asking, agencies - [Documentation](https://busymate.ai/docs.md): One AI assistant you brand as your own, for your own customers, connected to your own systems. - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md): Web embed, iOS, Android, desktop, sign-in contract, MCP client OAuth - [Changelog](https://busymate.ai/changelog.md): What shipped, release by release - [Articles](https://busymate.ai/articles.md): Researched reads on AI assistants, agents and your website - [Privacy policy](https://busymate.ai/privacy.md): The AI Assistant privacy policy. - [Terms of service](https://busymate.ai/terms.md): The AI Assistant terms of service. - [Data processing addendum](https://busymate.ai/legal/dpa.md): The AI Assistant data processing addendum. - [SMS support program](https://busymate.ai/sms.md): The AI Assistant SMS support program. - [App Store](https://busymate.ai/store.md): Apps built for your mate - [Artifacts](https://busymate.ai/artifact.md): Public pages made by businesses' assistants - [Free tools: check your website for AI assistants](https://busymate.ai/tools.md): Free checker tools for any website owner — llms.txt, WebMCP readiness, MCP server - [AI chatbot connectors for every channel](https://busymate.ai/connectors.md): Every connector the assistant works through, grouped by category — what is ready today and what is on the way ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "How the platform works" description: "How AI Assistant works: one assistant that takes your brand, your content, your systems and your rules — from setup to human handoff. Change settings, not code." last_updated: "2026-10-05T21:34:58+03:00" --- # How the platform works Source: https://busymate.ai/platform Last modified: 2026-10-05T21:34:58+03:00 How AI Assistant works: one assistant that takes your brand, your content, your systems and your rules — from setup to human handoff. Change settings, not code. ## In this section - [White-label AI assistant for agencies and SaaS](https://busymate.ai/platform/white-label.md): An assistant under your own name, on your own domain - [Download AI Assistant Console | Desktop app](https://busymate.ai/desktop.md): Download the Console desktop app (macOS, Windows, Linux) — notifications, badge, deep links; machine manifest at /api/desktop/releases ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "White-label AI assistant for agencies and SaaS" description: "Launch an assistant with your brand, content and tools. Multilingual conversations and human handoff, with domain and branding features matched to your plan." last_updated: "2026-10-01T17:51:38+03:00" --- # White-label AI assistant for agencies and SaaS Source: https://busymate.ai/platform/white-label Last modified: 2026-10-01T17:51:38+03:00 Launch an assistant with your brand, content and tools. Multilingual conversations and human handoff, with domain and branding features matched to your plan. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "WebMCP: make your website something an assistant can use" description: "Your website tells assistants what it can do — book, order, check a status, answer. What changes for your customers, what AI Assistant does on a WebMCP site, and how to enable it in an afternoon." last_updated: "2026-09-27T22:02:30+03:00" --- # WebMCP: make your website something an assistant can use Source: https://busymate.ai/webmcp Last modified: 2026-09-27T22:02:30+03:00 Your website tells assistants what it can do — book, order, check a status, answer. What changes for your customers, what AI Assistant does on a WebMCP site, and how to enable it in an afternoon. ## In this section - [Adopt WebMCP: a quick how-to and a copy-paste prompt for any assistant](https://busymate.ai/webmcp/adopt.md): How to adopt WebMCP: four steps and a copy-paste prompt for any assistant - [WebMCP tool inspector: see what an assistant can do on any website](https://busymate.ai/webmcp/inspect.md): WebMCP tool inspector — the tools a given website publishes, labelled by where each answer came from ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "Pricing" description: "Compare plans per workspace, included conversations and feature limits. See which plans include badge removal, custom domains and voice. AI Assistant for Shopify has separate plans." last_updated: "2026-10-05T21:48:45+03:00" --- # Pricing Source: https://busymate.ai/pricing Last modified: 2026-10-05T21:48:45+03:00 Compare plans per workspace, included conversations and feature limits. See which plans include badge removal, custom domains and voice. AI Assistant for Shopify has separate plans. ## Start free, grow when you are ready Every plan includes the assistant's conversations, your team's inbox and every surface you connect. No per-answer charges, no card for the free plan. ### Free — Free, no card needed - Assistant conversations a month: 100 - Team seats: 2 - Workspaces: 1 - Channels: Website chat and your hosted chat page - Knowledge sources: 3 - Indexed pages: 200 - Your brand only, no badge: Not included - Web search and page reading: Not included - Voice calls: Not included - Custom domain: Not included - API keys, webhooks and MCP: Not included - Single sign-on and audit log: Not included - Support: Community help ### Starter — $29/month, or $24.17/month billed yearly ($290/year) - Assistant conversations a month: 1,000 - Team seats: 5 - Workspaces: 1 - Channels: Plus your main messaging channels - Knowledge sources: 20 - Indexed pages: 2,000 - Your brand only, no badge: Included - Web search and page reading: Not included - Voice calls: Not included - Custom domain: Not included - API keys, webhooks and MCP: Not included - Single sign-on and audit log: Not included - Support: Standard support ### Growth — $99/month, or $82.50/month billed yearly ($990/year) (Most popular) - Assistant conversations a month: 5,000 - Team seats: 15 - Workspaces: 3 - Channels: All released channels; voice in beta - Knowledge sources: 100 - Indexed pages: 20,000 - Your brand only, no badge: Included - Web search and page reading: Included - Voice calls: Included - Custom domain: Included - API keys, webhooks and MCP: Included - Single sign-on and audit log: Not included - Support: Priority support ### Scale — $299/month, or $249.17/month billed yearly ($2,990/year) - Assistant conversations a month: 20,000 - Team seats: Unlimited - Workspaces: 10 - Channels: All released channels; voice in beta - Knowledge sources: 500 - Indexed pages: 100,000 - Your brand only, no badge: Included - Web search and page reading: Included - Voice calls: Included - Custom domain: Included - API keys, webhooks and MCP: Included - Single sign-on and audit log: Included - Support: Dedicated support ### Enterprise — Custom pricing - Assistant conversations a month: Unlimited - Team seats: Unlimited - Workspaces: Unlimited - Channels: All released channels; voice in beta - Knowledge sources: Unlimited - Indexed pages: Unlimited - Your brand only, no badge: Included - Web search and page reading: Included - Voice calls: Included - Custom domain: Included - API keys, webhooks and MCP: Included - Single sign-on and audit log: Included - Support: Dedicated support When a month's conversations are used up the assistant hands new chats to your team; nothing is charged beyond your plan. Prices are in USD, per workspace. ## Platform One price per workspace — each client, product or brand gets its own. Badge removal and custom domains depend on your plan; compare the included features above. If we do not know a price, we show it as unknown — never as zero. Talk to us: https://busymate.ai/contact. Partners and agencies: https://busymate.ai/solutions/agencies-white-label. Selling on Shopify? See the Shopify app's plans: https://busymate.ai/store/apps/busymate-ai-shopify ## What counts What each word on the bill means. ### What is a conversation? One chat between a customer and the assistant, on any surface — your website, the chat launcher, iOS, Android, desktop or a channel. Conversations are counted per workspace. ### What is model spend? What the AI providers charge for the models your conversations use, counted per provider and shown per workspace and per user in the Console. If we do not know a price, we show it as unknown — never as zero. ### What counts as a resolution in the Shopify app? A shopper conversation the assistant handled on its own, without your team — billed once per conversation, and only then. A handoff to your team, an "I'm not sure" reply, or a conversation nobody answers is never billed. Each plan includes a monthly number of resolutions, then charges per resolution up to the plan's monthly cap — that cap is the most Shopify will bill you in a month for this app, the plan's own fee included. The assistant is never switched off for billing. ### What happens when I reach my limit? Two different caps, same rule — never a silent overspend. On AI Assistant for Shopify, your plan's resolution cap never switches the assistant off: it keeps chatting and new conversations route to your team. On the platform, your workspace's own conversation and spend caps (set in the Console) work the other way — the assistant stops at that cap, so it never silently overspends. ### How is the Shopify app billed, and what happens after the trial? Shopify bills every paid plan on your regular Shopify invoice, never through us directly. A plan's free trial includes that plan's monthly resolutions from day one; nothing is charged until the trial ends, and you can change or cancel the plan from your Shopify admin at any time. Until you choose a plan, the app runs on the Free plan's limits. ### What is a seat? A teammate who can sign in to a workspace's Console and Inbox. Where a plan lists "Unlimited seats," that workspace has no per-seat charge and no cap on how many teammates you add. ### What does "Priority support" mean? A request from a workspace on a plan that lists "Priority support" is handled ahead of the standard queue, through the same support channel every workspace already uses. ### I run a Shopify store — can I also use the platform? Yes. Your Shopify store keeps its own plan, billed through Shopify. Anything beyond it — another channel, another site, another brand — is a separate workspace. Talk to us and we'll set up the exact combination for your case. ### I run an agency with Shopify clients — how does this work? Talk to us. We'll set up your Console with a workspace per client and confirm the billing that fits an agency running several client stores. ### Can I change or cancel a plan later? Yes, at any time, from Plan and billing in the Console. Upgrades apply right away; a downgrade or a cancellation takes effect at the end of the period you have already paid for. ### Does the free plan expire? No. A free workspace stays free for as long as you use it, keeps its knowledge and its conversations, and is never deleted for being quiet. ### Which payment methods do you take? Cards and the local payment methods our payment partner supports in your country, charged in {currency}. Invoices and receipts are available from the billing portal after every payment. ## Enterprise and agencies One Console, many workspaces — each with its own brand, domain, systems, limits and usage. Talk to us about volume. --- --- title: "Solutions — support, sales, help in your app, everyday tasks" description: "Every job, one assistant: customer support with hand-off, sales and onboarding, help inside your app, everyday tasks through your systems, customer insight and white-label for agencies — with voice, a team Inbox, integrations and site knowledge built in." last_updated: "2026-10-07T12:28:07+03:00" --- # Solutions — support, sales, help in your app, everyday tasks Source: https://busymate.ai/solutions Last modified: 2026-10-07T12:28:07+03:00 Every job, one assistant: customer support with hand-off, sales and onboarding, help inside your app, everyday tasks through your systems, customer insight and white-label for agencies — with voice, a team Inbox, integrations and site knowledge built in. ## In this section - [AI customer support with human handoff](https://busymate.ai/solutions/customer-support.md): Customer support that answers from your content and hands off to a person - [AI sales and onboarding assistant](https://busymate.ai/solutions/sales-onboarding.md): Sales and onboarding answers from your own product - [Embed an AI assistant in your app](https://busymate.ai/solutions/in-product-copilot.md): An assistant inside your app that acts for the signed-in user - [Everyday tasks through your systems, confirmed first](https://busymate.ai/solutions/operations-automation.md): Everyday tasks through your systems, confirmed first - [Learn what customers keep asking](https://busymate.ai/solutions/product-intelligence.md): Learn what customers keep asking, with the conversations as evidence - [White-label AI for agencies and resellers](https://busymate.ai/solutions/agencies-white-label.md): White-label AI for agencies and resellers - [Voice support: customers talk to your assistant](https://busymate.ai/solutions/voice-support.md): Voice support — customers speak to the assistant, same answers and rules as typing - [Human hand-off and a team Inbox](https://busymate.ai/solutions/handoff-inbox.md): Human hand-off and the team Inbox — a person joins the same conversation - [An assistant that knows your website](https://busymate.ai/solutions/site-knowledge.md): Site knowledge — answers from your own website and text, with sources ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "AI customer support with human handoff" description: "Answers from your own content, real help with orders and accounts for signed-in customers, and a person who joins the same conversation — if you turn it on — in 14 languages." last_updated: "2026-10-07T12:28:07+03:00" --- # AI customer support with human handoff Source: https://busymate.ai/solutions/customer-support Last modified: 2026-10-07T12:28:07+03:00 Answers from your own content, real help with orders and accounts for signed-in customers, and a person who joins the same conversation — if you turn it on — in 14 languages. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "AI sales and onboarding assistant" description: "Answers for prospects and new customers from your own docs, suggested first questions taken from your content, and a handoff to your sales team when a person should step in." last_updated: "2026-10-07T12:28:07+03:00" --- # AI sales and onboarding assistant Source: https://busymate.ai/solutions/sales-onboarding Last modified: 2026-10-07T12:28:07+03:00 Answers for prospects and new customers from your own docs, suggested first questions taken from your content, and a handoff to your sales team when a person should step in. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "Embed an AI assistant in your app" description: "An assistant inside your web, iOS, Android or desktop app that knows your docs, the user's own data and what they are allowed to do — and asks before it changes anything." last_updated: "2026-10-07T12:28:07+03:00" --- # Embed an AI assistant in your app Source: https://busymate.ai/solutions/in-product-copilot Last modified: 2026-10-07T12:28:07+03:00 An assistant inside your web, iOS, Android or desktop app that knows your docs, the user's own data and what they are allowed to do — and asks before it changes anything. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "White-label AI for agencies and resellers" description: "One Console, many clients. Each client gets its own workspace with its own brand, domain, systems, allowed models, limits and usage. Let an AI agent set up each client. Talk to us." last_updated: "2026-10-07T12:28:07+03:00" --- # White-label AI for agencies and resellers Source: https://busymate.ai/solutions/agencies-white-label Last modified: 2026-10-07T12:28:07+03:00 One Console, many clients. Each client gets its own workspace with its own brand, domain, systems, allowed models, limits and usage. Let an AI agent set up each client. Talk to us. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "Adopt WebMCP: a quick how-to and a copy-paste prompt for any assistant" description: "Five reasons, four steps and one prompt: paste it into the assistant you already use and it audits your site, proposes the tools and writes the code — for Shopify, WordPress, Webflow and plain HTML." last_updated: "2026-09-27T22:02:30+03:00" --- # Adopt WebMCP: a quick how-to and a copy-paste prompt for any assistant Source: https://busymate.ai/webmcp/adopt Last modified: 2026-09-27T22:02:30+03:00 Five reasons, four steps and one prompt: paste it into the assistant you already use and it audits your site, proposes the tools and writes the code — for Shopify, WordPress, Webflow and plain HTML. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "Agent Ready v1: the web standard an AI agent reads" description: "Can an AI find you, understand you, trust you and do useful work with you? The six sections, the ten requirements, the one-URL Markdown contract and the evidence behind every verdict." last_updated: "2026-09-27T22:02:30+03:00" --- # Agent Ready v1: the web standard an AI agent reads Source: https://busymate.ai/agent-ready Last modified: 2026-09-27T22:02:30+03:00 Can an AI find you, understand you, trust you and do useful work with you? The six sections, the ten requirements, the one-URL Markdown contract and the evidence behind every verdict. Version 1.2. Published by AI Assistant as `AI Assistant Agent Ready v1`. ## Sections and weights The six sections share 100 points. Each one grades one layer of what an agent meets on a website. | Section | Layer | Points | What it asks | | --- | --- | --: | --- | | Discover | discovery | 15 | Can an AI agent find your content? | | Understand | semantics | 15 | Does an agent understand your business correctly? | | Read | content | 20 | Can an agent consume your content efficiently? | | Act | actions | 20 | Can an agent take actions on your website? | | Connect | connectivity | 20 | Can external agents call your systems? | | Trust | safety | 10 | Can an agent authenticate, confirm actions, and reach a human? | ## Requirements Ten clauses decide readiness. Everything else the catalogue carries is a diagnostic. - **R1** (content) — Important content is present in the initial HTML. Proven by: initial_html_content. - **R2** (content) — Pages can expose a Markdown representation of themselves. Proven by: markdown_representation. - **R3** (discovery) — The site publishes a sitemap. Proven by: sitemap. - **R4** (discovery) — The site publishes an llms.txt. Proven by: llms_txt. - **R5** (discovery) — The site publishes a machine-readable capability manifest. Proven by: capability_manifest. - **R6** (semantics) — Pages declare their language and their canonical URL. Proven by: language_canonical. - **R7** (semantics) — The site publishes structured business or product metadata. Proven by: business_metadata. - **R8** (actions) — Web actions are declared when the page offers any. Proven by: page_tools. - **R9** (actions) — Backend agent tools or an API are declared when the service offers any. Proven by: programmatic_api. - **R10** (safety) — Authentication, authorization and human hand-off are explicit. Proven by: human_handoff, auth_explicit. ## Checks 35 checks make up the catalogue; 8 of them carry no weight — an unsettled convention is reported when found and never deducted when absent. A check whose `appliesWhen` is false leaves the denominator instead of counting against the site. - `sitemap` (discover, R3, 3 pts) — A sitemap lists the pages an agent should read. Expects: An XML sitemap (or a sitemap index) with at least one . - `llms_txt` (discover, R4, 4 pts) — llms.txt points an agent at the content that matters. Expects: GET /llms.txt returns text with at least one link. - `capability_manifest` (discover, R5, 3 pts) — agents.json joins content, interfaces, authentication and contact in one card. Expects: A JSON manifest at /.well-known/agents.json or /agents.json. - `manifest_twin_parity` (discover, diagnostic, 1 pts) — When agents.json is published at both paths, the two copies agree. Expects: /.well-known/agents.json and /agents.json answer with byte-identical bodies when both exist. - `sitemap_xml_valid` (discover, diagnostic, 1 pts) — The sitemap is a real urlset or sitemapindex document whose loc entries point at the site's own origin. Expects: 200, a or root element, and at least one same-origin . A redirect to another path is reported with the target. - `robots_ai_crawlers` (discover, diagnostic, 2 pts) — robots.txt lets AI search and user-requested retrieval reach your pages. Expects: robots.txt does not block search/citation or user-requested AI agents from /. - `discovery_link_headers` (discover, diagnostic, 1 pts) — HTTP Link headers tell an agent the site MEANT to expose these documents. Expects: Link: ; rel="describedby" and ; rel="alternate". - `robots_training_policy` (discover, diagnostic, optional) — The site states, either way, whether its pages may be used for model training. Expects: Optional: robots.txt names model-training crawler tokens. Opting out is a valid answer and costs nothing. - `llms_full_txt` (discover, diagnostic, optional) — llms-full.txt carries the whole corpus in one file. Expects: Optional: GET /llms-full.txt returns text. - `sitemap_md` (discover, diagnostic, optional) — sitemap.md is a human- and agent-readable index. Expects: Optional: GET /sitemap.md returns markdown. - `agents_md` (discover, diagnostic, optional) — AGENTS.md is a prose companion to the manifest. Expects: Optional: GET /AGENTS.md returns markdown. - `language_canonical` (understand, R6, 5 pts) — The page states what language it is in and which URL is canonical. Expects: and (or a canonical Link header). - `business_metadata` (understand, R7, 6 pts) — JSON-LD says who you are and what you sell, in a vocabulary every agent already parses. Expects: JSON-LD with an identity type (Organization, LocalBusiness, WebSite, Store) or a Product/Offer. - `structured_data_fields` (understand, diagnostic, 3 pts) — The identity node carries real fields, not just a bare @type. Expects: An identity node (Organization, Product, …) with a name, a description and a url. - `open_graph` (understand, diagnostic, 1 pts) — Open Graph gives a title, a description and an image to anything that previews a link. Expects: og:title, og:description and og:image. - `content_freshness` (understand, diagnostic, optional) — Content nodes say when they last changed, so an agent can tell fresh from stale. Expects: Optional: CreativeWork / DataFeedItem nodes carry dateModified (or datePublished). - `initial_html_content` (read, R1, 14 pts) — The content is in the served HTML, not assembled later by a script. Expects: One

, a
landmark and real prose in the first response. - `markdown_representation` (read, R2, 4 pts) — The SAME URL serves Markdown to a client that asks for it. Expects: GET the page with Accept: text/markdown → text/markdown and Vary: Accept. - `markdown_frontmatter` (read, diagnostic, 1 pts) — The Markdown carries its own canonical URL, language and last-updated date. Expects: YAML frontmatter with canonical, language and updated (or title/description/last_updated). - `markdown_alternate_link` (read, diagnostic, 1 pts) — The page advertises its Markdown alternate so an agent does not have to guess. Expects: or the same as a Link header. - `page_tools` (act, R8, 13 pts) — The page registers its own actions as tools an agent can call in the browser. Expects: WebMCP tools on document.modelContext / navigator.modelContext, on the pages scanned. - `page_tool_catalog` (act, diagnostic, 4 pts) — A static catalogue lets an agent read the page's tools without executing it. Expects: A WebMCP catalog document linked from the page or at a well-known path. - `page_tools_policy` (act, diagnostic, 3 pts) — Permissions-Policy leaves the page's tools governed — by the default allowlist or by an explicit one. Expects: No tools= directive (the draft default is self), or an explicit tools= allowlist. A wildcard or a denial is the finding. - `programmatic_api` (connect, R9, 8 pts) — At least one programmatic description of the service exists — MCP, OpenAPI, GraphQL or another declared API. Expects: One of: a live MCP endpoint, an OpenAPI document, a GraphQL schema, or an API declared in the manifest. - `mcp_transport` (connect, diagnostic, 4 pts) — The MCP endpoint answers, negotiates a protocol revision and LISTS its tools. Expects: initialize and tools/list succeed over the transport the handshake actually ran on. Listing is not authorization to call. - `access_requirements` (connect, diagnostic, 3 pts) — The service documents which capabilities need a token and which do not. Expects: A manifest, a WWW-Authenticate challenge or protected-resource metadata that states the access requirements. - `oauth_metadata` (connect, diagnostic, 3 pts) — OAuth metadata discovery resolves, and advertises PKCE where a client must verify it. Expects: RFC 8414 / RFC 9728 metadata that resolves, with code_challenge_methods_supported. Dynamic client registration is optional. - `authenticated_execution` (connect, diagnostic, 2 pts) — An authenticated call actually succeeds — proof that a listed tool is a usable tool. Expects: An authenticated tools/call that returns a result. This scanner holds no token for your server and never calls a stranger's tool, so this stays UNVERIFIED — reported, never counted as a pass or as your failure. - `tool_annotation_coverage` (connect, diagnostic, optional) — Listed tools declare readOnlyHint, so a client can tell a read from a write before it calls. Expects: Optional: annotations on the listed tool definitions. Only meaningful from protocol revision 2025-03-26, which introduced them. - `openapi_spec` (connect, diagnostic, optional) — An OpenAPI document describes the HTTP API. Expects: Optional when MCP or another API already describes the interface. - `protocol_discovery_aliases` (connect, diagnostic, optional) — Optional well-known aliases (mcp.json, agent-card.json, api-catalog, …) are served cleanly or not at all. Expects: Optional: each alias is valid JSON or a clean non-200 — never the site's own HTML shell. - `human_handoff` (trust, R10, 4 pts) — An agent can hand the conversation to a person. Expects: A contact email, phone or contact page an agent can quote. - `contact_signal_sources` (trust, diagnostic, 1 pts) — A machine-readable contact signal exists independent of any stored crawl. Expects: A mailto: link, a /contact link, a JSON-LD contactPoint, or a Contact: line in llms.txt — any one is enough. - `auth_explicit` (trust, R10, 3 pts) — The site states how an agent authenticates — or states that nothing needs authenticating. Expects: Authentication declared in the manifest, or OAuth metadata, or an explicit public posture. - `action_confirmation` (trust, diagnostic, 2 pts) — A consequential action is actually confirmed with the person before it runs. Expects: A client/workflow test that drives a write action and observes the confirmation. This scanner does not run one against a stranger's service, so it stays UNVERIFIED — never a pass, and never a deduction blamed on you. ## Verdicts - `pass` — what the clause expects came back. - `partial` — some of it is in place; the evidence names the half that is not. - `optional-found` / `optional-missing` — an unsettled convention, worth no points either way. - `fail` — asked for, and nothing was there. - `unverified` — the probe could not run. It keeps its weight and is listed apart; a refusal, a timeout or a redirect that never lands is never rounded up to a pass. ## Evidence Every check records the call it made, the answer this document expects and the answer it actually got. Only headers that change the answer are kept, and credentials never are. A count of tools behind sign-in reads as unknown rather than zero when nobody signed in to count it. ## Related - Grade a web address against this document: https://busymate.ai/ready.md - What a site publishes for assistants to act on: https://busymate.ai/webmcp.md - The developer guide: https://busymate.ai/developers.md --- --- title: "Who runs on AI Assistant" description: "Businesses running a live assistant under their own brand, at their own web address, with their own systems. Open one and talk to it. No logo wall, no numbers we did not measure." last_updated: "2026-10-05T21:48:45+03:00" --- # Who runs on AI Assistant Source: https://busymate.ai/customers Last modified: 2026-10-05T21:48:45+03:00 Businesses running a live assistant under their own brand, at their own web address, with their own systems. Open one and talk to it. No logo wall, no numbers we did not measure. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "Everyday tasks through your systems, confirmed first" description: "Routine requests, scheduled checks and multi-step tasks through your own systems. Every change is confirmed first, every run leaves a record, and silence never counts as success." last_updated: "2026-10-07T12:28:07+03:00" --- # Everyday tasks through your systems, confirmed first Source: https://busymate.ai/solutions/operations-automation Last modified: 2026-10-07T12:28:07+03:00 Routine requests, scheduled checks and multi-step tasks through your own systems. Every change is confirmed first, every run leaves a record, and silence never counts as success. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "Learn what customers keep asking" description: "See what customers ask again and again, where the assistant gets stuck and what your docs are missing — grouped by topic, with the conversations as evidence, and a suggested fix." last_updated: "2026-10-07T12:28:07+03:00" --- # Learn what customers keep asking Source: https://busymate.ai/solutions/product-intelligence Last modified: 2026-10-07T12:28:07+03:00 See what customers ask again and again, where the assistant gets stuck and what your docs are missing — grouped by topic, with the conversations as evidence, and a suggested fix. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "Voice support: customers talk to your assistant" description: "Let customers speak to your assistant instead of typing — on your website or inside your app, in their own language — with the same answers, the same rules and the same way to reach a person." last_updated: "2026-10-07T12:28:07+03:00" --- # Voice support: customers talk to your assistant Source: https://busymate.ai/solutions/voice-support Last modified: 2026-10-07T12:28:07+03:00 Let customers speak to your assistant instead of typing — on your website or inside your app, in their own language — with the same answers, the same rules and the same way to reach a person. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "Human hand-off and a team Inbox" description: "When a customer asks for a person, or one of your rules decides, a teammate picks the conversation up in the Inbox, replies in the same thread and hands it back — with alerts, assignment rules and ratings." last_updated: "2026-10-07T12:28:07+03:00" --- # Human hand-off and a team Inbox Source: https://busymate.ai/solutions/handoff-inbox Last modified: 2026-10-07T12:28:07+03:00 When a customer asks for a person, or one of your rules decides, a teammate picks the conversation up in the Inbox, replies in the same thread and hands it back — with alerts, assignment rules and ratings. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "An assistant that knows your website" description: "Point it at your website or paste in your own text. It answers only from that, shows its sources and says when it is not sure — try it on your own site before you sign up." last_updated: "2026-10-07T12:28:07+03:00" --- # An assistant that knows your website Source: https://busymate.ai/solutions/site-knowledge Last modified: 2026-10-07T12:28:07+03:00 Point it at your website or paste in your own text. It answers only from that, shows its sources and says when it is not sure — try it on your own site before you sign up. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "AI chatbot connectors for every channel" description: "Connect one AI assistant to your website, messaging apps, store and tools — 56 connectors in 7 categories, 15 ready today, the rest honestly marked." last_updated: "2026-10-08T16:19:19+03:00" --- # AI chatbot connectors for every channel Source: https://busymate.ai/connectors Last modified: 2026-10-08T16:19:19+03:00 Connect one AI assistant to your website, messaging apps, store and tools — 56 connectors in 7 categories, 15 ready today, the rest honestly marked. ## Messaging channels Where a customer writes to you — your site, the messaging apps, mail and the phone. Category page: https://busymate.ai/connectors/category/messaging-channels.md - [Web chat](https://busymate.ai/connectors/web.md) — ready today: Web chat — the embed launcher and full-page chat on your own website, ready today - [Telegram](https://busymate.ai/connectors/telegram.md) — ready today: Telegram — your bot answers direct messages and group mentions with in-chat sign-in, and Telegram Business answers from your own account - [Email](https://busymate.ai/connectors/email.md) — ready today: Email — a support inbox your mate reads and answers in-thread, with team hand-off - [Slack](https://busymate.ai/connectors/slack.md) — in beta: Slack — answer your team and community in a workspace channel - [Discord](https://busymate.ai/connectors/discord.md) — coming soon: Discord — answer members in a server channel or DM - [Microsoft Teams](https://busymate.ai/connectors/teams.md) — coming soon: Microsoft Teams — answer staff and customers in the chat they use for work - [WhatsApp](https://busymate.ai/connectors/whatsapp.md) — in beta: WhatsApp — answer customers on your WhatsApp Business number, chats in the Inbox (try +1 607 669 2331) - [Facebook Messenger](https://busymate.ai/connectors/messenger.md) — coming soon: Facebook Messenger — answer the messages your Facebook Page receives - [Instagram](https://busymate.ai/connectors/instagram.md) — coming soon: Instagram — answer Instagram direct messages to your business account - [SMS](https://busymate.ai/connectors/sms.md) — in beta: SMS — answer plain text messages on your own number, US and international (try +1 607 669 2331) - [Phone calls](https://busymate.ai/connectors/phone.md) — in beta: Phone calls — your mate answers calls in the caller's language with a live Inbox transcript and hand-over to a person (try +1 607 669 2331) - [Apple Messages for Business](https://busymate.ai/connectors/apple-messages.md) — coming soon: Apple Messages for Business — answer in the Messages app from Maps, Safari and Spotlight - [Viber](https://busymate.ai/connectors/viber.md) — coming soon: Viber — answer subscribers of your Viber bot - [LINE](https://busymate.ai/connectors/line.md) — coming soon: LINE — answer on a LINE Official Account - [WeChat](https://busymate.ai/connectors/wechat.md) — coming soon: WeChat — answer followers of a WeChat Official Account ## Apps and platforms The apps you ship and the desktop software your team works in. Category page: https://busymate.ai/connectors/category/apps.md - [iOS in-app support](https://busymate.ai/connectors/ios.md) — ready today: iOS app in-app support — the identity-bridged web chat inside your own iOS app, ready today - [Android in-app support](https://busymate.ai/connectors/android.md) — ready today: Android app in-app support — the identity-bridged web chat inside your own Android app, ready today - [Desktop app](https://busymate.ai/connectors/desktop.md) — in beta: Desktop app — the Console in its own window with notifications; macOS, Windows and Linux, all in beta ## Websites and site builders The web chat on the builder your site already runs on — one script, no plugin. Category page: https://busymate.ai/connectors/category/websites-cms.md - [WordPress](https://busymate.ai/connectors/wordpress.md) — ready today: WordPress — a real, workspace-generated plugin (widget, inline block/shortcode, signed-in visitor recognition) - [Ghost](https://busymate.ai/connectors/ghost.md) — ready today: Ghost — the web chat embed via Code Injection, no plugin - [Wix](https://busymate.ai/connectors/wix.md) — ready today: Wix — the web chat embed via Custom Code - [Squarespace](https://busymate.ai/connectors/squarespace.md) — in beta: Squarespace — the web chat embed via Code Injection - [Webflow](https://busymate.ai/connectors/webflow.md) — in beta: Webflow — the web chat embed via the site's custom code ## Commerce Stores and payments your mate reads from and, with a yes, acts in. Category page: https://busymate.ai/connectors/category/ecommerce.md - [WooCommerce](https://busymate.ai/connectors/woocommerce.md) — ready today: WooCommerce — catalogue answers and a signed-in customer's own order status on a WooCommerce store; returns are answered from your policy page and handed to a person - [Shopify](https://busymate.ai/connectors/shopify.md) — in beta: Shopify — the open-source storefront app: catalogue, policies, order help, hand-off - [BigCommerce](https://busymate.ai/connectors/bigcommerce.md) — in beta: BigCommerce — catalogue answers and order help on a BigCommerce store - [Magento / Adobe Commerce](https://busymate.ai/connectors/magento.md) — coming soon: Magento — catalogue answers and order help on a Magento / Adobe Commerce store - [Stripe](https://busymate.ai/connectors/stripe.md) — coming soon: Stripe — read a customer's invoices and subscriptions; refunds go to a person ## CRM, helpdesk and sales The systems your team already keeps customers, tickets, leads and bookings in. Category page: https://busymate.ai/connectors/category/crm-helpdesk.md - [HubSpot](https://busymate.ai/connectors/hubspot.md) — coming soon: HubSpot — contacts, timeline entries and tickets written from conversations - [Zendesk](https://busymate.ai/connectors/zendesk.md) — coming soon: Zendesk — hand-offs become tickets with the transcript - [Salesforce](https://busymate.ai/connectors/salesforce.md) — coming soon: Salesforce — leads and cases written from conversations - [Freshdesk](https://busymate.ai/connectors/freshdesk.md) — coming soon: Freshdesk — hand-offs become tickets with the transcript - [Intercom](https://busymate.ai/connectors/intercom.md) — coming soon: Intercom — import conversations and contacts, or hand off into Intercom - [Pipedrive](https://busymate.ai/connectors/pipedrive.md) — coming soon: Pipedrive — leads and deals written from sales conversations - [Zoho](https://busymate.ai/connectors/zoho.md) — coming soon: Zoho — contacts and leads in Zoho CRM, tickets in Zoho Desk - [Help Scout](https://busymate.ai/connectors/helpscout.md) — coming soon: Help Scout — hand-offs land in a Help Scout mailbox - [Mailchimp](https://busymate.ai/connectors/mailchimp.md) — coming soon: Mailchimp — opt-ins added to an audience with conversation tags - [Google Calendar](https://busymate.ai/connectors/google-calendar.md) — coming soon: Google Calendar — bookings written straight into a calendar - [Calendly](https://busymate.ai/connectors/calendly.md) — coming soon: Calendly — event types offered and booked in the chat ## Knowledge sources Where your mate reads your content from — every answer cites its source. Category page: https://busymate.ai/connectors/category/knowledge-base.md - [Website crawl](https://busymate.ai/connectors/site-crawl.md) — ready today: Website crawl — a robots-aware same-origin crawl of your help site, every answer cited - [Zendesk Help Center](https://busymate.ai/connectors/zendesk-help-center.md) — ready today: Zendesk Help Center — published Zendesk help articles as a knowledge source - [Notion](https://busymate.ai/connectors/notion.md) — coming soon: Notion — shared Notion pages as a knowledge source - [Files and PDFs](https://busymate.ai/connectors/files.md) — coming soon: Files and PDFs — PDF and document upload as a knowledge source - [Google Drive](https://busymate.ai/connectors/google-drive.md) — coming soon: Google Drive — a Drive folder of Docs, Sheets and PDFs as a knowledge source - [Confluence](https://busymate.ai/connectors/confluence.md) — coming soon: Confluence — Confluence spaces as a knowledge source - [GitHub](https://busymate.ai/connectors/github.md) — coming soon: GitHub — a repository's docs folder or README as a knowledge source ## Automation and developers Tools, workflows and the surfaces your own systems call — or are called from. Category page: https://busymate.ai/connectors/category/automation-developers.md - [Your tools, over MCP](https://busymate.ai/connectors/mcp.md) — ready today: Your tools over MCP — your mate calls your systems; any MCP client can reach it - [WebMCP page tools](https://busymate.ai/connectors/webmcp.md) — ready today: WebMCP page tools — a page's own actions as tools the assistant and any agentic browser can use - [Webhooks](https://busymate.ai/connectors/webhooks.md) — ready today: Webhooks — signed HTTP calls to your endpoint on chosen events - [REST API](https://busymate.ai/connectors/api.md) — ready today: REST API — a documented REST API with per-workspace keys - [Zapier](https://busymate.ai/connectors/zapier.md) — coming soon: Zapier — conversation events trigger Zaps; Zaps can message the assistant - [Make](https://busymate.ai/connectors/make.md) — coming soon: Make — conversation events start Make scenarios - [n8n](https://busymate.ai/connectors/n8n.md) — coming soon: n8n — conversation events start n8n workflows, self-hosted or cloud - [Google Sheets](https://busymate.ai/connectors/google-sheets.md) — coming soon: Google Sheets — a spreadsheet row per chosen event - [Airtable](https://busymate.ai/connectors/airtable.md) — coming soon: Airtable — a record per chosen event in an Airtable base - [Jira](https://busymate.ai/connectors/jira.md) — coming soon: Jira — hand-offs and reported bugs become Jira issues ## Related - [Getting started | AI Assistant](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in | AI Assistant](https://busymate.ai/developers.md) - [Pricing | AI Assistant](https://busymate.ai/pricing.md) --- --- title: "WebMCP tool inspector: see what an assistant can do on any website" description: "Put in a web address and see the actions a site publishes for assistants — each name, what it does, what it needs, and whether it only reads or changes something." last_updated: "2026-09-27T22:02:30+03:00" --- # WebMCP tool inspector: see what an assistant can do on any website Source: https://busymate.ai/webmcp/inspect Last modified: 2026-09-27T22:02:30+03:00 Put in a web address and see the actions a site publishes for assistants — each name, what it does, what it needs, and whether it only reads or changes something. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "Security and protocols" description: "How AI Assistant keeps your data separate, checks who a customer is, asks before changing anything and never shows your keys again — with the exact standards named." last_updated: "2026-09-28T00:08:41+03:00" --- # Security and protocols Source: https://busymate.ai/security Last modified: 2026-09-28T00:08:41+03:00 How AI Assistant keeps your data separate, checks who a customer is, asks before changing anything and never shows your keys again — with the exact standards named. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "Download AI Assistant Console | Desktop app" description: "The desktop app for the people who answer: system notifications the moment a conversation needs a human, a badge for what is waiting, and links that open the exact conversation. Free, for every platform below." last_updated: "2026-10-03T22:04:43+03:00" --- # Download AI Assistant Console | Desktop app Source: https://busymate.ai/desktop Last modified: 2026-10-03T22:04:43+03:00 The desktop app for the people who answer: system notifications the moment a conversation needs a human, a badge for what is waiting, and links that open the exact conversation. Free, for every platform below. ## Download ### macOS - **macOS (Apple silicon + Intel)** — v1.1.3 (build 21) · 6.5 MB · 2026-10-02 · signed and notarized by Apple · macOS 10.15 or later https://busymate.ai/downloads/console-desktop/1.1.3/Busymate-AI-1.1.3-build21-mac-universal.dmg SHA-256 `74cab0e3b8c42c49087a6bffb87b1d5a20c82406ea75ba2863f5ea17152eee1e` - **Mac App Store** — the same app, kept current by the App Store: https://apps.apple.com/app/busymate-ai/id6809772800 ### Windows - **Windows 10/11 (64-bit) — MSI** — v1.1.3 (build 21) · 3.1 MB · 2026-10-02 · preview build, unsigned · Windows 10 1809 or later https://busymate.ai/downloads/console-desktop/1.1.3/Busymate-AI-1.1.3-build21-win-x64.msi SHA-256 `f8c0f6e81aa5d93d61c180412ec6a5b915438609778d20fbeb7319edf20037e0` - **Windows 10/11 (64-bit) — installer** — v1.1.3 (build 21) · 2.3 MB · 2026-10-02 · preview build, unsigned · Windows 10 1809 or later https://busymate.ai/downloads/console-desktop/1.1.3/Busymate-AI-1.1.3-build21-win-x64-setup.exe SHA-256 `7bd48ddda0fb75ac486c8a9bcf813aea2830b95ed056d1b548d37394b7dc913f` ### Linux - **Linux (x86-64) — AppImage** — v1.1.3 (build 21) · 81.9 MB · 2026-10-02 · preview build, unsigned · glibc 2.31 (Ubuntu 20.04) or later https://busymate.ai/downloads/console-desktop/1.1.3/Busymate-AI-1.1.3-build21-linux-x86_64.AppImage SHA-256 `4d9dcc39f4496fd744a6f1612d268884482aea4fa19202db65184dca7106ed93` - **Debian / Ubuntu (x86-64) — .deb** — v1.1.3 (build 21) · 3.6 MB · 2026-10-02 · preview build, unsigned · glibc 2.31 (Ubuntu 20.04) or later https://busymate.ai/downloads/console-desktop/1.1.3/Busymate-AI-1.1.3-build21-linux-amd64.deb SHA-256 `c93af42d9d74e4786cf262b6a0f846bdfd2f607bc52caff8bdb6d1b7261a019a` Every release, with its notes: https://github.com/serebano/busymate-ai-desktop/releases ## Release notes — v1.1.3 (2026-10-02) - Sign-in keeps working through the new sign-in server, and the app can now learn a new sign-in address without an app update. Full notes: https://github.com/serebano/busymate-ai-desktop/releases/tag/v1.1.3-build21 ## What's new since 2026-09-13 ### In the app - On a Mac the window buttons sit on the Console's own bar — one bar, the same air around every control. ### In the Console it opens - The rail, the Inbox and the Overview follow the language you pick. - Soft is the default look in light and in dark, and breadcrumbs read as a plain path, a slash between places. - Inbox replies show as formatted text — bold, lists and links — never as raw markup. - Every workspace wears its own icon in the switcher and the breadcrumb, the way its website shows it. - Press ⌘K anywhere: search opens centred, groups its results by page and speaks your language. - Setting up moved into the chat: name your website and your mate builds the assistant from it while you watch. ## Requirements - macOS: macOS 10.15 or later · Apple silicon + Intel · 6.5 MB · signed and notarized by Apple - Windows: Windows 10 1809 or later · 64-bit · 2.3 MB · preview build, unsigned - Linux: glibc 2.31 (Ubuntu 20.04) or later · 64-bit · 81.9 MB · preview build, unsigned ## Questions - **Is it safe to open?** Yes — the macOS build is signed with our Developer ID and notarized by Apple, so it opens like any other app. Every download lists its size and SHA-256 checksum. - **Does it update itself?** Depends on the platform. Updates itself: macOS. Not yet — download a new version by hand: Windows 1.1.3, Linux 1.1.3. - **Do Console updates need a reinstall?** No — the app is a window onto the web Console, so every Console improvement is there the next time you open it. Only the shell itself arrives as a new build. - **Is it free?** Yes, on every plan; it signs in with your AI Assistant account. --- --- title: "AI chatbot for messaging channels" description: "One AI assistant for your website chat, email and messaging apps, with a shared Inbox and hand-off to your team. See which channel connectors are ready." last_updated: "2026-10-08T16:19:19+03:00" --- # AI chatbot for messaging channels Source: https://busymate.ai/connectors/category/messaging-channels Last modified: 2026-10-08T16:19:19+03:00 One AI assistant for your website chat, email and messaging apps, with a shared Inbox and hand-off to your team. See which channel connectors are ready. A customer who starts on your site and follows up by email should not have to explain twice. Each channel connector brings those messages into one conversation history and one Inbox, so your mate answers with the full context and a teammate can step in anywhere. ## Connectors - [Web chat](https://busymate.ai/connectors/web.md) — ready today - [Telegram](https://busymate.ai/connectors/telegram.md) — ready today - [Email](https://busymate.ai/connectors/email.md) — ready today - [Slack](https://busymate.ai/connectors/slack.md) — in beta - [Discord](https://busymate.ai/connectors/discord.md) — coming soon - [Microsoft Teams](https://busymate.ai/connectors/teams.md) — coming soon - [WhatsApp](https://busymate.ai/connectors/whatsapp.md) — in beta - [Facebook Messenger](https://busymate.ai/connectors/messenger.md) — coming soon - [Instagram](https://busymate.ai/connectors/instagram.md) — coming soon - [SMS](https://busymate.ai/connectors/sms.md) — in beta - [Phone calls](https://busymate.ai/connectors/phone.md) — in beta - [Apple Messages for Business](https://busymate.ai/connectors/apple-messages.md) — coming soon - [Viber](https://busymate.ai/connectors/viber.md) — coming soon - [LINE](https://busymate.ai/connectors/line.md) — coming soon - [WeChat](https://busymate.ai/connectors/wechat.md) — coming soon ## Questions ### Which messaging channels can I switch on today? 3 of the 15 channel connectors are ready today; each card says whether it is live or in beta. The rest are being built, and their pages describe exactly how they will be set up. ### Do I need a separate assistant for each channel? No. You set up one assistant with one knowledge base and one set of tools, then connect the channels you want. What it learns about a customer on one channel is there on the next. ### Are messages from every channel in the same Inbox? Yes. Web chat, email and the messaging apps arrive in the same Console Inbox, labelled with the channel they came from, and a reply goes back on that channel. ## Related - All connectors: https://busymate.ai/connectors.md --- --- title: "In-app AI support for iOS and Android" description: "Add AI support chat to your own iOS and Android apps, signed-in customer included, and run the Console as a desktop app. Connectors, setup and status." last_updated: "2026-10-08T16:19:19+03:00" --- # In-app AI support for iOS and Android Source: https://busymate.ai/connectors/category/apps Last modified: 2026-10-08T16:19:19+03:00 Add AI support chat to your own iOS and Android apps, signed-in customer included, and run the Console as a desktop app. Connectors, setup and status. Customers ask for help where they are, and inside a mobile app that means a chat that already knows who they are. The official iOS and Android SDKs load hosted chat, connect your authenticated backend and handle microphone permission on tap. Each includes installation docs and a buildable example app. ## Connectors - [iOS in-app support](https://busymate.ai/connectors/ios.md) — ready today - [Android in-app support](https://busymate.ai/connectors/android.md) — ready today - [Desktop app](https://busymate.ai/connectors/desktop.md) — in beta ## Questions ### Do I have to ship an SDK inside my app? Install the versioned Swift package for iOS or Gradle library for Android. Hosted copy, colours and tools update from the service; SDK changes and new OS capabilities require an app release. ### How does the chat know who the customer is? Your own backend mints a short-lived launch token for the signed-in customer and the app hands it to the chat. The platform verifies it; nobody types an email address. ### Is there a desktop app for my team? Yes, in beta: the Console runs in its own window with notifications, so a hand-off is never missed in a browser tab. ## Related - All connectors: https://busymate.ai/connectors.md --- --- title: "AI chatbot for WordPress, Wix and more" description: "Add an AI chatbot and live chat to WordPress, Ghost, Wix, Squarespace or Webflow: a real WordPress plugin, one snippet elsewhere. Setup and status." last_updated: "2026-10-08T16:19:19+03:00" --- # AI chatbot for WordPress, Wix and more Source: https://busymate.ai/connectors/category/websites-cms Last modified: 2026-10-08T16:19:19+03:00 Add an AI chatbot and live chat to WordPress, Ghost, Wix, Squarespace or Webflow: a real WordPress plugin, one snippet elsewhere. Setup and status. Your website is where most questions start. These connectors put your mate on every page of the builder you use: it answers from your own pages, recognises signed-in members where the builder allows it, and hands the conversation to your team when a person is needed. ## Connectors - [WordPress](https://busymate.ai/connectors/wordpress.md) — ready today - [Ghost](https://busymate.ai/connectors/ghost.md) — ready today - [Wix](https://busymate.ai/connectors/wix.md) — ready today - [Squarespace](https://busymate.ai/connectors/squarespace.md) — in beta - [Webflow](https://busymate.ai/connectors/webflow.md) — in beta ## Questions ### Will a chatbot slow my site down? The launcher loads after your page, from one small script, and the full chat only downloads when a visitor opens it. Your own content and layout are never rewritten. ### Does it work on a free website plan? WordPress, Ghost and Wix work on their standard plans. Squarespace and Webflow only allow custom code on paid plans, which is why those two are marked beta. ### What does the assistant answer from? From the pages you add as a knowledge source, with a link to the page each answer came from. It does not guess outside what your site says. ## Related - All connectors: https://busymate.ai/connectors.md --- --- title: "AI chatbot for online stores" description: "An AI shopping assistant for Shopify, WooCommerce and BigCommerce stores: product answers, order lookups and hand-off to your team. Setup and status." last_updated: "2026-10-08T16:19:19+03:00" --- # AI chatbot for online stores Source: https://busymate.ai/connectors/category/ecommerce Last modified: 2026-10-08T16:19:19+03:00 An AI shopping assistant for Shopify, WooCommerce and BigCommerce stores: product answers, order lookups and hand-off to your team. Setup and status. Store questions have answers in your catalogue, your policies and your order history. The commerce connectors let your mate read all three: it recommends from the real catalogue, quotes your own shipping and returns policy, and looks up a signed-in shopper's orders, with any change confirmed first. ## Connectors - [WooCommerce](https://busymate.ai/connectors/woocommerce.md) — ready today - [Shopify](https://busymate.ai/connectors/shopify.md) — in beta - [BigCommerce](https://busymate.ai/connectors/bigcommerce.md) — in beta - [Magento / Adobe Commerce](https://busymate.ai/connectors/magento.md) — coming soon - [Stripe](https://busymate.ai/connectors/stripe.md) — coming soon ## Questions ### Can it see a customer's orders? Only a signed-in shopper's own orders, looked up from your store when they ask. Anything that changes an order or moves money waits for a yes, or goes to your team. ### Which stores are supported today? 1 of the 5 commerce connectors are ready today, only released connectors count; beta and planned connections are marked separately. ### Does it replace my store's checkout or theme? No. It sits on top of your storefront as a chat; your products, checkout and theme stay exactly as they are. ## Related - All connectors: https://busymate.ai/connectors.md --- --- title: "CRM and helpdesk connectors for AI chat" description: "Connect your AI chatbot to HubSpot, Salesforce, Zendesk, Calendly and more: contacts, tickets and meetings from every conversation. Status per connector." last_updated: "2026-10-08T16:19:19+03:00" --- # CRM and helpdesk connectors for AI chat Source: https://busymate.ai/connectors/category/crm-helpdesk Last modified: 2026-10-08T16:19:19+03:00 Connect your AI chatbot to HubSpot, Salesforce, Zendesk, Calendly and more: contacts, tickets and meetings from every conversation. Status per connector. An assistant is only useful to sales and support if its conversations end up where your team works. These connectors will write a contact and the transcript to your CRM, open a ticket in your helpdesk when a person is needed, and book the meeting in your calendar while the visitor is still in the chat. ## Connectors - [HubSpot](https://busymate.ai/connectors/hubspot.md) — coming soon - [Zendesk](https://busymate.ai/connectors/zendesk.md) — coming soon - [Salesforce](https://busymate.ai/connectors/salesforce.md) — coming soon - [Freshdesk](https://busymate.ai/connectors/freshdesk.md) — coming soon - [Intercom](https://busymate.ai/connectors/intercom.md) — coming soon - [Pipedrive](https://busymate.ai/connectors/pipedrive.md) — coming soon - [Zoho](https://busymate.ai/connectors/zoho.md) — coming soon - [Help Scout](https://busymate.ai/connectors/helpscout.md) — coming soon - [Mailchimp](https://busymate.ai/connectors/mailchimp.md) — coming soon - [Google Calendar](https://busymate.ai/connectors/google-calendar.md) — coming soon - [Calendly](https://busymate.ai/connectors/calendly.md) — coming soon ## Questions ### Can I use a CRM connector today? Not yet: every connector in this category is being built, and each page says so. Today a hand-off lands in the Console Inbox, and a webhook can forward it to any system you run. ### What will be written to my CRM? The contact the visitor agreed to share, the conversation transcript and, where it applies, the ticket or lead a hand-off creates. You choose which of those each connector may write. ### Will my team have to leave the helpdesk they use? No. The point of these connectors is that your team keeps working in its own helpdesk or CRM, with the conversation already there. ## Related - All connectors: https://busymate.ai/connectors.md --- --- title: "Train an AI chatbot on your content" description: "Connect your website, help center and documents so the AI assistant answers from your own content and cites every source. Which sources work today." last_updated: "2026-10-08T16:19:19+03:00" --- # Train an AI chatbot on your content Source: https://busymate.ai/connectors/category/knowledge-base Last modified: 2026-10-08T16:19:19+03:00 Connect your website, help center and documents so the AI assistant answers from your own content and cites every source. Which sources work today. An assistant is as good as what it has read. Knowledge connectors keep your mate current with the content you already maintain: it indexes the sources you choose, re-reads them, and shows a citation under each answer, so a customer can check the source and your team can see why it answered that way. ## Connectors - [Website crawl](https://busymate.ai/connectors/site-crawl.md) — ready today - [Zendesk Help Center](https://busymate.ai/connectors/zendesk-help-center.md) — ready today - [Notion](https://busymate.ai/connectors/notion.md) — coming soon - [Files and PDFs](https://busymate.ai/connectors/files.md) — coming soon - [Google Drive](https://busymate.ai/connectors/google-drive.md) — coming soon - [Confluence](https://busymate.ai/connectors/confluence.md) — coming soon - [GitHub](https://busymate.ai/connectors/github.md) — coming soon ## Questions ### How do I keep answers up to date? Edit the source, not the assistant. A connected website or help center is read again, so a changed policy page changes the answer. ### Does it make up answers it cannot find? It answers from your indexed content and says so when the answer is not there, offering a person instead of guessing. ### Which content sources work today? 2 of the 7 knowledge connectors are ready today, including a crawl of your own website; the others are being built and say so on their pages. ## Related - All connectors: https://busymate.ai/connectors.md --- --- title: "AI assistant API, MCP and webhooks" description: "Connect your AI assistant to your own code: MCP tools, WebMCP page actions, signed webhooks, a REST API and workflow tools. Docs and status per connector." last_updated: "2026-10-08T16:19:19+03:00" --- # AI assistant API, MCP and webhooks Source: https://busymate.ai/connectors/category/automation-developers Last modified: 2026-10-08T16:19:19+03:00 Connect your AI assistant to your own code: MCP tools, WebMCP page actions, signed webhooks, a REST API and workflow tools. Docs and status per connector. Beyond answering, an assistant becomes useful when it can look something up or make a change in your own systems. These connectors give it that reach, and give your developers theirs: every action is shown to the customer and confirmed before it runs, and every event can leave the platform as a signed call to your endpoint. ## Connectors - [Your tools, over MCP](https://busymate.ai/connectors/mcp.md) — ready today - [WebMCP page tools](https://busymate.ai/connectors/webmcp.md) — ready today - [Webhooks](https://busymate.ai/connectors/webhooks.md) — ready today - [REST API](https://busymate.ai/connectors/api.md) — ready today - [Zapier](https://busymate.ai/connectors/zapier.md) — coming soon - [Make](https://busymate.ai/connectors/make.md) — coming soon - [n8n](https://busymate.ai/connectors/n8n.md) — coming soon - [Google Sheets](https://busymate.ai/connectors/google-sheets.md) — coming soon - [Airtable](https://busymate.ai/connectors/airtable.md) — coming soon - [Jira](https://busymate.ai/connectors/jira.md) — coming soon ## Questions ### Can the assistant change data in my systems? Only through tools you connect and allow, and every change is shown in full and confirmed before it runs. Reading and writing are separate permissions. ### Do I need a developer to use these? The MCP, API and webhook connectors are made for developers. The workflow connectors in this category are being built for teams who would rather click than code. ### What is ready to build on today? 4 of the 10 connectors here are ready today: the documented REST API, signed webhooks, MCP tools and WebMCP page actions. ## Related - All connectors: https://busymate.ai/connectors.md --- --- title: "Meet the assistant your website could have" description: "Put in a web address and talk to the assistant that site could have — built from its own public pages, live in seconds, on a link you can share." last_updated: "2026-10-08T13:42:17+03:00" --- # Meet the assistant your website could have Source: https://busymate.ai/try Last modified: 2026-10-08T13:42:17+03:00 Put in a web address and talk to the assistant that site could have — built from its own public pages, live in seconds, on a link you can share. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "Documentation" description: "One AI assistant you brand as your own, for your own customers, connected to your own systems." last_updated: "2026-09-28T08:16:01+03:00" --- # Documentation Source: https://busymate.ai/docs Last modified: 2026-09-28T08:16:01+03:00 **AI Assistant** is a white-label AI platform: you run **your mate** — an AI assistant that can use tools — as your own product, under your name, on your web address, for your customers, connected to your own systems (through MCP, an open standard). It answers everyone, acts for signed-in customers, and hands off to a person on your terms. AI Assistant brings the assistant; you bring the brand and the data. If you have customers who need help, answers, or actions taken on their behalf, AI Assistant gives you a production assistant without building one. ## What your mate is **Your mate** is the assistant. One shared assistant serves every business, but each workspace is fully separate and fully branded, so your customers only ever see *your* assistant. Your mate can: - **Answer** questions in natural language, with streaming responses and Markdown formatting. - **Act** by calling tools — your tools — to read and change your customers' data, always within permissions you control. - **Hand off** to a person when a conversation needs one. The same assistant, rendered as your brand. Nothing about your mate names our brand to your customers unless you want it to. ## What you get as a white-label Diagram: Your customers reach your branded assistant — your mate — which calls your tools and can hand off to your team - **Your own branded assistant.** A workspace with your name, logo, colors, welcome copy, and voice. See [Getting started](https://busymate.ai/docs/getting-started). - **Your customers.** Your customers reach the assistant on your web address — signed in with your own sign-in, or as visitors if you allow it. Their conversations, history, and data stay inside your workspace. - **Your tools.** Connect your own MCP server so your mate can act on your customers' data — look things up, make changes, run your workflows. See [Connecting your systems](https://busymate.ai/docs/connectors). - **Human handoff.** When the assistant reaches its limit, a teammate can step into the same conversation. See [Human handoff](https://busymate.ai/docs/human-handoff). - **Usage and analytics.** See how much your assistant is used, per AI provider and over time, against your workspace limit. See [Usage and analytics](https://busymate.ai/docs/usage). - **Governance.** Choose which features are on, whether customers pick a model or get one default, and where your limits sit. See [Governance and models](https://busymate.ai/docs/governance). ## How your customers reach it You choose the channel — often more than one: - **A hosted page** on a web address you control (for example `assistant.yourdomain.com`), pointed at your workspace. - **An embed** on your own site or app — your mate drops into a panel or a chat bubble, on your pages. Either way, your customers see your brand, not ours. Setup is covered in [Getting started](https://busymate.ai/docs/getting-started). ## Where AI Assistant fits AI Assistant is the same technology that powers our own assistant — and it already runs live for outside partners, not just for us. That is the point: **AI Assistant is universal.** There is no special-case code for any one business. Every white-label is just another workspace, configured, never hand-coded — which is exactly why your assistant is stable, upgradeable, and gets every improvement the platform ships. > **A note on honesty.** These docs describe what the product does now, plainly. Where a capability is still being switched on for white-labels, the page says so and points you to the changelog — you should never be surprised by a gap. ### What is your mate? The assistant every business runs, rendered as your brand. One shared assistant; each workspace fully separate, fully branded, so your customers only ever see your assistant. ### Do I need my own AI model? No. The platform runs the models. You choose which ones your workspace may use and whether customers pick one or get a single default — see [Governance and models](https://busymate.ai/docs/governance). ### What do my customers see? Your name, your colors, your web address or your embed, and answers from your content and your tools. Nothing names our brand unless you want it to. ### Where do I start? [Getting started](https://busymate.ai/docs/getting-started) walks through the five steps — workspace, web address, sign-in, systems, publish — and the [guides](https://busymate.ai/docs/guides) cover each job end to end. ## Explore the section - **[Getting started](https://busymate.ai/docs/getting-started)** — your workspace, your web address, your branding, embedding. - **[The assistant experience](https://busymate.ai/docs/assistant-experience)** — what your customers actually see. - **[Governance and models](https://busymate.ai/docs/governance)** — features, model choice, limits. - **[Usage and analytics](https://busymate.ai/docs/usage)** — how much it's used, and against what limit. - **[Human handoff](https://busymate.ai/docs/human-handoff)** — bringing a person into the chat. - **[Connecting your systems (MCP)](https://busymate.ai/docs/connectors)** — let your mate act on your customers' data. - **[Managing from chat](https://busymate.ai/docs/managing-from-chat)** — run your workspace conversationally. --- --- title: "Getting started" description: "How to set up your assistant: your workspace, your web address, your branding, and adding the chat to your own site." last_updated: "2026-09-28T08:16:01+03:00" --- # Getting started Source: https://busymate.ai/docs/getting-started Last modified: 2026-09-28T08:16:01+03:00 Getting your AI Assistant assistant live takes five steps — workspace, web address, sign-in, systems, publish — and you do them yourself in the Console. Open [Console → Integration](https://busymate.ai/console/integration) for your workspace and follow its live checklist. It is generated from your real settings, so its URLs, sign-in fields, code snippets and checks are always current. ## The five steps Diagram: Setup flow: workspace, web address, sign-in, systems, publish ### 1. Your workspace A **workspace** is your own space on the platform. It carries your name, a short slug, and your branding. Everything your customers do — conversations, history, connected accounts — stays inside your workspace and is never visible to any other. A platform owner can create the workspace in **Console → Platform → Workspaces** or through the AI Assistant management MCP; the invited admin then completes the Integration checklist without anyone handing off. ### 2. Your web address Your assistant is served at a **web address you choose**, mapped to your workspace: - **To start**, every workspace gets its own `.busymate.ai` address. - **Your own domain** (for example `assistant.yourdomain.com`) once you point it at the platform and it’s verified. From then on, your customers only ever see your domain. Under the hood, an address resolves to exactly one workspace. An address we haven't mapped yet stays plain and unbranded — your branding appears only once your address is verified and switched on, so there's never a half-branded window in front of your customers. ### 3. Your customers' sign-in Decide how your customers are known to the assistant: - **Signed in as themselves** — you connect your own sign-in, and each customer reaches your mate as *them*, so your mate can act on *their* data (and only theirs). - **Visitors** — if you'd rather let anyone chat without signing in, you can allow guest access. Visitors get answers and guidance but not actions on a specific customer's private data. You can offer both: visitors at the front door, signed-in sessions for your customers. ### 4. Your systems (optional) If you want your mate to *do* things — not just answer — connect your own **MCP server**. That's how your mate reads and changes your customers' data through your API, under your rules. This is optional: an answers-only assistant needs no tools at all. See [Connecting your systems](https://busymate.ai/docs/connectors). ### 5. Publish When branding, web address, sign-in, and (optionally) systems are set, run the **checks** and **publish** from the Console. Publishing is versioned — a change you make is prepared, checked, then switched on, so what your customers see only ever moves forward to a complete setup. A missing sign-in setup, an unreachable connection, or an unsafe action rule blocks publishing with a clear reason. ## Embedding your mate on your own site Beyond a hosted page, you can **embed** your mate directly into your product — a side panel or a chat bubble on your own pages. The embed runs on your site's own address (which we add to your workspace's allowed list), so the assistant lives right where your customers already are, still fully your brand. It's one script tag: ```html ``` Hosted page, embed, or both — it's your call, and you can add the embed later without redoing anything. ## What to prepare - Your **product name** and brand assets (logo, colors, a short welcome message). - The **web address** you want (a subdomain to start, or your own domain to verify). - How your customers **sign in** — or whether you want guest access. - Optionally, your **MCP server** URL if you want your mate to take actions. ### Do I need my own domain to start? No. Every workspace answers at its `.busymate.ai` address immediately. Add your own domain when you are ready — see [Serve your assistant on your own domain](https://busymate.ai/docs/guides/custom-domain). ### Can I add the embed later? Yes. Hosted page, embed, or both; adding the embed later changes nothing about the workspace. ### What blocks publishing? A missing sign-in setup, an unreachable connection or an unsafe action rule. The checks name the blocker; the draft stays a draft. ### Who creates the workspace? A platform owner, in Console → Platform → Workspaces or through the management MCP. The invited admin then completes the Integration checklist without anyone handing off. ## Next - **[The assistant experience](https://busymate.ai/docs/assistant-experience)** — what your customers see once you're live. - **[Governance and models](https://busymate.ai/docs/governance)** — turn features on and set your model rules. - **[Connecting your systems (MCP)](https://busymate.ai/docs/connectors)** — let your mate act on your customers' data. --- --- title: "The assistant experience" description: "What your customers see — the full chat with history, projects, a model choice if you allow it, streaming answers, and a way to reach a person." last_updated: "2026-09-28T08:16:01+03:00" --- # The assistant experience Source: https://busymate.ai/docs/assistant-experience Last modified: 2026-09-28T08:16:01+03:00 Your customers see a full chat under your brand: streaming answers, saved conversations and projects in a side rail, a model choice if you allow it, and a way to reach a person in the same conversation. Signed-in customers get their own history and account actions; visitors get answers and guidance. It works like the chat apps they already know, and nothing names our brand. ## The chat, end to end Diagram: The assistant layout: a left rail with projects and conversation history, a central conversation that streams answers, and a composer with a model choice and a way to reach a person - **Streaming, formatted answers.** Responses stream in live and render as rich text — headings, lists, tables, and code — not a wall of plain text. - **Conversation history.** Every chat is saved. Your customers switch between conversations from a sidebar, reopen any one right where they left off, and each is auto-titled from what they asked. They can rename or delete their own conversations. - **Projects.** Related conversations can be grouped into **projects** in the side rail, so a customer working on one topic keeps those chats together. - **A model choice.** Customers can pick which model answers — if your rules allow it. If you pin one model for your workspace, the assistant stays on it. See [Governance and models](https://busymate.ai/docs/governance). - **A way to reach a person.** When the assistant can't finish something, your customer can ask for a person, and a teammate steps into the same conversation. See [Human handoff](https://busymate.ai/docs/human-handoff). ## Signed in, or as a visitor How much a customer sees depends on how you set up sign-in (see [Getting started](https://busymate.ai/docs/getting-started)): - **Signed-in customers** get their own private history and — if you've connected your systems — actions taken on *their* account, scoped to just their data. - **Visitors** (if you allow guest access) can still chat and get answers and guidance, without signing in. Visitors don't get actions on a specific customer's private data. ## It's your brand, everywhere The name at the top, the colors, the welcome message, the avatar — all yours. The same assistant can run as a full page at your web address and as an embedded panel inside your product, and it looks and behaves the same in both. Your customers never see our brand; they see you. > **Consistent light and dark.** The assistant renders correctly in both light and dark themes automatically, following each person's system setting. ### Do my customers need an account? Not if you allow guest access. Visitors chat and get answers; signed-in customers also get private history and actions on their own account — see [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors). ### Can customers pick the model? Under a "customers pick" rule, from your allowed list. Under a one-default rule the assistant stays on the model you pinned. ### Does it follow dark mode? Yes. The assistant renders in light and dark automatically, following each person's system setting. ### Where does conversation history live? Inside your workspace, keyed to the customer. A visitor's history stays with that visitor; a signed-in customer's follows them across devices. ## Next - **[Governance and models](https://busymate.ai/docs/governance)** — decide which features are on and how models are chosen. - **[Human handoff](https://busymate.ai/docs/human-handoff)** — how a person joins the chat. - **[Connecting your systems (MCP)](https://busymate.ai/docs/connectors)** — let the assistant act, not just answer. --- --- title: "Governance and models" description: "As a workspace admin: which features are on within your plan, whether customers pick a model or get one default, and your limits." last_updated: "2026-09-28T08:16:01+03:00" --- # Governance and models Source: https://busymate.ai/docs/governance Last modified: 2026-09-28T08:16:01+03:00 Governance is where a workspace admin decides what the assistant may do within its limit. You switch features on or off — guest access, human handoff, actions, branding — choose whether customers pick a model or get one default from your allowed list, and set your limits. The controls live in your **Console** and apply to your workspace only. ## Features within your workspace limit Your workspace limit sets a ceiling; within it, you turn features on or off for your workspace: - **Guest access** — let anyone chat without signing in, or require sign-in. - **Human handoff** — let customers reach a person, and give your team the Inbox. Off by default until you turn it on. See [Human handoff](https://busymate.ai/docs/human-handoff). - **Actions** — whether the assistant can do things through your connected systems, and which. See [Connecting your systems](https://busymate.ai/docs/connectors). - **Branding** — your name, logo, colors, and welcome copy. Think of it as two layers: your **workspace limit** is the ceiling the platform sets; your **settings** are where you land inside it. You can move freely up to the ceiling, never past it. Diagram: Your workspace limit sets a ceiling; your settings sit inside it; customer choices sit inside your settings ## Model choice: who picks the model You control which model answers your customers, with two settings: | Setting | What your customers see | Use it when | |---|---|---| | **Customers pick** | A model choice in the composer; each customer picks from the models you allow. | You want to offer a range and let power users decide. | | **One default** | One model, pinned. The assistant stays on it and won't switch. | You want consistent cost and behavior for everyone. | You also set an **allowed list** — the models available under either setting — so "customers pick" still means *your* shortlist, never the entire catalog. The setting is **enforced end to end**: under **one default**, a request to switch models is refused, so a customer can't route around your choice. The picker only ever offers models on your allowed list. > **Rolling out.** Under a one-default setting the composer will show the pinned model as a plain label with no picker at all — a small visual refinement. The setting itself is already enforced today; the picker just doesn't offer other models to switch to. ## Limits Your workspace carries a usage limit. You can see how close you are on the [Usage and analytics](https://busymate.ai/docs/usage) page, per AI provider and over time, so a busy month never surprises you. ## Where these live All of the above sit in your **Console** — a governance panel for model choice and limits, a branding panel, a connections panel, and a usage panel — each scoped to your workspace. Platform-wide settings (creating workspaces, verifying domains) stay with the platform team; your controls are your own workspace's. ### Can a customer switch models under one default? No. The setting is enforced end to end: a request to switch is refused, so nobody routes around your choice. ### What is the allowed list? Your shortlist of the catalog. Under "customers pick" the picker offers only those models; under one default the pinned model must be on it. ### Who can change these settings? Your workspace admins, for your workspace only. Platform-wide settings — creating workspaces, verifying domains — stay with the platform team. ### How do I turn on human handoff? Here, in Governance, then staff the Inbox — the steps are in [Set up human handoff](https://busymate.ai/docs/guides/human-handoff-setup). ## Next - **[Usage and analytics](https://busymate.ai/docs/usage)** — track usage against your limit. - **[The assistant experience](https://busymate.ai/docs/assistant-experience)** — what your rules look like to a customer. - **[Managing from chat](https://busymate.ai/docs/managing-from-chat)** — the same controls, conversationally. --- --- title: "Usage and analytics" description: "See how much your assistant is used — per AI provider, for today, the last 7 and 30 days, and all time — against your limit." last_updated: "2026-09-28T08:16:01+03:00" --- # Usage and analytics Source: https://busymate.ai/docs/usage Last modified: 2026-09-28T08:16:01+03:00 The usage panel in your **Console** shows how much your assistant is used, per AI provider, for four periods — today, the last 7 days, the last 30 days and all time — against your workspace limit, with a small trend chart. If a price is unknown, the row says so instead of showing zero. ## What you see The usage panel gives you, for your workspace: - **Usage per AI provider.** Each AI provider your assistant uses is listed with its own totals, so you can see where the volume actually goes. - **Four periods.** Every figure is shown for **today**, the **last 7 days**, the **last 30 days**, and **all time** — so a spike today reads differently from a steady month. - **Used vs limit.** Your usage against your workspace limit, so you always know the headroom you have left. - **A trend at a glance.** A small trend chart shows the shape of recent usage, so a change in pace is obvious without reading numbers. Diagram: Usage panel: per-provider cards each showing today, 7-day, 30-day and all-time totals, plus a used-versus-limit bar and a trend sparkline ## Why it's broken down this way Different providers cost and behave differently, and a single blended number hides the story. Splitting by provider and by window lets you answer the real questions: *Is today unusual? Are we trending toward the limit this month? Which provider drives the cost?* — at a glance, without exporting anything. Usage ties directly to your [Governance and models](https://busymate.ai/docs/governance) settings: the models you allow and the choice you make shape which providers show up here and how fast usage grows. ### Why is usage split by provider? Providers cost and behave differently. A single blended number hides which one drives the volume; the split answers it at a glance. ### What counts as usage? Model spend per provider, per window, against your workspace limit. A row the platform cannot price is shown as unpriced. ### Where do the limits come from? Your workspace limit sets the ceiling; your [Governance and models](https://busymate.ai/docs/governance) settings shape how fast usage grows. ### Can I see usage from chat or MCP? Yes. Ask the signed-in assistant, or call the same workspace-scoped tools from any MCP client — see [Managing from chat](https://busymate.ai/docs/managing-from-chat). ## Next - **[Governance and models](https://busymate.ai/docs/governance)** — set the model choice and limits that drive these numbers. - **[The assistant experience](https://busymate.ai/docs/assistant-experience)** — what generates the usage in the first place. --- --- title: "Human handoff" description: "How a teammate joins a conversation in the same chat, and how a customer asks to talk to a person." last_updated: "2026-09-28T08:16:01+03:00" --- # Human handoff Source: https://busymate.ai/docs/human-handoff Last modified: 2026-09-28T08:16:01+03:00 Some conversations need a person. AI Assistant lets a customer ask for a human in the chat and lets a teammate step into the **same** conversation from the Inbox — no re-explaining, no new channel — then hand it back to the assistant. Handoff is opt-in, so your mate only offers a person you have actually staffed. ## How a customer asks for a person Your customer simply says so. When they ask to talk to a person — "can I speak to someone", "get me a human", "I need an agent" — the assistant recognizes the request and raises a handoff, rather than trying to muddle through. The customer stays right where they are; nothing sends them to a separate widget or email. ## How your team joins On your side, the **Inbox** collects conversations waiting for a person. A teammate opens one, sees the full history the customer and the assistant already built, and **takes over** — replying in the same conversation. To the customer it is seamless: the same conversation, now with a person answering. Diagram: A customer asks for a person in the assistant chat; the conversation appears in your Inbox; a teammate takes over and replies in the same conversation When the teammate is done, the conversation can return to the assistant — the handoff is a moment in the conversation, not a dead end. ## Assignment and alerts Choose **manual claim**, **round robin**, or **least active** in the Console. The automatic modes consider only teammates who are marked available and still have capacity. Every decision records how it was made, how many teammates were eligible, who was chosen, and their measured load — so an unexplained or fake assignment cannot appear successful. The Inbox in the app is where your team is told first. For an automatically assigned request, the alert goes only to that teammate, and also reaches their linked browser or phone push and personal Telegram. We only mark an alert as reaching someone once an endpoint confirms it; an in-app alert with no linked endpoint stays as accepted. Email, a workspace Telegram and webhooks are not switched on yet (Rolling out). We do not label them delivered just because they are set up: every attempt is recorded as accepted or suppressed, so a silent gap is visible. AI Assistant adds these routes as your deployment turns them on. ## Turning it on Human handoff is **opt-in**. It is off until you turn it on for your workspace, because it depends on your team being ready to answer. When you turn it on (in [Governance and models](https://busymate.ai/docs/governance)), the assistant starts offering a person and your Inbox goes live. Leave it off and the assistant simply never promises a person it cannot deliver. > **Honest by design.** With handoff off, the assistant will not tell a customer "I'll connect you to someone" — it offers a person only when you have actually staffed one. That keeps the promise real. ### How does a customer ask for a person? In their own words — "can I talk to someone". The assistant recognizes the request and raises it; the customer stays in the same conversation. ### What does the teammate see? The full conversation the customer and the assistant already built, before they claim it. Their reply goes into that same conversation. ### Which alerts are switched on? The Inbox in the app, plus each teammate's linked browser or phone push and personal Telegram. Email, a workspace Telegram and webhooks are Rolling out. ### How do I set it up? Turn it on in Governance, staff the Inbox, pick how conversations are assigned — step by step in [Set up human handoff](https://busymate.ai/docs/guides/human-handoff-setup). ## Next - **[Governance & model policy](https://busymate.ai/docs/governance)** — enable handoff and set who can answer. - **[The assistant experience](https://busymate.ai/docs/assistant-experience)** — where the user asks for a human. --- --- title: "Connecting your systems (MCP)" description: "Connect your own MCP server so the assistant can act on your customers' data — each customer authorizing with their own account." last_updated: "2026-09-28T08:16:01+03:00" --- # Connecting your systems (MCP) Source: https://busymate.ai/docs/connectors Last modified: 2026-09-28T08:16:01+03:00 MCP (the Model Context Protocol) is an open standard for giving an AI assistant tools. AI Assistant lets your mate use your tools through your own MCP server, on behalf of your customers, under rules you set. Each tool gets an access level — open to anyone, signed-in customers, or on the customer's behalf — and every change you mark waits for a confirmation card. Your server learns who the customer is from a signed token it verifies, and returns only that customer's data. If your systems already speak MCP, your mate connects to them the same way it connects to anyone's — no platform-specific glue. ## How your mate acts on your customers' data When your assistant needs to do something, it calls a tool on your MCP server. Two things make that safe: 1. **Your mate tells your server who the customer is** — as a short-lived, cryptographically **signed** token your server verifies. It can't be faked or replayed, so your server always knows exactly which of your customers a request is for. 2. **Your server enforces the scope.** Because your MCP server knows the customer, it returns and changes only *that* customer's data. Your mate never sees more than your server hands it. Diagram: A customer chats with your mate; your mate calls your MCP server carrying a signed token identifying the customer; your server verifies it and returns only that customer's data ## Access levels Every tool you expose gets an access level, so the assistant can only reach what's appropriate for who's asking: | Access level | Who it's for | What it allows | |---|---|---| | **Open to anyone** | Anyone, including visitors | Safe, non-personal look-ups — product info, general help. | | **Signed-in customers** | A signed-in customer | Look-ups and actions on **their own** data only. | | **On the customer's behalf** | A signed-in customer, for actions that need their say-so | The same, for actions you want the customer to authorize. | | **Confirmation step** | Any change you mark | The customer must confirm before it runs — the full action is shown first. | Changes that matter are held behind a **confirmation step**: Your mate shows exactly what it's about to do and waits for a yes. Nothing changes silently. ## Setting it up The **Integration** section in your AI Assistant Console is the source of truth for this setup. It is generated from the selected workspace's live settings, so its URLs, sign-in values, snippets, and release checklist stay current — there is no separate handoff document to keep in sync. 1. Open [Console → Integration](https://busymate.ai/console/integration) and select the workspace you are configuring. 2. Follow its MCP step to **Connections**, add your server URL and how it authenticates, then run the probe. 3. Review every tool it finds and set each one's access level and confirmation deliberately. 4. Run the checks and publish. A failed probe or an incomplete sign-in setup blocks publishing, instead of producing a half-connected assistant. The Integration section also gives you a copy-ready brief and the AI Assistant management MCP address for teams that want an AI agent to do the same setup. See [Getting started](https://busymate.ai/docs/getting-started). ### Connect Claude Code to the management MCP One command; the browser handles sign-in with your normal account (OAuth 2.1 — nothing is pasted): ```bash claude mcp add --transport http busymate-ai https://busymate.ai/mcp ``` Then run `/mcp` inside Claude Code and choose **busymate-ai → Authenticate**. Any other HTTP-MCP client (Claude Desktop, Cursor, …) connects with just the URL `https://busymate.ai/mcp` — sign-in is discovered automatically, so no other configuration is needed. ## Customers connecting their own accounts **Each customer can connect their own account** to a service you do not run. Use it when a customer must authorize their own account elsewhere. Set the connection's authorization details in **Connections**, then publish its on-the-customer's-behalf tools. There are two ways the assistant can act for a signed-in customer: - **Automatic (a signed action proof)** — recommended when your product has already verified the visitor. AI Assistant creates a short-lived, workspace-and-connection-bound proof for your MCP server, so account access is automatic and the customer does not see a second sign-in or consent prompt. - **Each customer signs in once (OAuth)** — use this when a separate consent is intentional. The assistant shows **Authorize account tools** once, uses OAuth 2.1 with PKCE, and binds the grant to the workspace, the connection, and the verified customer. Both fail closed. Your MCP server works out the customer only from the verified token, and never trusts an account id passed in a tool's arguments. OAuth grants can be revoked from the account menu; signed proofs expire in at most five minutes and are pinned to one connection. ### Does my server have to speak MCP? Yes — standard MCP over HTTPS, JSON-RPC 2.0, with schemas on `tools/list`. No platform-specific glue. ### How does my server know which customer is asking? From the verified token your mate sends: a short-lived signed proof, or a per-customer OAuth token. Never from an account id in a tool's arguments. ### Automatic proof or per-customer OAuth? The signed proof when your product already verified the visitor and you want no second consent. OAuth when a separate consent screen is intentional. ### Where do I set it up? Console → Connections, then run the checks and publish. The steps, the probe and a worked call are in [Connect your MCP server as assistant tools](https://busymate.ai/docs/guides/connect-mcp-server). ## Next - **[Getting started](https://busymate.ai/docs/getting-started)** — where your MCP server is connected. - **[Governance and models](https://busymate.ai/docs/governance)** — turn actions on and set confirmation rules. - **[The assistant experience](https://busymate.ai/docs/assistant-experience)** — how actions appear to a customer. --- --- title: "Managing from chat" description: "Manage your workspace by chatting — ask the assistant to change branding, features and limits, within your role." last_updated: "2026-09-28T08:16:01+03:00" --- # Managing from chat Source: https://busymate.ai/docs/managing-from-chat Last modified: 2026-09-28T08:16:01+03:00 You can manage your AI Assistant workspace in the Console, or ask the signed-in assistant to do the same work in chat. Both use the same AI Assistant management tools (MCP at `https://busymate.ai/mcp`). Look-ups run right away; changes show you exactly what will change and wait for your yes; and every call stays within the workspaces your account may manage. ## Use the Console Every control this section describes lives in the visual **Console** scoped to your workspace: - **Branding** — your name, logo, colors, and welcome copy. - **Governance** — model choice (customers pick, or one default), your allowed models, and limits. See [Governance and models](https://busymate.ai/docs/governance). - **Connections** — the tools your assistant can use. See [Connecting your systems](https://busymate.ai/docs/connectors). - **Usage** — how much your assistant is used, per AI provider and over time. See [Usage and analytics](https://busymate.ai/docs/usage). - **Handoff** — turn human support on and manage the Inbox. See [Human handoff](https://busymate.ai/docs/human-handoff). Each panel is point-and-click, changes are reviewed before they publish, and everything you can touch is your workspace's — never anyone else's. ## Scoped by who you are Management is always **role-scoped**, whether from the Console or from chat: Diagram: Three levels: the platform team manages all workspaces; a workspace admin manages only their own workspace; a guest gets guidance only, no management - A **workspace admin** (you) manages your own workspace — your branding, your rules, your usage. A change to anyone else's workspace is structurally impossible for you. - The **platform team** (us) manages workspaces across the platform — creating one, verifying a domain. - A **guest** gets no management at all — just help understanding what the assistant does. Your role comes from your verified sign-in, never from anything typed in a chat, so the boundary holds no matter what's asked. ## Manage by chatting Conversational management is shipped. Ask things such as *"Show this workspace's integration status,"* *"List the content, skills, and plugins I can publish,"* *"Add this MCP connection,"* or *"Review the last 30 days of conversations."* The assistant uses the same workspace-scoped management tools the Console uses. Inside AI Assistant, a verified workspace admin or a member of the platform team gets the first-party `platform-management` connector automatically. There is no second MCP setup step in the Console and no shared application token: every call rides the signed-in person's own grant to the management address above. The contract is deliberately simple: - **Look-ups run right away.** For example, `get_tenant_integration`, `list_tenant_resources`, `list_tenant_conversations`, and `list_tenant_insights` return current workspace state. - **Changes show their payload and wait for approval.** For example, `upsert_tenant_connector` and `publish_tenant_runtime` do nothing until the signed-in admin confirms the exact action. - **A workspace admin is held to their active workspace.** A workspace id put in a prompt cannot cross that boundary, and membership is checked again when the tool runs. - **The platform team uses its verified role.** Guests get guidance only and are never given management tools. Older integrations may still call support-era names such as `upsert_tenant_support_connector` and `list_support_insights`. They still work as compatibility names, but new clients should use the product-neutral names. ## Connect from another MCP client External MCP clients connect directly to `https://busymate.ai/mcp` with OAuth 2.1 (Claude Code: `claude mcp add --transport http busymate-ai https://busymate.ai/mcp`, then `/mcp` → Authenticate). The account you connect with decides which workspaces and actions are available; putting a workspace id in a prompt or a tool argument never grants access. Keep confirmation on for changes. ### Can a workspace admin change another workspace? No. A workspace admin is held to their active workspace; a workspace id in a prompt or a tool argument never crosses that boundary. ### Are changes confirmed? Yes. A change shows its exact payload and does nothing until the signed-in admin confirms it. Look-ups run right away. ### Which MCP clients work? Any HTTP-MCP client — Claude Code, Claude Desktop, Cursor — with the URL `https://busymate.ai/mcp`. Sign-in is discovered at the address, so no extra configuration is needed. ### Is the developer-tools MCP the same server? No. The management MCP serves this product only; the developer-tools product has its own server, and neither borrows tools or credentials from the other. ## Next - **[Governance and models](https://busymate.ai/docs/governance)** — inspect or change the same rules from the Console or chat. - **[Usage and analytics](https://busymate.ai/docs/usage)** — inspect workspace usage in the Console or ask for it. - **[Getting started](https://busymate.ai/docs/getting-started)** — set up your workspace first. --- --- title: "Glossary" description: "The AI Assistant vocabulary — each term in plain words first, then its technical name, linked to the guide that uses it." last_updated: "2026-09-28T08:16:01+03:00" --- # Glossary Source: https://busymate.ai/docs/glossary Last modified: 2026-09-28T08:16:01+03:00 The words these docs use, defined once. Each entry gives the plain phrase first and the technical name in parentheses, then links to the guide that uses it. Generic standards get one line and a link to the specification. Every developer page follows the same convention at the first mention of a term. ## Workspace (workspace) Your own space on the platform, kept separate from everyone else's: name, slug, branding, web addresses, sign-in provider, connections, content, model rules and limits. Everything your customers do stays inside it. In the API and tool names it is called a workspace. See: [Getting started](https://busymate.ai/docs/getting-started) ## Your address on our domain (default host) The `.busymate.ai` address every workspace answers at from the moment it exists, before any DNS work. See: [Serve your assistant on your own domain](https://busymate.ai/docs/guides/custom-domain) ## Your own domain (white-label host) Your own web address, mapped to your workspace after you prove you own it (a TXT record) and point it at us (a CNAME). Your customers see your domain only. See: [Serve your assistant on your own domain](https://busymate.ai/docs/guides/custom-domain) ## Signed-in customer (identified launch) Opening the assistant as a known customer: the widget or app hands over a proof your product signed, and your mate serves that customer's history and account tools. See: [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors) ## Sign-in proof (launch token) A short-lived signed proof (a JWT, ES256 by default, at most 120 seconds) your API creates for one signed-in customer: issuer, audience busymate-ai, workspace claim, unchanging subject, nonce, one-time jti. See: [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors) ## One-time values (nonce and jti) The two values on a sign-in proof that can be used once. The widget generates the nonce and your endpoint echoes it; the jti is the proof's own id. Each pair is consumed exactly once, so a replay is refused. See: [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors) ## Your sign-in provider (identity provider) What the platform checks sign-in proofs against: your issuer, public-key URL (JWKS), audience, workspace and subject claims, allowed algorithms, maximum proof age and the endpoint that creates proofs. See: [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors) ## Access levels (tool tiers) The three levels a tool can have: open to anyone (public — non-personal look-ups), signed-in customers (identified — their own data), on the customer's behalf (delegated — for changes you want explicitly authorized). See: [Connect your MCP server as assistant tools](https://busymate.ai/docs/guides/connect-mcp-server) ## Confirmation step (confirm gate) The per-tool flag that stops a change at a card showing the exact action; it runs only after the customer says yes. Not a fourth level — a step on any level's tool. See: [Connect your MCP server as assistant tools](https://busymate.ai/docs/guides/connect-mcp-server) ## Action proof (signed actor token) The pass your mate sends your MCP server when your product already verified the visitor: signed by the platform, valid at most five minutes, issuer https://busymate.ai, audience your origin, workspace and connection pinned. No second consent prompt. See: [Connect your MCP server as assistant tools](https://busymate.ai/docs/guides/connect-mcp-server) ## Each customer connects their own account (per-user OAuth) The alternative: each customer authorizes their own account with your authorization server through OAuth 2.1 with PKCE. Use it when a separate consent screen is intentional. See: [Connect your MCP server as assistant tools](https://busymate.ai/docs/guides/connect-mcp-server) ## Connection (connector) A registered MCP server on your workspace: address, transport, how it authenticates, how it learns who the customer is, and the access level and confirmation flag of every tool it exposes. See: [Connect your MCP server as assistant tools](https://busymate.ai/docs/guides/connect-mcp-server) ## Published version (revision) One frozen, published set of your settings. Draft, then checks (preflight), then publish, then live. A failed check leaves the draft a draft. "Live" (projection) is the copy the assistant serves; published and live are reported separately. See: [Getting started](https://busymate.ai/docs/getting-started) ## Handoff (intervention) A conversation moving from the assistant to your team, with the whole chat attached. Raised when a customer asks for a person, when a connected system requires it (a refund above your limit), or when one of your rules decides. In tool names it is an intervention. See: [Set up human handoff](https://busymate.ai/docs/guides/human-handoff-setup) ## Who can open a shared page (artifact visibility) Only you (private), your team (internal), or anyone with the link (public — listed in the gallery and the sitemap). See: [Share pages the assistant makes](https://busymate.ai/docs/guides/artifacts) ## Allowed websites (embed origin and launch origin) An embed origin is a website allowed to show the chat launcher; a launch origin is a website allowed to open the full-page chat with a sign-in proof. Both are settings on your workspace. See: [Serve your assistant on your own domain](https://busymate.ai/docs/guides/custom-domain) ## Resolution (Shopify plans) A shopper conversation the assistant handled on its own, without your team — billed once per conversation, and only then. A handoff to your team, an "I'm not sure" reply, or a conversation nobody answers is never billed. The unit the Shopify plans count. See: [AI support assistant for your Shopify store](https://busymate.ai/docs/guides/shopify) ## MCP (Model Context Protocol) The open standard for giving an AI assistant tools over HTTPS. Specification: modelcontextprotocol.io. ## JSON-RPC 2.0 The request-and-response format MCP uses. Specification: jsonrpc.org/specification. ## OAuth 2.1 with PKCE The sign-in flow the management MCP and per-customer connections use; PKCE is the check that ties the returned code to the app that started the flow. Specification: the OAuth 2.1 draft and RFC 7636. ## JWT and JWKS A JWT is the signed set of claims a sign-in proof is; JWKS is the public keys it is checked against. Specifications: RFC 7519 and RFC 7517. --- --- title: "Guides" description: "Step-by-step guides for AI Assistant: Shopify, connecting your systems, human handoff, in-app support for iOS and Android, your own domain, your content, signed-in customers and shared pages." last_updated: "2026-10-09T00:39:52+03:00" --- # Guides Source: https://busymate.ai/docs/guides Last modified: 2026-10-09T00:39:52+03:00 Step-by-step guides for AI Assistant: Shopify, connecting your systems, human handoff, in-app support for iOS and Android, your own domain, your content, signed-in customers and shared pages. ## In this section - [Install spotlight knowledge search](https://busymate.ai/docs/guides/knowledge-widget.md): Add keyboard-first documentation search with your existing knowledge index, configurable triggers, and cited answers. - [AI support assistant for your Shopify store](https://busymate.ai/docs/guides/shopify.md): Add AI Assistant to your storefront with no theme edit, let it learn your products and policies, and give signed-in shoppers answers about their orders. - [AI support assistant for your WooCommerce store](https://busymate.ai/docs/guides/woocommerce.md): Create a read key in your store admin, let your mate learn the catalogue and policies, and give a signed-in customer answers about their own orders. - [Install the real WordPress plugin (not just a script tag)](https://busymate.ai/docs/guides/wordpress.md): Install the AI Assistant plugin, add the floating widget or an inline [bmai_assistant] block, publish your knowledge, and recognize signed-in visitors. - [Add your mate to a Ghost publication](https://busymate.ai/docs/guides/ghost.md): Wire the embed through Ghost's own Code Injection, let it learn your posts and pages, recognize signed-in members, and add an inline placement. - [Add the assistant to your Webflow site](https://busymate.ai/docs/guides/webflow.md): Paste the embed where your plan allows it or insert it with the Designer Extension, then teach it your content and recognize signed-in visitors. - [Add your mate to a BigCommerce store](https://busymate.ai/docs/guides/bigcommerce.md): Add the Script Manager embed or the single-click app, connect your live catalogue and orders over MCP, and recognize signed-in customers. - [Add your mate to a Wix site](https://busymate.ai/docs/guides/wix.md): Add the embed via Custom Code on Premium or an Embed HTML element on the free plan, let it learn your pages, and recognize signed-in Members. - [Add your mate to a Squarespace site](https://busymate.ai/docs/guides/squarespace.md): Add the embed with a Code or Embed Block, let it learn your pages, recognize signed-in members, and add page actions with WebMCP. - [Connect your MCP server as assistant tools](https://busymate.ai/docs/guides/connect-mcp-server.md): Register your MCP server as your assistant's tools, give each tool an access level, mark the changes that need a confirmation card, then publish. - [Set up human handoff](https://busymate.ai/docs/guides/human-handoff-setup.md): Turn on handoff, staff the Inbox, choose how conversations are assigned, set how your team is alerted, and measure with ratings and response targets. - [In-app AI support for iOS and Android](https://busymate.ai/docs/guides/mobile-in-app-support.md): Show your assistant's chat inside your iOS or Android app, pass sign-in through your own API, and verify on a real device. - [Install and configure the iOS SDK](https://busymate.ai/docs/guides/ios-sdk.md): Install the versioned iOS SDK, configure identity and microphone permission, and build the example app. - [Install and configure the Android SDK](https://busymate.ai/docs/guides/android-sdk.md): Install the versioned Android SDK, configure identity and microphone permission, and build the example app. - [Serve your assistant on your own domain](https://busymate.ai/docs/guides/custom-domain.md): Claim your address, prove you own it with one DNS record, point it at us with another, verify, and get a certificate automatically. - [Teach your assistant your own content](https://busymate.ai/docs/guides/knowledge.md): Let it read your help site or paste in text, publish, test what it finds, and keep every answer sourced — it says when it is not sure. - [Let your assistant search the web](https://busymate.ai/docs/guides/web-access.md): Turn on web search and page reading per workspace, choose the sites, set the limits, and test exactly what your assistant would get. - [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors.md): Let the assistant trust who is signed in: publish your public key, have your API sign a short-lived proof, and wire getIdentity and refreshIdentity. - [Recognize signed-in customers in a desktop app](https://busymate.ai/docs/guides/identity-desktop.md): Electron, Tauri or WebView2: mint before you navigate, put the proof in the URL fragment, then signal sign-in, sign-out and resume through the preload. - [Recognize signed-in customers in React Native](https://busymate.ai/docs/guides/identity-react-native.md): Copy one shim, inject it before content loads, and answer the same four identity messages every native bridge answers — one WebView, either platform. - [Recognize signed-in customers in Flutter](https://busymate.ai/docs/guides/identity-flutter.md): Register one JavaScript channel before loadRequest, copy one Dart file, and wire sign-in, sign-out and resume — no per-platform code. - [Sign identity tokens from your backend](https://busymate.ai/docs/guides/identity-backend-signing.md): Copy the mint endpoint for Node, PHP, Python or Go, build the identical ES256 claim set, publish your JWKS, and prove it with the conformance checker. - [Native identity bridge compatibility](https://busymate.ai/docs/guides/app-bridge-v2.md): Understand the frozen identity v2 contract, existing app compatibility and when native capabilities require an app release. - [Fix a signed-in customer who shows as a guest](https://busymate.ai/docs/guides/identity-troubleshooting.md): Match your exact symptom to its cause and the conformance-checker cell that proves it, including the WebView-loads-your-own-page case. - [Follow a visitor across workspaces](https://busymate.ai/docs/guides/visitor-journey.md): Platform operators: open one visitor's route across every workspace, read each stop's honest identity state, and erase the visitor on request. - [See which website tries became customers](https://busymate.ai/docs/guides/preview-funnel.md): Platform operators: read every website try with its instruments, the six-stage funnel, and an honest outcome: converted, probable, or left. - [Share pages the assistant makes](https://busymate.ai/docs/guides/artifacts.md): Ask your mate for a report, diagram or how-to and get a self-contained page at your address; choose who can open it, comment inline, manage it from chat. - [Let the assistant use your page](https://busymate.ai/docs/guides/page-tools.md): Publish what your page already does — look up an order, book a slot, start a return — as actions the assistant runs, asking first before changing anything. - [Forms and sign-in inside the chat](https://busymate.ai/docs/guides/form-cards.md): Ask for missing details as a card with real fields instead of a list to type, and let visitors sign in to your site without leaving the conversation. - [Let your users sign in from the chat](https://busymate.ai/docs/guides/in-chat-sign-in.md): Give customers a sign-in card inside the chat, using the accounts you already run: what they get, how to switch it on, and what stays with you. - [How your page and the widget talk to each other](https://busymate.ai/docs/guides/widget-page-api.md): The host and widget contract: open, preset, ask and identify from your page, listen to the widget's events, and share page tools both ways. - [Ask without signing in: the public tools](https://busymate.ai/docs/guides/public-tools.md): What anyone can ask the site assistant or the MCP server without an account — pricing, overview, docs search, status, contact — and what stays private. - [Telegram: answer customers from your bot or your own account](https://busymate.ai/docs/guides/telegram.md): Connect a bot so your mate answers customers on Telegram, answer from your own account with Telegram Business, and get hand-off alerts as a teammate. - [Email channel: your support address and your own mailbox](https://busymate.ai/docs/guides/email.md): Use your workspace's support address or connect your own mailbox, and let your mate answer, draft, summarize and forward email from the Inbox. - [Set up the EmailEngine email channel](https://busymate.ai/docs/guides/emailengine.md): Choose the server, connect a mailbox, let your mate use it, pick how AI replies, import past mail, and fix the common setup problems. - [Run email on your own EmailEngine server](https://busymate.ai/docs/guides/email-emailengine.md): Move your workspace's mail onto an EmailEngine server you run: the token, the address we call from, webhooks, the checks and what we store. - [Get a signed webhook on every event](https://busymate.ai/docs/guides/webhooks.md): Register an endpoint, verify the signature and timestamp on every call, choose your events, and handle retries and the dead-letter state. - [Read and reply over the REST API](https://busymate.ai/docs/guides/api.md): Create a workspace API key, call the REST endpoints or the MCP server with it, list and read conversations, post an operator reply, and rotate the key. - [Keep HubSpot current from every conversation](https://busymate.ai/docs/guides/hubspot.md): Create a private app token, connect it in the Console, and let hand-offs open tickets while resolved conversations keep each customer's record up to date. - [Turn a hand-off into a Zendesk ticket](https://busymate.ai/docs/guides/zendesk.md): Give the Console your subdomain, agent email and API token, and each request for a person arrives in your queue with the thread, page and requester. ## Related - [Getting started](https://busymate.ai/docs/getting-started.md) - [Developer guide: MCP, SDKs and sign-in](https://busymate.ai/developers.md) - [Pricing](https://busymate.ai/pricing.md) --- --- title: "Install spotlight knowledge search" description: "Add keyboard-first documentation search with your existing knowledge index, configurable triggers, and cited answers." last_updated: "2026-09-26T20:38:55+03:00" --- # Install spotlight knowledge search Source: https://busymate.ai/docs/guides/knowledge-widget Last modified: 2026-09-26T20:38:55+03:00 AI Assistant can put a keyboard-first search palette on your own site that searches the **same index your chat uses**. Nothing is crawled or embedded a second time. You set it up in **Console → Knowledge search**. Every change saves itself, **Undo** writes the previous settings back, and a revision conflict asks you to reload instead of overwriting another editor's change. There is nothing to publish. ## 1. Choose what visitors can search Review the page index and the coverage note in **Knowledge search**, then pick the sources: all indexed knowledge, published knowledge only, or connected sources only. Turning the palette on makes those sources searchable by anyone on your site. A page you excluded from retrieval stays excluded here too. ## 2. Allow your site's origin Add your site's exact origin to the workspace's allowed embed origins. The palette uses the same origin list as the chat widget, with its own on/off switch. An origin that is not on the list cannot frame it, and there is no wildcard. ## 3. Install the loader Copy the tag your Console shows. Its host name belongs to your workspace, and its attributes carry your trigger settings: ```html ``` The loader only installs listeners: no settings, no frame, no storage and no download until someone first opens the palette. The optional floating button is drawn locally. Because nothing is fetched before that first open, a trigger change reaches your site only when you copy the tag again. ## 4. Pick the triggers - **Shortcut:** `mod+k` means Command+K on Apple devices and Control+K elsewhere. A custom shortcut combines `mod`, `ctrl`, `meta`, `alt` and `shift` with one letter or digit, for example `alt+shift+p`. The `/` key is optional. - **Your own controls:** add the `data-busymate-kb-trigger` attribute to any button or search field. A click opens the palette, starting from the field's value or the element's `data-query`. - **From script:** `window.BusymateKB.open("billing")` opens it with a query (up to 500 characters; anything but a string opens it empty), `window.BusymateKB.close()` closes it, and `window.BusymateKB.configure({ hotkey: "alt+k", slash: true, trigger: "floating", label: "Search" })` changes the triggers on the page. Shortcuts are ignored while someone is typing in an input, a textarea, a select, a content-editable element or a text box. ## 5. Match your site's look and language The theme is, in order: the page's own explicit choice (`data-theme="light"` or `"dark"` on ``, or a `light` or `dark` class there), then the **Appearance** setting in Console (**System** means follow the page), then the operating system. The palette reads the Console setting each time it opens, so a change applies at once and there is nothing to recopy. The language is the page's ``, then the tag's `data-lang`, then the browser's preference. The loader watches ``, so a theme or language switch reaches an open palette without a reload. A page that sets its language only in script passes it with `window.BusymateKB.configure({ lang: "de" })`. ## What visitors see The palette opens centred over a dimmed page, and as a full-height sheet at 640 px wide and below. It lives in a shadow root, so your site's CSS never reaches it and its styles never reach your page. It wears your workspace branding. With nothing typed it offers **Actions** (search the docs, ask your mate), **Go to** (your top indexed pages, shallowest first) and **Recent searches**, kept in the visitor's browser. Search still works when a browser blocks storage. Typing shows results grouped by page. A page whose title, top heading or address names the query ranks first, with at most two sections per page, each showing the sentence that matched. Retrieval combines word matches with meaning, and a match on meaning alone has to be a close one to appear. When a page exists in several languages, the copy in the page's language wins. A short answer, when turned on, quotes an excerpt and links its source. It needs both the query's words and a close match in meaning, so weak evidence gets a plain refusal instead. A failed search says so and never looks like zero results. The last row, **Ask your mate about this**, opens your chat with the query filled in for the visitor to review; it never sends by itself. Arrow keys, Tab, Enter and Escape drive the palette. Every row belongs to one listbox a screen reader can reach from the search field, and focus returns to the opening control on close. ## Manage from any MCP client The palette calls `POST /api/v1/kb/search` on your workspace host with `{"query":"billing"}` and an optional `lang`; the workspace comes from the host, never the body. With `Accept: application/json` it answers `{query, results, answer, refused, searchId}`; with `Accept: text/event-stream` it streams `results`, optional `answer` chunks, then `done`. Group results by `pageUrl`. Searches are limited to 30 a minute per visitor address range and 600 a minute per workspace; a refused request gets `429` with `Retry-After`, an outage `503`. Agents and scripts manage the settings with the MCP tools `search_knowledge`, `get_kb_widget_config` and `set_kb_widget_config`, or `GET` and `POST /api/v1/kb/config` with a workspace key from the [REST API](https://busymate.ai/docs/guides/api). A change needs confirmation plus the `revision` it replaces. Never put an API key in the install tag. Where the platform's WebMCP provider is on, the palette also offers `search_knowledge` as a page tool. ## What is recorded The events are `kb.search.performed`, `kb.result.clicked`, `kb.zero_results` and `kb.handoff_to_chat`, stored without IP addresses or query text. Console previews and management API searches are left out. Their Insights totals are not built yet, and a missing total is never shown as zero. ## Verify 1. Open a page on your site and press the shortcut: the palette opens, and your browser's network panel shows no settings or palette request before that moment. 2. Search for a phrase from one of your pages: its section appears with the matching sentence, and Enter opens it in a new tab. 3. Choose **Ask your mate about this**: the chat opens with the query filled in and not yet sent. 4. Switch the **Appearance** setting in Console and open the palette again: it follows the new setting without recopying the tag. ### Does the palette crawl my site again? No. It searches the index your chat already uses, with the sources you picked in step 1, so a page you excluded from retrieval stays excluded. ### Does the loader slow down my pages? It installs listeners only. The settings, the palette and its styles download the first time someone opens it, never on page load. ### Why did my new shortcut not take effect? The shortcut rides the install tag, because the loader fetches nothing before the palette opens. Copy the tag from Console again after changing a trigger setting. Appearance is read when the palette opens, so it needs no new tag. ### Can the palette answer from pages that are not in my index? No. Results and short answers come only from your indexed knowledge. When the evidence is too weak, the palette says it cannot answer rather than guessing. ## Next - **[Teach your assistant your own content](https://busymate.ai/docs/guides/knowledge)**: the index this palette searches. - **[REST API](https://busymate.ai/docs/guides/api)**: workspace keys and the rest of the workspace API. --- --- title: "AI support assistant for your Shopify store" description: "Add AI Assistant to your storefront with no theme edit, let it learn your products and policies, and give signed-in shoppers answers about their orders." last_updated: "2026-09-26T19:46:12+03:00" --- # AI support assistant for your Shopify store Source: https://busymate.ai/docs/guides/shopify Last modified: 2026-09-26T19:46:12+03:00 AI Assistant for Shopify is an open-source app that adds your mate, your store's own support assistant, to your storefront — no theme edit. It learns your products, policies and pages, answers shoppers in their own language, and looks up a signed-in shopper's orders. It is listed in our own app catalogue. > **Install today:** the listing at [/store/apps/busymate-ai-shopify](https://busymate.ai/store/apps/busymate-ai-shopify) is where the install status lives. Its button either installs the app or, while self-serve install is not open, takes you to [/contact](https://busymate.ai/contact) to request access. ## Before you start - The **Online Store** channel and a theme that supports app embeds (Theme editor → App embeds). - Access to the store's admin to install apps and edit the theme. - The app is open source (MIT); the repository is linked from its listing at [/store/apps/busymate-ai-shopify](https://busymate.ai/store/apps/busymate-ai-shopify). Plans are on the listing and on [/pricing](https://busymate.ai/pricing). ## 1. Install Open the listing. If its button offers a request instead of an install, send the request and we will follow up to connect your store. When it installs directly: 1. Open the listing and install the app. Shopify asks you to approve the permissions it uses. 2. The app creates your assistant and connects it to your store — nobody on our side has to do anything. 3. It sets your name and colors, lets your storefront show the chat, connects your store's orders, learns your catalog and policies, and switches the assistant on. 4. Your assistant runs at an address of its own on our domain. No DNS work; the storefront loads it through the app embed. ## 2. Turn it on 1. In the app's Home, use the theme-editor link — it opens **Online Store → Themes → Customize → App embeds** with the **AI Assistant assistant** embed ready. 2. Switch it on and click **Save**. The **Ask us** launcher appears on every storefront page. 3. Home confirms the embed is on by reading your public storefront. We can't confirm it on a password-protected store — switch it on above and the check passes once the store opens. ## 3. Check what it learned At install — and on every reinstall, product change, or when you press **Re-train** under Store connection — the app reads your products, shop policies and pages and gives them to the assistant as its content. Home shows what it learned and when. - Only sellable products count; draft and archived products are left out (and counted separately). - Answers cite the page they came from. When the answer is not in your content, your mate says so instead of guessing. ## 4. Name and brand it Open **Assistant settings** in the app. The assistant's name, colors and welcome message are yours — change them and the storefront launcher follows. Nothing here names our brand to your shoppers. ## 5. Signed-in shoppers When a shopper is signed in, the assistant knows who they are and can check their orders. It can look up order status and tracking, and — with the shopper's confirmation — update an address, start a return, or cancel or refund an order. Larger refunds go to you: a refund above your limit is handed to your team with the request attached, never run by the assistant. Nothing changes silently — every change shows the full action first and waits for a yes. ## 6. Billing - **No plan selected yet** — choose the $0 Free plan or a paid plan on Shopify's pricing page; Free-plan limits apply until you do. - Plans include a monthly number of AI **resolutions** (a shopper conversation the assistant handled on its own); paid plans charge per extra resolution up to a monthly cap. The assistant is never switched off for billing. - All charges are billed through Shopify App Pricing on your Shopify invoice. Plans and caps are on the listing and on [/pricing](https://busymate.ai/pricing). ## What the app can and can't touch - **Permissions it asks for, and why:** your products, pages and shop policies (to learn your store), and your orders, customers, fulfilments and returns (to answer signed-in shoppers and, on confirmation, act on an order). - **What it does not ask for:** access to your theme code; orders older than 60 days (requested separately if you need them). - **Live vs learned:** order look-ups read Shopify live at the moment you ask; products and policies are learned at install and on re-train. - AI answers can be wrong — the assistant answers from your content, cites its source, and says when it is not sure. ## Verify 1. Open the storefront. The launcher is visible. Ask a policy question — the reply cites the policy page. 2. Sign in as a test customer and ask "where is my order". The reply names that shopper's order only. 3. Ask for a refund above your limit. The assistant hands the conversation to your team; it appears in the Inbox. 4. Switch the storefront language. The reply follows the shopper's language. ## Technical details For developers — the merchant flow above needs none of this. At install the app provisions one workspace per store through the AI Assistant MCP (`provision_partner_tenant`), authorized by a proof-of-shop signature, so no operator is involved. It sets branding, allows your storefront origins, registers the store's Admin API as the assistant's connection, trains on the catalog, and publishes one version. Signed-in identity rides Shopify's App Proxy: Shopify signs the request and the app mints a short-lived ES256 launch token for that shopper. The connection's tools have access levels — open to anyone (products, policies), signed-in shoppers (their orders, shipments, returns), and on the shopper's behalf with a confirmation card (update an address, start a return, cancel or refund, up to your refund limit). Content limits are the platform's: at most 40 sources, 20,000 characters each, 40,000 total; large catalogs are trimmed and Home says so. ### Does the app edit my theme? No. It adds an app embed you switch on in the Theme editor. Uninstalling the app removes it. ### Where does the assistant run? At an address of its own on our domain, created at install. The storefront only loads the chat. You can later serve it at your own domain — see [Serve your assistant on your own domain](https://busymate.ai/docs/guides/custom-domain). ### Can it refund an order? Up to the refund limit you set, and only after the shopper confirms the exact action. Above that limit it hands the conversation to your team. ### What does it cost? Plans are on the listing and on [/pricing](https://busymate.ai/pricing). Until you pick one on Shopify, the app shows "No plan selected" and the Free-plan limits apply. ## Next - **[Teach your assistant your own content](https://busymate.ai/docs/guides/knowledge)** — what the app learns, and how to add more. - **[Set up human handoff](https://busymate.ai/docs/guides/human-handoff-setup)** — staff the Inbox before shoppers ask for a person. - **[Serve your assistant on your own domain](https://busymate.ai/docs/guides/custom-domain)** — move from the default address to yours. --- --- title: "AI support assistant for your WooCommerce store" description: "Create a read key in your store admin, let your mate learn the catalogue and policies, and give a signed-in customer answers about their own orders." last_updated: "2026-09-17T13:48:07+03:00" --- # AI support assistant for your WooCommerce store Source: https://busymate.ai/docs/guides/woocommerce Last modified: 2026-09-17T13:48:07+03:00 AI Assistant reaches a WooCommerce store through the store's own REST API: the catalogue, categories, shipping zones and policy pages become content your mate answers from, and a signed-in customer can ask where their order is. Nothing is installed inside WooCommerce for that — the connection is a read key you create in the store admin. Every step below is proven against a real WooCommerce store, end to end, by a shopper in the widget. ## Before you start - A WooCommerce store on HTTPS with **Settings → Permalinks** set to anything but **Plain**: the REST routes live under `/wp-json/wc/v3/`, and plain permalinks do not serve them. - An admin account on the store, to create the key. - Your workspace open in the Console. ## 1. Create a read key 1. In the store admin, open **WooCommerce → Settings → Advanced → REST API** and choose **Add key**. 2. Describe it so you recognize it later, pick the user it acts as, and set **Permissions** to **Read**. 3. Generate it. The consumer key (`ck_…`) and consumer secret (`cs_…`) are shown once — copy both before leaving that page. Read is enough for everything here: a write key would let the assistant change orders and move money, so the connection does not ask for one. ## 2. Connect the store Open [Console → Knowledge base](https://busymate.ai/console/knowledge) and add the store with three values: the store address, the consumer key and the consumer secret. The secret is stored value-blind — afterwards the Console shows a hint, never the value. It is verified before anything is saved: one call to `GET /wp-json/wc/v3/system_status` proves the site really runs WooCommerce, the credential authenticates, and the key reads more than a public resource. A failure is reported as a sentence, never saved as a row claiming to be connected. Over MCP: `connect_commerce`, `get_commerce_status` and `sync_commerce`, each taking a `kind` of `woocommerce`. ## 3. Choose what it reads Four corpora, and you pick the set: - **Products** — name, price, stock state and description, each cited to its own permalink. - **Categories** — the category archive a shopper can open. - **Shipping** — the store's shipping zones. - **Policies** — your WordPress pages for shipping, returns, refunds, privacy and terms, so the answer and the page a customer is pointed at stay the same text. Products are bounded by a page limit you set, 1 to 50, default 20. It is the same knowledge pipeline as a website source or pasted text — see [Teach your assistant your own content](https://busymate.ai/docs/guides/knowledge). ## 4. Let it re-read the store The store is re-synced on a schedule you set — daily by default, hourly at most. A sync compares the newest edit time across products and pages against the last one seen; when nothing changed it is skipped and not one memory is rewritten. **Sync now** in the Console, or `sync_commerce`, forces a pass. ## 5. Order lookup for a signed-in customer Order lookup is identity-gated: it answers only with the signed-in customer's own orders, and has no anonymous arm. The match is made on **your store's own customer id**. The plugin signs the WordPress user id into the proof — exactly the customer a WooCommerce order carries — so the store filters on it directly, and no email or phone number crosses the browser. A storefront that signs customers in another way falls back to a verified email. Ownership is checked **again** on every order returned: a filter you asked for is not a filter that was applied. An order number alone is a guessable integer, never sufficient. What comes back: order number, status, the dates placed, paid and completed, the total, the shipping method, the items, and a tracking number when the store recorded one. ## 6. Put the chat on the storefront One WordPress plugin does both jobs: it loads the chat on every storefront page and signs a short-lived proof of who is logged in, so order lookup needs no second sign-in. Your customer database is never shared. 1. Download the plugin from the store connection card in your Console; the zip is built for your workspace, so there is nothing to type into it. 2. In wp-admin, open **Plugins → Add New → Upload Plugin**, upload the zip and activate it. 3. Its status screen lists the values for **Console → Identity** and has a **Test identity** button that proves the signing endpoint answers. Without the plugin the chat still works — add the embed script to your theme — but the storefront must then sign identity itself: [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors). ## Returns are answered, not started The connection deliberately offers no `start_return` action. WooCommerce core has no customer-initiated return resource in its REST API, and `POST /orders//refunds` is an admin refund that moves a merchant's money — not something to run on a visitor's say-so. Returns are a plugin choice that differs per store. So the assistant answers the returns **policy** from your own returns page, with a citation, and hands the conversation to a person for the rest. ## Manage from any MCP client Every step above is available from any MCP client on your own account: ```bash claude mcp add --transport http busymate-ai https://busymate.ai/mcp ``` ## Troubleshooting - **401** — the key was refused: check the consumer key and secret, and that the key has **Read** permission. - **404** — the address answers but the REST API is not there: WooCommerce is not active, or **Settings → Permalinks** is still **Plain**. - **Unreachable** — the address is wrong or the store is down. The connect reports the status it saw. ## Verify 1. The Console card shows the store name, the WooCommerce version and the currency read at connect. 2. Ask about a product only your catalogue knows. The reply cites the product's own page. 3. Ask about your returns policy. The reply cites the returns page and offers a person rather than starting a return. 4. Sign a test customer in and ask where their order is: the reply names that customer's orders only. Ask signed out and the assistant asks them to sign in. ### Does the key need Write permission? No. Read covers the catalogue, the policies and order lookup. Write access is never asked for, because everything it would unlock moves a merchant's money. ### Can a shopper see somebody else's order? No. The lookup runs only for a signed-in customer, is scoped to that customer's own key, and re-checks ownership on every row before showing it. There is no search-all-orders path. ### How often does it re-read my catalogue? On the schedule you set — daily by default, hourly at most. An unchanged store is skipped, so re-syncing a quiet catalogue costs nothing. ### Do I need the plugin? Only to hand over who is signed in. The chat can go on the site with the embed script; the plugin saves you signing the proof by hand. ## Next - **[Teach your assistant your own content](https://busymate.ai/docs/guides/knowledge)** — help pages beside the catalogue. - **[Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors)** — the proof order lookup relies on. - **[Set up human handoff](https://busymate.ai/docs/guides/human-handoff-setup)** — staff the Inbox before the returns questions. --- --- title: "Install the real WordPress plugin (not just a script tag)" description: "Install the AI Assistant plugin, add the floating widget or an inline [bmai_assistant] block, publish your knowledge, and recognize signed-in visitors." last_updated: "2026-09-26T20:38:55+03:00" --- # Install the real WordPress plugin (not just a script tag) Source: https://busymate.ai/docs/guides/wordpress Last modified: 2026-09-26T20:38:55+03:00 AI Assistant reaches WordPress through a real, installable plugin — not a copy-pasted script tag. The plugin loads the floating widget on every front-end page and signs a short-lived proof of who is logged in, so a returning signed-in visitor never has to sign in twice. This is the WordPress-specific path. Wix, Squarespace and Webflow don't yet have a native app of their own — on those builders you still add the one script tag from [Add AI Assistant to WordPress, Wix or Squarespace](https://busymate.ai/articles/add-ai-assistant-wordpress-wix-squarespace). ## Before you start - A self-hosted WordPress site (wordpress.org). The widget works on any PHP build; signed-in visitor recognition additionally needs the OpenSSL PHP extension (ES256) — without it the widget still loads, and the settings screen names exactly what your host is missing. - An admin account on the site. - Your workspace open in the Console. ## 1. Download your plugin Every workspace's plugin is generated for that workspace — your workspace id and the embed origin are baked in at download time, so there is nothing to type into it. 1. In your [Console](https://busymate.ai/console), open your connection settings and choose **Download WordPress plugin**. 2. In wp-admin, open **Plugins → Add New → Upload Plugin**, upload the zip and activate it. 3. Activation generates the site's own ES256 signing key. Its settings screen shows the values a signed-in-visitor identity provider needs (issuer, JWKS URL, the launch endpoint) and a **Test identity** button that proves the signing endpoint answers. The plugin's own copy, look and available tools all come from AI Assistant at chat time — updating any of that never means updating the plugin. ## 2. Put the chat where you want it Out of the box the plugin adds the floating widget to every page — nothing else to do. To put a button inside a specific page (a contact page, a pricing page) that opens the same assistant — optionally with a starting question — use the **AI Assistant trigger** block in the block editor, or the shortcode anywhere shortcodes work, for example `[bmai_assistant label="Ask about sizing" prompt="What sizes do you have?"]`. Both ship directly in the plugin you downloaded — no separate install, no iframe to hand-place. See the live example at [wordpress.demo.busymate.ai](https://wordpress.demo.busymate.ai) (Larkspur Studio), where both the floating widget and an inline block are visible. **Always give the button a `prompt`.** Without one the chat opens on an empty composer. With one, the question is sent for the visitor, exactly as if they had typed it. ### If the open chat covers your page On a theme that runs edge to edge, the open chat panel sits on top of your content on a wide screen. Under **Settings → AI Assistant → Widget → On wide screens**, switch from *Float the chat over the page* to *Make room for the chat beside the page*: your pages shift left only while the chat is open, and only above 1100 pixels. Phones and tablets never move. If your theme styles `padding` on the `` element itself, move that to a wrapper first, because in this mode the widget owns it. The reserved width is also published on `` for anything the padding cannot reach: see [the widget page API](https://busymate.ai/docs/guides/widget-page-api). ## 3. Teach it your content Point a [website source](https://busymate.ai/docs/guides/knowledge) at your site, or paste in your own pages and policies — the same knowledge pipeline every connection uses, with citations back to the page an answer came from. ## 4. Recognize signed-in visitors The plugin signs the WordPress user id into its proof, so a signed-in visitor is recognized automatically once you register it as an identity provider — see [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors) for the exact fields (issuer, JWKS URL, the launch endpoint the plugin's settings screen shows) and how to verify the wiring end to end before trusting it with real customer data. ## Agent-ready out of the box The plugin makes your site readable and operable by AI agents and answer engines, with nothing to configure: - **`/llms.txt`**: a short index of your site (name, key pages, latest content, contact) that an assistant reads before answering about you. - **`/agents.json`**: the capability card an agent looks for first: your content index, your workspace's MCP interface once you connect one, and a human contact. - **Markdown on request, on the same page**: request a published page or post with `Accept: text/markdown` and get that page back as clean Markdown with a small frontmatter. Visitors and search engines keep seeing HTML. - **Structured data and discovery headers**: JSON-LD on every page, and `Link:` headers pointing at `/llms.txt` and `/agents.json`. - **Your WordPress abilities as browser tools**: on WordPress 6.9+ with the core Abilities API, a signed-in visitor's own abilities join the same WebMCP tool surface the plugin's page tools use. Each is generated from your published content and connected workspace, and updates the moment you save a post. See the live example at [wordpress.demo.busymate.ai/llms.txt](https://wordpress.demo.busymate.ai/llms.txt) and [/agents.json](https://wordpress.demo.busymate.ai/agents.json). ## Manage from any MCP client Every step above is available from any MCP client on your own account: ```bash claude mcp add --transport http busymate-ai https://busymate.ai/mcp ``` ## Troubleshooting - **Settings screen warns about openssl** — the site's PHP build is missing the OpenSSL extension with EC (prime256v1) support; ask your host to enable it. The widget itself still works; only signed-in visitor recognition is unavailable until then. - **The widget never appears** — check the browser console for a blocked or 404'd request to `/embed/v1.js`; a caching plugin that strips query-string-free ` ``` 1. In Ghost admin, open **Settings → Code injection**. 2. In **Site Header**, paste the tag. 3. Save. The floating widget now appears on every page and post — nothing else to configure for that part. See the live example at [ghost.demo.busymate.ai](https://ghost.demo.busymate.ai) (The Meridian Line). ## 2. Put the chat inline on a page Out of the box you get the floating widget. For an inline placement on a specific page (an About or Contact page), add an **HTML card** in Ghost's editor with the same frame the widget opens, placed in the page flow instead of a corner button: ```html ``` The live demo shows both placements at once — the floating widget and an inline card on its About page. ## 3. Teach it your content Point a [website source](https://busymate.ai/docs/guides/knowledge) at your own Ghost URL — the same crawler every connection uses, reading your published pages and posts and citing back to the page an answer came from. ## 4. Recognize signed-in members Ghost's native **Members** feature is the identified-visitor layer: register your own site (or a small backend you control) as an identity provider — see [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors) for the exact fields (issuer, JWKS URL, the launch endpoint) — then define `window.BusymateAI.getIdentity` in Code Injection **before** the embed ` ``` 1. In the BigCommerce control panel, open **Storefront → Script Manager**. 2. Create a script and paste the tag. 3. Set it to load on the storefront, footer placement. The floating widget now appears on every storefront page — nothing else to configure for that part. This same script can also be created through the Admin API's Content Scripts resource (`POST /v3/content/scripts`) if you are scripting the install. There is no hosted BigCommerce demo store to open yet — a trial store cannot be launched to the public without a plan, so none is shown. The install above is the whole of it; the catalogue read and the order lookup work the same way on your own store once the loader is in place. ## 2. Or install the native app (single-click) For a one-click install instead of a pasted script, a BigCommerce app (registered on the [developer portal](https://devtools.bigcommerce.com)) can install the same loader via the Scripts API on install, and add a "Chat with your mate" widget through the Widgets API in Page Builder. This is the same OAuth single-click pattern every BigCommerce app uses — see [Connect an MCP server](https://busymate.ai/docs/guides/connect-mcp-server) for the credential shape once installed. ## 3. Teach it your catalogue Connect an MCP server reading your store's own Admin API v3 (products, categories) and orders — see [Connect an MCP server](https://busymate.ai/docs/guides/connect-mcp-server). A store-level API account (Products + Orders read scope is enough for grounded answers) is all it needs; nothing is hardcoded, every answer reflects your live stock and prices. ## 4. Recognize signed-in customers BigCommerce's **Customer Login API** identifies who is shopping. Register your own storefront (or a small backend you control) as an identity provider — see [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors) for the exact fields (issuer, JWKS URL, the launch endpoint) — then define `window.BusymateAI.getIdentity` in your Script Manager script **before** the embed ` ``` 3. Set it to load on **All pages**, placement **Body — end**. Save, then **Publish**. 4. Open the **published** page (not the Editor preview) in a private window and confirm the chat bubble appears. **On a free Wix site**, contact us about site-widget app access. Do not assume a public app installation is available because the demo works. ## 2. Teach it your content Point a [website source](https://busymate.ai/docs/guides/knowledge) at your own Wix URL — the same crawler every connection uses, reading your published pages and citing back to the page an answer came from. ## 3. Recognize signed-in visitors Wix's **Members Area** is a client-side feature (Velo's `wix-members` API), so identity has to be bridged from your site's own code rather than a server-side plugin: define `window.BusymateAI.getIdentity` (see [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors) for the exact shape) inside a Velo page/site code file, **before** the embed script runs, reading the signed-in member from `wix-members` client-side. ## Manage from any MCP client Every step above is available from any MCP client on your own account: ```bash claude mcp add --transport http busymate-ai https://busymate.ai/mcp ``` ## Troubleshooting - **A pasted script tag never appears on a free site** — expected, and not fixable from your side: a free site reports `shouldLoadAllExternalScripts: false` in its page source and never fetches the loader (check with `performance.getEntriesByType('resource').filter(r => r.name.includes('busymate.ai'))` on the published page — empty, however the tag was added). Use Custom Code on Premium. For free-site app access, contact us. - **It works in the Editor preview but not on the published page** — always verify on the actual published URL; the Editor's preview runtime can differ from what a real visitor's browser does with a lazy-loaded element. - **A signed-in member is still treated as a guest** — `getIdentity` must be defined and resolved before the embed script tag runs; test it with `window.BusymateAI.getIdentity()` in the browser console. ## Verify 1. Open your published site in a private window: the chat bubble appears and answers from your own pages, with citations. 2. If you wired identity, sign in as a Wix Member and ask something only a signed-in visitor should see — the reply recognizes that visitor. 3. Ask it to hand off to a person — the conversation reaches your Inbox. ### Do I need Wix Premium? Yes, for the released Custom Code connection. For site-widget app access on a free site, contact us; the working demo does not establish general availability. ### Why does the widget sometimes take a moment to appear? The loader is `async` and the widget mounts after the page settles, so give a published page a second before deciding it isn't there. If it never appears on a free site, check you added it as the app's site widget rather than as a pasted script — see above. ### Can I recognize a signed-in Wix Member? Yes, by bridging `wix-members` to `window.BusymateAI.getIdentity` in your site's Velo code — see [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors). ## Next - **[Teach your assistant your own content](https://busymate.ai/docs/guides/knowledge)** — your Wix pages, crawled and cited. - **[Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors)** — the `getIdentity` bridge for Wix Members. - **[Set up human handoff](https://busymate.ai/docs/guides/human-handoff-setup)** — staff the Inbox before visitors start asking to talk to someone. --- --- title: "Add your mate to a Squarespace site" description: "Add the embed with a Code or Embed Block, let it learn your pages, recognize signed-in members, and add page actions with WebMCP." last_updated: "2026-09-26T20:38:55+03:00" --- # Add your mate to a Squarespace site Source: https://busymate.ai/docs/guides/squarespace Last modified: 2026-09-26T20:38:55+03:00 Squarespace has no plugin runtime, so AI Assistant reaches a Squarespace site through the universal embed — one script tag placed via a **Code Block** or **Embed Block** inside a page. Squarespace's own **Code Injection** (a site-wide header/footer script, the simplest path on WordPress/Ghost/BigCommerce) is a **paid-plan feature on Squarespace** — it is greyed out behind an upgrade prompt on the free trial and on the entry Personal plan, so start with the block-based path below if you're not sure which plan you're on. ## Before you start - A Squarespace site with editor access. - Know your plan: **Business plan or higher** unlocks Code Injection (Settings → Advanced → Code Injection). Below that, a Code Block or Embed Block on each page is the free-tier path. - Your site's **Site Availability** (Settings → Website → Site Availability) must be Public for the embed to render for visitors; a Password Protected or Private site keeps the whole page, embed included, behind a gate. **On a 14-day trial, "Public" is itself paid-plan-gated** ("Upgrade to publish"). Everything else below works without publishing; a real visitor reaching the widget does not. - Your workspace open in the [Console](https://busymate.ai/console). ## 1. Add the embed The tag to paste is the one your Console connection settings show, with your workspace's own address: ```html ``` **If your plan has Code Injection (Business or higher):** 1. Open **Settings → Advanced → Code Injection**. 2. Paste the tag into **Header**. 3. Save. The floating widget now appears on every page — nothing else to configure for that part. **On a plan without Code Injection:** 1. Open the page you want the widget on (or repeat this on every page) in the Squarespace editor. 2. Add a **Code Block** (or an **Embed Block**, which wraps the same idea) and paste the same script tag. 3. Save and **publish the page** — a block's script only runs on the published site, not in the editor preview. Either way, the widget needs your site to be **Public** to render for a real visitor — see "Before you start" above. ## 2. Register the page's own actions (WebMCP) Alongside the embed script, a second small script can register the page's own actions — "view the class schedule," "book a session" — through the standard `document.modelContext` WebMCP surface, so the assistant can act instead of only answering. Drop it in that same block (or Code Injection panel), right after the embed script tag. See [Add page actions with WebMCP](https://busymate.ai/docs/guides/page-tools) for the shape. ## 3. Teach it your content Point a [website source](https://busymate.ai/docs/guides/knowledge) at your own Squarespace site URL — the same crawler every connection uses, reading your published pages and citing back to the page an answer came from. ## 4. Recognize signed-in customers Squarespace's native **Member Areas** feature (on Business/Commerce plans) is the identified-visitor layer: register your own site (or a small backend you control) as an identity provider — see [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors) for the exact fields (issuer, JWKS URL, the launch endpoint) — then define `window.BusymateAI.getIdentity` **before** the embed ` ``` ## Search and canonical Keep one primary address. Your workspace's search setting decides whether the address is indexable; its `sitemap.xml` and `robots.txt` are generated from your settings. ## Remove Domains → Remove (or `remove_tenant_custom_domain`) unmaps the address and cleans up. Your address on our domain keeps serving. ## Troubleshooting - **A 200 on `/` is not proof.** Until the address is mapped and published, signed-in paths answer 403 with `unknown_host`. Test a signed-in path, not the landing page. - **TXT not found** — check the exact record name (`_busymate-support.` plus your address) and wait for the change to spread. - **CNAME conflict** — an A, AAAA or TXT record at the same name blocks the CNAME at most providers. ## Verify 1. `https://ai.yourdomain.com/` renders your brand, not the plain shell. 2. A signed-in path at the new address no longer answers 403. 3. `https://ai.yourdomain.com/sitemap.xml` lists your address. ### Do I need DNS for the address on our domain? No. `.busymate.ai` is live from the start. DNS is only for your own domain. ### Who sets up the certificate? We do, automatically, once verification succeeds. There is nothing to upload or renew. ### Can I keep both addresses? Yes. Mark one primary; both answer with your brand. Links and the sitemap follow the primary one. ### Why does my address answer 403? It is not mapped yet, or the version that maps it is not published. Verify the domain and publish; the 403 disappears. ## Next - **[Getting started](https://busymate.ai/docs/getting-started)** — workspace, web address, sign-in, systems, publish. - **[A white-label AI assistant on your own domain](https://busymate.ai/platform/white-label)** — why the domain is the product. - **[White-label AI for agencies and resellers](https://busymate.ai/solutions/agencies-white-label)** — one address per client. --- --- title: "Teach your assistant your own content" description: "Let it read your help site or paste in text, publish, test what it finds, and keep every answer sourced — it says when it is not sure." last_updated: "2026-09-12T01:26:39+03:00" --- # Teach your assistant your own content Source: https://busymate.ai/docs/guides/knowledge Last modified: 2026-09-12T01:26:39+03:00 AI Assistant makes your mate answer from your own content: point it at a website you run, or paste in text you wrote, then publish. Every answer is sourced, and your mate admits when it cannot be sure. ## 1. Add a website source Point the assistant at your help site. The crawler is robots-aware, stays on the same origin and runs asynchronously; you set how many pages it may index, from 1 to 50 (the default is 20). - Console: [Console → Knowledge](https://busymate.ai/console/knowledge) → **Add source** → URL and page limit. - MCP: `add_tenant_knowledge_source` with `url` and `max_pages`; then `list_tenant_knowledge_sources`, `reindex_tenant_knowledge_source`, `set_tenant_knowledge_source_enabled` and `delete_tenant_knowledge_source` to manage it. A source shows its status, the pages and chunks indexed, the last index time and the last error, so an empty crawl is visible rather than silent. ## 2. Or publish curated text Publish text you wrote — facts, how-tos, references, glossary entries — as `knowledge_sources` on the revision itself (`publish_tenant_runtime`). Each source has a caller-stable `key`, a `label`, a `kind` (`fact`, `howto`, `reference` or `glossary`) and its `content`. - Limits: at most 20,000 characters per source, 40 sources, 40,000 characters in total. An over-limit payload is refused before anything is written. - Re-publishing the same source replaces it. The Shopify app uses exactly this path when it learns your products, policies and pages. ## 3. Publish to go live Content reaches your mate through a published version: select the sources, run the checks, publish. Published versions are frozen, so what your customers see only ever moves forward to a complete setup. See [Getting started](https://busymate.ai/docs/getting-started). ## 4. Test what it finds - Ask your mate a question only your content can answer. The reply cites the source. - Over MCP, `search_tenant_knowledge` returns the matching excerpt with where it came from, so you can check what the assistant would read before a customer does. - Ask something your content does not cover. Your mate says it is not sure and, if handoff is on, offers a person. ## Starter suggestions The welcome screen's suggestion pills are generated from your published content. Publish good sources and the first prompts your customers see are already about your product. ## The wording rule Say it the way it works: the assistant **answers only from your content, with sources, and admits when it cannot be sure**. Claim nothing beyond that sentence. ## Manage from any MCP client Every step above is available from any MCP client connected with your own account: ```bash claude mcp add --transport http busymate-ai https://busymate.ai/mcp ``` ## Technical details For developers: curated text is stored in 2,000-character parts, and every answer drawn from a source carries a `[K:xxxx]` citation the reader can follow back to the exact part. ## Verify 1. A content-only question returns a cited answer. 2. An out-of-scope question is declined; with handoff on, a person is offered. 3. Change a page, reindex the source, ask again — the answer follows the change. ### How much content can I add? Per revision: up to 40 curated sources of 20,000 characters each, 40,000 characters in total. A website source indexes up to 50 pages per source. ### Does it crawl my whole site? No. One origin, the page limit you set, and robots rules respected. Add several sources for several sections. ### Can it make things up? It answers from your content, with sources, and admits when it cannot be sure. Publish what you want it to know; keep the rest out. ### Do I have to re-publish after a crawl? A website source is indexed on its own schedule; curated text is part of the revision. Reindex when your pages change; publish when you change what is selected. ## Next - **[Governance and models](https://busymate.ai/docs/governance)** — the features and limits around the assistant. - **[AI customer support with human handoff](https://busymate.ai/solutions/customer-support)** — grounded answers plus a person. - **[AI sales and onboarding assistant](https://busymate.ai/solutions/sales-onboarding)** — pre-sales answers from your own docs. --- --- title: "Let your assistant search the web" description: "Turn on web search and page reading per workspace, choose the sites, set the limits, and test exactly what your assistant would get." last_updated: "2026-09-23T16:47:50+03:00" --- # Let your assistant search the web Source: https://busymate.ai/docs/guides/web-access Last modified: 2026-09-23T16:47:50+03:00 AI Assistant lets your mate look things up on the web when your own knowledge does not have the answer — today's news, a price, a product's specification — by **searching the web** and **reading a page**. It always tries your knowledge first, says which it used, and links the page when it answers from the web. Everything here lives in **Console → Web access**. Every control saves itself and is live the moment the page says **Saved**; **Undo** writes the previous values back. There is no draft and nothing to publish. ## 1. Switch it on Web access is **off** for a new workspace: nothing reaches the web until an admin turns on **Web access**. Under it, **Search the web** and **Read a page** can each be turned off on their own — for example, read the pages your customers paste in, but never search. The page opens with one plain sentence about what your mate can do **right now**, read from the saved settings rather than from anything still being typed, and where those settings come from. A workspace that switched on live web search in an earlier version of its settings starts with **Search the web** on and **Read a page** off, and the page says so; the first change you make here takes over from that older setting. ## 2. Choose the sites - **Only these sites** — when the list is empty, any public site may be used. When it has entries, only those sites and their subdomains are searched or read. - **Never these sites** — always refused, even when the same site is also allowed. Enter a site the way you would say it: `example.com` or `*.example.com`. A full address such as `https://example.com/page` is refused with a note, because the lists match on the site, not on a path. Both lists apply to searching and to reading a page — including every address a link redirects to, so a short link cannot lead your mate to a site you blocked. A site you block inside one you allow (allow `example.com`, block `forum.example.com`) is also left out of search results. ## 3. Set the limits Searches and page reads count together. | Limit | What it bounds | Range | |---|---|---| | Per conversation | Lookups one conversation may make | 1 – 50 | | Per day | Lookups the whole workspace may make in a UTC day | 1 – 100,000 | A lookup counts when it is **attempted**, so a site that keeps failing is not a free retry loop. When a limit is reached, your mate tells the person plainly that it cannot look anything else up — it never pretends it searched. ## 4. Decide how it answers - **Cite sources** (on by default) — your mate names and links the page it used, never cites a page it did not open, and never invents an address. - **Safe search** (on by default) — asks the search to leave out explicit results. ## 5. Try it The **Try it** box at the bottom of the page runs one real search or one real page read under the **saved** settings and shows exactly what your mate would get: the answer with its sources, or the reason it would refuse. Tests do not count toward your limits and are not recorded as usage; they have a small allowance of their own, six every ten minutes. ## What is never read Page reading refuses, before a single byte is fetched: addresses that are not `http` or `https`, addresses that carry a user name or password, addresses that name a port, and anything that is not on the public internet — local, private and cloud-metadata addresses, including a public name that resolves to a private one and a redirect that lands on one. A site that asks assistants not to read a page (`robots.txt`) is respected. The text of a page is bounded, and your mate is told when it was cut. ## Manage from any MCP client The same settings are available to agents and scripts: `get_tenant_web_access`, `set_tenant_web_access` and `test_tenant_web_access` over MCP, or `GET /api/v1/web-access`, `POST /api/v1/web-access` and `POST /api/v1/web-access/test` over the [REST API](https://busymate.ai/docs/guides/api). A change names only the fields to change — every other field is kept — and is live when it returns. The Insights metrics `web_searches` and `web_fetches` count lookups per day. Each lookup is also recorded in the events trail with its site and outcome, never the question or the page text. ## Verify 1. In **Try it**, search for something your knowledge does not cover — the answer arrives with its sources. 2. Add that answer's site to **Never these sites** and run the same test — it is refused with the blocked-site reason. 3. Turn **Web access** off and ask your mate the question in the chat — it says it cannot look this up here and answers from your knowledge. ### Does my mate search the web for every question? No. It answers from your own knowledge first and goes to the web only when that knowledge does not have the answer, or when the question is about something that changes, such as news or prices. It says which one it used. ### Does it cost me more when it searches? Each lookup is bounded by the per-conversation and daily limits you set, so you decide the ceiling. Tests from the Try-it box never count toward them. ### Can it read pages behind a login or on my private network? No. It only reads public addresses. Private, local and cloud-metadata addresses are refused before anything is fetched, and so is any address carrying a user name or password. ### Can I allow only my own sites? Yes. Add them to **Only these sites** and both searching and page reading stay on those sites and their subdomains. ## Next - **[Teach your assistant your own content](https://busymate.ai/docs/guides/knowledge)** — the knowledge your mate tries first. - **[REST API](https://busymate.ai/docs/guides/api)** — keys, scopes and the rest of the workspace API. --- --- title: "Recognize signed-in customers" description: "Let the assistant trust who is signed in: publish your public key, have your API sign a short-lived proof, and wire getIdentity and refreshIdentity." last_updated: "2026-10-08T14:26:39+03:00" --- # Recognize signed-in customers Source: https://busymate.ai/docs/guides/identified-visitors Last modified: 2026-10-08T14:26:39+03:00 AI Assistant recognizes your signed-in customers without sharing an account database. Your API signs a short-lived proof for each one (a launch token — an ES256 JWT valid for 120 seconds with a one-time nonce), you publish the matching public key (JWKS) as the workspace's identity provider, and the widget calls `getIdentity`, `identityChanged`, and `signedOut`. Your mate then serves that customer's history and account tools — only theirs. ## Two identities - **Your team** signs in to the Console with their own accounts. - **Your customers** never get a platform account. Each launch carries a proof your product signed, whose subject is your unchanging customer id. ## 1. Keys Create an ES256 key pair. Publish the public key at `https://yourdomain/.well-known/jwks.json` with a `kid`; keep the private key on your server. ES256 is the reference algorithm; the allowed list is part of the registration. ## 2. Register the provider Open [Console → Identity](https://busymate.ai/console/identity) — or call `upsert_tenant_identity_provider` — and enter: | Field | Value | |---|---| | Issuer | your origin, for example `https://yourdomain` | | JWKS URL | `https://yourdomain/.well-known/jwks.json` | | Audience | `busymate-ai` | | Workspace claim | `tenant_id`, equal to your workspace id | | Subject claim | `sub` — the unchanging internal customer id | | Max proof age | at most 120 seconds | | Mint endpoint | the URL of the endpoint from step 3 | Save the draft, run the checks, publish. An incomplete sign-in setup blocks the release. ## 3. The mint endpoint Your API exposes one endpoint requiring your own signed-in session, returning a freshly signed proof for that customer: ```typescript import { SignJWT, importJWK } from "jose"; // POST https://YOUR-PRODUCT-DOMAIN/api/bmai/identity — requires YOUR OWN logged-in product session. app.post("/api/bmai/identity", requireSession, async (req, res) => { // Fresh on EVERY mint. Never persist the launch token/nonce in localStorage, // sessionStorage, cookies, React state, or module state: every assistant // launch consumes this pair exactly once. const nonce = typeof req.body?.nonce === "string" ? req.body.nonce : ""; if (!/^[A-Za-z0-9_-]{32,200}$/.test(nonce)) return res.status(400).json({ error: "invalid_nonce" }); const key = await importJWK(JSON.parse(process.env.AI_LAUNCH_PRIVATE_JWK), "ES256"); const token = await new SignJWT({ tenant_id: process.env.BMAI_TENANT_ID, // the tenant id shown in Console → Identity nonce, // equals the sibling field below name: req.user.displayName, // optional low-sensitivity display claim }) .setProtectedHeader({ alg: "ES256", kid: process.env.AI_LAUNCH_KEY_ID }) .setIssuer(process.env.BMAI_ISSUER) // the Issuer you registered in Console → Identity .setAudience("busymate-ai") .setSubject(req.user.id) // IMMUTABLE internal account id; never email/phone/session id .setJti(crypto.randomUUID()) // one-time (replay-protected) .setIssuedAt() .setExpirationTime("120s") // <= registered max age (120s) .sign(key); res.set("Cache-Control", "no-store"); res.status(201).json({ token, nonce, expiresIn: 120 }); }); ``` - The nonce arrives from the widget, must match `^[A-Za-z0-9_-]{32,200}$`, and is echoed back. - Claims: `iss`, `aud`, `sub`, your workspace claim, `nonce`, a one-time `jti`, `iat`, `exp` within the registered max age. - Respond `201` with `{ token, nonce, expiresIn }` and `Cache-Control: no-store`. Each pair is consumed exactly once. ## 4. Wire the widget Define `window.BusymateAI.getIdentity` before the embed script loads. It returns a fresh `{ token, nonce }` for a signed-in customer and `null` for a signed-out one. Call `identityChanged()` after login, token rotation and every account switch, which upgrades the live conversation in place, and `signedOut()` on logout, which ends the session and clears the transcript. Never keep a token or nonce in storage, cookies or state. Console → Integration renders the full embed snippet with your values. ## 5. Pick your platform New native apps use official SDK identity v2. For web and compatibility transports, `https://busymate.ai/sdk/v1/kit/` supplies `identityChanged()` and `signedOut()` bindings for the platform rows below. | You are building | Installation | Guide | |---|---|---| | A website, any framework | `kit/web/busymate-identity.js` | this page | | iOS (WKWebView) | Official Swift package, distribution 1.0.1 | [iOS SDK](https://busymate.ai/docs/guides/ios-sdk) | | Android (WebView) | Official Gradle module, distribution 1.0.0 | [Android SDK](https://busymate.ai/docs/guides/android-sdk) | | Electron · Tauri · WebView2 | `kit/desktop/preload.js` | [Desktop](https://busymate.ai/docs/guides/identity-desktop) | | React Native | `kit/react-native/busymateIdentity.js` | [React Native](https://busymate.ai/docs/guides/identity-react-native) | | Flutter | `kit/flutter/busymate_identity.dart` | [Flutter](https://busymate.ai/docs/guides/identity-flutter) | | Your API | `kit/backend/{node,php,python,go}` | [Backend signing](https://busymate.ai/docs/guides/identity-backend-signing) | **An app WebView loading your OWN page is a fifth shape.** The assistant asks that page, not your app; see [Fix a signed-in customer who shows as a guest](https://busymate.ai/docs/guides/identity-troubleshooting). Three rules apply everywhere, and missing any is silent: **register the bridge before the page loads**, **mint fresh on every ask** (a proof is single-use, so a cached one is refused), and **signal both directions** (an unsignalled sign-out leaves a conversation in front of the next person at that device). Third-party cookie policy has no bearing on any of it. ## 6. Full-page open For a hosted page instead of an embed, mint the same pair and open your address with the token and nonce in the URL **fragment**, never the query string; the hosted-handoff snippet in Integration shows the form. ### The redirect handoff your own login page must complete When a signed-out visitor clicks **Sign in** on your hosted page, the platform sends them to your registered `loginUrl` with `return_to` and a one-time `bmai_nonce`. On that same request your login page must complete the customer's sign-in, mint the pair with the received `bmai_nonce`, and redirect to the **exact** `return_to` with `#bmai_token=&bmai_nonce=` in the fragment. A login page that ignores `return_to` leaves the chat a guest; Console → Integration → Identity flags it. ## 7. Sign in inside the chat A `sign_in` tool, as a page tool or on your connected server, signs a visitor in without leaving the conversation and re-mints the session in place. Without it, a signed-out visitor gets the redirect above, which is why `loginUrl` matters even if you add the tool later. See [Let your users sign in from the chat](https://busymate.ai/docs/guides/in-chat-sign-in). ## 8. Let the diagnostics sign in as a test account Your mate can run its full diagnostics as one of your own test accounts (Console → Connections → Test account, or `verify_tenant_private_tools`), which needs a sign-in without a browser. Add the machine arm to your mint endpoint, or publish a `sign_in` tool: [Sign identity tokens from your backend](https://busymate.ai/docs/guides/identity-backend-signing) has both. ## 9. Acceptance checklist Setup progress proves configuration, not that the flow works. **Console → Identity → "Test identified launch"** fetches your JWKS, checks a key exists for every registered algorithm, pushes an unsigned probe through the live verifier (which must refuse it), and reports whether the provider is published. Each failure names its reason, and the same check gates the release. Paste a real token your endpoint minted, with its nonce, to prove the last step; `test_tenant_identity_provider` is the MCP twin. ```text REQUIRED AUTH + HISTORY ACCEPTANCE — AI Assistant / your mate Setup progress is configuration evidence; it does not prove this workflow. [ ] Console -> Identity -> "Test identified launch" is GREEN on your provider row. (It fetches your JWKS and checks a key exists for every algorithm you registered, then pushes a deliberately unsigned probe through the same verifier the live launch uses and requires it to be REFUSED, and confirms the provider is in the draft AND the published revision. Do not eyeball the form.) [ ] Signed out: getIdentity returns null and the assistant remains anonymous. [ ] Login without reloading the host page: call identityChanged(); the frame becomes identified. [ ] Every getIdentity call returns a different nonce AND JWT jti. No launch token or nonce is persisted. [ ] The subject is the same immutable internal AI Assistant account id across sessions/devices — never email, phone, browser id, or session id. [ ] Send an identified message; refresh the host page; the same conversation reappear. [ ] That refresh produces no launch_replayed, invalid_token, or silent anonymous fallback. [ ] Logout: call signedOut(); account data is unavailable and the frame is anonymous. [ ] Login again as the same account: call identityChanged(); that user's identified history returns. [ ] Switch to a second account: call identityChanged(); it cannot see the first user's history or data. Do not rely on a post-message-only identify() flow. Use identityChanged() after login, access-token/session rotation, and every account switch; use signedOut() after logout. ``` ## 10. Check your own integration "My customer shows up as a guest" is the symptom every mistake here produces. The [Identity check](https://busymate.ai/developers/identity-check) grades your page's lifecycle, the CLI grades your backend, and both exit `0` passed, `1` failed, `2` could not be observed. In the Console, **Identity health** shows the same cells against real traffic. [Fix a signed-in customer who shows as a guest](https://busymate.ai/docs/guides/identity-troubleshooting) walks each symptom to its cause. ## Verify 1. Signed out: the assistant is a visitor session. 2. Log in without reloading and call `identityChanged()`: the frame is identified. 3. The same customer on a second device sees the same history. 4. A second account cannot see the first's history or data. ### Do you store my customers' accounts? No. Each launch carries a proof your product signed; the subject is your id. Conversations are keyed to that subject inside your workspace. ### Why does the proof expire in 120 seconds? It is a launch proof, not a session. A fresh one is minted per launch and used once, so a leaked proof is useless within moments. ### Which algorithm must I use? ES256 is the reference. The algorithms your provider accepts are part of its registration, checked against your JWKS. ## Next - **[Connect your MCP server as assistant tools](https://busymate.ai/docs/guides/connect-mcp-server)** — the tools that need this identity. - **[In-app AI support for iOS and Android](https://busymate.ai/docs/guides/mobile-in-app-support)** — the same proof through a native bridge. - **[White-label SDK → Customer identity](https://busymate.ai/developers#identity)** — the full contract. --- --- title: "Recognize signed-in customers in a desktop app" description: "Electron, Tauri or WebView2: mint before you navigate, put the proof in the URL fragment, then signal sign-in, sign-out and resume through the preload." last_updated: "2026-09-21T07:42:22+03:00" --- # Recognize signed-in customers in a desktop app Source: https://busymate.ai/docs/guides/identity-desktop Last modified: 2026-09-21T07:42:22+03:00 AI Assistant treats your desktop shell as its own platform. An Electron, Tauri or WebView2 window loads the assistant as the **top-level** document — there is no parent window to ask, so first launch carries identity differently than a website or a mobile WebView does, and everything after first launch goes through a small preload instead. ## 1. Mint before you navigate, not after With no parent to ask, first launch is served well by asking nobody: your main process mints the sign-in proof itself and puts the pair in the URL **fragment** before the window ever loads the address. ```typescript // Full-page open with identity in the URL FRAGMENT — never sent in the // request line, referrer, or logs; the destination strips it before exchange. function newLaunchNonce() { const bytes = new Uint8Array(32); crypto.getRandomValues(bytes); return btoa(String.fromCharCode(...bytes)) .replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, ""); } const nonce = newLaunchNonce(); const accessToken = await getProductAccessToken(); // YOUR existing auth helper if (!accessToken) throw new Error("Sign in before opening an identified assistant"); const returnTo = new URL(location.href); returnTo.search = ""; returnTo.hash = ""; const response = await fetch("https://YOUR-PRODUCT-DOMAIN/api/bmai/identity", { method: "POST", credentials: "include", cache: "no-store", headers: { "content-type": "application/json", authorization: "Bearer " + accessToken }, body: JSON.stringify({ nonce, returnTo: returnTo.href }), }); if (response.status === 401) throw new Error("Sign in before opening an identified assistant"); if (!response.ok) throw new Error("AI identity mint failed (" + response.status + ")"); const identity = await response.json(); if (typeof identity.token !== "string" || typeof identity.nonce !== "string") { throw new Error("AI identity mint returned an invalid response"); } if (identity.nonce !== nonce) throw new Error("AI identity nonce mismatch"); const url = new URL("https://your-assistant.busymate.ai/"); url.hash = new URLSearchParams({ bmai_token: identity.token, bmai_nonce: identity.nonce, }).toString(); location.assign(url); ``` `channel=desktop` (set on the URL, shown above as part of the address) labels the session "Desktop app" everywhere it appears — the Console, the transcript, the checker. ## 2. Copy the preload Electron: `https://busymate.ai/sdk/v1/kit/desktop/preload.js`, with `contextIsolation: true` and `nodeIntegration: false`. Your main process answers the `busymate:mint-identity` IPC channel the preload sends; a runnable main process is at `https://busymate.ai/sdk/v1/kit/desktop/sample-main.js`. - **Tauri** — the same three calls become one `#[tauri::command] fn busymate_mint()` plus `invoke("busymate_mint")` from an init script. Tauri's own `__TAURI_INTERNALS__` global is already recognized as a shell. - **WebView2** — `AddScriptToExecuteOnDocumentCreatedAsync` installs the identical shim; answer over `CoreWebView2.PostWebMessageAsJson`, which delivers a real object rather than a string. ## 3. Everything after first launch goes through the preload No more handshakes: call `busymateDesktop.identityChanged()` on login, token rotation or account switch; `busymateDesktop.signedOut()` on logout; `busymateDesktop.onResume()` when the window regains focus or wakes from sleep. Each mints fresh through the same main-process endpoint as first launch — never a cached pair. ## 4. What you never have to configure Cookies, third-party or otherwise. Identity arrives from your own main process on first launch and on every later call, so nothing in this integration depends on a cookie policy, a partition setting, or your window's session store. ## Verify 1. Launch signed in: the greeting names the right customer on the very first screen, with no visible handshake. 2. Sign out inside your app; the next customer to use the window gets a guest session, not the last one's history. 3. Minimize, wait past the token's lifetime, and restore the window: the assistant is still identified, not silently downgraded to a guest. 4. Run `node v2/scripts/identity-conformance.mjs --host --json` with `channel=desktop`; it names any obligation your shell still misses instead of a bare pass or fail. ### Why mint before the window navigates instead of asking after it loads? A desktop window has no parent to ask, and the resume budget for an in-page ask is short. Minting in the main process and handing over the pair in the URL fragment needs no round trip inside the loaded page at all. ### Does Tauri need the exact same preload file as Electron? No. The three calls collapse to one Rust command your init script invokes; the file it replaces is `preload.js`, not a Tauri equivalent of it. ### Why does WebView2 answer differently from Electron? `CoreWebView2.PostWebMessageAsJson` hands the page a real object. Electron's preload does the equivalent through `contextBridge`, so both avoid re-parsing a string on the page side. ### Is `channel=desktop` required, or only cosmetic? Set it. It labels every session "Desktop app" in the Console and the transcript, and the checker reads it to grade the right lifecycle. ## Next - **[Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors)** — the contract this shell implements, the claims your mint endpoint signs. - **[Sign identity tokens from your backend](https://busymate.ai/docs/guides/identity-backend-signing)** — the endpoint your main process calls. - **[Fix a signed-in customer who shows as a guest](https://busymate.ai/docs/guides/identity-troubleshooting)** — symptom-first fixes when a cell fails. --- --- title: "Recognize signed-in customers in React Native" description: "Copy one shim, inject it before content loads, and answer the same four identity messages every native bridge answers — one WebView, either platform." last_updated: "2026-09-21T07:42:22+03:00" --- # Recognize signed-in customers in React Native Source: https://busymate.ai/docs/guides/identity-react-native Last modified: 2026-09-21T07:42:22+03:00 AI Assistant reaches a React Native app the same way it reaches any native shell: a small bridge answers who is signed in. React Native hides both platforms' native bridges behind one `WebView` component, so the kit installs a single shim that speaks the same wire messages on either OS. ## 1. Copy the shim Copy `https://busymate.ai/sdk/v1/kit/react-native/busymateIdentity.js` into your app. It installs the Android-shaped interface on the page and forwards every message to your own `onMessage` handler — the same four messages every platform answers. ## 2. Inject before content loads, not after Pass the shim's source to your `WebView` as `injectedJavaScriptBeforeContentLoaded`, and forward everything it posts back to `bridge.onMessage(event.nativeEvent.data, event.nativeEvent.url)` from the component's own `onMessage` prop — the full wiring is in the runnable sample below. Use `injectedJavaScriptBeforeContentLoaded`, never `injectedJavaScript`: the latter runs after load, so the very first identity ask can arrive before your bridge exists and gets no answer at all. ## 3. What the shim mimics underneath On Android the underlying interface looks like this — the shim gives your page the identical shape without you writing it: ```kotlin // Gradle installation + lifecycle: https://busymate.ai/docs/guides/android-sdk // Source: https://github.com/serebano/busymate-ai-sdk-android/tree/1.0.0 import android.webkit.WebView import ai.busymate.bridge.BusymateBridge fun installAssistant( webView: WebView, account: () -> String?, mint: (Map, (BusymateBridge.MintResult) -> Unit) -> Unit ) { BusymateBridge.install(webView, BusymateBridge.Config( assistant = "your-assistant", origins = listOf("https://your-assistant.busymate.ai"), account = account, mint = mint )) // mint calls YOUR authenticated backend with request["nonce"], then done(result). // Backend endpoint: https://YOUR-PRODUCT-DOMAIN/api/bmai/identity webView.loadUrl("https://your-assistant.busymate.ai/?channel=android") } // Microphone: declare INTERNET + RECORD_AUDIO; construct and retain // BusymateMicrophone in Activity.onCreate BEFORE STARTED/loadUrl; forward // WebChromeClient.onPermissionRequest. See the guide for renderer recovery. // Call BusymateBridge.accountChanged() on login/logout/account changes. ``` Your own `identityProvider` calls your authenticated API on every ask, never a cached value; `bridge.identityChanged()` on login, rotation or account switch; `bridge.signedOut()` on logout. ## 4. Run the sample first `https://busymate.ai/sdk/v1/kit/react-native/Sample.jsx` is a working screen: a fake sign-in toggle, the shim installed, the widget reacting to both directions. Confirm it behaves before wiring your own auth store in. ## Verify 1. Signed out, open the screen: the assistant runs an anonymous, guest session. 2. Sign in inside your app, without reloading the WebView, and call `identityChanged()`: the same thread becomes identified. 3. Background the app past the token's lifetime, then foreground it: the assistant re-asks and gets a fresh answer, not a refused stale one. 4. Sign out and reopen the screen: the previous customer's history is gone, not merely hidden. 5. Run `node v2/scripts/identity-conformance.mjs --host --json` against `channel=android`; React Native answers through the same wire shape the checker already grades. ### Do I need a separate integration for iOS builds of the same app? No. The `WebView` component and this shim are the same on both platforms; only your native project's build configuration differs, not this bridge. ### Why can't I use `injectedJavaScript` — it is simpler to reason about? It runs once the page has already loaded, which is after the assistant's first identity ask. A handler installed that late misses the one ask that matters most, the first one. ### Does the shim work with Expo's managed WebView? Any component built on `react-native-webview` accepts the same two props (`injectedJavaScriptBeforeContentLoaded`, `onMessage`), so the shim asks nothing extra of your bundler or build tool. ### What if my app never installs the shim? The assistant still runs, anonymously. A missing bridge is a supported, guest state — never a broken chat — until you wire identity in. ## Next - **[Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors)** — the four obligations this bridge answers. - **[In-app AI support for iOS and Android](https://busymate.ai/docs/guides/mobile-in-app-support)** — the native bridge this shim mirrors. - **[Fix a signed-in customer who shows as a guest](https://busymate.ai/docs/guides/identity-troubleshooting)** — symptom-first fixes when a cell fails. --- --- title: "Recognize signed-in customers in Flutter" description: "Register one JavaScript channel before loadRequest, copy one Dart file, and wire sign-in, sign-out and resume — no per-platform code." last_updated: "2026-09-21T07:42:22+03:00" --- # Recognize signed-in customers in Flutter Source: https://busymate.ai/docs/guides/identity-flutter Last modified: 2026-09-21T07:42:22+03:00 AI Assistant recognizes a Flutter app through one JavaScript channel your WebView plugin already knows how to register — no bridge code to write yourself, only a channel name and a small Dart file to wire in before the page loads. ## 1. Register the channel before `loadRequest` Name it exactly `BusymateAINative`; that name already carries the shape the assistant probes for on launch. Register it — and its compatibility twin, both named in the sample below — on your `WebViewController` before you call `loadRequest`, the same "before the page loads" rule every platform in this kit follows. ## 2. Copy the identity file Copy `https://busymate.ai/sdk/v1/kit/flutter/busymate_identity.dart` into your app. It answers the same three messages every native bridge answers: an identity request, an open-url request for external links, and a close request for the sheet. ## 3. Wire the four obligations Your channel handler calls your own authenticated API for a fresh `{ token, nonce }` pair on every identity request — never a cached one. Call the bridge's sign-in signal on login, token rotation and account switch; its sign-out signal on logout; and its resume signal from your widget's `didChangeAppLifecycleState` when the app returns to the foreground. A signed-out answer is `null`, never a stale pair. ## 4. Run the sample first `https://busymate.ai/sdk/v1/kit/flutter/sample.dart` is a working screen with a fake sign-in switch and the channel already registered. Confirm it behaves — an anonymous chat, then an identified one on the fake sign-in — before you connect your own auth store. ## Verify 1. Signed out, open the screen: the assistant runs an anonymous, guest session. 2. Sign in inside your app and signal it: the same conversation becomes identified, with no reload. 3. Put the app in the background past the token's lifetime, then bring it forward: the assistant re-asks and is answered fresh, not refused as stale. 4. Sign out: the next person to open the screen gets a guest session, not the previous customer's. 5. Run `node v2/scripts/identity-conformance.mjs --host --json` for whichever native platform your build targets — the WebView underneath is still iOS or Android, and the checker grades that layer. ### Why one Dart file instead of separate iOS and Android code? The `BusymateAINative` channel name is recognized by `webview_flutter` on both platforms' underlying WebViews, so registering it once covers the same bridge shape on either OS. ### What is the "compatibility twin" the sample also registers? An older channel name kept for apps that shipped before this vocabulary existed; the sample registers both so neither generation of the assistant's probe goes unanswered. ### Does my Flutter app need cookies configured for this to work? No. Identity arrives from your own channel handler on every ask, so no cookie or WebView storage setting has any bearing on whether a customer is recognized. ### Can I ship the chat before my API can mint identity yet? Yes. Without a signed answer the assistant runs anonymously; wire the four obligations in whenever your endpoint is ready, and the channel starts answering on the next open. ## Next - **[Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors)** — the four obligations this channel answers. - **[In-app AI support for iOS and Android](https://busymate.ai/docs/guides/mobile-in-app-support)** — the same wire messages from the native side. - **[Fix a signed-in customer who shows as a guest](https://busymate.ai/docs/guides/identity-troubleshooting)** — symptom-first fixes when a cell fails. --- --- title: "Sign identity tokens from your backend" description: "Copy the mint endpoint for Node, PHP, Python or Go, build the identical ES256 claim set, publish your JWKS, and prove it with the conformance checker." last_updated: "2026-09-26T20:38:55+03:00" --- # Sign identity tokens from your backend Source: https://busymate.ai/docs/guides/identity-backend-signing Last modified: 2026-09-26T20:38:55+03:00 AI Assistant needs exactly one endpoint on your API to recognize a signed-in customer: one that requires your own session and returns a freshly signed proof. Four ready-to-copy samples build the identical claim set in Node, PHP, Python and Go, so the language you already run is never a reason to hand-roll a JWT. ## 1. Pick your language, copy one file Node (zero dependencies): `https://busymate.ai/sdk/v1/kit/backend/node/mint.mjs`. PHP (zero dependencies): `https://busymate.ai/sdk/v1/kit/backend/php/mint.php`. Python (`cryptography`): `https://busymate.ai/sdk/v1/kit/backend/python/mint.py`. Go (standard library): `https://busymate.ai/sdk/v1/kit/backend/go/mint.go`. Each builds the same response from the same claims; only the syntax differs. ## 2. The one shape every language builds The Node sample shows the reference shape — the others build the identical claims in their own syntax: ```typescript import { SignJWT, importJWK } from "jose"; // POST https://YOUR-PRODUCT-DOMAIN/api/bmai/identity — requires YOUR OWN logged-in product session. app.post("/api/bmai/identity", requireSession, async (req, res) => { // Fresh on EVERY mint. Never persist the launch token/nonce in localStorage, // sessionStorage, cookies, React state, or module state: every assistant // launch consumes this pair exactly once. const nonce = typeof req.body?.nonce === "string" ? req.body.nonce : ""; if (!/^[A-Za-z0-9_-]{32,200}$/.test(nonce)) return res.status(400).json({ error: "invalid_nonce" }); const key = await importJWK(JSON.parse(process.env.AI_LAUNCH_PRIVATE_JWK), "ES256"); const token = await new SignJWT({ tenant_id: process.env.BMAI_TENANT_ID, // the tenant id shown in Console → Identity nonce, // equals the sibling field below name: req.user.displayName, // optional low-sensitivity display claim }) .setProtectedHeader({ alg: "ES256", kid: process.env.AI_LAUNCH_KEY_ID }) .setIssuer(process.env.BMAI_ISSUER) // the Issuer you registered in Console → Identity .setAudience("busymate-ai") .setSubject(req.user.id) // IMMUTABLE internal account id; never email/phone/session id .setJti(crypto.randomUUID()) // one-time (replay-protected) .setIssuedAt() .setExpirationTime("120s") // <= registered max age (120s) .sign(key); res.set("Cache-Control", "no-store"); res.status(201).json({ token, nonce, expiresIn: 120 }); }); ``` See [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors) for the full claim table, the never-put-in-a-token list, and the key-rotation order. The short version: `iss`, `aud`, your workspace claim and `sub` (your unchanging internal id, never an email or session id) are required on every mint; `nonce` is echoed back verbatim; `jti` is one-time; `exp - iat` is at most 120 seconds. ## 3. The one thing a hand-rolled ES256 JWT gets wrong All four samples do the ES256 **DER → raw `r‖s`** signature conversion explicitly. Skip it and a library that expects the raw form refuses every token your endpoint mints, and the refusal reads exactly like a wrong key rather than a wrong encoding — which is why every sample spells the conversion out instead of trusting a library default. ## 4. Publish the key, never the endpoint's private half Publish the **public** key at `/.well-known/jwks.json` with a `kid` and a short cache lifetime. If the object about to be served carries a `d` field, stop: that is the private scalar, and none of the four samples will print it for you. Rotate by publishing the new key beside the old one, waiting past your cache lifetime, switching which `kid` signs, waiting one more token lifetime, then removing the old key — never the reverse order. ## 5. Prove the endpoint, not just the file A copied file with a wrong claim, a missing `Cache-Control: no-store`, or a clock five minutes off from real time all look identical from the outside: a customer stuck as a guest. Run the CLI (`node v2/scripts/identity-conformance.mjs --host --json`) against the live endpoint before wiring any platform to it — it checks the response your language actually produces, not the sample you started from. ## 6. Let the diagnostics sign in as a test account Your mate can run its full diagnostics as one of your own test accounts (Console → Connections → Test account, or `verify_tenant_private_tools`). The endpoint above cannot serve that: it requires the customer's own session, and a check is a server with none. You publish nothing secret for this and share no key: the check presents a short-lived signed assertion, you verify it against our published keys with any standard JOSE library, and you answer with the same launch token the endpoint already mints. The check POSTs to the same endpoint with an `Authorization: Bearer` assertion instead of a session: | | | |---|---| | Format | JWT (RFC 7519), signed **ES256**, `kid` in the header | | Our keys | `https://busymate.ai/.well-known/jwks.json` | | `iss` | `https://busymate.ai` | | `aud` | **your identity provider's issuer origin**, so an assertion minted for you is inert everywhere else | | `sub` | the **login** of the test account registered in your workspace | | `purpose` | `test-account-sign-in`, valid nowhere else | | `tenant_id` | your registered workspace claim value | | `nonce` | the nonce in the body; echo it back | | `jti`, `iat`, `exp` | one-time id; at most **60 seconds** old | **The one rule that matters:** a valid assertion means the platform is asking on behalf of the account named in `sub`. It does not mean "mint for whoever `sub` says". Check `sub` against your own list of review logins and refuse anything else, or you have handed over the ability to impersonate your customers. ```typescript // Add this ONE branch to the endpoint from step 3. Everything else there // stays exactly as it is: your customers' browsers keep using the session arm. import { createRemoteJWKSet, jwtVerify } from "jose"; // Our published keys. Cache the key set — do not fetch it per request. const BUSYMATE_JWKS = createRemoteJWKSet( new URL("https://busymate.ai/.well-known/jwks.json"), ); // The review logins YOUR product recognises. THIS LIST IS THE SECURITY BOUNDARY: // a valid assertion means "busymate.ai is asking on behalf of ", never // "mint for whoever says". Anything not in here must be refused, or you // have handed us the ability to impersonate your customers. const REVIEW_LOGINS = new Set(["bmaireview@your-assistant.example"]); app.post("/api/bmai/identity", async (req, res) => { const auth = req.headers.authorization ?? ""; if (auth.startsWith("Bearer ")) { let claims; try { ({ payload: claims } = await jwtVerify(auth.slice(7), BUSYMATE_JWKS, { issuer: "https://busymate.ai", // YOUR provider's issuer origin. An assertion minted for someone else // fails here, which is what audience binding is for. audience: "https://YOUR-PRODUCT-DOMAIN", algorithms: ["ES256"], maxTokenAge: "60s", })); } catch { return res.status(401).json({ signedIn: false, reason: "invalid_assertion" }); } // Single-purpose: this token is valid for nothing else, and nothing else // is valid here. if (claims.purpose !== "test-account-sign-in") { return res.status(403).json({ signedIn: false, reason: "wrong_purpose" }); } if (typeof claims.sub !== "string" || !REVIEW_LOGINS.has(claims.sub)) { return res.status(403).json({ signedIn: false, reason: "not_a_review_account" }); } const user = await findUserByLogin(claims.sub); // YOUR lookup if (!user) { return res.status(403).json({ signedIn: false, reason: "not_a_review_account" }); } // The SAME mint your browser arm already calls, with the SAME nonce rules. return res.json(await mintLaunchToken(user, String(claims.nonce ?? req.body.nonce))); } // ── unchanged: your customers' own session ────────────────────────────── const user = await currentUser(req); if (!user) return res.status(401).json({ signedIn: false }); return res.json(await mintLaunchToken(user, req.body.nonce)); }); ``` Before calling it done, check that a request with no `Authorization` behaves exactly as before, and that a token signed with your own key, an assertion for another `aud`, one naming a real customer who is not a review login, and one older than 60 seconds are all **refused**. A valid assertion returns the same `{ token, nonce, expiresIn }` your browser arm returns, and Console → Connections → Test account → **Run full check** reports `sign_in` green. If our JWKS answers `404`, this arm is not available yet. Already expose sign-in as a tool? Then you need none of this: the check calls your own `sign_in` on a connected server with the account's login and password, or its **code** if you registered the account as *One-time code (fixed review code)*. Either arm is enough, and the Console names the one your workspace is missing. ## Verify 1. `POST` your endpoint your own session cookie and a fresh nonce; it returns `201` with `{ token, nonce, expiresIn }` and `Cache-Control: no-store`. 2. The same request signed out, or with no session, is refused — never a token for nobody. 3. Two calls in a row return two different `jti` values and two different signatures, never a cached pair. 4. Run the CLI against the endpoint; every claim, TTL, nonce-echo and clock-skew cell passes before any platform guide above is wired to it. ### Why does the reference sample show Node when my API is in a different language? The claim set and response shape are identical across all four; Node is shown once as the shape, and the PHP, Python and Go files build the same result in their own syntax. ### What happens if I skip the DER-to-raw conversion? Most ES256 verifiers, including the one this platform runs, refuse the token outright. It reads as a rejected key, not as an encoding mistake, which is why the samples handle it for you. ### Can I sign with more than one algorithm? Yes, if you register more than one in your provider setup; every mint must use an algorithm in that registered list, checked against your published JWKS. ### Do I need a separate signing key per platform I integrate? No. One key pair, one JWKS entry, and every platform's guide above calls the same mint endpoint your key signs. ## Next - **[Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors)** — the full claim contract and the key-rotation order. - **[Fix a signed-in customer who shows as a guest](https://busymate.ai/docs/guides/identity-troubleshooting)** — symptom-first fixes when a cell fails. - **[In-app AI support for iOS and Android](https://busymate.ai/docs/guides/mobile-in-app-support)** — the platforms that call this endpoint from a native bridge. --- --- title: "Native identity bridge compatibility" description: "Understand the frozen identity v2 contract, existing app compatibility and when native capabilities require an app release." last_updated: "2026-10-07T12:31:33+03:00" --- # Native identity bridge compatibility Source: https://busymate.ai/docs/guides/app-bridge-v2 Last modified: 2026-10-07T12:31:33+03:00 AI Assistant runs inside a mobile app through one small file: the app bridge. Kit v2 freezes that identity bridge. Hosted chat improvements arrive from our side; adding a native OS capability, such as microphone permission, needs your app's own release. For a new iOS or Android app, install the [official iOS SDK](https://busymate.ai/docs/guides/ios-sdk) or [official Android SDK](https://busymate.ai/docs/guides/android-sdk). This page documents the underlying frozen identity contract and compatibility integrations. SDK distribution versions and identity protocol versions are separate. Hosted updates do not replace app releases for new SDK code or OS permissions. Existing versioned identity files remain available for compatibility. The full message contract is published beside the files, at `https://busymate.ai/sdk/v2/2.0.0/CONTRACT.md`. ## 1. Know what the bridge can do - `hello` reports the bridge version, the platform, the WebView version, your app build and the assistant it was installed for. - `state` says whether someone is signed in, with a scrambled account key. Your user id never leaves the device. - `mint` asks your backend for a short-lived sign-in token. Your code gets what the chat sent (a `nonce` to sign) plus `assistant` and `origin`, which the bridge sets itself so a page can never choose them. - `open` opens an `https` link in the system browser. Any other link is refused. - `action` hands a named action, such as `close`, to your app. Anything you do not handle is ignored. The bridge also tells the chat when your app returns to the foreground, and when it reloaded the chat after the system stopped the web view. Only your own chat can reach it: exactly `https://.busymate.ai` and the exact `https` origins you list. There are no wildcards, so another company's chat, a shared artifact or any other busymate.ai page opened inside your app is refused, and your backend is never asked. List only hosts that serve the chat itself. ## 2. Install it on Android Copy `BusymateBridge.kt` from the address above into your project and check its SHA-256 against `SHA256SUMS` in the same folder. Remove the kit v1 bridge (`BusymateAIWebViewBridge`, the `BusymateAINative` and `SupportChatNative` JavaScript interfaces) and any copied `native-identity.js` or `wire.js`. Then install the bridge before the first `loadUrl`, and forward renderer crashes so the chat recovers instead of the app closing: ```kotlin // Copy https://busymate.ai/sdk/v2/2.0.0/android/BusymateBridge.kt (check SHA256SUMS). // Needs androidx.webkit:webkit >= 1.8 and androidx.lifecycle:lifecycle-process. BusymateBridge.install(webView, BusymateBridge.Config( assistant = "your-assistant", origins = emptyList(), account = { session.userIdOrNull }, // null when signed out mint = { request, done -> // YOUR backend signs; never a key in the app backend.mintBusymate(request["nonce"] as String) { token, nonce -> done(if (token != null) BusymateBridge.MintResult.Token(token, nonce) else BusymateBridge.MintResult.Failed) } }, )) // In your WebViewClient: the chat recovers instead of the app closing. override fun onRenderProcessGone(view: WebView, detail: RenderProcessGoneDetail) = BusymateBridge.onRenderProcessGone(view, detail) // Optional, only faster: after sign-in, sign-out or an account switch. BusymateBridge.accountChanged() ``` ## 3. Install it on iOS Copy `BusymateBridge.swift` (iOS 14 or later) and check its SHA-256. Remove the old `BusymateAI` and `SupportChat` message handlers. Install the bridge before the first `load`, and forward web content crashes from your navigation delegate: ```swift // Copy https://busymate.ai/sdk/v2/2.0.0/ios/BusymateBridge.swift (iOS 14+, check SHA256SUMS). BusymateBridge.install(on: webView, config: .init( assistant: "your-assistant", origins: [], account: { Auth.shared.userId }, // nil when signed out mint: { request in // YOUR backend signs; never a key in the app guard let pair = try await Backend.mintBusymate(nonce: request.nonce) else { return nil } return .init(token: pair.token, nonce: pair.nonce) })) // In your WKNavigationDelegate: the chat reloads and restores itself. func webViewWebContentProcessDidTerminate(_ webView: WKWebView) { BusymateBridge.contentProcessDidTerminate(webView) } // Optional, only faster: after sign-in, sign-out or an account switch. BusymateBridge.accountChanged() ``` If your app sets `WKAppBoundDomains`, add the assistant's domains to that list, or the bridge cannot be reached. ## 4. Configure your website Keep the embed script. Tell it who is signed in on your website and how to get a fresh token from your backend, and delete any page script that talked to the app directly. `account()` is your website's own session: inside your app's WebView it returns `null`, and the chat then asks the app itself, so one web bundle serves both: ```html ``` React Native, Flutter and Electron apps use the matching file from the same folder: `react-native/busymateBridge.js` with `core/busymateBridgeCore.js`, `flutter/busymate_bridge.dart`, or `electron/preload.js` with `electron/main.js`. Each takes the same `account` and `mint` callbacks. For these, load the hosted chat page directly rather than a page that embeds it. ## 5. Keep your backend as it is Your signer keeps producing ES256 tokens with `nonce` and `jti` that expire within 120 seconds. In the app it signs the `nonce` the bridge passes; on your website `getIdentity` receives `{ nonce }` as well, and you may sign that one or your own. See [Sign identity tokens from your backend](https://busymate.ai/docs/guides/identity-backend-signing). The identity bridge itself requests no OS permission. Enabling the microphone adapter requires your microphone declaration and OS authorization. The chat can reach only your own sign-in token, an `https` link and close. Mention chat data shared with AI Assistant in your privacy label; the AI disclosure and the report control are shown inside the chat. Voice: use the [complete iOS/Android microphone integration guide](https://busymate.ai/sdk/microphone/1.0.0/README.md): setup, tap-triggered OS permission, media callbacks, cleanup and device checks. ## Verify 1. Signed out, open the chat: a guest chat that answers. 2. Sign in inside your app: the same conversation shows your customer's name, with no reload. 3. Put the app in the background for a minute, then bring it back: the same conversation, and no "That chat had ended". 4. Switch accounts: the first person's conversation disappears and the second person is recognized. 5. Sign out: the chat goes back to a guest. Every session records which bridge version it came through and whether the customer was recognized, so we can tell you how each build of your app is doing without access to your code. ## Test your integration The official SDK repositories include buildable example apps, configuration tests and build instructions. Build checks do not substitute for OS permission tests on physical devices. Run the verification steps above and each platform's microphone checklist with your actual backend, workspace and supported OS versions. ### Do I have to update again later? The identity file stays frozen. Optional native capabilities need your app's release; existing builds keep working. ### What happens to app builds that still ship the old bridge? Existing versioned bridge files remain compatibility paths. Test your supported builds against your workspace; guest access depends on your workspace settings. ### Is my user id sent to AI Assistant? No. The bridge sends a scrambled key made from your app id and the user id, only so the chat can tell that the person changed. The token your backend signs carries the id you choose to put in it. --- --- title: "Fix a signed-in customer who shows as a guest" description: "Match your exact symptom to its cause and the conformance-checker cell that proves it, including the WebView-loads-your-own-page case." last_updated: "2026-10-07T12:28:07+03:00" --- # Fix a signed-in customer who shows as a guest Source: https://busymate.ai/docs/guides/identity-troubleshooting Last modified: 2026-10-07T12:28:07+03:00 AI Assistant shows almost the same symptom for every identity mistake: a customer you know is signed in shows up in the chat as a guest. This page starts from what you see, names the layer that actually broke, and identifies the exact cell in the conformance checker that will confirm the fix — instead of guessing across your website, your app and your backend at once. ## 1. Match your symptom to a cause | You see | The likely cause | What proves it | |---|---|---| | Signed in on the site, the chat still offers Sign in | Your bridge answered nothing on the first ask — often because it registered after the page had already loaded and asked once | The [Identity check](https://busymate.ai/developers/identity-check)'s first-launch cell | | The first message is identified, every one after is a guest | Your app's WebView loads your OWN page rather than the assistant directly, and that page only answers the very first ask | See "Your app's WebView loads your own page" below | | The customer signs out; the chat still shows their name | The sign-out call was never wired, so the previous session survives until the view is destroyed | The checker's logout cell | | It works on one native platform, fails on the other | The two bridges answer at the wire level differently — one can deliver a JSON string where the other delivers a real object, and a string with no `type` field is silently dropped | Run the checker against each platform on its own | | A launch that worked a moment ago is refused as expired, or as not-yet-valid | Your server's clock has drifted past the verifier's tolerance | The CLI's clock-skew cell reads your `iat` against server time | | A sign-in works once, then every later ask is refused | A launch proof is single-use; something cached the pair and answered a second ask with it | The checker's token-expiry cell mints twice and expects two different answers | ## 2. When your app's WebView loads a page you built The shape that hides an otherwise-correct integration: your app's WebView does not load the assistant directly — it loads a page you built, and that page embeds the assistant. The assistant then asks its parent, which is your own page, and your page has no session of its own; the customer is signed in *natively*, one layer further out. A token on the launch URL answers the first ask and nothing after it, so a resume, a reconnect, an expiry and a restart each quietly fall back to no session there. For an existing kit v1 integration, the fix has two halves, and both are required: keep the native bridge from [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors) installed in the app, and give your own page the small asker that forwards later questions to it — `https://busymate.ai/sdk/v1/kit/web/native-identity.js`. Installing only the bridge leaves it correct and unreachable in that legacy setup. For a new native integration, follow the [official SDK setup](https://busymate.ai/docs/guides/mobile-in-app-support); do not copy the v1 asker into an SDK v2 integration. ## 3. Read the exact missing step, do not guess it Two checks, one set of rules. The [Identity check](https://busymate.ai/developers/identity-check) runs the lifecycle half against a page of yours and grades what comes back: a token that was not fresh, a sign-out that changed nothing, a bridge that answered late. The CLI — `node v2/scripts/identity-conformance.mjs --host --json` — runs the half a browser cannot reach: JWKS reachability, key and algorithm agreement, claim shape, clock skew, and the CORS rules of your own endpoint. Each prints pass, fail, or could-not-observe per cell, together with the step it is missing, rather than a bare "identity broken". ## Verify 1. Run the browser check and the CLI against the same host; note any cell that fails or comes back unobserved. 2. Fix the named step, not the whole integration — one obligation from [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors) is usually the entire gap. 3. Re-run both. A clean pass on every cell, not a green first screen, is what "fixed" means here. 4. In Console → Identity health, the same picture appears per platform — the fastest way to tell whether the fix reached every customer, not only the one browser you tested from. ### Do I need to know which layer is broken before I run the checker? No. Point it at your host and it names the layer itself — a page, a bridge, or your signing endpoint — instead of asking you to guess between them. ### What if the CLI cannot reach my identity endpoint at all? It reports that cell as could-not-observe, not as a pass. An unreachable endpoint is never counted as working; fix reachability, then re-run. ### The browser check and the CLI disagree — which one is right? Neither overrides the other. The browser proves the lifecycle a real page produces; the CLI proves what a browser cannot see, your endpoint's own response. A real integration passes both. ### Does either check keep or send on a real token? No. Both record shapes — whether two mints differ, whether a claim is present — never the token, the nonce, or a claim's value. ### My symptom is not on this page — where do I look next? Start at [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors)'s four obligations; nearly every guest-when-signed-in report traces back to one of them. ## Next - **[Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors)** — the contract every platform below implements. - **[Sign identity tokens from your backend](https://busymate.ai/docs/guides/identity-backend-signing)** — the endpoint every check above talks to. - **[In-app AI support for iOS and Android](https://busymate.ai/docs/guides/mobile-in-app-support)** — the native bridge this page's WebView case depends on. --- --- title: "Follow a visitor across workspaces" description: "Platform operators: open one visitor's route across every workspace, read each stop's honest identity state, and erase the visitor on request." last_updated: "2026-09-28T08:16:01+03:00" --- # Follow a visitor across workspaces Source: https://busymate.ai/docs/guides/visitor-journey Last modified: 2026-09-28T08:16:01+03:00 A platform operator can follow one visitor across every workspace they reached on AI Assistant — as a route with stops: where they arrived first, where they came back, whether they ever signed in there, and how much they talked. It is for the platform team only; a workspace operator sees a visitor's history inside their own workspace and nothing beyond it. ## Two visitor ids, two scopes - **Workspace visitor id (`dv1_…`)** — derived per workspace from one first-party browser token. It groups a returning browser's sessions inside ONE workspace and powers the Inbox's "Returning visitor" badge and "This visitor" filter. Two workspaces never share it. - **Platform visitor id (`pv1_…`)** — derived from the same token under a platform-only secret, with no workspace in the derivation, so the same browser gets the same id everywhere. It exists only in the platform's own graph and is readable only by platform operators. No canvas or device fingerprinting is involved: the only signal is the opaque token the widget keeps in the browser. ## 1. Open a journey - **From the Inbox** — on a returning visitor's conversation, the contact panel's badge offers **Cross-workspace journey →** to platform staff. It looks the workspace visitor id up in the platform graph and opens the route. - **From Console → Platform → Visitors** — paste a `pv1_…` or `dv1_…` id into the search field, or pick a row of the recent-touchpoints feed. - **From your AI tools (MCP)** — `get_visitor_journey` with `pv1_id`, or `list_visitor_touchpoints` with `dv1_visitor_id` for the reverse lookup. ## 2. Read the route Each stop is one workspace, in order of first visit, and shows: | On the stop | Meaning | |---|---| | The workspace's mark | Its real icon, or a monogram when none is published | | First seen → last seen | The hop's arrival and most recent launch | | Sessions · conversations | Counted at read time from that workspace's own tables — the graph stores no conversation data | | `returned ×N` | The visitor came back to this workspace N times | | Identity | One of four honest states, below | Identity per stop is never merged across workspaces: - **Linked to an account** — the workspace's own resolution is unambiguous; the subject is shown. - **Anonymous** — recognised by the browser id only; never signed in there. - **Seen with multiple accounts** — that browser was used with more than one account in this workspace. No subject is claimed; the count of accounts is shown instead. - **No visitor id recorded** — the hop predates durable visitor ids. Tap a stop for its touchpoint detail: entry page, referrer, sessions, conversations, the workspace visitor id, and a link to the workspace's Workspace 360 page. ## 3. Retention The platform graph keeps a touchpoint for a fixed window after the visitor was last seen there (the window is printed on the journey, e.g. "90 days") and prunes it on its own schedule, independent of any workspace's settings. A visitor with no stops left is dropped from the graph. ## 4. Erase a visitor (GDPR) **Purge this visitor everywhere** deletes the platform record — the id and every hop — after you confirm the exact call. Workspace-owned data (sessions, conversations, the workspace's own visitor grouping) is not touched; redact those in the workspace. The erasure is written to the platform audit log as a digest of the id, never the id itself. Redacting a contact inside a workspace also purges that person's platform record. From your AI tools: `purge_platform_visitor_identity` with `pv1_id` and `confirm: true`. ## Who can see what | Reader | Sees | |---|---| | Workspace operator | That workspace's visitor history only (Inbox badge, filter, previous conversations) | | Platform operator | The cross-workspace route, the touchpoint feed, the purge | Every layer enforces the same rule: the platform tables have no workspace-scoped read policy, the functions re-check the operator role on every call, the MCP tools serve only platform operators, and the Console section exists only in the platform navigation. None of the calls accept a workspace parameter. ## Verify 1. Open a returning visitor's conversation in the Inbox as a platform operator: the badge offers **Cross-workspace journey →** and opens the route. 2. Check one stop against that workspace's own Inbox: the sessions and conversations match, and the identity state is the one the workspace shows. 3. Sign in as a workspace operator instead: no journey link appears, and the Platform section is not in the navigation. ### Can a workspace see where its visitors went next? No. A workspace operator sees that workspace's own visitor history only. The cross-workspace route exists only for platform operators, and no call accepts a workspace parameter. ### Is the visitor fingerprinted? No. The only signal is the opaque first-party token the widget keeps in the browser. There is no canvas or device fingerprinting. ### What does the purge remove? The platform record: the platform visitor id and every hop. Data a workspace owns, such as its sessions and conversations, stays until that workspace redacts it. ## Reference - Console: `/console/platform/visitors?pv1=` · `?dv1=` · `&stop=` - MCP: `get_visitor_journey` · `list_visitor_touchpoints` · `purge_platform_visitor_identity` - Related: [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors) --- --- title: "See which website tries became customers" description: "Platform operators: read every website try with its instruments, the six-stage funnel, and an honest outcome: converted, probable, or left." last_updated: "2026-09-28T08:16:01+03:00" --- # See which website tries became customers Source: https://busymate.ai/docs/guides/preview-funnel Last modified: 2026-09-28T08:16:01+03:00 Every time someone previews your mate on their own website (the hero quick start, `/try/`), AI Assistant keeps the try — and now answers the two questions a platform operator asks about it: **did this try become a customer, and if not, where did it leave?** Console → Platform → Previews shows every try with its instruments, a conversion funnel for the window, and one honest outcome line per try. Platform operators only; a workspace never sees another workspace's tries. ## 1. Read the funnel The widget under the timeline is a sequence of six bars for the active range (last 7 / 30 / 90 days, or the whole retained window): | Stage | What proves it | |---|---| | **Tried** | The preview session exists | | **Reached a step** | The "Keep this assistant" flow reached at least one quick-start step | | **Signed up** | A platform account is known for the try — the scan-id stamp of a signed-in landing, or a signed-in session owner | | **Created workspace** | A workspace was created or joined after the try began, or the scan stamped one | | **Published** | That workspace's runtime was published at least once | | **Subscribed** | The account holds an active or trialing subscription, or paid an invoice | Each bar is labelled with its count and the share of the previous bar; the table under the bars repeats the numbers, and the per-site table lists tries, converted, probable and the conversion rate per host. A bar the platform could not prove (the account facts were unreadable) is drawn outlined with a `?` — never a zero. ## 2. Read a try Open **Every try** to list every try across hosts, newest first, or pick a site and then a session. Each row and the detail pane carry the same instruments: - **Outcome** — `Converted → (day N)`, `Probably → `, or `Left at: · last seen `. - **Stages** — the six chips, reached or not; an unproven chip says so. - **Quick-start steps** — `step N of 6` with the seconds each step took, and the verdict when a step failed. - **Identity** — the same badge model as the Inbox: `no visitor id`, `anonymous`, `returning · N earlier tries`, `linked to `, or `seen with N accounts` (a shared browser is never assigned to one account). - **Account** — the email, when it signed up, whether it existed before the try, the subscription status. - **Client** — country, device class, OS and browser, referrer, entry URL and the UTM campaign. No IP is stored or shown. - **AI readiness** — the cached scorecard for the host (checks passed, the missing ones) and how many pages the scan read. - **Links** — open the try (`/try/`), open the visitor's cross-workspace journey, open the workspace. - **Evidence** — the named facts the verdict came from (`scan_stamp`, `session_owner`, `domain_owner`, `sibling_session`, `runtime_receipt`, `subscription` …). ## 3. Converted, probable, or left The verdict is only as strong as the link: - **Converted** — unambiguous. The try's scan id was stamped by a signed-in landing, or the session's own signed-in owner created or joined the workspace. - **Probable** — a plausible but unproven link: the workspace merely owns the tried domain, the conversion was stamped on a sibling try of the same browser, or the account joined a workspace after the try without the scan stamp. It is shown as probable and counted separately; it is never called converted. - **Left** — no workspace is linked; the row says the furthest stage and when the visitor was last seen. ## 4. Filter, export, act - **Filters** — minimum stage reached, outcome (converted / probable / left), site, search, date range. The `Subscribed` stage filter narrows to tries with a workspace and then checks subscriptions. - **Export CSV** — every try in the current filter with all instruments as columns (bounded to 200 rows per export). - **Realtime** — a new try, a new quick-start step or a conversion updates the page on its own; nothing polls. - **Actions** — mark a lead, add a note, copy the invite link (unchanged from the Previews explorer). ## From your AI tools (MCP) - `list_platform_previews` — every try with instruments; `host`, `q`, `range_days`, `stage`, `outcome`, `limit`, `offset`. - `get_platform_preview` — one try's full instrument set by `session_id`. - `get_platform_preview_funnel` — the rollup for `days` (optionally one `host`). All three are platform-operator only and refuse a workspace caller before anything runs. The account facts come from `get_platform_preview_conversion_facts`, which re-checks the operator role on every call. ## Verify 1. Run a preview on a test site from the hero quick start, then open **Console → Platform → Previews**: the try appears on its own, with its quick-start steps. 2. Sign up from that try and create a workspace: the row turns to **Converted** with the evidence `scan_stamp` or `session_owner`. 3. Filter the outcome to **left**: every row names its furthest stage and when the visitor was last seen. ### Why is a try marked probable instead of converted? The link is plausible but not proven: for example the workspace only owns the tried domain, or the conversion was stamped on another try from the same browser. Probable is counted apart and never called converted. ### Why is a funnel bar outlined with a question mark? The account facts behind that stage could not be read, so the stage is unproven. It is never drawn as zero. ### Can a workspace see these tries? No. The page, the export and the MCP tools are for platform operators only and refuse a workspace caller before anything runs. ## Reference - Console: `/console/platform/previews?view=tries` · `&stage=` · `&outcome=converted|probable|left` · `&site=` · `&session=` - Related: [Follow a visitor across workspaces](https://busymate.ai/docs/guides/visitor-journey) · [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors) --- --- title: "Share pages the assistant makes" description: "Ask your mate for a report, diagram or how-to and get a self-contained page at your address; choose who can open it, comment inline, manage it from chat." last_updated: "2026-09-12T01:26:39+03:00" --- # Share pages the assistant makes Source: https://busymate.ai/docs/guides/artifacts Last modified: 2026-09-12T01:26:39+03:00 An artifact in AI Assistant is one self-contained web page your mate builds on request — a report, a diagram, a how-to — served at your assistant's address under `/artifact/`. You decide who may open it (only you, your team, or anyone with the link), comment on it inline, send a thread back to your mate for a fix, and manage everything from your AI tools (MCP). ## What an artifact is - One web page with everything inline. External scripts, stylesheets and fetches are rejected when it publishes, so a page never breaks because a third party changed. - Addressed by a short lowercase name (slug) that is unique inside your workspace. Platform pages live at `busymate.ai/artifact/`; your workspace's live at your address. - Owned by whoever created it, inside your workspace. Older addresses that served pages redirect to the current one. ## 1. Create - **In chat** — ask your mate for the page you want. It builds the page and publishes it at your address. - **From your AI tools** — `create_artifact` with `slug`, `title`, `html`, `description`, `tags` and `visibility`. The call succeeded only if the response says `created: true`; anything else is an error to read, not a page to assume. ## 2. Set visibility | Who can open it | Who | Listed | |---|---|---| | Only you (default) | You | No | | Your team | Signed-in members of your workspace | No | | Anyone with the link | Public | In the gallery and the sitemap | Change it any time in [Console → Artifacts](https://busymate.ai/console/artifacts) or with `set_artifact_visibility`. A private page never leaks a title or a share card, even to a stale scraper. ## 3. Comment and iterate Open the artifact and select text, an element or a region to start a thread anchored to it. **Send to your mate** activates the thread for the AI: Your mate replies in the thread and applies the change as one `update_artifact`. Resolve the thread when the page is right; reopen it if it is not. ## 4. Meet the quality bar Every artifact your mate publishes is held to the same bar: - An in-page language switcher covering all 14 locales, with right-to-left layout for Arabic. - Diagrams as inline SVG that follows light and dark themes; never an external image. - No horizontal scroll at 390 px wide; contrast at WCAG AA. - Concise: illustrations and numbered steps over walls of text. ## Console and AI tools The Console lists, previews, retitles and re-scopes pages. Your AI tools (MCP) do the same: `list_artifacts`, `get_artifact`, `update_artifact`, `set_artifact_visibility`, `delete_artifact`, plus `list_artifact_comments`, `add_artifact_comment`, `reply_artifact_comment` and `resolve_artifact_comment`. Connect a client once: ```bash claude mcp add --transport http busymate-ai https://busymate.ai/mcp ``` ## Examples Public artifacts on the platform host: the [Inbox proof of 2026-09-02](https://busymate.ai/artifact/busymate-ai-inbox-proof-2026-09-02), the [DevTools integration](https://busymate.ai/artifact/bmdev-integration) and [Build your MCP server](https://busymate.ai/artifact/build-your-mcp-server). The gallery at [/artifact](https://busymate.ai/artifact) lists every public one. ## Verify 1. The page renders in light and dark themes with no sideways scroll on a phone. 2. Switching it to "anyone with the link" adds it to the gallery and the sitemap; switching back removes it. 3. A comment sent to your mate gets a reply and one update; resolving the thread closes it. 4. The slug URL opens at your address. ### Who can see a private page? Only you. "Your team" opens it to your workspace's signed-in members; "anyone with the link" makes it public and listed. ### Can a page load external scripts or styles? No. Publishing rejects external resources; everything is inline so the page cannot break later. ### How do I fix a page your mate built? Comment on the exact spot and send the thread to your mate. It replies in the thread and applies one update. ### Where does it live? At your address under `/artifact/`. Platform-owned pages live at `busymate.ai/artifact/`. ## Next - **[Conversation-derived product intelligence](https://busymate.ai/solutions/product-intelligence)** — reports your mate can publish as artifacts. - **[Managing from chat](https://busymate.ai/docs/managing-from-chat)** — the same management tools, conversationally. - **[The gallery](https://busymate.ai/artifact)** — public artifacts, live. --- --- title: "Let the assistant use your page" description: "Publish what your page already does — look up an order, book a slot, start a return — as actions the assistant runs, asking first before changing anything." last_updated: "2026-09-12T04:18:56+03:00" --- # Let the assistant use your page Source: https://busymate.ai/docs/guides/page-tools Last modified: 2026-09-12T04:18:56+03:00 AI Assistant already knows what your business says. **Page tools** let your assistant do what your *page* does — check an order, reserve a slot, begin a return — by calling functions your site already has, in the visitor's own session. Write each action once: it reaches every visitor, over WebMCP where the browser supports it and the assistant's own bridge elsewhere, apps included. Diagram: Your page registers actions once; the assistant reaches them via WebMCP in the browser, or its own bridge elsewhere Your assistant is already on the page, from the embed script you added at setup. Page tools ride that same script — nothing extra to install. ## 1. Decide what the page can do Pick three to seven things a visitor does here, noting whether each only **reads** or **changes** something. | Reads | Changes | |---|---| | Look up an order, check stock, show today's slots | Book, pay, cancel, submit a form, change an address | Name each with a verb — `check_order_status`, `start_return` — and describe it as you would to a new colleague; that description is what the assistant reads to decide when to use it. ## 2. Register them One call, where those actions live: ```javascript // One call, both transports: the browser's own WebMCP where it exists, // and the assistant's bridge everywhere else (Safari, Firefox, app WebViews). BusymateAI.registerPageTools([ { name: "check_order_status", description: "Look up an order by its number and say where it is.", inputSchema: { type: "object", properties: { orderNumber: { type: "string", description: "The order number, as printed on the receipt" } }, required: ["orderNumber"], additionalProperties: false, }, annotations: { readOnlyHint: true }, execute: async ({ orderNumber }) => (await fetch(`/api/orders/${orderNumber}`)).json(), }, ]); ``` `execute` runs **in your page**, on the visitor's own session — the assistant never receives your cookies, tokens or markup, only what you return. Mark every read with `annotations: { readOnlyHint: true }`. Anything unmarked counts as a change: the assistant shows the exact call and waits for a yes, with no way off. Give every argument in `inputSchema.properties` a one-line `description` — the assistant reads it to decide what to pass, and one with none is a guess. Each tool validates independently: a real mistake (a bad name, no `execute`) is logged with the exact field and excluded while the rest of the call registers; a missing description registers with a console warning naming it. With a bundler, import `registerPageTools` from `/sdk/v1/webmcp/index.js` on your assistant's address instead of the global. ## 3. Forms you already have If the action is a real `
`, annotate it and register every annotated form with one call to `registerDeclarativeForms()` — no other JavaScript: ```html
``` The form keeps working as before. Submitting changes something, so it asks first — unless you add `data-tool-readonly` to a form that only filters what is on screen. ## 4. Ask with a form, not a list When an action needs details the visitor has not given, return a **form card** rather than asking in prose — and register `sign_in` when something needs their account, so they never leave the conversation to log in. [Forms and sign-in inside the chat](https://busymate.ai/docs/guides/form-cards) has both contracts and a copy-paste example. ## 5. Tools that come and go A tool the visitor cannot use should not be offered. Pass `{ signal }` from an `AbortController` and `abort()` when the view goes away. ## 6. Who can see them Tools are exposed only to your assistant's own address by default; any other origin is refused by name. Add one by naming it exactly in `exposedTo` — no wildcards, since `*.example.com` would hand every subdomain the right to run your actions. **Site page tools**, under Channels and access, is about your VISITORS: turn it off and the Site tools sheet stops appearing, without a site change. **Assistant may operate the host page**, under Integration › Page tools, is about the ASSISTANT: | Setting | What the assistant may do | | --- | --- | | **No** | Never calls your actions; visitors can still run them from the Site tools sheet. | | **Read-only actions** | Looks things up — an order status, a cart — but changes nothing; a changing tool is refused before it is offered, and the assistant says plainly it can read but not act. | | **All actions, with confirmation** | Also runs changes, each confirmed with the visitor in chat first. | New workspaces start at **All actions, with confirmation** — safe, since nothing is reachable until your page registers a tool naming your assistant in `exposedTo`. The panel takes allow/deny lists by tool-name prefix (blocking wins) and logs every attempt. ## 7. Let a checker see them The SDK writes `` into your head, rewritten whenever your tool list changes, so an inspector can confirm registration without a console. With a server, serve that document at a real URL and link it from your served head — the only version a reader sees without running the page. ## Verify 1. Open your site and press **Site tools** — every tool is listed with its description, arguments and read-only mark. 2. Run a read-only tool from it; the result matches what your page shows. 3. Run one that changes something: it asks first, showing the exact call; declining leaves the page untouched. 4. Ask the assistant in plain words — it picks your tool rather than describing a page. 5. Open the page in Safari or your mobile app: the list is identical, the bridge covering what the browser does not. 6. Navigate away from the view you registered on: the tool leaves the list. 7. View the page source: a `webmcp-catalog` link is present and lists the same tools. ### Do I need Chrome for this to work? No. Where the browser implements WebMCP your tools register with it; everywhere else — Safari, Firefox, any iOS or Android WebView — the assistant uses its own bridge. You write them once either way. ### Can the assistant run something without asking? Only what you marked `readOnlyHint`. Everything else stops at a confirmation showing the exact call and arguments, until the visitor agrees. ### What can the assistant see? Only what your `execute` returns — never your session, storage or markup, and treated as content rather than instructions, so page text cannot redirect it. ### Can another site use my tools? No. They are exposed to an exact list of origins — your assistant's address by default — and a call from elsewhere is refused by name, not ignored. ### I already wrote the browser API by hand. Do I have to change? No. The one call registers on that browser API where it exists and adds the bridge where it does not, so the reason to switch is reach, not correctness. ## Next - **[Forms and sign-in inside the chat](https://busymate.ai/docs/guides/form-cards)** — cards a tool asks with, and in-chat sign-in. - **[Connect your MCP server as assistant tools](https://busymate.ai/docs/guides/connect-mcp-server)** — actions on your servers rather than the page. - **[Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors)** — so a page tool can answer about *this* customer's order. --- --- title: "Forms and sign-in inside the chat" description: "Ask for missing details as a card with real fields instead of a list to type, and let visitors sign in to your site without leaving the conversation." last_updated: "2026-09-15T19:31:30+03:00" --- # Forms and sign-in inside the chat Source: https://busymate.ai/docs/guides/form-cards Last modified: 2026-09-15T19:31:30+03:00 AI Assistant can ask for what it is missing as a **form card** — labelled fields and one button, inside the conversation — instead of writing "I'll need: 1. your name 2. your phone number". On a phone that difference is the whole experience: the right keyboard per field, the visitor's own autofill, and nothing to remember. The same card lets a visitor authenticate on *your* site while the conversation keeps going. Diagram: A tool answers with a field list; the chat draws the card; the submitted values go back to the tool ## 1. Decide which action needs details Any action the visitor asks for that you cannot complete from what they said: a booking that needs a name and a phone number, an order lookup that needs the order number, a return that needs a reason. Write down the fields, their types, and which are required. ## 2. Answer with a card instead of a result A tool asks for a form by returning one, in place of its answer: ```javascript BusymateAI.registerPageTools([ { name: "book_table", description: "Book a table. Call with no arguments to show the booking form.", inputSchema: { type: "object", properties: {} }, annotations: { readOnlyHint: false }, async execute(input) { // No details yet? Ask for them as a CARD, not as a sentence. if (!input?.name) { return { $bmForm: 1, title: "Book a table", description: "Two minutes and you're done.", fields: [ { name: "name", label: "Your name", type: "text", required: true, autocomplete: "name" }, { name: "phone", label: "Phone", type: "tel", required: true, autocomplete: "tel" }, { name: "party", label: "People", type: "number", min: 1, max: 12 }, { name: "time", label: "Time", type: "time" }, ], submit: { label: "Book it", tool: "book_table" }, cancel: { label: "Not now" }, }; } // Submitted: the same tool, now with the visitor's values. const response = await fetch("/api/bookings", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(input), }); return response.ok ? await response.json() : { error: "could_not_book" }; }, }, ]); ``` Answer with `$bmForm: 1` and a `fields` array. `submit.tool` names where the values go — usually the same tool, now with arguments. A field `type` is `text`, `textarea`, `tel`, `email`, `number`, `date`, `time`, `select` or `password`, with optional `required`, `placeholder`, `help`, `autocomplete`, `min`/`max`, and `options` for a select. Twelve fields at most. ## 3. Or declare it from your MCP server A [connected MCP server](https://busymate.ai/docs/guides/connect-mcp-server) needs no page: attach the identical object at `_meta.ui.form` on the tool result. That is the same declaration channel as `_meta.ui.resourceUri` — one says "mount my document", the other "draw these fields" — and both render on the **visitor's** surface, the embedded widget and your hosted chat, not only in the Console. If you write neither, the assistant still shows a card: it asks for the details it is missing with the platform's own form rather than a list. Your own tool is better, because it knows its fields and completes the action as well as collecting it. That same card appears when an argument was never the visitor's to give. Before any tool runs, the platform checks each string argument against the visitor's own words: a value they typed goes through, a value that looks generated (`customer@example.com`, `John Doe`, `123-456-7890`, `12345`) or a required value that appears nowhere in what they said is **not sent** — the field is asked for instead. So your tool is never handed an invented email to write into a real record, and you do not need a guard of your own for it. Optional arguments the assistant is meant to choose, values from an `enum`, and dates it worked out from "tomorrow" are untouched. ## 4. Sign a visitor in without leaving the chat If what they asked for needs their account, the honest answer is not "go and find the Sign in button". Sign-in is the same contract under a standard name: register `sign_in` — a [page tool](https://busymate.ai/docs/guides/page-tools) or a tool on your connected server — and return a form card from it. `sign_up` and `sign_out` are its optional companions. ```javascript BusymateAI.registerPageTools([ { name: "sign_in", description: "Show the sign-in form in the chat when something needs the visitor's account.", inputSchema: { type: "object", properties: {} }, // Showing a form changes nothing, so no confirmation stands in front of it. annotations: { readOnlyHint: true }, execute: () => ({ $bmForm: 1, title: "Sign in", description: "You'll stay right here in this conversation.", fields: [ { name: "email", label: "Email", type: "email", required: true, autocomplete: "username" }, { name: "password", label: "Password", type: "password", required: true, autocomplete: "current-password" }, ], submit: { label: "Sign in", tool: "sign_in_submit" }, cancel: { label: "Not now" }, }), }, { name: "sign_in_submit", description: "Complete the sign-in the card collected.", inputSchema: { type: "object", properties: {} }, annotations: { readOnlyHint: false }, async execute({ email, password }) { const response = await fetch("/api/login", { method: "POST", credentials: "same-origin", headers: { "content-type": "application/json", "x-csrf-token": window.CSRF_TOKEN }, body: JSON.stringify({ email, password }), }); // `signedIn: true` is the ONE thing the chat reads. On it, the widget // re-asks your page for an identity token and the SAME conversation // continues signed in — no reload, nothing retyped. if (!response.ok) return { signedIn: false, error: "invalid_credentials" }; return { signedIn: true }; }, }, ]); ``` Your card is drawn as you wrote it, and it may have as many steps as your login does: a submit that answers with another form replaces the card with the next step. [Let your users sign in from the chat](https://busymate.ai/docs/guides/in-chat-sign-in) walks through the passwordless, two-step version. A `password` field is accepted only on a card that submits back into your own page, so its value goes from the input straight to your `execute` — never to the assistant, the transcript or a log, and the settled card shows `•••••` rather than the value or its length. Send your CSRF token and rate-limit the endpoint as you already do: this is a form on your page. Register none of it and there is no sign-in card: the assistant falls back to your real sign-in link rather than standing something of ours in for your login. ## 5. Let the conversation carry on When your sign-in tool answers `{ signedIn: true }`, the widget asks your page for a fresh identity token — the `getIdentity` handoff in [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors) — and re-mints the session **in place**. Nothing reloads, the visitor retypes nothing, and what they asked for before signing in is answered straight after. The token is verified against your registered JWKS exactly as at launch, so signing in here grants nothing a normal sign-in would not. ## Verify 1. Ask for something your tool needs details for. A card appears with your fields — not a numbered list in a message. 2. On a phone, tap the phone field: the dial pad opens. Tap the email field: the @ row does. 3. Leave a required field empty and submit: it says so and nothing is sent. 4. Submit the form. Your tool runs with the values and the assistant answers from what it returned. 5. Signed out, ask for something needing an account: the sign-in card appears in the chat, not a link away. 6. Sign in from the card. The same conversation continues, now identified, and your original request is answered without repeating it. 7. Open the tool call's details: the password is `•••••`, never the value. ### Does the assistant see what the visitor types? Only for an ordinary form, where the values become a visible message — which is what a booking or an order number should be. A card that submits into your own page never shows its values to the assistant, and a `password` field is only accepted on that kind of card. ### What if my tool returns something that is not a form? Nothing changes. The card only renders for a result that positively declares `$bmForm: 1` with at least one usable field; everything else shows as it always has. ### Can I use it without WebMCP page tools? Yes. A connected MCP server declares the same object at `_meta.ui.form`, and the platform's own card needs nothing from you at all. ### Why not just link to my login page? A link ends the conversation. The visitor signs in somewhere else, comes back to a chat that may have moved on, and retypes their question. The card keeps the thread. ## Next - **[Let the assistant use your page](https://busymate.ai/docs/guides/page-tools)** — registering the tools a card belongs to. - **[Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors)** — the identity handoff a sign-in card completes. - **[Connect your MCP server as assistant tools](https://busymate.ai/docs/guides/connect-mcp-server)** — declaring a card from a server instead of a page. --- --- title: "Let your users sign in from the chat" description: "Give customers a sign-in card inside the chat, using the accounts you already run: what they get, how to switch it on, and what stays with you." last_updated: "2026-10-02T18:13:27+03:00" --- # Let your users sign in from the chat Source: https://busymate.ai/docs/guides/in-chat-sign-in Last modified: 2026-10-02T18:13:27+03:00 AI Assistant lets a customer sign in without leaving the conversation, with the account they already have with you. You implement one tool: your sign-in card opens in the thread when a question needs their account, the credentials go to your own site, and the conversation carries on signed in. No platform account is created, and nothing about their login reaches the assistant. Diagram: A question needs an account; a sign-in card opens in the thread; the same conversation continues signed in, vouched for by a short-lived proof your site signs ## Yours end to end - **Sign-in and sign-up are your product's.** The card, login page and account creation are the ones you already run, and the form you return is drawn verbatim. AI Assistant never stores a password or creates a customer account; it only verifies the proof your site signs. ## 1. Register your accounts as the identity provider Open [Console → End-user identity](https://busymate.ai/console/identity), or call `upsert_tenant_identity_provider`. Enter your issuer, JWKS URL, audience, workspace and subject claims, the maximum proof age and the mint endpoint from [Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors), plus your **customer login URL**, which the hosted chat and step 4 use. Save, press **Test identified launch**, then publish. The check is standards-only: an ES256 (or RS256) JWT verified against your JWKS for issuer, audience, subject, workspace claim, the launch nonce, a one-time `jti`, age and expiry. A failed check names the claim, never the value. ```typescript import { SignJWT, importJWK } from "jose"; // POST https://YOUR-PRODUCT-DOMAIN/api/bmai/identity — requires YOUR OWN logged-in product session. app.post("/api/bmai/identity", requireSession, async (req, res) => { // Fresh on EVERY mint. Never persist the launch token/nonce in localStorage, // sessionStorage, cookies, React state, or module state: every assistant // launch consumes this pair exactly once. const nonce = typeof req.body?.nonce === "string" ? req.body.nonce : ""; if (!/^[A-Za-z0-9_-]{32,200}$/.test(nonce)) return res.status(400).json({ error: "invalid_nonce" }); const key = await importJWK(JSON.parse(process.env.AI_LAUNCH_PRIVATE_JWK), "ES256"); const token = await new SignJWT({ tenant_id: process.env.BMAI_TENANT_ID, // the tenant id shown in Console → Identity nonce, // equals the sibling field below name: req.user.displayName, // optional low-sensitivity display claim }) .setProtectedHeader({ alg: "ES256", kid: process.env.AI_LAUNCH_KEY_ID }) .setIssuer(process.env.BMAI_ISSUER) // the Issuer you registered in Console → Identity .setAudience("busymate-ai") .setSubject(req.user.id) // IMMUTABLE internal account id; never email/phone/session id .setJti(crypto.randomUUID()) // one-time (replay-protected) .setIssuedAt() .setExpirationTime("120s") // <= registered max age (120s) .sign(key); res.set("Cache-Control", "no-store"); res.status(201).json({ token, nonce, expiresIn: 120 }); }); ``` ## 2. Put a sign-in card in the chat Register a tool named `sign_in`, as a page tool on any page where the chat is embedded or on your [connected MCP server](https://busymate.ai/docs/guides/connect-mcp-server), and return a form card from it: ```javascript BusymateAI.registerPageTools([ { name: "sign_in", description: "Show the sign-in form in the chat when something needs the visitor's account.", inputSchema: { type: "object", properties: {} }, // Showing a form changes nothing, so no confirmation stands in front of it. annotations: { readOnlyHint: true }, execute: () => ({ $bmForm: 1, title: "Sign in", description: "You'll stay right here in this conversation.", fields: [ { name: "email", label: "Email", type: "email", required: true, autocomplete: "username" }, { name: "password", label: "Password", type: "password", required: true, autocomplete: "current-password" }, ], submit: { label: "Sign in", tool: "sign_in_submit" }, cancel: { label: "Not now" }, }), }, { name: "sign_in_submit", description: "Complete the sign-in the card collected.", inputSchema: { type: "object", properties: {} }, annotations: { readOnlyHint: false }, async execute({ email, password }) { const response = await fetch("/api/login", { method: "POST", credentials: "same-origin", headers: { "content-type": "application/json", "x-csrf-token": window.CSRF_TOKEN }, body: JSON.stringify({ email, password }), }); // `signedIn: true` is the ONE thing the chat reads. On it, the widget // re-asks your page for an identity token and the SAME conversation // continues signed in — no reload, nothing retyped. if (!response.ok) return { signedIn: false, error: "invalid_credentials" }; return { signedIn: true }; }, }, ]); ``` `sign_up` and `sign_out` are optional companions on the same contract. The fields are yours: email and password, an emailed code, or one button that starts the sign-in you already offer. A `password` field is accepted only on a card that submits back into your own page, so the value goes from the input to your `execute` and nowhere else, and the settled card shows `•••••`. When your tool answers `{ signedIn: true }`, the widget asks your page for a fresh proof through `getIdentity` and re-mints the session in place: same thread, now identified, the earlier question answered. The field vocabulary is in [Forms and sign-in inside the chat](https://busymate.ai/docs/guides/form-cards). A form may answer with another form, drawn next in the same card, so a multi-step login (email or phone, a code, a consent box) is still one `sign_in` tool. Keep step state in your own page; the form has no hidden field. For a one-time code, the card is two steps: where to send it, then the code. ```javascript // The contact the code was sent to. It lives HERE, in your page, for the // one hop between the two cards: the form spec has no hidden-value field, and // inventing one would simply be dropped by the parser. let pendingContact = null; BusymateAI.registerPageTools([ { name: "sign_in", description: "Show the sign-in form in the chat when something needs the visitor's account.", inputSchema: { type: "object", properties: {} }, // Showing a form changes nothing, so no confirmation stands in front of it. annotations: { readOnlyHint: true }, execute: () => ({ $bmForm: 1, title: "Sign in", description: "We'll text or email you a one-time code. You'll stay right here.", fields: [ // `autocomplete: "username"` is not decoration. The chat reads it to // know this box asks for a CONTACT, and refuses a bare one-time code // typed here before your endpoint is ever called (#3518) — the // predictable mistake, since the next card asks for exactly that code. { name: "contact", label: "Phone or email", type: "text", required: true, autocomplete: "username" }, ], submit: { label: "Send me a code", tool: "sign_in_send_code" }, cancel: { label: "Not now" }, }), }, { name: "sign_in_send_code", description: "Send the one-time code, then ask for it.", inputSchema: { type: "object", properties: {} }, annotations: { readOnlyHint: false }, async execute({ contact }) { // Belt and braces: the card refuses a bare code, and so does this. A // tool that answers "sent" for a value nothing can be sent to leaves the // visitor waiting for a message that will never arrive. if (/^\d{4,8}$/.test(String(contact ?? "").replace(/\s+/g, ""))) { return { signedIn: false, error: "not_a_contact" }; } const response = await fetch("/api/auth/otp/start", { method: "POST", credentials: "same-origin", headers: { "content-type": "application/json", "x-csrf-token": window.CSRF_TOKEN }, body: JSON.stringify({ contact }), }); if (!response.ok) return { signedIn: false, error: "could_not_send_code" }; pendingContact = contact; // A form may answer with a form. This is the SECOND card, in the same // conversation — the visitor never leaves and never retypes anything. return { $bmForm: 1, title: "Enter your code", description: "We sent a 6-digit code. It expires shortly.", fields: [ // NOT `password`: a one-time code is not a stored credential, and // `one-time-code` is what lets a phone offer the SMS it just got. { name: "code", label: "Code", type: "text", required: true, autocomplete: "one-time-code" }, ], submit: { label: "Sign in", tool: "sign_in_submit" }, cancel: { label: "Not now" }, }; }, }, { name: "sign_in_submit", description: "Complete the sign-in the card collected.", inputSchema: { type: "object", properties: {} }, annotations: { readOnlyHint: false }, async execute({ code }) { const response = await fetch("/api/auth/otp/verify", { method: "POST", credentials: "same-origin", headers: { "content-type": "application/json", "x-csrf-token": window.CSRF_TOKEN }, body: JSON.stringify({ contact: pendingContact, code }), }); // `signedIn: true` is the ONE thing the chat reads. On it, the widget // re-asks your page for an identity token and the SAME conversation // continues signed in — no reload, nothing retyped. if (!response.ok) return { signedIn: false, error: "invalid_code" }; return { signedIn: true }; }, }, ]); ``` Give the code field `autocomplete: "one-time-code"` and type `text`, so a phone can offer the SMS it just received. With no tool registered, nothing is invented: the assistant gives your real sign-in link or sends the visitor to your login URL at the top level (step 3). ## 3. Know what happens where | Where the chat runs | What the Sign in control does | |---|---| | Embedded on your page, `sign_in` registered | The card opens in the thread. Nothing leaves the page. | | Embedded on your page, no `sign_in` tool | Your page goes to your login URL with `return_to` and a one-time `bmai_nonce`, then hands the proof back to the widget. | | Your hosted chat address | The same redirect, with the proof in the URL fragment. | | Your iOS or Android app | The app runs its own login over the native bridge. | | No `sign_in` tool and no login URL published | Nothing is offered. | A credential is never typed into a frame that is not yours: the card submits into your page, and a redirect always happens at the top level, on your origin. ## 4. Connect a customer who is already signed in A customer already signed in to your product is signed in to the chat without a form. The widget opens your login URL once per tab in a hidden frame with `bmai_prompt=none`, which, like `prompt=none`, means answer only from an existing session. Your login redirects back with the proof in the fragment and the session is re-minted signed in. It works when: - your customer login URL is published on the current revision; - your login honours `bmai_prompt=none`, sending a signed-out visitor straight back to `return_to` with `#error=login_required` (the OpenID Connect answer) — or with nothing; - the probe finishes within three seconds; it fails silently, so the visitor stays a guest with the Sign in control still there. It only ever adds an identity and is not attempted inside a native app. Where third-party cookies are blocked, the handoff can run once as a page navigation, only for a browser that has signed in to your chat before: a first-time visitor is never sent to your login page, and `error=login_required` ends the attempt for good. ## 5. Choose what a signed-in customer can do Each connected tool carries an access level. **Public** tools answer anyone, **identified** tools run only after the proof was verified, and **delegated** tools also need *Allow delegated customer account access* on the provider. Set the levels in [Connect your MCP server as assistant tools](https://busymate.ai/docs/guides/connect-mcp-server). Each site at [demo.busymate.ai](https://demo.busymate.ai) has a demo customer to sign in as. ## Verify 1. Signed out, ask something that needs an account: the card appears in the thread. 2. Sign in from the card: the same conversation continues and your earlier question is answered. 3. Open the tool call's details: the password shows as `•••••`. 4. Sign in to your product in another tab, then open the hosted chat: it is signed in with no form. ### Do my customers need an account with AI Assistant? No. They sign in to your product. Your site signs a short-lived proof, the assistant verifies it against your public key, and the subject is your own customer id. ### Where do sign-ups happen? In your product, the way they do today. A new customer creates an account with you and comes back to the chat signed in. ### Can the assistant read the password? No. A password field is accepted only on a card that submits into your own page. The value never enters a tool argument, the transcript or a log. ## Next - **[Recognize signed-in customers](https://busymate.ai/docs/guides/identified-visitors)**: the keys, the claims and the mint endpoint. - **[Forms and sign-in inside the chat](https://busymate.ai/docs/guides/form-cards)**: the card contract in detail. - **[Connect your MCP server as assistant tools](https://busymate.ai/docs/guides/connect-mcp-server)**: the identified tools it unlocks. --- --- title: "How your page and the widget talk to each other" description: "The host and widget contract: open, preset, ask and identify from your page, listen to the widget's events, and share page tools both ways." last_updated: "2026-09-26T20:38:55+03:00" --- # How your page and the widget talk to each other Source: https://busymate.ai/docs/guides/widget-page-api Last modified: 2026-09-26T20:38:55+03:00 AI Assistant puts your assistant on a page with one script tag, and the page that carries it can drive it, listen to it and hand it tools. This is that contract, every call in one direction and every message in the other, with a runnable copy of each on the [playground](https://busymate.ai/playground). Diagram: Your page calls the widget through window.BusymateAI; the widget posts busymate.ai.v1 messages back; page tools flow both ways through the standard model-context surface The **launcher** is the script: it draws the button and the panel and installs `window.BusymateAI`. The **frame** is the chat inside the panel, loaded from the assistant's origin. Your page talks only to the launcher, which talks to the frame over a pinned `postMessage` channel and trusts no other sender. ## 1. Mount the widget One tag, before ``. `data-assistant` is your workspace slug, which the Console's Integration page prints; the other attributes are optional labels. ```html ``` The tag is `async`, and every call below is safe before it loads: commands queue until the frame is up. A launcher look set in the Console arrives a moment after the launcher. `data-launcher="custom"` holds the button, invisible, until that look loads (0.8 seconds at most); `data-launcher="hidden"` never shows it, for a page that opens the chat from its own control. ## 2. Open and preset ```javascript // The loader installs window.BusymateAI. Every call is safe before the frame // has loaded — commands queue and deliver on load. BusymateAI.open(); BusymateAI.close(); BusymateAI.toggle(); BusymateAI.isOpen(); // → true | false ``` ```javascript // Preset the panel from the page: colour scheme + language. // Neither is persisted by the frame — your page owns them while it embeds it. BusymateAI.setTheme("dark"); // "light" | "dark" | "system" BusymateAI.setLocale("de"); // any BCP 47 tag the platform serves BusymateAI.setLocale(null); // unpin — the frame follows the visitor again BusymateAI.open(); ``` `setTheme` and `setLocale` return `false` for a value they do not accept. The frame persists neither: your page owns the panel's theme and language while it embeds it. ### Make room for the panel By default the panel floats over your page. `data-layout="push"` makes the page yield instead: while the panel is open, above 1100 pixels wide, the launcher reserves the panel's real width as padding on `` and hands it back on close. Phones never move, and reduced motion snaps instead of animating. ```html ``` In this mode the launcher owns the padding and `overflow-x` of ``, so move any root padding of your theme to a wrapper. A full-bleed block is anchored to the viewport, so give it the page width the loader publishes, as the snippet does. A launcher docked bottom-left reserves the left side instead. ## 3. Page to chat `ask(text)` opens the panel and sends the prompt through the frame's own composer, under every guard a typed message gets. `{ submit: false }` only fills the composer. It returns `false` for empty text; calls made before the frame loads queue, eight at most. ```javascript // Open the panel and send a prompt — the same append path a typed message takes. BusymateAI.ask("What can you do on this page?"); ``` ```javascript // Fill the composer only; the visitor reads, edits and presses send. BusymateAI.ask("Book a table for two on Friday at 19:00", { submit: false }); ``` ```html ``` ```javascript // Every example prompt on this page is one call — the same call your // own "try it" buttons make. BusymateAI.ask("Compare the plans and recommend one for a two-person shop."); ``` ## 4. Chat to page The frame posts messages to your page, and the launcher already acts on each one, so your page listens only to observe. Compare `event.origin` with the assistant's origin, derived from the loaded script rather than typed, because a workspace on its own domain serves the frame from there. ```javascript // The frame posts busymate.ai.v1.* messages to your page. The loader already // acts on every one of them; your page only listens to OBSERVE. // audit docs-and-developer-path-08 (2026-09-18): derived, never a hardcoded // literal — a workspace on its own custom domain serves the frame from a // different origin than the one this doc happens to render on. const ORIGIN = window.BusymateAI?.origin ?? new URL(document.currentScript?.src ?? document.querySelector('script[data-assistant]').src).origin; window.addEventListener("message", (event) => { if (event.origin !== ORIGIN) return; const { type, ...data } = event.data ?? {}; if (typeof type !== "string" || !type.startsWith("busymate.ai.v1.")) return; console.log(type, data); // busymate.ai.v1.ready { visitorKind, displayClaims } a session is live // busymate.ai.v1.close — ✕ pressed inside the frame // busymate.ai.v1.navigate { href } a same-origin link was clicked // busymate.ai.v1.open_url { url } any other link (new tab) // busymate.ai.v1.resize_to { w, h } resize_end resize_by { dw, dh } }); ``` ### Same-site navigation A reply's link to your own origin navigates your page in place, conversation intact. The launcher pushes the URL, dispatches `popstate` for History-API routers, and a `busymate:hostnavigate` event for a page with no router. A page that does not change is reloaded normally. ```javascript // A same-origin link in the chat navigates YOUR page in place (same tab). // SPA routers already listening for popstate resync on their own; this // dedicated event needs no router at all. window.addEventListener("busymate:hostnavigate", (event) => { const { href } = event.detail; myRouter.push(new URL(href).pathname); }); ``` ### Open state `` carries an open or closed attribute from the first frame, for CSS, and `window` receives an open and a close event, for scripts, each only on a real change. Do not watch for the panel's `