# Biel.ai docs > Ask AI assistant for technical documentation This file contains all documentation content in a single document following the llmstxt.org standard. ## View analytics Click **Analytics** in the top navigation bar, then choose your **Project** and date range using **From** and **To**. Use the **Assistant**, **Search**, and **MCP** tabs to switch views. **Download report** opens the browser's print dialog, where you can save a PDF. ![View analytics](./images/view-analytics.jpg) The **Analytics** view tracks project activity for a selected period, organized into Assistant, MCP, and Search tabs: :::important Only **Administrator**, **Maintainer**, or **Editor** roles can view analytics. See [Manage roles](https://docs.biel.ai/administration/roles.md). ::: ## Assistant analytics {#chatbot-analytics} * **Chats:** Total number of chat sessions. * **Messages:** Total number of messages exchanged. * **Unique users:** Distinct saved IP addresses, plus one user for each chat without a saved IP address. * **Helpful** and **Not helpful:** Positive and negative feedback counts. * **Satisfaction:** Percentage calculated from feedback, treating answers without feedback as positive. * **Daily chat activity:** Graph showing chat activity over time. * **Key pages driving conversations:** URLs where assistant conversations originated, with occurrence counts. * **Top countries driving conversations:** Geographic distribution showing which countries users are chatting from. * **Frequently asked questions** *(Professional, Business, and Enterprise plans)*: Most common questions asked to your assistant, grouped by semantic similarity. Analyzed daily. * **Content gaps** *(Professional, Business, and Enterprise plans)*: Questions the assistant couldn't answer, grouped by semantic similarity. Analyzed daily. ## MCP analytics Use this tab to understand how people use your documentation through connected MCP clients. * **Chats via MCP:** Conversations created through **Ask**. **Find docs** and **Get docs** calls do not create chat sessions. * **Messages via MCP:** Total **Ask**, **Find docs**, and **Get docs** calls. Each call counts once, including separate document pagination calls. * **Unique users:** Users of **Ask** conversations, estimated from IP addresses. Retrieval calls do not contribute to this count. * **Daily MCP activity:** Calls over time, separated by action. * **Top MCP clients:** Editors and agents making MCP calls, with message counts and percentage shares. Client names are supplied by the clients themselves. * **MCP actions:** Counts and shares for **Ask** (`biel_ai`), **Find docs** (`biel_search`), and **Get docs** (`biel_get_document`). ## Search analytics * **Unique users:** Number of distinct users who performed searches. * **Searches:** Total number of search queries. * **Searches clicked:** Percentage of searches where users clicked on a result. * **Click position:** Average rank of clicked results. Lower positions indicate that people find useful results nearer the top; it remains unavailable until clicks include a result rank. * **Daily search activity:** Graph showing search activity over time. * **Top search terms:** Most frequently searched terms with occurrence counts. * **Searches without results:** Queries that returned no results. Use these to identify missing content or indexing gaps. * **Searches without clicks:** Queries for which no result was opened. This list stays empty until every recorded click in the selected period includes its originating query, so Biel.ai does not report an incomplete list as a content issue. ## Troubleshooting ### FAQs or content gaps not showing - **Plan requirement**: These features require a Professional, Business, or Enterprise plan. - **Recently upgraded**: Wait 24 hours — the analysis runs daily. - **No historical data**: Biel.ai only processes conversations that occur after your upgrade. - **No conversations**: There were no assistant conversations to analyze from the previous day. --- ## Manage projects Projects are the core organizational unit in Biel.ai where you configure your assistant's behavior, data sources, and security settings. ## View all projects The **Projects** dashboard displays a list of all your projects. Starter, Professional and Business include unlimited projects. After your trial ends, choose a paid plan to reactivate your projects. ![Projects list](./images/project-list.jpg) ## Project detail page From the **Projects** dashboard, click on a project name to open its detail page. ![Project details](./images/project-details.jpg) Here you can: ### Project information - View the project ID - Click **Snippet** to choose **AI Assistant** or **AI Search** and copy its installation code - Access the project details using the **Settings** button ### Testing and monitoring - Click **New chat** to open the assistant in a modal and test its answers - Click **Refresh sources** to recrawl content and check the **Sources loading** or **Sources loaded** status - Open **Logs** or **View logs** to troubleshoot indexing issues - Open **Analytics** in the top navigation bar and select this project to review assistant, MCP, and search usage - Click **Demo** to open the public demo page, when enabled ### Chat management - View all chat entries and conversation history - Filter conversations by date, sentiment, status, or metadata - Find a conversation by entering any four or more characters from its ID; separate multiple IDs with commas - Click on any chat entry to view its details ### Project actions - Open **Settings** > **General**, then click **Delete project** at the bottom of the page ### Chat detail view From the project detail page, click on any chat entry in the conversation list to view its full details. ![Chat details](./images/chat-details.jpg) This view shows detailed information about that specific conversation: ### User information - Email address (if provided) - Country and IP address - Sentiment analysis of the conversation ### Conversation metadata - URL where the chat originated - Date and time of the conversation - Full conversation history ### Actions - **Download**: Export the chat in PDF, Excel, or CSV format - **Delete**: Remove the chat entry ### Bulk actions Select chat entries using the checkboxes, choose an option from **Select action**, and click **Apply**: - **Archive selected**: Move conversations to the archived list while preserving their history. Set the **Status** filter to **Archived** to view them and use **Unarchive selected** to restore them. - **Export selected to CSV**, **Export selected to XLS**, or **Export selected to PDF**: Download selected conversations. - **Delete selected**: Remove selected conversations from the dashboard. ## Project settings From the project detail page, click the **Settings** button (top right) to open the project settings. The settings layout has a left sidebar with seven groups; each group has its own page with one or more sections. ![Project settings](./images/project-settings.jpg) :::important Only **Administrator** or **Maintainer** roles can manage project settings. See [Manage roles](https://docs.biel.ai/administration/roles.md). ::: The header on every settings page has a **Refresh sources** button: - **Refresh sources**: Re-crawl all configured sources. After clicking, you're sent to the project's chat-list page where the loading status is visible. To permanently delete a project and all its data, open **General** and use the **Delete project** section at the bottom of the page. Each section card has its own **Save** button. On **Sources**, one Save button saves the configuration across all source types. File uploads are saved as soon as they finish. Click **Refresh sources** after changing sources to index the updated content. ### General Basic project information: - **Name**: Display name for the project. - **Demo page**: Enable or disable the public demo page used for testing. ### Sources Configure the data sources your assistant can answer from. Pick a source type from the chip selector at the top of the page; each chip reveals its own form. - **URLs**: Index specific web pages. - **Sitemaps**: Index entire websites using XML sitemaps. The Sitemaps tab also exposes URL-filter regex patterns to control which sitemap URLs get crawled. - **GitHub**: Index GitHub repositories directly. - **OpenAPI**: Import API specifications. - **Confluence**: Connect a Confluence workspace. - **Files**: Upload documents (PDF, CSV, Excel, Word, TXT, MD). Available once the project has been created. For detailed configuration, see [Sources](https://docs.biel.ai/customization/data-sources/overview.md). ### Assistant {#chatbot} Three sections, each with its own **Save** button: - **Conversation** — the **Welcome message** and suggested questions shown when the chat opens. See [Initial message](https://docs.biel.ai/customization/initial-message.md) and [Suggested questions](https://docs.biel.ai/customization/suggested-questions.md). - **AI model and instructions** — model selection, prompt configuration (default prompt or custom prompt), think mode, and web search. See [Models](https://docs.biel.ai/customization/models.md), [Custom prompt](https://docs.biel.ai/customization/custom-prompt.md), and [Reasoning modes](https://docs.biel.ai/customization/reasoning-modes.md). - **Actions** — buttons the assistant can suggest when users need to take a next step. See [Actions](https://docs.biel.ai/customization/actions.md). ### Search Two sections: - **Search Filters** — filter chips that narrow search results by URL pattern. See [Search filters](https://docs.biel.ai/customization/search-filters.md). - **Boost Rules** — rank specific URLs higher in search results. Available with the boost permission. ### MCP Configure Model Context Protocol integration so AI coding assistants can talk to this project. - **Enable MCP server**: Allow access through MCP. - **MCP server name**: Custom name using letters, numbers, hyphens, and underscores, such as `acme-docs`. Leave blank to use the project name. - **Metadata tag**: Tag used to identify conversations originating from MCP. Available during your trial and on **Professional** and higher plans. See [MCP server](https://docs.biel.ai/integrations/mcp-server.md). ### Security & Privacy Two sections: - **Data Privacy** — toggle PII redaction and IP-address collection. See [Data privacy](https://docs.biel.ai/customization/data-privacy.md). - **Access Control** — require authentication for API access (Business plan), and restrict which domains the assistant widget runs on. ### Integrations Connect channel integrations from their cards. Discord and Slack have a **Connect** button that opens authorization. Microsoft Teams provides a downloadable manifest and a setup token. Each integration has its own setup controls. - **Discord** — see [Discord](https://docs.biel.ai/integrations/discord.md). - **Slack** — see [Slack](https://docs.biel.ai/integrations/slack.md). - **Microsoft Teams** — see [Microsoft Teams](https://docs.biel.ai/integrations/microsoft-teams.md). ## Crawl scheduling and limits Besides the manual **Refresh sources** trigger, Biel.ai recrawls some projects automatically, and applies limits so crawls stay within your plan and finish in a reasonable time. ### Automatic recrawl schedule Biel.ai recrawls a project's sources automatically based on your team's plan: | Plan | Automatic recrawl frequency | | --- | --- | | Business | Every week | | Professional, Growth | Every 30 days | | Other plans | None — trigger crawls manually with **Refresh sources** | A custom team agreement can override the recrawl interval. The interval is measured from the start of the last crawl, regardless of whether that crawl succeeded or failed. A project that has never been crawled waits for a manual first crawl, and a project with a crawl already running is skipped until that crawl finishes. To recrawl a project outside this schedule, or on a plan without automatic recrawl, click **Refresh sources**. ### Source limit enforcement Plans can limit the total number of indexed pages across all of a team's projects. The **Indexed pages** usage card on the subscription page shows the pages from the last crawl of each project, pooled across the team. If a crawl would exceed the allowance, Biel.ai stops indexing and emails the team. Reduce the content included in your sources or upgrade your plan, then click **Refresh sources** again. ### Crawl time limit Biel.ai uses a 2-hour soft limit for crawls. Crawls that run significantly longer may be canceled. If your crawls are consistently hitting this limit, [contact us](https://docs.biel.ai/support.md) for guidance --- ## Manage roles Biel.ai supports four team roles: **Administrator**, **Maintainer**, **Editor**, and **Viewer**. Each role grants a different level of access to projects, chats, analytics, and team settings. ![Manage roles](./images/manage-team.jpg) ## Available roles | Role | Access level | |------|-------------| | **Administrator** | Full access to all platform actions. | | **Maintainer** | Manage projects, sources, chats, analytics, and other members' roles. Cannot save team details, change branding, or create API keys. | | **Editor** | View all chats, access analytics, delete chats. Cannot create projects or edit settings. | | **Viewer** | View own chats only. No analytics, settings, or project creation. | ## Assign a role when inviting a team member ![Manage roles](./images/send-invitation.jpg) The **Invite team members** form is visible to **Administrators** on the **Team** page. Enter the member's email, select a role, and click **Send invitation**. Permissions take effect after they accept. Pending invitations appear below the form. ## Change a team member's role To update a team member's role: 1. In the [Biel.ai dashboard](https://app.biel.ai), click **Team** in the top navigation bar. 2. Locate the team member in the **Team members** list. 3. Click on their email address. 4. Select the new role from the dropdown and click **Update role**. Administrators and Maintainers can update other members' roles. You cannot change your own role or demote the team's last administrator. --- ## Manage subscription :::important **Administrators** and **Maintainers** can view subscription usage, billing details, and available invoices. Only **Administrators** can manage extra usage or open **Manage billing**. See [Manage roles](https://docs.biel.ai/administration/roles.md). ::: Open **Team** in the top navigation bar and click **Manage subscription**. If you do not have an active subscription, the button reads **Upgrade now**. For a self-service subscription, **Manage billing** lets you change or cancel your plan, view invoices, and update billing details. For a custom plan billed manually, select **Contact us** to request changes. Your subscription page shows interactions and indexed pages shared across all projects. Extra usage does not change your plan's indexed-page limit or unlock additional models and features. Starter, Professional and Business include unlimited projects. When your trial ends without a paid plan, all projects become inactive until you subscribe. ## Extra usage Keep your assistant running after your included interactions run out. With extra usage enabled, each additional billable interaction costs **$0.05**. Chat messages, searches, MCP retrieval, and answer continuations share your team's interaction allowance. A question can use multiple interactions. See [Reasoning modes](https://docs.biel.ai/customization/reasoning-modes.md) and [Web search](https://docs.biel.ai/customization/web-search.md). The **Interactions** card shows your usage, included allowance, extra interactions, and extra charges for the month. For example, **120 extra interactions cost $6.00**. Bonus interactions are free and are used before paid extra usage. Unused bonus interactions expire at the start of the next UTC calendar month. ### Enable extra usage Extra usage is **off by default for all subscribers**. An Administrator can enable it from the subscription page by authorizing charges to the saved payment method. Subscribing to a plan does not enable extra usage. As an Administrator: 1. Open **Team** > **Manage subscription**. 2. In the **Interactions** card, click **Manage limits**. 3. Optionally enter a **Monthly extra usage limit (USD)**. Leave it blank for no monthly cap, or enter **0** to prevent paid extras. 4. Authorize charges to your saved payment method at **$0.05 per additional interaction** and click **Enable extra usage**. Follow any card-verification instructions from your bank. This step does not charge you. Extra usage stays off until verification succeeds. ### Manage your monthly limit Click **Manage limits** in the **Interactions** card to change your limit, then select **Save limit**. You do not need to accept the pricing again when changing an enabled limit. There is **no monthly spending limit by default**. A positive limit controls extra spending across your team. Extra usage pauses when the limit cannot cover the next interaction. The spending period resets at the start of each UTC calendar month. Set the limit to **0** and click **Save limit** to prevent new paid extras. Interactions already in progress can finish, and charges for usage already consumed remain due. ### Usage alerts We email administrators at **80%** and **100%** of your monthly allowance, including any bonus interactions and the extra interactions your configured limit permits. If extra usage is off or your limit is **0**, alerts exclude paid extras. With extra usage enabled and no monthly cap, percentage alerts are not sent. At **80%**, follow the email's link to review your plan or extra usage settings. With extra usage off, reaching **100%** does not automatically stop your assistant or create extra charges. Support can pause interactions above your allowance until the next UTC calendar month. Your included allowance renews then. With extra usage enabled and a monthly spending limit set, new interactions pause when the limit cannot cover the next interaction. Increase your limit or wait until the next monthly allowance to resume, unless support has paused usage. ### Extra usage payments Extra usage is billed monthly, or earlier when new extra usage charges reach **$25**. Balances below **$1** carry forward. The **$25** payment threshold is separate from your optional monthly spending limit. If an extra usage payment fails, your assistant keeps running within your configured monthly limit. Unpaid charges remain due, and further usage may create additional payments. Open **Manage billing** to review your payment details. Your subscription page lists outstanding extra usage payments. If your bank requires approval, select **Complete payment** for each payment and follow the bank's instructions. For other payment issues, select **Contact support**. Support may pause paid extra usage while payments are outstanding. You can still use your included interactions, which renew each month. This pause stays in place across monthly resets. Contact support to resume paid extra usage. --- ## Manage team Open **Team** in the top navigation bar to view team details and members. ![Manage team](./images/manage-team.jpg) * Change the team name. * Change the team URL slug and timezone. * Enable or disable **Remove 'Powered by Biel.ai' branding** (whitelabel). * Invite new members. * Remove members. * Manage member roles and permissions. * Manage your subscription. Click **Save details** to apply changes to the **Details** card. :::important **Administrators** can save team details and change branding. The **Invite team members** form is visible to Administrators. **Administrators** and **Maintainers** can view the Team page and manage other members' roles. You cannot change your own role or remove the team's last administrator. See [Manage roles](https://docs.biel.ai/administration/roles.md). ::: --- ## Whitelabel White labeling lets you hide the "Powered by Biel.ai" text, link, and logo from the assistant widget to maintain a consistent brand experience. :::important This feature is available on the **Professional** plan and above. Only **Administrators** can save changes to white labeling. See [Manage roles](https://docs.biel.ai/administration/roles.md). ::: ## Remove Biel.ai branding 1. In [app.biel.ai](https://app.biel.ai), go to **Team** in the top navigation bar. 2. Under **Details**, check **Remove 'Powered by Biel.ai' branding**. ![Remove logo](./images/remove-logo.jpg) 3. Click **Save details**. To confirm, open any page where you've embedded the Biel.ai widget. The Biel.ai logo should no longer appear. --- ## Administration Administrative guides for managing Biel.ai.
Projects Configure assistant settings, sources, and security
Analytics Track usage, FAQs, and content gaps
Team Manage members, invitations, and settings
Roles Assign permissions to team members
Subscription Billing, invoices, and plan usage
Whitelabel Remove Biel.ai branding (Professional+)
--- ## Add source Add sources to a project. Supports files, URLs, sitemaps, hosted sites (ZIP), GitHub repositories, OpenAPI specifications, and Confluence spaces. All sources are indexed for search and chat. Use `multipart/form-data` when uploading binary content (files or site ZIPs). Use `application/json` for everything else, including private GitHub repositories and private Confluence spaces that need credentials. **Required permission:** `sources_create` | Source type | Limits / notes | |-------------|----------------| | Files (PDF, MD, TXT, DOCX, PPTX, XLSX, CSV, YAML, JSON, RST, HTML, CSS, JS, XML) | 10 MB per file. `multipart/form-data` only | | URLs | Must be publicly accessible | | Sitemaps | Must end in `.xml` | | Hosted sites (ZIP) | 250 MB per ZIP. `multipart/form-data` only. `site_name` is required | | GitHub repositories | Public repos work via either content type. Private repos require a personal access token (JSON only) | | OpenAPI specifications | JSON or YAML URL | | Confluence spaces | Public spaces work via either content type. Private spaces require username + API token (JSON only) | If a value is wrong, such as a sitemap URL that doesn't end in `.xml`, the request returns `400` with the errors listed by field name. If the values look right but the source still can't be added, such as an unsupported file type or a corrupt ZIP, the request returns `422` with a single `error` message explaining why. Request --- ## Biel.ai API Biel.ai is an AI-powered documentation assistant. It indexes your technical documentation and provides AI chat and search capabilities through widgets, MCP servers, and this REST API. **Base URL:** `https://app.biel.ai` > The API is available on **Business** and **Enterprise** plans. [Contact us](https://biel.ai/contact) to upgrade. Chat, search, document retrieval, and answer continuations share your team's included interaction allowance. With [extra usage](https://docs.biel.ai/administration/subscription.md#extra-usage) enabled, interactions beyond that allowance cost $0.05 each. ## Versioning This document describes **API v2** (`/api/v2/`). If you have an existing v1 integration, see the [migration guide](https://docs.biel.ai/api/migrate-from-v1.md). v1 is scheduled for retirement in **January 2027**. ## Authorization & permissions Biel.ai uses API key authentication with granular permissions. - **Public projects**: Widget operations, including reading project configuration, searching, and sending messages, do not require an API key. Project, source, conversation, sync, analytics, and team management operations require one; check each endpoint. - **Private projects**: All operations require an API key. > Projects are public by default. Configure this in **Project settings**. ### Available permissions | Permission | Description | Required For | |------------|-------------|--------------| | `projects_read` | Read project details | Getting project information, listing projects | | `projects_create` | Create projects | Creating new projects | | `projects_update` | Update project settings | Updating project configuration | | `projects_delete` | Delete projects | Removing projects | | `search` | Search and read indexed documents within projects | Searching project content, retrieving indexed document text, tracking search clicks, submitting message feedback | | `sources_read` | View project sources | Listing project sources, getting source detail | | `sources_create` | Upload sources | Adding files, URLs, sitemaps, repositories, OpenAPI specs, and Confluence spaces to projects | | `sources_delete` | Delete sources | Removing sources from projects | | `sync_create` | Trigger a sync or a single-page re-crawl | Re-crawling project sources, re-crawling one page | | `sync_read` | Read sync status | Polling sync runs | | `analytics_read` | Read project analytics | Reading chat, search, MCP, and insights analytics | | `chats_create` | Create chats and send messages | Interacting with the AI chat | | `chats_read` | Read conversations | Listing chats, retrieving a conversation | | `chats_delete` | Delete conversations | Deleting a conversation | | `teams_update` | Update team settings | Renaming a team, changing its slug, managing members | > Keys created before v2 may carry legacy permission names (`project_read`, `project_search`, `project_sources_*`, `project_sync`, `chat_create`). They remain valid as aliases of their v2 equivalents, so you don't need to re-issue keys. ### Create an API key 1. In [app.biel.ai](https://app.biel.ai), click **Team** in the top navigation and scroll to **API keys**. 2. Click **Create API key** and enter a **Key name**. 3. Under **Project access**, select the intended project, or **All projects in this team** if the integration needs team-level operations. Select the required permissions. 4. Click **Create API Key** and copy the key. You won't be able to view it again. ### Using your API key Include the key in the `Authorization` header: ``` Authorization: Api-Key ``` > Read-only keys (`projects_read`, `search`) can be exposed client-side. The `search` permission allows retrieval that consumes interactions. Restrict client-side keys to the intended project and permissions. Keys with write permissions should always be stored server-side. API Key authentication using the format: `Api-Key ` Create your API key in Team Settings and assign the required permissions for your use case. Security Scheme Type: apiKey Header parameter name: Authorization --- ## Create a project Create a new project. The slug is auto-generated. Configure the project with [`PATCH /api/v2/projects/{slug}/`](/api/update-project) after creation. **Required permission:** `projects_create` Request --- ## Delete a chat Delete a conversation. **Required permission:** `chats_delete` Request --- ## Delete a project Permanently delete a project, all its sources, indexed content, and chat history. **Required permission:** `projects_delete` Request --- ## Delete source Remove a source and its indexed content from a project. **Required permission:** `sources_delete` Request --- ## Get chat analytics Aggregate KPIs and daily activity for the AI chat over a date range. MCP-only conversations are excluded. For those, see [`GET /api/v2/projects/{slug}/analytics/mcp/`](/api/get-mcp-analytics). **Required permission:** `analytics_read` Request --- ## Get a chat Retrieve a single conversation, including all of its messages ordered chronologically. **Required permission:** `chats_read` Request --- ## Get indexed document text Read a document's complete indexed text without contacting the original source site. First search with `source_types=all` and copy a result's `document_id`. This returns text chunks in reading order with available page or worksheet references, not a live page or an original binary file. Responses contain up to `limit` chunks (default 20, maximum 20). When `next_cursor` is not null, repeat the request using that cursor and the same `document_id` and `limit`. Continue until `next_cursor` is null. References and cursors are scoped to the project and its active index. After an index refresh or a 404, search again for a current reference. Existing project access, allowed-domain, trial and interaction-limit checks apply. Each successful read counts as a search interaction and does not create a chat. Older repository or OpenAPI indexes and older uploaded files with backticks in their names may require a recrawl (409). Each successful pagination request counts separately toward your team's interaction allowance. With extra usage enabled, interactions beyond that allowance cost **$0.05** each. See [extra usage](https://docs.biel.ai/administration/subscription.md#extra-usage). **Required permission:** `search` (private projects only). Request --- ## Get advanced analytics insights Surface conversation-driven insights for the project: top recurring questions (`faqs`) and content gaps where users asked something the assistant could not answer (`content_gaps`). Each item includes the related chats so you can drill into the original conversations. **Plan-gated:** requires a plan that includes advanced analytics. When your team does not have access, the endpoint returns 200 with `{ "has_access": false }` and no payload. Treat that as a successful response rather than an error, and prompt the user to upgrade. **Required permission:** `analytics_read` Request --- ## Get MCP analytics Aggregate KPIs and daily activity for conversations that originated from the MCP server. **Required permission:** `analytics_read` Request --- ## Get project details Retrieve project settings, filters, and metadata. **Required permission:** `projects_read` (private projects only). Request --- ## Get search analytics Aggregate KPIs and daily activity for the search experience over a date range. Counts come from [`GET /api/v2/projects/{slug}/search/`](/api/search-project) calls and [`POST /api/v2/projects/{slug}/search/click/`](/api/track-search-click) events. **Required permission:** `analytics_read` Request --- ## Get source detail Retrieve detail for a single source. **Required permission:** `sources_read` Request --- ## Get a sync run Retrieve a specific sync run by UUID. Returns the same shape as [`GET /api/v2/projects/{slug}/sync/`](/api/get-sync-status), but addresses a single run instead of the latest one. Use the `uuid` returned by [`POST /api/v2/projects/{slug}/sync/`](/api/sync-project). **Required permission:** `sync_read` Request --- ## Get latest sync status Inspect the most recent sync run for the project, including overall status, the URLs that were processed, and the event log for the run. Use this to: - Detect when an automated [`POST /api/v2/projects/{slug}/sources/`](/api/add-source) followed by [`POST /api/v2/projects/{slug}/sync/`](/api/sync-project) flow has finished (`status` transitions from `running` to `success`/`error`/`warning`). - Surface failures with actionable context. `events` includes per-URL warnings and errors. For lightweight polling, prefer [`GET /api/v2/projects/{slug}/`](/api/get-project) and read its `last_sync` summary instead. It returns the same `status` and timestamps without the full event log. Returns 404 when the project has never been synced. **Required permission:** `sync_read` Request --- ## Get a team Retrieve the team identified by `slug`. The `slug` must match the team that owns the authenticating API key. Requesting any other team returns 404. Any valid API key authenticates this call, no specific scope is required. Request --- ## Invite a team member Send an email invitation to join the team with the given role. The invitee becomes a member once they accept. **Required permission:** `teams_update` Request --- ## List chats List chats for a project. Results are paginated and ordered by `created_at`. **Required permission:** `chats_read` Request --- ## List projects List projects accessible to the API key. Results are paginated. **Required permission:** `projects_read` Request --- ## List sources List all sources associated with a project. Results are paginated. **Required permission:** `sources_read` Request --- ## List team members List the active members of the team. The `slug` must match the team that owns the authenticating API key. Any valid API key authenticates this call, no specific scope is required. Request --- ## List teams accessible to the API key Return the team this API key belongs to. Because every API key is scoped to a single team, the returned array always contains exactly one entry. Any valid API key authenticates this call, no specific scope is required. --- ## Migrate from API v1 to v2 API v2 replaces v1 as the documented, actively developed API. v1 keeps working for existing integrations, but it no longer receives new features and is scheduled for retirement in January 2027. This guide lists the changes required to move a v1 integration to v2 before that date. The [v1 reference](https://docs.biel.ai/api-v1/biel-ai-api.md) remains available until v1 is retired. ## What stays the same - **Authentication.** Send `Authorization: Api-Key `, exactly as in v1. Existing API keys keep working; you don't need to re-issue them. - **Base URL.** `https://app.biel.ai`. - **Public project access.** Read operations on public projects still work without an API key. - **Search.** Request parameters and the response shape of the search endpoint are unchanged; only the base path changes. ## Endpoint mapping Every v1 endpoint has a direct v2 replacement. | v1 endpoint | v2 endpoint | | --- | --- | | `POST /api/v1/chats/` | `POST /api/v2/projects/{slug}/chats/` | | `GET /api/v1/projects/{slug}/` | `GET /api/v2/projects/{slug}/` | | `GET /api/v1/projects/{slug}/search/` | `GET /api/v2/projects/{slug}/search/` | | `GET /api/v1/projects/{slug}/sources/` | `GET /api/v2/projects/{slug}/sources/` | | `POST /api/v1/projects/{slug}/sources/` | `POST /api/v2/projects/{slug}/sources/` | | `DELETE /api/v1/projects/{slug}/sources/{source_uuid}/` | `DELETE /api/v2/projects/{slug}/sources/{source_uuid}/` | | `POST /api/v1/projects/{slug}/sources/sync/` | `POST /api/v2/projects/{slug}/sync/` | ## Permission renames v2 renames API key permissions to a consistent `_` scheme. | v1 permission | v2 permission | | --- | --- | | `project_read` | `projects_read` | | `project_search` | `search` | | `project_sources_read` | `sources_read` | | `project_sources_create` | `sources_create` | | `project_sources_delete` | `sources_delete` | | `project_sync` | `sync_create` | | `chat_create` | `chats_create` | Keys created before v2 may carry the legacy names. They remain valid as aliases of their v2 equivalents, so no key rotation is needed. ## Breaking changes ### Send a message: project moved to the path Sending a message now happens under the project, at [`POST /api/v2/projects/{slug}/chats/`](/api/send-message). Remove `project_slug` from the request body and put the slug in the URL instead. The rest of the body (`message`, `chat_uuid`, `url`, `email`, `think_mode`, `metadata`) and the 200/201 response are unchanged. ```bash title="v1" curl -X POST https://app.biel.ai/api/v1/chats/ \ -H "Authorization: Api-Key $BIEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"project_slug": "my-project", "message": "How do I install the widget?"}' ``` ```bash title="v2" curl -X POST https://app.biel.ai/api/v2/projects/my-project/chats/ \ -H "Authorization: Api-Key $BIEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"message": "How do I install the widget?"}' ``` ### Get project: settings grouped under `config` The v1 response returned all settings as top-level fields. In v2, feature settings are grouped under a `config` object, and the response adds identity and lifecycle fields (`slug`, `uuid`, `name`, `is_private`, `last_sync`, `created_at`, `updated_at`). | v1 field | v2 field | | --- | --- | | `initial_message` | `config.chat.initial_message` | | `suggested_questions` | `config.chat.suggested_questions` | | `think_mode` | `config.chat.think_mode` | | `filters` | `config.search.filters` | | `mcp_enabled` | `config.mcp.enabled` | | `mcp_server_name` | `config.mcp.server_name` | | `mcp_metadata_tag` | `config.mcp.metadata_tag` | | `whitelabel` | `whitelabel` (unchanged) | `slug` is the project identifier used in API paths and the embeddable widget's `project` attribute. Copy it from the project's installation code. The separate `uuid` field identifies the project record. ### Get project: new settings with no v1 equivalent The `config` object also carries settings that v1 did not have. A v1 integration that reads or writes project settings will encounter them for the first time in v2. | v2 field | Description | | --- | --- | | `config.prompt.use_default` | Whether the built-in system prompt is used. | | `config.prompt.version` | Version of the built-in assistant prompt. | | `config.prompt.extend` | Custom instructions appended to the built-in prompt, or used on their own when `use_default` is `false`. | | `config.chat.actions` | Call-to-action buttons the chat widget renders alongside answers. Each has `name`, `button_text`, and `url`. | `config.chat.actions` is read-only. Read-only fields are returned in responses but rejected in requests, so an integration that reads a project and sends the whole object back to update it gets a validation error. Send only the fields you want to change. ### Sync: new path and asynchronous response Sync is its own resource in v2, no longer nested under sources. - The endpoint moves from `POST /api/v1/projects/{slug}/sources/sync/` to `POST /api/v2/projects/{slug}/sync/`. - v2 returns `202 Accepted` with a sync run summary (`uuid`, `status`, timestamps) instead of the v1 `200` with a message. Poll [`GET /api/v2/projects/{slug}/sync/`](/api/get-sync-status) or read the project's `last_sync` field to track completion. - Calling the endpoint while a sync is already running cancels the in-progress run and starts a fresh one. v1 returned `400` in that case. If your integration relied on the `400` to avoid duplicate syncs, check the sync status before triggering a new run. ### Add source: `201` status and typed sources - Adding a source with [`POST /api/v2/projects/{slug}/sources/`](/api/add-source) returns `201 Created` instead of `200 OK`. - The `sources` array in the response now contains typed source objects with a `uuid`, which you can poll through [`GET /api/v2/projects/{slug}/sources/{source_uuid}/`](/api/get-source) to track ingestion. ### List sources: paginated response and new source types - v1 returned a bare JSON array of sources. v2 returns a paginated object, so read the sources from `results` instead of iterating the response directly. | Field | Description | | --- | --- | | `count` | Total number of sources matching the query. | | `next` | URL of the next page, or `null` on the last page. | | `previous` | URL of the previous page, or `null` on the first page. | | `results` | The sources on this page. | Page size defaults to 20 and is capped at 100. Use the `limit` and `offset` query parameters to page through a project with more sources than that, or follow `next` until it is `null`. - Source objects now include `created_at`, and the `type` enum adds `repository`, `openapi`, and `confluence`. If your integration validates `type` against a fixed list, update it. ## New in v2 These capabilities have no v1 equivalent: - **Projects**: create, list, update, and delete projects. - **Chats**: list chats, retrieve a full conversation, delete a conversation, and submit message feedback. - **Sources**: add GitHub repositories, OpenAPI specifications, and Confluence spaces, including private ones via a JSON body with credentials. - **Sync**: poll sync runs and read the event log for a run. - **Analytics**: read aggregate chat, search, MCP, and insights metrics. - **Teams**: manage the team that owns the API key, including members and invitations. The team response also reports subscription status and plan (`subscription`) and trial state (`trial`). - **Search click tracking**: report result clicks to improve search analytics. - **OpenAPI validation**: check an OpenAPI specification against the same checks Biel runs when it indexes it, so you can catch a spec that would fail to parse before the next sync. See the [API v2 reference](https://docs.biel.ai/api/biel-ai-api.md) for details. --- ## Re-crawl a single page Re-crawl one page and replace it in the project's search index, without touching the rest of the index. Returns immediately with `202`; the crawl runs in the background. Use this when one page changed. To re-crawl every source in the project, use [`POST /api/v2/projects/{slug}/sync/`](/api/sync-project) instead. ## Requirements - The URL must be on a host Biel.ai already crawls for this project: one of its embed domains, or the host of one of its URL or sitemap sources. Host matching is exact. A URL on any other host returns `400`, which keeps the endpoint from being used as a fetch-anything proxy. - The project must have been indexed at least once. Run a full sync first, until then this endpoint returns `409`. A page the index doesn't hold yet is added rather than replaced, and counts against your plan's page limit. ## Result reporting The `202` means the page was accepted and queued, not that it was indexed. The background job is fire-and-forget: if the page can't be fetched, is excluded by the project's URL filters, or produces no indexable content, the run is dropped and no status is reported back. The next call, or the next full sync, is the retry. Use [`GET /api/v2/projects/{slug}/search/`](/api/search-project) to confirm the new content is in the index. **Required permission:** `sync_create` Request --- ## Remove a team member Remove a member from the team. The `id` is the membership id returned by [`GET /api/v2/teams/{slug}/members/`](/api/list-team-members). The team's last admin cannot be removed. **Required permission:** `teams_update` Request --- ## Search project content Keyword search across indexed project content by default. Set `search_type=hybrid` to combine keyword matches and semantic similarity. Source selection is independent: omit `source_types` for web-page snippets, or supply a comma-separated list of `page`, `file`, `repository`, `openapi` (or `all`) to retrieve indexed chunks from those source categories without generating an answer. Document results include source type, full chunk text, and available page or worksheet references. Non-URL sources have `url: null`. Explicit source selections also include an opaque `document_id`. Pass it to `GET /api/v2/projects/{slug}/documents/{document_id}/` to read the complete indexed text, following continuation cursors for larger documents. References belong to this project and its current index; search again after an index refresh. This endpoint does not accept a `limit` parameter; the MCP search tool limits the results it presents to its caller. Hybrid retrieval requires an index with embeddings configured. Backend failures return an error without an automatic keyword fallback. Existing project access, domain, trial, and interaction-limit checks apply. URL-based `filter_title` filters exclude results without a matching URL. Each successful search counts as one interaction toward your team's allowance. With extra usage enabled, interactions beyond that allowance cost **$0.05** each. See [extra usage](https://docs.biel.ai/administration/subscription.md#extra-usage). **Required permission:** `search` (private projects only). Request --- ## Send a message Send a message and get an AI response. Returns 201 for new chats, 200 for existing ones. To append to the latest output-capped assistant response, omit message and send chat_uuid and continue_message_id. Continuation returns the same user_message_id and assistant messageId with the combined text. Existing conversations require X-Chat-Restore-Token in addition to project access. Chat and answer continuations consume interactions from your team's allowance. With extra usage enabled, interactions beyond that allowance cost **$0.05** each. See [extra usage](https://docs.biel.ai/administration/subscription.md#extra-usage). **Required permission:** `chats_create` Request --- ## Submit feedback for a message Record a like (`1`) or dislike (`0`) reaction on an AI-generated message. **Auth:** - Public projects: no API key required (the widget calls this endpoint client-side). - Private projects: API key with `search` permission. Request --- ## Start a sync Re-crawl all project sources and update the search index. Returns immediately; the crawl runs in the background. Poll [`GET /api/v2/projects/{slug}/sync/`](/api/get-sync-status), or the `last_sync` field from [`GET /api/v2/projects/{slug}/`](/api/get-project), to track completion. Calling this endpoint while a sync is already running cancels the in-progress run and starts a fresh one. When only one page changed, use [`POST /api/v2/projects/{slug}/recrawl/`](/api/recrawl-url) instead. It replaces that page in the existing index and leaves the rest of the project untouched. Rate limits may apply to this endpoint. **Required permission:** `sync_create` Request --- ## Track a search result click Register a click on a search result for analytics. Call this after the user clicks on a result returned by [`GET /api/v2/projects/{slug}/search/`](/api/search-project). Include the optional `query` and 1-based `position` when they are available to attribute the click to the result list that produced it. Clients that do not provide attribution can continue to send an empty body. **Required permission:** `search` (private projects only). Request --- ## Update a project Update one or more project settings. Only the supplied fields are modified. Feature configuration is grouped under `config` (for example, `config.mcp.enabled`). **Required permission:** `projects_update` Request --- ## Update a team member Change a member's role. The `id` is the membership id returned by [`GET /api/v2/teams/{slug}/members/`](/api/list-team-members). **Required permission:** `teams_update` Request --- ## Update team settings Update the team's `name` and/or `slug`. The `slug` in the path must match the team that owns the authenticating API key. Include only the fields you want to change. **Required permission:** `teams_update` Request --- ## Validate an OpenAPI specification Validate an OpenAPI specification against the same checks Biel runs when it indexes your spec, including `$ref` resolution. A `200` means the next sync will parse the spec; a `422` returns the validation errors it would fail with. Designed for CI/CD: publish your spec, call this endpoint, and fail the pipeline on a non-2xx status. This catches changes that would break API indexing before Biel's next sync does. Submit the spec either by `url` (Biel fetches it and resolves relative `$ref`s against it) or inline as `content` (JSON or YAML). **Required permission:** none. Any valid API key works. Request --- ## WebSocket API The WebSocket API enables real-time, streaming chat with your Biel.ai project. Use it when you need token-by-token AI responses instead of waiting for the full response via the [REST API](https://docs.biel.ai/api/biel-ai-api.md). Chat and answer continuations consume interactions from your team's allowance. With [extra usage](https://docs.biel.ai/administration/subscription.md#extra-usage) enabled, interactions beyond that allowance cost $0.05 each. **Endpoint:** `wss://app.biel.ai/ws/messages/{projectId}/` To continue an existing chat: `wss://app.biel.ai/ws/messages/chat/{chatId}/` ## Connect Open a WebSocket connection to: ``` wss://app.biel.ai/ws/messages/{projectId}/ ``` Replace `{projectId}` with your project slug (e.g., `jfvzioa17q`). ## Send a message Send a JSON message to the WebSocket: ```json { "projectId": "your-project-slug", "from": "user", "message": "How do I authenticate?", "url": "https://docs.example.com/auth", "email": "user@example.com" } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `projectId` | string | No | Project slug for client bookkeeping; the connection path selects the project. | | `from` | string | No | Client message label; use `"user"` when included. | | `message` | string | Yes | The user's message (Markdown supported). | | `chatId` | string | No | Chat session UUID. Omit for the first message — included in the AI response. | | `url` | string | No | Page URL where the chat is happening. Used for domain validation. | | `email` | string | No | Email or ID for conversation tracking. | | `apiKey` | string | No | API key with `chat_create` permission. Required for private projects. | | `thinkMode` | boolean | No | Enable reasoning mode for deeper analysis. | | `retrievalMode` | string | No | Regular-mode retrieval: `auto` or `instant`. Omit for the existing default. Unsupported values are ignored; `thinkMode: true` takes precedence. See [Reasoning modes](https://docs.biel.ai/customization/reasoning-modes.md). | | `capabilities` | array of strings | No | Include `"activity.v1"` together with a valid `requestId` to receive operational progress updates. | | `requestId` | string | No | Unique caller-generated identifier for this turn: 1–80 characters from `A-Z`, `a-z`, `0-9`, `.`, `_`, `:`, or `-`. Negotiating servers echo it on answer and status frames. | | `restoreToken` | string | No | Opaque conversation restore token returned by the server. Retain it with the chat ID and send it on subsequent turns. A chat ID alone is not authorization. | | `metadata` | string | No | Tag to identify the conversation source. | ## Receive a response The server sends JSON messages back. Partial messages stream token-by-token; the final message includes sources. ```json { "projectId": "your-project-slug", "chatId": "550e8400-e29b-41d4-a716-446655440000", "from": "ai", "messageId": "msg-uuid", "message": "To authenticate, use the...", "timestamp": "2026-01-15T10:30:00Z", "isPartial": false, "sources": [ { "title": "Authentication guide", "url": "https://docs.example.com/auth" } ] } ``` | Field | Type | Description | |-------|------|-------------| | `projectId` | string | Project slug. | | `chatId` | string | Chat session UUID. Use this in subsequent messages to continue the conversation. | | `from` | string | Always `"ai"`. | | `messageId` | string | Message UUID. | | `message` | string | AI response content (Markdown). | | `timestamp` | string | ISO 8601 timestamp. | | `isPartial` | boolean | `true` for streaming tokens, `false` for the final message. | | `sources` | array | Source references (only in final message). Each has `title` and `url`. | | `incomplete` | boolean | `true` if generation could not complete, including output limits or interruption. Only in the final message. | | `stopReason` | string | Provider stop reason or a classified recovery reason on the final frame. | | `continuationCount` | integer | Number of automatic continuations for this generation request. | | `continuationAvailable` | boolean | Whether the latest capped response can be continued through the REST API. | | `requestId` | string | Turn identifier, when progress was negotiated. May be absent on older servers. | | `restoreToken` | string | Opaque conversation restore token. Store it with `chatId`; older servers may omit it. | | `interrupted` | boolean | Optional negotiated marker that generation was interrupted. Keep any useful draft and offer an explicit retry. | | `isError` | boolean | Optional negotiated error marker. Do not treat an error message as a replacement for an existing draft. | | `retryable` | boolean | Optional negotiated indication that retry is appropriate. Wait for the connection to recover before sending a retry. | ## Receive progress updates To request progress, include both the capability and a new turn identifier in your message: ```json { "projectId": "your-project-slug", "from": "user", "message": "How do I authenticate?", "capabilities": ["activity.v1"], "requestId": "turn-1", "retrievalMode": "auto" } ``` A supporting server sends status frames alongside the answer stream: ```json { "type": "status", "version": 1, "requestId": "turn-1", "sequence": 2, "stage": "searching_docs", "state": "started", "detail": { "searchRound": 1 } } ``` | Field | Description | |-------|-------------| | `type`, `version` | `"status"` and `1` identify this progress extension. | | `requestId` | Identifies the active turn. | | `sequence` | Increases within each turn, starting at 1. | | `stage` | `contextualizing`, `searching_docs`, `reviewing_results`, `preparing_docs`, `searching_web`, `writing_answer`, `checking_sources`, `completed`, `failed`, or `interrupted`. | | `state` | `started`, `completed`, or `failed`. | | `detail` | Optional details within the object: `searchRound`, `documentCount`, `reason`, or `retryable`. `reason` can be `generation_failed`, `stream_interrupted`, or `disconnected`. | Status frames describe actual operations, rather than private model reasoning. They have no `from` or `message` field: handle them separately from chat messages. Only accept supported frames for the active turn and ignore stale or duplicate sequence numbers. Not every operation appears in every answer, and a final `completed` status can arrive after the final answer. Hide successful progress when the final answer arrives. Preserve a useful interrupted draft and let the user choose whether to retry; do not automatically replay requests. The widget follows this behavior and offers [spinner or loading dots](https://docs.biel.ai/customization/chat-progress.md) as a display option. ### Compatibility Clients that omit progress negotiation retain the existing answer stream, without status frames. New clients must also accept answers from older servers that omit `requestId`, `restoreToken`, and progress updates. Keep a generic loading indicator in that case. Updating the backend alone does not change an older installed widget's interface. ## Authentication The WebSocket API uses the same authentication model as the [REST API](https://docs.biel.ai/api/biel-ai-api.md): - **Public projects** — No API key required. Domain restrictions still apply. - **Private projects** — Include `apiKey` in the first message payload with `chat_create` permission. Domain validation is checked on every message using the `url` field. If your project has allowed domains configured, the `url` must match one of them. ## Rate limiting | Limit | Threshold | Penalty | |-------|-----------|---------| | Per chat session | 15 messages/minute | Rejected until window resets | | Per IP address | 100 messages/minute | IP blocked for 1 hour | | Burst detection | 10 messages within a 30-second window | Rejected while the burst threshold is met | ## Continue a capped answer Automatic continuation happens on the backend for both REST and WebSocket clients. For a manual continuation, use the [REST message endpoint](https://docs.biel.ai/api/send-message.md) with `chat_uuid` and `continue_message_id`, omit `message`, and send the stored restore token in `X-Chat-Restore-Token`. The response contains the original assistant message UUID and its complete text including the appended suffix. Replace that message in your UI; do not append a new user or assistant turn. --- ## Accessibility Both the chat and search widgets ship with keyboard and screen reader support enabled by default. This page describes that behavior and the properties you can use to adjust it. ## Keyboard support ### Chat modal | Key | Action | | --- | --- | | Tab | Moves to the next control. While the modal is open, focus stays inside it. | | Shift + Tab | Moves to the previous control, also confined to the modal. | | Esc | Closes the modal. | | Enter | Sends the message when the input has focus. | ### Search modal | Key | Action | | --- | --- | | Tab and Shift + Tab | Move between controls, confined to the modal. | | ↓ and ↑ | Move through the search results. | | Enter | Opens the selected result. | | Ctrl or Cmd + Enter | Opens the selected result in a new tab. | | Esc | Closes the modal. | Set `hide-navigation-buttons` to `true` to hide the on-screen hints for these keys. The shortcuts keep working. ## Focus behavior When either modal opens, focus moves to its input unless `disable-autofocus` is enabled. Focus stays inside the modal for as long as it is open. When the modal closes, focus returns to the element that opened it, usually the chat or search button, so keyboard users resume where they left off. In [embedded mode](https://docs.biel.ai/customization/embedded-mode.md), the assistant is part of the page rather than an overlay. It does not trap focus or respond to Esc, and it is exposed as a labelled region rather than a dialog, since there is no dialog to open or close. ## Disabling Esc to close If your site already binds Esc to something else, set `escape-close` to `false` on `` or `` directly. The launcher components `` and `` do not expose this property: ```html ``` With `escape-close` set to `false`, the close button and clicking outside the modal continue to work. ## Closing by clicking outside Both modals close when you click outside them. On `` or `` directly, set `click-outside-close` to `false` to require the close button or Esc instead: ```html ``` Clicks that begin inside the widget are ignored, so selecting text in an answer and releasing the mouse past the edge does not close it. In embedded mode the assistant is inline content, so it ignores clicks outside as well as Esc. ## Screen reader labels Both modals expose themselves as dialogs, except the assistant in embedded mode, which is a labelled region. The chat modal is named by its `header-title` and the search modal by its `search-placeholder`, so setting those to something meaningful for your site also improves what screen readers announce: ```html Ask AI ``` The controls are named by their tooltip text, which you can translate with `close-button-text`, `expand-button-text`, `collapse-button-text`, `refresh-button-text`, `settings-button-text`, and `connect-button-text`. See [Widget customization](https://docs.biel.ai/customization/layout.md) for the full list. Setting `hide-tooltips` to `true` hides the tooltips visually but keeps these accessible names, so screen reader users are unaffected. ## Color contrast If you override the widget colors, check the resulting combinations against the [WCAG contrast guidelines](https://www.w3.org/WAI/WCAG21/quickref/#contrast-minimum), particularly for placeholder text and source links, which sit on lighter backgrounds than the rest of the modal. See [Styles](https://docs.biel.ai/customization/styles.md) for the available custom properties. --- ## Actions Actions are clickable buttons that Biel.ai can add to assistant answers. Each action has a trigger that describes when the button should appear. For example, you can show a **Contact support** button when a user reports a problem, or a **Book a call** button when they ask about enterprise pricing. Unlike suggested questions, which appear when the chat opens, actions only appear when their trigger matches the user's message. ## Common uses Actions give users a clear next step without making them leave the conversation first. | Button | Appears when | | --- | --- | | Open a support ticket | A user reports a problem the assistant cannot resolve. | | Book a call | A user asks about pricing or enterprise plans. | | Start a trial | A user asks how to get started. | ## How actions work 1. You create an action with a name, trigger, button label, and URL. 2. When a user sends a message, Biel.ai checks the message against each action's trigger. 3. If a trigger matches, Biel.ai adds the corresponding button to the answer. 4. An answer can contain no actions, one action, or several actions. 5. In the web widget, the action appears as a button. In integrations such as Slack, it appears as a link. The trigger is sent to the LLM to determine whether the action is relevant, but users never see it. The URL is attached to the button by Biel.ai. It does not appear in the answer text unless you include it there yourself. ## Action fields | Field | Description | | --- | --- | | **Name** | Internal identifier for the action. Use only letters, numbers, hyphens, and underscores, for example `contact_support`. Each name must be unique within the project. | | **When to use** | Plain-language description of when the action should appear. Biel.ai uses this as the trigger, so describe the user's intent and situation as specifically as possible. | | **Button text** | Label shown to the user, for example `Contact support`. | | **URL** | Address that opens in a new tab when the user clicks the button. The URL can include [conversation placeholders](#pass-conversation-context). | ## Pass conversation context When an action opens a form or external tool, that destination does not automatically receive the conversation context. You can include placeholders in the **URL** to pass useful information, such as the conversation ID, the user's latest question, or a link back to the conversation. For example: ```text https://support.example.com/new?conversation_id={chat_id} ``` Before showing the button, Biel.ai replaces each placeholder with its value. You can map these values to any field your destination supports, such as a subject line, hidden form field, or query parameter. ### Available placeholders | Placeholder | Value | | ------------ | ---------------------------------------------------------------------------------------------------- | | `{chat_id}` | The conversation ID. Use the **Conversation ID** filter on the project's **Chats** tab to find it. | | `{chat_url}` | Direct link to the conversation in the Biel.ai dashboard. The viewer must be signed in to your team. | | `{question}` | The user's most recent message, up to 500 characters. | Placeholder values are URL-encoded. Characters such as `&` and `?` in a user's message therefore cannot break the rest of the URL. If a placeholder has no value, Biel.ai replaces it with an empty value rather than leaving the placeholder text in the URL. ### Example The following support action passes the user's latest question and a link to the conversation: ```text https://support.example.com/new?subject={question}&conversation={chat_url} ``` This can help the person receiving the request understand what the user was asking without requiring the user to repeat the context. ## Configure an action 1. In the [Biel.ai dashboard](https://app.biel.ai), select your project. 2. Click **Settings**. 3. Open **Assistant** in the left sidebar and, under **Actions**, click **Add action**. 4. Enter the **Name**, **When to use**, **Button text**, and **URL**. Use a name such as `contact-support` without spaces; the button text can be `Contact support`. ![Configure a Contact support action](./images/settings-chatbot-actions.jpg) 5. Click **Save** on the Actions card. Biel.ai rejects URLs that contain unrecognized placeholders, so placeholder typos are caught when you save the action. You can add as many actions as you need. After creating an action, open the assistant on your site and send a message that should match its trigger. Verify that the expected button appears. ## Write effective triggers The **When to use** field determines whether Biel.ai considers an action relevant. Clear, specific triggers make actions more likely to appear at the right time. * **Describe the user's intent.** Write `When the user asks to talk to a human, reports a billing problem, or expresses frustration` instead of `Show the support button`. * **Name the situations the action covers.** Broad triggers can cause buttons to appear too often. For example, `When the user needs help` could match almost any support question. * **Keep triggers distinct.** If multiple actions have overlapping triggers, Biel.ai may show more than one button. This is useful when both actions are relevant, but avoid overlap when it would confuse the user. For example, this trigger is too broad: ```text When the user needs help. ``` A more useful trigger describes the situations that should lead to the action: ```text When the user reports a bug, says something is not working, or asks to talk to a person. ``` --- ## Chat progress The assistant shows a spinner and the current operation while preparing an answer in Auto, Instant, and Think modes, including chat opened through **Ask AI** in the search widget. Labels describe operations such as **Searching documentation**, **Searching documentation again**, and **Writing your answer**. They reflect work performed; they do not expose the model's private reasoning. Hovering the spinner does not open a popup. The indicator disappears after successful completion, leaving the answer in the chat. Progress updates require both a supporting widget version and backend. Older installed widget versions continue using their existing interface. Update your installed widget package to use the options below; a backend update alone does not update it. ## Use loading dots Set `loading-indicator="dots"` to use the previous bouncing dots animation instead of the spinner and visible progress text: ```html Ask AI ``` The option works on ``, ``, ``, and ``. On the search widgets, it controls the assistant shown after selecting **Ask AI**. | Attribute | Default | Description | | --- | --- | --- | | `loading-indicator` | `spinner` | `spinner` shows the current operation; `dots` shows bouncing dots without visible progress text. | | `loading-text` | `Loading…` | Fallback label before a progress update arrives, or when the backend does not provide updates. | Dots keep progress announcements available to screen readers. Interrupted or failed answers still show their status and **Retry** when available. ## Set the fallback loading text Use `loading-text` to translate the initial loading label: ```html ``` After the first progress update, the current operation replaces this fallback label. With dots, the label remains available to screen readers without appearing visually. You can also set these options as JavaScript properties on any of the four widgets: ```javascript const widget = document.querySelector('biel-button'); widget.loadingIndicator = 'dots'; widget.loadingText = 'Chargement…'; ``` ## Recover an interrupted answer If generation fails or the connection interrupts an answer, the widget keeps any text already received. When retry is available, **Retry** sends the last request again after the connection is ready. It creates a new response in the conversation; it does not resume the interrupted response. Requests are not automatically resubmitted. **Continue generating** serves a different purpose: when an answer reaches its length limit, it asks the assistant to continue from where it left off in the same conversation. Continuations consume interactions from your team's allowance. With [extra usage](https://docs.biel.ai/administration/subscription.md#extra-usage) enabled, continuations beyond the included allowance cost $0.05 per interaction. ## Customize the indicator Change the spinner color independently of the rest of the widget with [`--biel-activity-spinner-color`](./styles.mdx). Use [`--biel-loading-dot-color`](./styles.mdx) for loading dots, or target the [spinner CSS part](https://docs.biel.ai/customization/styles.md) for finer control. --- ## Prompt customization Biel.ai offers two modes for controlling how the assistant responds: **Default prompt** (optimized for technical documentation) and **Custom prompt** (full control). ## Default prompt The default prompt gives clear, step-by-step technical answers based on your documentation. It asks clarifying questions when a request is unclear and says when the documentation does not contain enough information instead of guessing. You can extend the default prompt with additional instructions—for example, adding a signature to responses or modifying the tone. Prompt extensions are limited to `6,000` characters. ## Custom prompt Write your own prompt for full control over the assistant's behavior. Custom prompts are limited to `8,000` characters. :::warning Custom prompts may disable built-in safeguards and advanced processing features. ::: ## Configure the prompt :::important Only **Administrator** or **Maintainer** roles can manage projects. See [Manage roles](https://docs.biel.ai/administration/roles.md). ::: 1. In the Biel.ai dashboard, select your project. 2. Click **Settings**. 3. Open **Assistant** in the left sidebar and, under **AI model and instructions** > **Define prompt**: ![The AI model and instructions section with the Define prompt options](./images/settings-chatbot-llm-settings-default-prompt.jpg) - Select **Use default prompt** and optionally add instructions in **Extend prompt**, or - Select **Custom prompt** and write your full instructions in **Extend prompt**. 4. Click **Save** on the AI model and instructions card. ### Examples **Extending the default prompt:** ``` Always start responses with "Hi!" ``` **Custom prompt:** ``` You are a customer support assistant for [Product Name]. Provide clear, accurate answers related to product features, troubleshooting, and usage. Keep responses professional and focused on the product. Only respond based on the information you can extract from CONTEXT and the conversation HISTORY. ``` --- ## Dark mode To enable dark mode in the Biel.ai chat widget, set `data-theme="dark"` on your site's `` tag. The widget detects the attribute and switches automatically, so it always matches your site's active theme. ## Automatic theme switching The widget follows changes to `data-theme` in real time. If your framework uses a different theme attribute or class, synchronize its theme with `data-theme` on ``. Setting another framework's theme alone does not change the widget palette. ## Force dark mode permanently If your site is always dark, add the attribute statically: ```html ``` The widget renders in dark mode for every visitor, regardless of their system's `prefers-color-scheme` setting. ## Customize dark mode colors Dark mode uses the widget's default dark palette. To adjust individual colors (background, text, buttons), override the `--biel-*` CSS variables — see [Styles](https://docs.biel.ai/customization/styles.md) for the full variable list. --- ## Data privacy Configure how Biel.ai stores chat message text and IP addresses, and whether the widget asks users to accept your terms. :::important Only **Administrator** or **Maintainer** roles can manage projects. See [Manage roles](https://docs.biel.ai/administration/roles.md). ::: ## Remove personally identifiable information Biel.ai can detect and redact names, emails, and phone numbers from chat message text before saving it. Detected values are replaced with redaction placeholders. 1. In the [Biel.ai dashboard](https://app.biel.ai), select your project. 2. Click **Settings**. 3. Under **Security & Privacy** > **Data Privacy**, enable **Remove personally identifiable information (PII)**. ![Remove personally identifiable information (PII) setting](./images/settings-security-data-privacy-remove-pii.jpg) 4. Click **Save** on the Data Privacy card. Future conversations automatically redact PII. ## Disable IP address collection Stop saving user IP addresses with chats and messages. This changes how analytics estimates unique users: chats without a saved IP each count as one user. Country information can still be derived from the request. 1. In the [Biel.ai dashboard](https://app.biel.ai), select your project. 2. Click **Settings**. 3. Under **Security & Privacy** > **Data Privacy**, enable **Disable IP address collection**. ![Disable IP address collection setting](./images/settings-security-data-privacy-disable-ip-collecton.jpg) 4. Click **Save** on the Data Privacy card. ## Require Terms & Conditions acceptance Require users to accept Terms & Conditions before starting a conversation. ![Assistant widget for docs](./images/accept-terms-and-conditions.jpg) Add these attributes to your ``: ```html Ask AI ``` Replace `` with your project ID. Update the `terms-description` link to point to your own Terms & Conditions. --- ## Confluence as a data source Connect a Confluence Cloud space to Biel.ai to index your team's pages and make them searchable through the assistant. ## Prerequisites - A [Biel.ai account](https://app.biel.ai/accounts/signup/). - An existing [project](https://docs.biel.ai/quickstart.md#2-create-a-project). - An Atlassian account with access to the Confluence pages you want to index. - Confluence Cloud (Server is not supported). ## 1. Generate a Confluence API token 1. Open your [Atlassian account's API tokens](https://id.atlassian.com/manage-profile/security/api-tokens). 2. Click **Create API token**, enter a name, and select an expiration date. Use a token without scopes for Biel.ai's connection to your site's URL. 3. Click **Create**, then **Copy to clipboard**. You cannot view the token again after closing this screen. See [Manage API tokens for your Atlassian account](https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/) for details. ## 2. Connect Confluence to Biel.ai 1. In the [Biel.ai dashboard](https://app.biel.ai), select your project. 2. Go to **Settings** > **Sources** > **Confluence**. 3. Enter the space URL, such as `https://yourcompany.atlassian.net/wiki/spaces/DOCS`. 4. Click the settings icon beside the URL to show **Credentials**, then enter your Atlassian account **Email** and **API Token**. ![The Confluence tab of the Sources settings page with Space URL and credentials](../images/settings-sources-confluence.jpg) 5. Click **Save**. 6. Click **Refresh sources** to index the space's pages. :::tip[Finding your space URL] Navigate to any page in your Confluence space and copy the URL up to `/spaces/SPACENAME`. ::: Monitor the loading status in the project dashboard and open **Logs** to check which pages were indexed. ## Troubleshooting ### Authentication failed - Verify your email matches your Atlassian account. - Check the API token is correct and hasn't expired. - Ensure you have access to the specified space. ### Pages not indexing - Check that pages are published (not drafts). - Verify space permissions allow API access. - Large spaces may take longer to process. ### Content quality issues - Confluence macros may not render properly in AI responses. - Consider excluding template or boilerplate pages with URL filters. --- ## Files Upload documents directly to your project. Biel.ai indexes their content for chat responses. :::tip Uploaded files remain private. Your assistant does not expose a link to the stored file as a source. ::: ## When to use file uploads Use file uploads for: - Internal documents such as handbooks, policies, and procedures - Offline content that is not published on the web - PDF manuals, Office documents, and spreadsheets - Confidential content that needs to stay private ## Supported formats | Format | Extensions | |--------|------------| | PDF | `.pdf` | | Word | `.docx` | | PowerPoint | `.pptx` | | Excel | `.xlsx` | | Delimited data | `.csv` | | Markdown and text | `.md`, `.txt` | | Structured data | `.yaml`, `.yml`, `.json`, `.xml` | | Documentation and web files | `.rst`, `.html`, `.css`, `.js` | ## Requirements - Each file can be up to 10 MB. - Use the listed extension. Legacy Office formats such as `.doc`, `.xls`, and `.ppt` are not supported. - Files must not be empty or password-protected. ## Upload files 1. In the [Biel.ai dashboard](https://app.biel.ai), select an existing project. Files are available after you create the project. 2. Go to **Settings** > **Sources** > **Files**. ![The Files tab of the Sources settings page with the upload area](../images/settings-sources-files.jpg) 3. Drag files into the upload area, or click **Browse files**. Files upload automatically; wait until they appear in the uploaded-file list. 4. Click **Refresh sources** to index the files. Check the loading status and **Logs** in the project dashboard. ## How files are indexed Biel.ai processes PDF, Word, and PowerPoint files page by page. It processes each Excel sheet separately. This keeps retrieved content aligned with the page or sheet where it came from. Scanned PDFs are processed with OCR. Clear, high-resolution scans generally produce better results than low-quality scans or pages with difficult layouts. ## Manage files For text and HTML files, use the **Preview** or **Edit** icon next to the file. After editing, click **Save** in the editor. For other formats, delete the old version and upload the replacement. Click **Refresh sources** after changing files to index the current set. Use the **Download** icon next to an uploaded file in **Settings** > **Sources** > **Files** to retrieve the original file. To remove a file, click its **Delete** icon. ## Troubleshooting ### Upload failures - Check that the file is no larger than 10 MB. - Verify the file format is [supported](#supported-formats). - Check that the file is not empty, corrupt, or password-protected. ### Content not indexing - Refresh sources after upload, then allow the crawl to finish. - For scanned PDFs, use a clear scan with legible text. - If a large document is only partly indexed or a crawl reports that files were skipped, try refreshing sources again. [Contact us](https://biel.ai/contact) if the problem continues. --- ## GitHub repositories Add GitHub repositories to include documentation, README files, and code comments in your assistant's knowledge base. :::tip File content remains private. Your assistant won't expose file links as sources to users. ::: ## When to use GitHub repositories Use GitHub repositories for: - Documentation stored with code (README files, docs folders) - Private internal documentation - API documentation and code examples - Developer guides and technical content ## Add a repository 1. In the [Biel.ai dashboard](https://app.biel.ai), select your project. 2. Go to **Settings** > **Sources** > **GitHub**. ![The GitHub tab of the Sources settings page with advanced options](../images/settings-sources-github.jpg) 3. Enter the repository URL (e.g., `https://github.com/owner/repo`). 4. Click **Save**. 5. Click **Refresh sources** to index the repository. Check the loading status and **Logs** in the project dashboard. ### Private repositories Private repos require a GitHub personal access token: 1. Go to [GitHub Settings > Personal access tokens](https://github.com/settings/tokens). 2. Click **Generate new token (classic)**. 3. Select the `repo` scope and click **Generate token**. 4. Copy the token. 5. In Biel.ai, click the settings icon beside the repository URL to expand **Advanced options**, then paste the token in **GitHub token**. 6. Click **Save**, then **Refresh sources**. ## Filter files Control which files get indexed using include and exclude patterns. Open the repository's **Advanced options** and enter comma-separated values in **Include patterns** or **Exclude patterns**. Click **Save**, then **Refresh sources** to apply them. | Pattern | Action | Effect | |---------|--------|--------| | `*.md` | Include | Only Markdown files | | `docs/` | Include | Only files in docs folder | | `*.rst` | Include | Only reStructuredText files | | `node_modules/` | Exclude | Skip dependencies | | `.git/` | Exclude | Skip Git metadata | | `*.test.*` | Exclude | Skip test files | | `build/` | Exclude | Skip build artifacts | ## Advanced options * **Multiple repositories**: Add different repositories as separate sources * **Branch selection**: Default branch is indexed (usually `main` or `master`) * **Submodules**: Not automatically indexed—add as separate sources ## Troubleshooting ### Repository not found - Check URL format: `https://github.com/owner/repo`. - For private repos, verify the token has `repo` scope and hasn't expired. ### Files not indexing - Check that include patterns match your file paths. - Review exclude patterns for over-exclusion. - Verify files are in supported formats (Markdown, plain text, reStructuredText). ### Token issues - Confirm the token has `repo` scope. - Regenerate the token if it has expired. - Check that repository permissions haven't changed. --- ## OpenAPI # OpenAPI documents Add OpenAPI specs to index API documentation. Structured YAML/JSON is parsed more accurately than crawling API docs websites — all endpoints, parameters, and schemas are captured. :::tip File content remains private. Your assistant won't expose file links as sources to users. ::: ## Requirements - Valid OpenAPI/Swagger syntax (versions 2.0, 3.0.x, 3.1.x). - JSON (`.json`) or YAML (`.yaml`, `.yml`) format. - Publicly accessible URL. ## Add an OpenAPI document 1. In the [Biel.ai dashboard](https://app.biel.ai), select your project. 2. Go to **Settings** > **Sources** > **OpenAPI**. 3. Enter the document URL. ![The OpenAPI tab of the Sources settings page](../images/settings-openapi.jpg) 4. To add another specification, click **Add OpenAPI URL** and enter its URL. 5. Click **Save**. 6. Click **Refresh sources** to index the specifications. Check the loading status and **Logs** in the project dashboard. Example URLs: ```text https://api.example.com/openapi.json https://docs.example.com/swagger.yaml https://api.example.com/v1/openapi.yml ``` ## Troubleshooting ### Document not loading - Check the URL is publicly accessible. - Verify valid OpenAPI syntax. ### Validation errors - Check logs for validation details. - Fix syntax errors and click **Refresh sources**. --- ## Sources overview Configure content sources that your assistant uses to answer questions. Sources determine what information is available to users. :::important Only Administrator and Maintainer roles can manage sources. See [Manage roles](https://docs.biel.ai/../administration/roles.md). ::: ## Source types
Sitemaps Add entire websites using XML sitemaps
URLs Add individual web pages
Files Upload documents in PDF, Word, Excel, and other formats
GitHub Add code repositories and their documentation
Confluence Import from Confluence
OpenAPI Add OpenAPI/Swagger specifications for API documentation
Private content Manage private and authenticated content
## Add a source 1. In the [Biel.ai dashboard](https://app.biel.ai), select your project. 2. Go to **Settings** > **Sources**. ![The Sources settings page with the source type tabs](../images/setting-sources.jpg) 3. Choose a source type and configure it. 4. Click **Save**. 5. Click **Refresh sources** to index the updated content. The project dashboard shows **Sources loading** while content is being indexed and **Sources loaded** when it finishes. Open **Logs** to check which pages were processed, then test your assistant. To upload files, create the project first, then open **Settings** > **Sources** > **Files**. Uploads are saved as soon as they finish; click **Refresh sources** to index them. --- ## Private content Biel.ai can access content behind login pages and VPN protection. This requires custom configuration and a Business or Enterprise plan. Contact [info@biel.ai](mailto:info@biel.ai) to discuss your requirements. --- ## Sitemaps Add entire websites using XML sitemap files. Sitemaps efficiently index large amounts of content from a single domain. ## When to use sitemaps Use sitemaps to: - Add complete documentation sites or blogs - Index hundreds or thousands of pages efficiently - Automatically discover new pages as they're added - Handle structured website content ## Requirements Sitemaps must: - End with `.xml` - Be publicly accessible - Follow the [XML Sitemap Protocol](https://www.sitemaps.org/) Supported types: - Standard sitemaps (single XML files) - Sitemap indexes (reference multiple sitemaps) - Nested sitemaps (linked sitemaps) ## Add sitemaps 1. In the [Biel.ai dashboard](https://app.biel.ai), select your project. 2. Go to **Settings** > **Sources** > **Sitemaps**. ![The Sitemaps tab of the Sources settings page](../images/settings-sitemaps.jpg) 3. Enter the sitemap URL (must end in `.xml`). 4. Click **Save**. 5. Click **Refresh sources** to discover and index the sitemap's pages. Check the loading status and **Logs** in the project dashboard. Example sitemap URLs: ``` https://docs.example.com/sitemap.xml https://blog.example.com/sitemap.xml https://help.example.com/sitemap_index.xml ``` ## Find sitemaps Common locations: ``` https://yoursite.com/sitemap.xml https://yoursite.com/sitemap_index.xml https://yoursite.com/sitemaps/sitemap.xml ``` Platform-specific patterns: | Platform | Sitemap URL | |----------|-------------| | Docusaurus | `https://yoursite.com/sitemap.xml` | | GitBook | `https://yourorg.gitbook.io/sitemap.xml` | | WordPress | `https://yoursite.com/wp-sitemap.xml` | For other platforms, check `robots.txt` at `https://yoursite.com/robots.txt` for sitemap declarations. ## Filter URLs Use URL filters to decide which pages from your sitemaps Biel indexes. Each filter has a [regular expression pattern](https://docs.python.org/3/library/re.html#regular-expression-syntax) and an action: **Include** or **Exclude**. Biel compares the pattern with the complete URL, such as `https://docs.example.com/guides/install/`. 1. Go to **Projects** > your project > **Settings** > **Sources** > **Sitemaps**. 2. Add one or more filter rules under **Filter URLs**. ![Filter URLs with include and exclude rules under the Sitemaps tab](../images/settings-sources-sitemap-filter-urls.jpg) 3. Click **Save**, then **Refresh sources** to apply the filters to the next crawl. ### Choose an action - If no include rules exist, all URLs are included by default. - If include rules exist, a URL is kept when it matches any include pattern. - An exclude rule always takes precedence: a matching URL is skipped even when it also matches an include rule. Filters apply to URLs from every sitemap configured in the project. ### Write a URL pattern Start with the part of the URL you want to match. For example, this include pattern keeps documentation paths on any configured domain: ```regex /docs(?:/|$) ``` Use regular expression syntax rather than wildcard syntax: write `/docs(?:/|$)`, not `**/docs/**`. Patterns are case-sensitive. To restrict a rule to one domain, match from the beginning of the complete URL: ```regex ^https://docs\.example\.com/guides(?:/|$) ``` In this pattern: - `^` means the match must start at the beginning of the URL. - `docs\.example\.com` matches the domain; `\.` represents a literal dot. - `/guides(?:/|$)` matches `/guides`, everything below it, and no similarly named path such as `/guides-old`. You can omit `^https://` when a path pattern should apply to every configured domain. ### Examples | Pattern | Action | Effect | |---|---|---| | `^https://docs\.example\.com/docs(?:/|$)` | Include | Only index `/docs` and pages below it on this domain | | `/api(?:/|$)` | Exclude | Skip API reference paths on any configured sitemap domain | | `/deprecated(?:/|$)` | Exclude | Skip deprecated sections | | `^https://docs\.example\.com/(?:en|fr)(?:/|$)` | Include | Only index English and French paths | | `\.pdf(?:$|[?#])` | Exclude | Skip PDF URLs | | `/[0-9]+\.[0-9]+\.[0-9]+(?:/|$)` | Exclude | Skip versioned paths such as `/1.2.3/` | To include selected sections from different domains, create one include rule per section. For example: | Pattern | Action | |---|---| | `^https://docs\.example\.com(?:/|$)` | Include | | `^https://example\.com/extensions/product(?:[-/]|$)` | Include | | `^https://example\.com/api/Product(?:[./]|$)` | Include | All other sitemap URLs are omitted because they do not match an include rule. You do not need to create exclude rules for every unrelated path. Avoid broad catch-all rules unless they are intentional: - An include rule containing `.*` includes every URL. - An exclude rule containing `.*` excludes every URL. ## Sitemap index files Large sites often use index files that reference multiple sitemaps: ```xml https://example.com/docs-sitemap.xml https://example.com/blog-sitemap.xml ``` Biel.ai automatically follows sitemap indexes and processes all referenced sitemaps. ## Troubleshooting ### Sitemap not found - Check URL format (must end with `.xml`). - Try common sitemap locations listed in [Find sitemaps](#find-sitemaps). - Check `robots.txt` for sitemap declarations. ### Partial indexing - Verify pages in the sitemap are publicly accessible. - Review URL filters for over-exclusion. - JavaScript-heavy pages may not index properly. --- ## URLs Add individual web pages to your project. Use URLs when you need specific pages rather than entire websites. :::tip For multiple pages from the same website, use [sitemaps](https://docs.biel.ai/customization/data-sources/sitemaps.md) instead. ::: ## When to use URLs Use URLs to: - Add specific pages from different websites - Test new content before adding full sites - Include only high-priority pages from larger sites - Add pages that aren't in sitemaps ## Requirements - Publicly accessible (not behind login). - Full URL with protocol (e.g., `https://example.com/page`). - Page contains text content (not just images or videos). ## Add URLs 1. In the [Biel.ai dashboard](https://app.biel.ai), select your project. 2. Go to **Settings** > **Sources** > **URLs**. ![The URLs tab of the Sources settings page](../images/setting-sources-urls.jpg) 3. Enter the full URL (including `https://`). 4. Click **Save**. 5. Click **Refresh sources** to index the pages. Check the loading status and **Logs** in the project dashboard. Example URLs: ``` https://example.com/blog/getting-started https://docs.example.com/api-reference https://support.example.com/troubleshooting ``` ## Troubleshooting ### URL not indexing - Verify the URL is publicly accessible. - Check the URL includes `https://`. - Check if the site blocks crawlers in `robots.txt`. ### Content not appearing - Wait 5-10 minutes for processing. - Test with specific questions about the page content. - Check if the page relies on JavaScript to render content. --- ## Embedded mode Embedded mode renders the assistant inline in your page layout instead of as a floating button. Use it to build dedicated help pages or embed the assistant within a specific section of your site. ## Preview ## Add embedded mode Add the following to your HTML: ```html ``` Replace `` with your project's ID from the [Biel.ai dashboard](https://app.biel.ai). --- ## Initial message The initial message is the first text the assistant displays when a user opens it. Use it to greet visitors, provide instructions, or set the tone. :::important Only **Administrator** or **Maintainer** roles can manage projects. See [Manage roles](https://docs.biel.ai/administration/roles.md). ::: ## Customize the initial message 1. In the [Biel.ai dashboard](https://app.biel.ai), select your project. 2. Click **Settings**. 3. Open **Assistant** in the left sidebar and enter your text in **Conversation** > **Welcome message**. ![The Conversation section with the Welcome message field](./images/settings-chatbot-conversaton-ui.jpg) 4. Click **Save** on the Conversation card. Open the assistant on your site to verify the updated message appears. --- ## Widget customization Configure the assistant and search widgets by setting HTML attributes. Override text properties to localize the widget. ## biel-button The `` component adds a floating AI chat button to your site. Use `` to render the same assistant inline; it accepts the assistant modal properties below. See [Embedded mode](https://docs.biel.ai/customization/embedded-mode.md). ![Biel bot](./images/biel-widget-docs.jpg) ### Usage ```html Ask AI ``` ### Assistant button properties {#chatbot-button-properties} | Property | Description | |------------------------|-----------------------------------------------------------------------------------------------| | **Layout** | | | | `project` | **Required****Type**: `string`The project ID. | | `button-position` | **Type**: `string`**Default value**: `default`**Available values:** `default`, `bottom-right`, `bottom-left`, `center-right`, `center-left`, `custom` Controls the position of the chat button on your webpage. Use `custom` to position the button using CSS.| | `button-style` | **Type**: `string`**Default value**: `default`**Available values:** `default`, `dark`, `light`Defines the visual style of the chat button. `dark` and `light` choose a launcher palette; `default` inherits the page styling. The modal theme is controlled separately by `data-theme`.| | `custom-font` | **Type**: `boolean`**Default value**: `false`When set to `true`, disables loading of the Inter font. Use this if your site already uses a different font to improve load time and maintain font consistency.| | `hide-icon` | **Type**: `boolean`**Default value**: `false`When set to `true`, the button icon hides. | | `ai-icon` | **Type**: `string`**Default value**: `biel`**Available values:** `biel`, `bot`, `sparks`, `question-mark`Specifies which AI icon to display in the button.| | `hide-avatars` | **Type**: `boolean`**Default value**: `false`When set to `true`, hides avatars in the chat interface.| | `api-key` | **Type**: `string`**Default value**: ``API key for authenticating requests to private projects. Required for private projects with `chat_create` and `project_read` permissions. Not required for public projects.| | `api-url` | **Type**: `string`**Default value**: Biel.ai APIOverride the base API URL for self-hosted or custom endpoints.| The "Powered by Biel.ai" branding is controlled by your team's **Remove 'Powered by Biel.ai' branding** setting. An eligible plan enables that setting; you still need to activate it and click **Save details**. See [Whitelabel](https://docs.biel.ai/administration/whitelabel.md). ### Assistant modal properties {#chatbot-modal-properties} | Property | Description | |------------------------|-----------------------------------------------------------------------------------------------| | **Layout** | | | | `disable-input` | **Type**: `boolean`**Default value**: `false`When set to `true`, the user input field is disabled. | | `disable-autofocus` | **Type**: `boolean`**Default value**: `false`When set to `true`, opening the assistant does not focus the message input automatically. | | `email` | **Type**: `string`**Default value**: `` An email address or ID for conversation tracking. This ID will be associated with the chat session in your project dashboard for analytics and user tracking purposes. | | `metadata` | **Type**: `string`**Default value**: ``Custom metadata to attach to chat sessions. Use this to pass additional contextual information (e.g., user plan, page URL, or other identifiers) that will be associated with the conversation for analytics purposes. | | `expand-modal` | **Type**: `boolean`**Default value**: `false`When set to `true`, the chat modal opens in its expanded state by default. | | `hide-close-button` | **Type**: `boolean`**Default value**: `false`When set to `true`, the close icon hides. | | `hide-expand-button` | **Type**: `boolean`**Default value**: `false`When set to `true`, the expand button icon hides. | | `hide-refresh-button` | **Type**: `boolean`**Default value**: `false`When set to `true`, the refresh button hides. | | `hide-feedback` | **Type**: `boolean`**Default value**: `false`When set to `true`, removes the feedback options (like thumbs up/down) that users can use to rate AI responses. | | `hide-sources` | **Type**: `boolean`**Default value**: `false`When set to `true`, hides the sources section from AI responses in the chat interface. | | `hide-inline-citations` | **Type**: `boolean`**Default value**: `false`When set to `true`, removes numeric inline citations from AI answers and their numbers from source cards. The sources section remains available unless `hide-sources` is also set. | | `hide-settings-button` | **Type**: `boolean`**Default value**: `false`When set to `true`, hides the reasoning mode selector above the message input. Only applies if reasoning mode is enabled for your project. | | `hide-connect-button` | **Type**: `boolean`**Default value**: `false`When set to `true`, hides the Connect menu above the message input. This menu provides MCP (Model Context Protocol) connection options when MCP is enabled for the project. | | `hide-tooltips` | **Type**: `boolean`**Default value**: `false`When set to `true`, hides the tooltips that appear when hovering over header icons. | | `loading-indicator` | **Type**: `string`**Default value**: `spinner`**Available values:** `spinner`, `dots`Shows a spinner with the current operation while the assistant is working. Use `dots` for the previous bouncing dots animation without visible progress text. Screen reader announcements and error recovery remain available. See [Chat progress](https://docs.biel.ai/customization/chat-progress.md). | | `loading-text` | **Type**: `string`**Default value**: `Loading…`Loading label before the first progress update arrives. With `dots`, this label is announced to screen readers without appearing visually. See [Chat progress](https://docs.biel.ai/customization/chat-progress.md). | | `modal-position` | **Type**: `string`**Default value**: `center`**Available values:** `center`, `top-center`, `top-left`, `top-right`, `center-left`, `center-right`, `bottom-left`, `bottom-right`, `sidebar-left`, `sidebar-right`Determines where the chat modal appears on the screen when opened. Use `sidebar-left` or `sidebar-right` to dock the chat as a side panel.| | `show-terms-modal` | **Type**: `boolean`**Default value**: `false`When set to `true`, displays a terms and conditions modal before starting the chat. | | `think-mode-enabled` | **Type**: `boolean`**Default value**: `false`Legacy option that starts a new conversation in Think mode when reasoning mode is enabled for the project. Use `default-think-mode` to choose Auto, Instant, or Think. A visitor's saved choice takes precedence. See [Reasoning modes](https://docs.biel.ai/customization/reasoning-modes.md). | | `default-think-mode` | **Type**: `string`**Available values:** `auto`, `fast`, `think`Starting mode for a new conversation when reasoning mode is enabled for the project. A visitor's saved choice takes precedence. This property takes precedence over the legacy `think-mode-enabled` option. See [Reasoning modes](https://docs.biel.ai/customization/reasoning-modes.md). | | `keep-conversation` | **Type**: `boolean`**Default value**: `true`When set to `false`, clears the conversation history on page navigation. By default, a conversation can be restored across page reloads for one hour after its last saved update, using browser storage. Each widget instance keeps its own conversation; use a stable HTML `id` when placing several widgets on a page. | | `render-math` | **Type**: `boolean`**Default value**: `true`When set to `true`, typesets supported LaTeX in AI answers with MathJax. Set to `false` to leave LaTeX source unchanged. | | `render-diagrams` | **Type**: `boolean`**Default value**: `true`Renders Mermaid diagrams in AI answers. Set to `false` to show their source code instead. | | `mermaid-theme` | **Type**: `string`**Default value**: `default`Theme used for rendered Mermaid diagrams. | | `mathjax-url` | **Type**: `string`**Default value**: `https://cdn.jsdelivr.net/npm/mathjax@3.2.2/es5/tex-svg.js`The MathJax script URL. Set this to a self-hosted copy when your site's Content Security Policy blocks the default CDN. | | **MCP Integration** | | | | `mcp-server-url` | **Type**: `string`**Default value**: ``Override the MCP server URL. Use for custom or self-hosted MCP servers, or when authentication is required. Takes priority over the API-provided URL. See [MCP Server](https://docs.biel.ai/integrations/mcp-server.md). | | **Text** | | | | `assistant-label` | **Type**: `string`**Default value**: `Assistant`Label text displayed above AI responses in the chat. | | `close-button-text` | **Type**: `string`**Default value**: `Close`Tooltip text for the close button in the assistant header. | | `collapse-button-text` | **Type**: `string`**Default value**: `Collapse`Tooltip text for the collapse button in the assistant header. | | `error-message-4-0-3` | **Type**: `string`**Default value**: `Oops! The request URL or API key is invalid or not authorized for this project.`403 unauthorized message. | | `error-message-4-0-4` | **Type**: `string`**Default value**: `Oops! We could not find the provided project ID.`404 not found message. | | `error-message-default`| **Type**: `string`**Default value**: `Oops! Please try again later.`500 error message. | | `expand-button-text` | **Type**: `string`**Default value**: `Expand`Tooltip text for the expand button in the assistant header. | | `footer-text` | **Type**: `string`**Default value**: `AI answers may be inaccurate. Verify with official sources.`Footer text. | | `header-title` | **Type**: `string`**Default value**: `Company Name AI`Title text for the assistant header. | | `input-placeholder-text` | **Type**: `string`**Default value**: `Type your message`Placeholder text displayed in the assistant's input field. | | `connect-button-text` | **Type**: `string`**Default value**: `Connect`Tooltip text for the Connect button in the assistant header. | | `mcp-url-text` | **Type**: `string`**Default value**: `MCP URL`Label for the MCP URL option in the connect dialog. | | `mcp-url-description` | **Type**: `string`**Default value**: `Copy to clipboard`Description text for the MCP URL option in the connect dialog. | | `mcp-claude-text` | **Type**: `string`**Default value**: `Claude Code`Label for the Claude Code option in the connect dialog. | | `mcp-claude-description` | **Type**: `string`**Default value**: `CLI command`Description text for the Claude Code option in the connect dialog. | | `mcp-codex-text` | **Type**: `string`**Default value**: `Codex`Label for the Codex option in the Connect menu. | | `mcp-codex-description` | **Type**: `string`**Default value**: `Copy setup command`Tooltip text for copying the Codex setup command. | | `mcp-codex-copied-description` | **Type**: `string`**Default value**: `Command copied to clipboard`Confirmation after copying the Codex setup command. | | `mcp-copilot-text` | **Type**: `string`**Default value**: `Copilot (VS code)`Label for the Copilot option in the connect dialog. | | `mcp-copilot-description` | **Type**: `string`**Default value**: `Opens in a new tab`Description text for the Copilot option in the connect dialog. | | `mcp-cursor-text` | **Type**: `string`**Default value**: `Cursor`Label for the Cursor option in the connect dialog. | | `mcp-cursor-description` | **Type**: `string`**Default value**: `Opens in a new tab`Description text for the Cursor option in the connect dialog. | | `mcp-copied-text` | **Type**: `string`**Default value**: `Copied!`Confirmation text shown after copying an MCP value to the clipboard. | | `mcp-url-copied-description` | **Type**: `string`**Default value**: `URL copied to clipboard`Description text shown after copying the MCP URL. | | `mcp-claude-copied-description` | **Type**: `string`**Default value**: `Command copied to clipboard`Description text shown after copying the Claude Code command. | | `refresh-button-text` | **Type**: `string`**Default value**: `Refresh`Tooltip text for the refresh button in the assistant header. | | `continue-text` | **Type**: `string`**Default value**: `Continue generating`Label for continuing an answer that reached its length limit. | | `incomplete-text` | **Type**: `string`**Default value**: `This answer could not be completed. Ask for a shorter answer or a specific section.`Message shown when an answer cannot be completed. | | `message-too-long-text` | **Type**: `string`**Default value**: `Message is too long. Use at most 10,000 characters.`Validation message for an oversized question. | | `send-button-text` | **Type**: `string`**Default value**: `Send`Text displayed on the send button next to the input field. | | `sources-text` | **Type**: `string`**Default value**: `Sources`Text displayed for introducing sources in messages. | | `suggested-questions` | **Type**: `string`**Default value**: emptyA JSON array or comma-separated list of questions shown when users open the chat. For example, `suggested-questions='["How do I start?", "What can I build?"]'`. | | `suggested-questions-title` | **Type**: `string`**Default value**: `Suggested questions`The heading text that appears above the list of suggested questions in the chat interface. | | `settings-button-text` | **Type**: `string`**Default value**: `Settings`Tooltip text for the settings button (reasoning mode selector) in the assistant header. Only visible if reasoning mode is enabled for your project. | | `terms-checkbox-text` | **Type**: `string`**Default value**: `I have read and agree to the Terms & Conditions.`Text displayed next to the terms acceptance checkbox. | | `terms-description` | **Type**: `string`**Default value**: `Please review our Terms & Conditions before proceeding.`Description text shown in the terms and conditions modal. | | `terms-title` | **Type**: `string`**Default value**: `Chatbot Terms & Conditions`Title text for the terms and conditions modal. | | `think-mode-auto-text` | **Type**: `string`**Default value**: `Auto`Label for the Auto reasoning mode in the settings dropdown. | | `think-mode-auto-description` | **Type**: `string`**Default value**: `Balances speed and quality`Description for the Auto reasoning mode. | | `think-mode-fast-text` | **Type**: `string`**Default value**: `Instant`Label for the Instant reasoning mode in the settings dropdown. | | `think-mode-fast-description` | **Type**: `string`**Default value**: `Prioritizes speed`Description for the Instant reasoning mode. | | `think-mode-think-text` | **Type**: `string`**Default value**: `Think`Label for the Think reasoning mode in the settings dropdown. | | `think-mode-think-description` | **Type**: `string`**Default value**: `Takes longer for better accuracy`Description for the Think reasoning mode. | | `welcome-message` | **Type**: `string`**Default value**: ""A custom greeting message that appears when users first open the chat. | The `escape-close`, `click-outside-close`, and `show-modal` properties are available on `` directly. The `` launcher does not expose those properties. When using `` directly, you can also set `smooth-streaming="false"` to display response chunks as they arrive instead of smoothing their appearance. Its default is `true`. ## biel-search-button The `` component adds an AI-powered search bar to your site. Use `` to render the search interface directly; it accepts the search modal and assistant modal properties below. ![Biel search](./images/biel-search-widget.jpg) ### Usage ```html Search ``` ### Search button properties | Property | Description | |------------------------|-----------------------------------------------------------------------------------------------| | **Layout** | | | | `project` | **Required****Type**: `string`The project ID. | | `button-style` | **Type**: `string`**Default value**: `default`**Available values:** `default`, `rounded`Style of the button.| | `custom-font` | **Type**: `boolean`**Default value**: `false`When set to `true`, the [Inter font](https://fonts.google.com/specimen/Inter) will not be loaded. Useful if your site already uses a different font, enabling a quicker load time.| | `hide-ctrl-k` | **Type**: `boolean`**Default value**: `false`When set to `true`, hides the Ctrl+K hint and disables the launcher's Ctrl+K keyboard shortcut. | | `hide-icon` | **Type**: `boolean`**Default value**: `false`When set to `true`, the button icon hides. | | `ai-icon` | **Type**: `string`**Default value**: `biel`**Available values:** `biel`, `bot`, `sparks`, `question-mark`Specifies the AI icon in the assistant opened through Ask AI. The search launcher uses a search icon.| | `hide-avatars` | **Type**: `boolean`**Default value**: `false`When set to `true`, hides avatars in the chat interface.| | `api-key` | **Type**: `string`**Default value**: ``API key for authenticating requests to private projects. Required for private projects with `chat_create`, `project_search`, and `project_read` permissions. Not required for public projects.| ### Search modal properties | Property | Description | |------------------------|-----------------------------------------------------------------------------------------------| | **Layout** | | | | `disable-autofocus` | **Type**: `boolean`**Default value**: `false`When set to `true`, opening search does not focus the search input automatically. | | `hide-ask-ai-button` | **Type**: `boolean`**Default value**: `false`When set to `true`, the "Ask AI" button is hidden from the search results. | | `hide-descriptions` | **Type**: `boolean`**Default value**: `false`When set to `true`, hides descriptions in search results for a cleaner interface.| | `hide-filters` | **Type**: `boolean`**Default value**: `false`When set to `true`, hides the site filter dropdown. The dropdown appears beside the navigation hints when search filters are configured in your project settings. See [Search filters](https://docs.biel.ai/customization/search-filters.md). | | `hide-navigation-buttons` | **Type**: `boolean`**Default value**: `false`When set to `true`, hides navigation buttons (up and down arrows, enter, escape) in the search modal for a simplified interface. | | `modal-position` | **Type**: `string`**Default value**: `top-center`**Available values:** `center`, `top-center`, `top-left`, `top-right`, `center-left`, `center-right`, `bottom-left`, `bottom-right`, `sidebar-left`, `sidebar-right`Position of the search modal. Use `sidebar-left` or `sidebar-right` to dock as a side panel.| | `stacked` | **Type**: `boolean`**Default value**: `false`When set to `true`, displays search results in a stacked layout.| | `clean-titles` | **Type**: `boolean`**Default value**: `false`When set to `true`, removes site names from page titles that follow the format "Page Title | Site Name" for cleaner presentation.| | **Text** | | | | `ai-result-fragment` | **Type**: `string`**Default value**: `"Ask AI to answer your question"`Text displayed in the AI result section of the search modal. | | `all-sites-text` | **Type**: `string`**Default value**: `All sites`Label for the unfiltered option in the site filter dropdown. | | `search-placeholder` | **Type**: `string`**Default value**: `"Search or ask AI..."`Placeholder for the search input. | ### Search assistant modal properties {#search-chatbot-modal-properties} Most properties that can be defined in `` for configuring the assistant modal can be set in the `biel-search-button`. For details, see [Assistant modal properties](#chatbot-modal-properties). Diagram options (`render-diagrams` and `mermaid-theme`) are supported by `` and ``; the search widgets do not expose them. Use `` directly for `escape-close`, `click-outside-close`, and `show-search-modal`. These properties are not exposed by the `` launcher. ## Common customizations ### Change the assistant title {#change-the-chatbot-title} By default, the assistant header displays "Company Name AI". Set the `header-title` property to show your own title: ```html Ask AI ``` ### Change the button text Replace the inner text of the element to change what the button says: ```html Help ``` ### Open the chat modal from a custom element Use `` directly and set its `show-modal` property from a custom button: ```html ``` Use the equivalent `show-search-modal` property on `` to open search programmatically. The two launcher components open their modals when clicked; assigning these modal properties to a launcher does not open its modal. --- ## Models Biel.ai supports four models from OpenAI and Anthropic. GPT-6 Luna is the default and is available on every plan. Claude Haiku 5.5 is available on paid plans. GPT-6.1 Sol and Claude Sonnet 5.5 require a Business plan or above. The Business trial includes all four models. Extra usage does not unlock models outside your plan. ## Available models | Model | API model ID | Tier | | --- | --- | --- | | **GPT-6 Luna (default)** | `gpt-6-luna` | Fast | | GPT-6.1 Sol | `gpt-6.1-sol` | Advanced | | Claude Haiku 5.5 | `claude-haiku-5-5` | Fast | | Claude Sonnet 5.5 | `claude-sonnet-5-5` | Advanced | Start with GPT-6 Luna for routine documentation questions. Compare an advanced model using representative questions from your own documentation before switching. ## Change the model :::important Only **Administrator** or **Maintainer** roles can manage projects. See [Manage roles](https://docs.biel.ai/administration/roles.md). ::: 1. In the [Biel.ai dashboard](https://app.biel.ai), select your project. 2. Click **Settings**. 3. Open **Assistant** in the left sidebar and, under **AI model and instructions** > **Select model**, choose a model from the dropdown. 4. Click **Save** on the AI model and instructions card. Models marked **locked** require an eligible subscription. ## Data privacy Assistant interactions are opted out of third-party model training by default. Your data is not used to train or improve external AI models. --- ## Reasoning modes Control how the assistant reasons through questions with three modes: Auto, Instant, and Think. ![Reasoning mode selector in the chat widget](./images/widget-think-mode.jpg) ## Available modes | Mode | Description | Interactions per question | |------|-------------|--------------------------| | **Auto** (default) | Searches documentation using keywords and meaning. If it finds no usable documentation, tries keyword search once with the same question. If no supporting evidence is available, asks for more detail or documentation. | 1 | | **Instant** | Searches documentation once using keywords and meaning, then writes the answer. | 1 | | **Think** | Reviews results and can make additional focused searches and read fuller documentation pages before answering. Searches and review rounds are limited. | Up to 10 | Auto does not automatically switch to Think. Choose Think for questions that may need information from several documentation sections. Additional searches do not guarantee a correct answer. The interaction counts above cover the base documentation workflow. Enabling [web search](https://docs.biel.ai/customization/web-search.md) can add interactions. These interactions count toward your team's included allowance. With [extra usage](https://docs.biel.ai/administration/subscription.md#extra-usage) enabled, interactions beyond that allowance cost $0.05 each. All three modes show the current operation while answering. Progress disappears when the answer finishes. See [Chat progress](https://docs.biel.ai/customization/chat-progress.md) to choose between the default spinner and loading dots. ## Enable reasoning modes :::important Only **Administrator** or **Maintainer** roles can manage projects. See [Manage roles](https://docs.biel.ai/administration/roles.md). ::: 1. In the [Biel.ai dashboard](https://app.biel.ai), select your project. 2. Click **Settings**. 3. Open **Assistant** in the left sidebar and find the **AI model and instructions** section. 4. Check **Enable think mode**. ![Enable think mode in the AI model and instructions section](./images/settings-chatbotenable-think-mode.jpg) 5. Click **Save** on the AI model and instructions card. Once enabled, users can select their preferred mode from the selector above the chat input. This includes the assistant opened through **Ask AI** in the search widget. The selection persists across page reloads. ## Widget attributes Control reasoning mode behavior with these attributes on ``, ``, ``, or ``: | Attribute | Default | Description | |-----------|---------|-------------| | `default-think-mode` | `auto` | Starting mode for a new visitor: `auto`, `fast` (shown as Instant), or `think`. A visitor's saved choice takes precedence. | | `think-mode-enabled` | `false` | Legacy option to start in Think mode. `default-think-mode` takes precedence when both are set. | | `hide-settings-button` | `false` | Hide the mode selector above the input. On ``, this also hides it after a visitor selects **Ask AI** from search results. An embedded `` currently shows the selector whenever reasoning modes are enabled for the project. | **Start new visitors in Think mode:** ```html Ask AI ``` :::tip[Hide the mode selector] You can combine `default-think-mode` with `hide-settings-button` to hide the selector. A visitor's previously saved choice still takes precedence over the default. ```html Ask AI ``` ::: --- ## Search filters Search filters let users narrow search results by category. Each filter maps a label to a URL pattern — when selected, only matching results appear. ## Configure filters :::important Only **Administrator** or **Maintainer** roles can manage projects. See [Manage roles](https://docs.biel.ai/administration/roles.md). ::: 1. In the [Biel.ai dashboard](https://app.biel.ai), select your project. 2. Go to **Settings** > **Search**. 3. Under **Search Filters**, add one or more filters. Each filter requires: - **Label:** The label shown in the widget (for example, `API`, `Guides`, `Blog`). - **URL pattern:** A case-insensitive regular expression matched against result URLs. Use `\.` to match a literal dot and `.*` to match any characters. See [Pattern examples](#pattern-examples) for common use cases. ![The Search Filters settings card with Label and URL pattern fields](./images/settings-search-filters.jpg) 4. Click **Save** on the Search Filters card. ### Pattern examples | Goal | Pattern | Matches | | -------------------------- | --------------------- | ------------------------------------------------------------------------------------ | | Pages under a path | `/docs/api/.*` | `https://example.com/docs/api/overview`, `https://example.com/docs/api/auth/tokens` | | A specific subdomain | `docs\.example\.com` | `https://docs.example.com/guide`, `https://docs.example.com/api/v2` | | Any subdomain | `.*\.example\.com` | `https://docs.example.com/guide`, `https://blog.example.com/post` | | URLs containing a keyword | `release-notes` | `https://example.com/release-notes/v2`, `https://example.com/docs/release-notes` | ## Enable filters in the widget When you configure filters, the search widget shows a site dropdown beside the navigation hints. The dropdown does not appear if the project has no search filters. It starts at **All sites** and lets visitors choose one of your configured filters. ![Biel search results with the Documentation filter selected](./images/widget-search-filters.jpg) Use `all-sites-text="All documentation"` to replace the **All sites** label when the dropdown is visible: ```html Search ``` Set `hide-filters` to `true` to hide the dropdown: ```html Search ``` ## Customize filter appearance To style the dropdown, use the `--biel-dropdown-*` CSS custom properties. For details, see [Styles](https://docs.biel.ai/customization/styles.md). ## Limitations - Filters are available in `` and ``, not in the chat widget. - Each filter title must be unique within a project. - Filters do not affect the relevance ranking of results. --- ## Search The search widget finds documentation pages and sections across your indexed website content. Users can select **Ask AI** to turn a question into an assistant conversation. ![Biel search](./images/biel-search-widget.jpg) ## How search works The widget uses keyword search across the page title, description, section headings, keywords, and content. Title matches receive additional weight, and results can link directly to the matching section. Each successful search counts as one interaction. **Ask AI** uses assistant interactions in addition to the search. Both count toward your team's included allowance and cost $0.05 each beyond that allowance when [extra usage](https://docs.biel.ai/administration/subscription.md#extra-usage) is enabled. Text relevance is normalized between 0 and 1 before applying boosts. The final score can exceed 1 when a positive boost is added. You can adjust rankings with a [boost score](#boost-search-results): positive values (e.g., `0.5`) increase a page's ranking, negative values (e.g., `-0.5`) decrease it. The final score is the base score plus the boost. :::tip Pages with a combined boost of `-1.0` or lower are excluded from search results. Smaller negative boosts lower their ranking. ::: ## Installation - [CDN installation guide](https://docs.biel.ai/installation/cdn.md#add-the-search-widget) - [Platform-specific guides](https://docs.biel.ai/installation.md) ## Customization ### Widget appearance See [Layout](https://docs.biel.ai/customization/layout.md#biel-search-button) for styling and positioning options. ### Search filters You can configure filters that let users narrow search results by category (for example, API, Guides, Blog). For details, see [Search filters](https://docs.biel.ai/customization/search-filters.md). ### Metadata and keywords Add meta tags to improve how your content is indexed and ranked: ```html ``` For Docusaurus, Sphinx, and other documentation systems, see [Metadata by platform](#metadata-by-platform). ### Boost search results Use boost scores to prioritize certain pages. For example, boost guides by `0.5` so they rank higher, while leaving reference pages at `0` for natural ranking. If your team has access to **Boost Rules**, open **Settings** > **Search**, add a URL pattern and boost score, and click **Save** on that card. Click **Refresh sources** to apply the rule to indexed pages. A matching rule's boost is added to the page's metadata boost. Add the following meta tag to the **head** of the page: ```html ``` Click **Refresh sources** after updating page metadata so Biel.ai indexes the change. For Docusaurus, Sphinx, and other documentation systems, see [Metadata by platform](#metadata-by-platform). ### Metadata by platform Add the **head** tag directly in your markdown content: ```markdown --- title: Search Configuration --- # Search Configuration Your content here... ``` Use the `meta` directive in your reStructuredText files: ```rst .. meta:: :description: Learn how to configure and customize your Biel.ai assistant :keywords: assistant, configuration, customization, Biel.ai, setup :biel:boost_score: 0.5 Search Configuration ==================== ``` ## Limitations The search widget returns website pages. Uploaded files, repository files, and OpenAPI specifications can inform assistant answers but do not appear in the widget's page results. The API and MCP all-content search can retrieve those sources. --- ## Styles Two approaches for customizing widget styles: 1. **CSS custom properties** — Override colors, fonts, spacing, and sizing. 2. **CSS parts** (advanced) — Target specific elements inside the Shadow DOM. ## CSS custom properties Define CSS custom properties in your stylesheet using the `:root` selector: ```css :root { --biel-primary-color: #00D68F; --biel-primary-hover-color: #00b77a; } ``` ### Properties ```css :root { /* Colors */ --biel-primary-color: #0070F4; --biel-primary-light-color: #3a99ff; --biel-primary-hover-color: #005FCC; --biel-secondary-color: #f9fafb; --biel-secondary-hover-color: #ebebeb; --biel-light-color: #ccc; --biel-border-color: #949494; --biel-dark-color: #191919; --biel-dark-hover-color: #333; --biel-text-color: #5f6368; --biel-white-color: #fff; --biel-white-hover-color: var(--biel-secondary-hover-color); --biel-highlight-color: #ffb422; --biel-scrollbar-color: #888888; --biel-scrollbar-hover-color: #666666; --biel-code-header-color: #3a3a3a; --biel-code-body-color: #3b3b3b; --biel-table-header-color: #372b2b; /* Radii */ --biel-radius-sm: 6px; --biel-radius-md: 10px; --biel-radius-lg: 16px; /* Elevation */ --biel-shadow-1: 0 4px 12px rgba(0, 0, 0, 0.1); --biel-shadow-2: 0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -1px rgba(0, 0, 0, 0.06); /* Tooltip */ --biel-tooltip-bg: var(--biel-dark-color); --biel-tooltip-text: var(--biel-white-color); /* Fonts */ --biel-font-family: "Inter", "Tahoma", "sans-serif"; --biel-text-sm-font-size: 12px; --biel-text-font-size: 14px; --biel-text-lg-font-size: 16px; --biel-control-font-size: var(--biel-text-font-size); --biel-text-xl-font-size: 18px; --biel-text-xxl-font-size: 20px; --biel-code-snippet-font-family: "Courier New", "Courier", "monospace"; /* Biel button */ --biel-button-border-radius: 20px; --biel-button-box-shadow: rgba(60, 64, 67, 0.3) 0px 1px 2px 0px, rgba(60, 64, 67, 0.15) 0px 2px 6px 2px; --biel-button-dark-bg-color: var(--biel-primary-color); --biel-button-dark-bg-color-hover: var(--biel-primary-hover-color); --biel-button-dark-text-color: var(--biel-white-color); --biel-button-icon-size: 20px; --biel-button-light-bg-color: var(--biel-white-color); --biel-button-light-bg-color-hover: var(--biel-white-hover-color); --biel-button-light-text-color: var(--biel-primary-color); --biel-button-text-font-size: var(--biel-text-lg-font-size); --biel-button-text-font-weight: 400; --biel-button-padding: 8px 15px; --biel-button-position-top: 15px; --biel-button-position-bottom: 15px; --biel-button-position-left: 15px; --biel-button-position-right: 15px; --biel-button-z-index: auto; /* Biel bot */ --biel-bot-close-bg-color: var(--biel-white-color); --biel-bot-close-color: var(--biel-dark-color); --biel-bot-content-bg-color: var(--biel-white-color); --biel-bot-screenshot-bg-color: transparent; --biel-bot-content-border-color: rgba(0, 0, 0, 0.08); --biel-bot-content-border-radius: 12px; --biel-bot-content-box-shadow: var(--biel-shadow-2); --biel-bot-content-font-family: var(--biel-font-family); --biel-bot-content-position-bottom: 10px; --biel-bot-content-position-left: 10px; --biel-bot-content-position-right: 10px; --biel-bot-content-position-top: 10px; --biel-bot-content-max-width: 600px; --biel-bot-content-text-color: var(--biel-text-color); --biel-bot-wrapper-z-index: auto; --biel-bot-content-z-index: 300; /* Biel bot chat */ --biel-chat-scrollbar-color: var(--biel-scrollbar-color); --biel-chat-scrollbar-hover-color: var(--biel-scrollbar-hover-color); --biel-chat-embedded-height: 450px; --biel-loading-dot-color: var(--biel-footer-action-color); --biel-activity-text-color: var(--biel-text-color); --biel-activity-accent-color: var(--biel-primary-color); --biel-activity-border-color: var(--biel-border-color); --biel-activity-spinner-color: var(--biel-primary-color); /* Biel bot header */ --biel-header-font-family: var(--biel-font-family); --biel-header-font-size: var(--biel-text-xl-font-size); --biel-header-font-weight: 600; --biel-header-powered-by-font-weight: 400; --biel-header-powered-by-text-color: var(--biel-text-color); --biel-header-powered-by-link-color: var(--biel-dark-color); --biel-header-text-color: var(--biel-dark-color); --biel-header-border-color: var(--biel-light-color); /* Biel input options dropdown */ --biel-dropdown-bg-color: var(--biel-white-color); --biel-dropdown-border-color: var(--biel-light-color); --biel-dropdown-hover-bg-color: var(--biel-secondary-color); --biel-dropdown-selected-bg-color: var(--biel-white-hover-color); --biel-dropdown-selected-hover-bg-color: var(--biel-secondary-hover-color); --biel-dropdown-text-color: var(--biel-dark-hover-color); --biel-dropdown-text-secondary-color: var(--biel-text-color); /* Biel bot message */ --biel-message-biel-text-color: var(--biel-dark-color); --biel-message-user-text-color: var(--biel-white-color); --biel-message-biel-bg-color: var(--biel-secondary-color); --biel-message-user-bg-color: var(--biel-primary-color); --biel-message-avatar-width: 20px; --biel-message-avatar-height: 20px; --biel-message-padding: 10px; --biel-message-avatar-margin-right: 10px; --biel-message-border-radius: 10px; --biel-message-code-font-size: 14px; --biel-message-code-bg-color: var(--biel-code-body-color); --biel-message-code-inline-text-color: var(--biel-dark-color); --biel-message-code-inline-bg-color: var(--biel-white-hover-color); --biel-message-code-inline-border-radius: 4px; --biel-message-font-size: var(--biel-text-font-size); --biel-message-label-font-size: var(--biel-text-sm-font-size); --biel-message-h1-font-size: var(--biel-text-xxl-font-size); --biel-message-h2-font-size: var(--biel-text-xl-font-size); --biel-message-h3-font-size: var(--biel-text-lg-font-size); --biel-message-h4-font-size: var(--biel-text-lg-font-size); --biel-message-h5-font-size: var(--biel-text-lg-font-size); --biel-message-h6-font-size: var(--biel-text-lg-font-size); --biel-message-link-color: var(--biel-primary-light-color); --biel-message-source-font-size: 14px; --biel-message-source-bg-color: var(--biel-white-hover-color); --biel-message-source-bg-hover-color: var(--biel-light-color); --biel-message-source-text-color: var(--biel-dark-color); /* Inline citations */ --biel-citation-bg-color: var(--biel-message-source-bg-color); --biel-citation-bg-hover-color: var(--biel-message-source-bg-hover-color); --biel-citation-text-color: var(--biel-message-source-text-color); --biel-citation-text-hover-color: var(--biel-message-source-text-color); --biel-citation-font-size: 0.75em; /* Action buttons */ --biel-action-bg-color: var(--biel-message-source-bg-color); --biel-action-bg-hover-color: var(--biel-message-source-bg-hover-color); --biel-action-text-color: var(--biel-message-source-text-color); --biel-action-text-hover-color: var(--biel-message-source-text-color); --biel-action-font-size: var(--biel-message-source-font-size); /* Answer continuation and diagram dialog */ --biel-continue-button-bg-color: var(--biel-white-hover-color); --biel-continue-button-bg-color-hover: var(--biel-light-color); --biel-continue-button-color: var(--biel-dark-color); --biel-diagram-dialog-bg-color: var(--biel-bot-content-bg-color); /* Biel bot input */ --biel-input-color: var(--biel-dark-color); --biel-input-button-color: var(--biel-white-color); --biel-input-button-bg-color: var(--biel-primary-color); --biel-input-button-border-color: var(--biel-dark-color); --biel-input-button-hover-color: var(--biel-white-color); --biel-input-button-hover-bg-color: var(--biel-primary-hover-color); --biel-input-button-hover-border-color: var(--biel-primary-hover-color); --biel-input-border-color: #d8dee7; --biel-input-border-radius: 6px; --biel-input-border-focus-color: var(--biel-primary-color); --biel-input-font-family: var(--biel-font-family); --biel-input-textarea-max-height: 114px; --biel-input-textarea-min-height: 19px; /* Biel bot input options */ --biel-input-options-font-size: 13px; --biel-input-options-button-hover-bg-color: var(--biel-dropdown-hover-bg-color); --biel-input-options-button-hover-border-color: var(--biel-input-border-color); --biel-input-options-button-focus-border-color: var(--biel-input-border-focus-color); /* Biel bot code snippet */ --biel-code-snippet-header-text-color: var(--biel-light-color); --biel-code-snippet-content-text-color: var(--biel-white-color); --biel-code-snippet-header-bg-color: var(--biel-code-header-color); --biel-code-snippet-content-bg-color: var(--biel-dark-color); --biel-code-snippet-font-size: var(--biel-text-font-size); /* Biel bot table */ --biel-table-th-bg-color: var(--biel-table-header-color); --biel-table-bg-color: var(--biel-dark-color); --biel-table-content-text-color: var(--biel-white-color); /* Biel bot suggested questions */ --biel-suggested-questions-border-radius: 8px; --biel-suggested-questions-bg-color: var(--biel-white-color); --biel-suggested-questions-bg-hover-color: var(--biel-primary-color); --biel-suggested-questions-border-color: var(--biel-primary-color); --biel-suggested-questions-padding: 8px 12px; --biel-suggested-questions-text-color: var(--biel-dark-color); --biel-suggested-questions-text-hover-color: var(--biel-white-color); --biel-suggested-questions-title-font-size: var(--biel-text-sm-font-size); --biel-suggested-questions-font-size: var(--biel-text-font-size); /* Biel bot feedback */ --biel-feedback-bg-color: var(--biel-white-hover-color); --biel-feedback-bg-hover-color: var(--biel-light-color); --biel-feedback-background-selected-color: var(--biel-primary-color); --biel-feedback-text-color: var(--biel-dark-color); --biel-feedback-text-selected-color: var(--biel-white-color); /* Biel bot footer */ --biel-footer-font-size: var(--biel-text-sm-font-size); --biel-bot-footer-link: inherit; /* Biel answer footer (sources toggle + copy + thumbs row) */ --biel-footer-action-color: var(--biel-text-color); --biel-footer-action-copied-color: var(--biel-primary-color); --biel-footer-action-hover-bg: var(--biel-message-source-bg-color); --biel-footer-thumb-selected-bg: var(--biel-feedback-background-selected-color); --biel-footer-thumb-selected-color: var(--biel-feedback-text-selected-color); /* Biel sources toggle */ --biel-source-toggle-bg: var(--biel-white-color); --biel-source-toggle-border: var(--biel-input-border-color); --biel-source-toggle-border-hover-color: var(--biel-input-border-color); /* Biel source cards (expanded sources panel) */ --biel-source-card-bg: var(--biel-white-color); --biel-source-card-icon-color: var(--biel-text-color); --biel-source-card-border: var(--biel-search-result-border-color); --biel-source-card-border-hover-color: var(--biel-primary-color); --biel-source-card-title-color: var(--biel-message-source-text-color); --biel-source-card-host-color: var(--biel-text-color); /* Biel search button */ --biel-search-button-text-display: none; --biel-search-button-ctrl-k-display: none; --biel-search-button-border-radius: 20px; --biel-search-button-border-color: var(--biel-light-color); --biel-search-button-bg-color: var(--biel-white-color); --biel-search-button-text-color: var(--biel-dark-color); --biel-search-button-icon-size: 20px; --biel-search-button-width: 100%; --biel-search-button-max-width: fit-content; --biel-search-button-padding: 8px; --biel-search-button-icon-margin-right: 0px; --biel-search-button-text-font-size: var(--biel-text-lg-font-size); --biel-search-button-text-font-weight: 400; --biel-search-button-z-index: 300; /* Biel search */ --biel-search-content-bg-color: var(--biel-white-color); --biel-search-content-border-color: rgba(0, 0, 0, 0.08); --biel-search-content-border-radius: 12px; --biel-search-content-box-shadow: var(--biel-shadow-2); --biel-search-content-font-family: var(--biel-font-family); --biel-search-content-max-width: 700px; --biel-search-content-max-height: 100dvh; --biel-search-content-position-bottom: 10px; --biel-search-content-position-left: 10px; --biel-search-content-position-right: 10px; --biel-search-content-position-top: 10px; --biel-search-content-position-top-center: 50px; --biel-search-content-text-color: var(--biel-dark-color); --biel-search-content-z-index: 300; --biel-search-body-max-height: calc(80dvh - 30px); /* Biel search result */ --biel-search-result-bg-color: transparent; --biel-search-result-bg-hover-color: var(--biel-input-options-button-hover-bg-color); --biel-search-result-bg-selected-color: var(--biel-input-options-button-hover-bg-color); --biel-search-result-border-radius: 6px; --biel-search-result-border-color: var(--biel-light-color); --biel-search-result-border-hover-color: var(--biel-primary-color); --biel-search-result-description-color: var(--biel-scrollbar-hover-color); --biel-search-result-mark-color: var(--biel-primary-color); --biel-search-result-padding: 10px 8px; --biel-search-result-title-color: var(--biel-dark-color); --biel-search-result-title-font-size: var(--biel-text-xl-font-size); --biel-search-result-description-font-size: calc(var(--biel-text-lg-font-size) - 2px); --biel-search-result-description-line-height: 1.4; --biel-search-line-height: 1; /* Biel search ask ai button */ --biel-search-ask-ai-bg-color: var(--biel-primary-color); --biel-search-ask-ai-border-color: var(--biel-search-result-border-color); --biel-search-ask-ai-border-hover-color: var(--biel-primary-color); --biel-search-ask-ai-border-radius: 8px; --biel-search-ask-ai-color: var(--biel-white-color); /* Biel search filters */ --biel-search-filter-color: var(--biel-dark-color); --biel-search-filter-selected-color: var(--biel-white-color); --biel-search-filter-bg-color: var(--biel-white-color); --biel-search-filter-selected-bg-color: var(--biel-primary-color); --biel-search-filter-border-color: var(--biel-white-hover-color); --biel-search-filter-hover-color: var(--biel-white-hover-color); --biel-search-filter-selected-border-color: var(--biel-primary-color); --biel-search-filter-trigger-border-hover-color: var(--biel-input-border-color); /* Biel search footer */ --biel-search-footer-command-key-border-color: var(--biel-header-border-color); /* Biel search toctree */ --biel-search-toctree-page-bg-color: var(--biel-search-result-bg-hover-color); --biel-search-toctree-page-border-color: var(--biel-light-color); --biel-search-toctree-page-border-hover-color: var(--biel-primary-color); --biel-search-toctree-page-text-color: var(--biel-dark-color); --biel-search-toctree-count-color: var(--biel-scrollbar-hover-color); --biel-search-toctree-border-color: var(--biel-light-color); --biel-search-toctree-page-title-font-size: var(--biel-text-xl-font-size); --biel-search-toctree-page-title-font-weight: 500; --biel-search-toctree-count-font-size: var(--biel-text-sm-font-size); --biel-search-toctree-title-height: 100%; /* Biel terms modal */ --biel-terms-modal-color: var(--biel-dark-color); --biel-terms-modal-bg-color: var(--biel-white-color); --biel-terms-modal-box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); --biel-terms-modal-link-color: var(--biel-primary-light-color); --biel-terms-modal-accept-btn-bg-color-disabled: var(--biel-primary-light-color); --biel-terms-modal-accept-btn-color-disabled: var(--biel-white-color); --biel-terms-modal-accept-btn-bg-color: var(--biel-primary-color); --biel-terms-modal-accept-btn-color: var(--biel-white-color); --biel-terms-modal-accept-btn-bg-color-hover: var(--biel-primary-hover-color); --biel-terms-modal-decline-btn-bg-color: var(--biel-white-hover-color); --biel-terms-modal-decline-btn-hover-bg-color: var(--biel-light-color); --biel-terms-modal-decline-btn-color: var(--biel-dark-color); --biel-terms-modal-close-btn-color: var(--biel-footer-action-color); --biel-terms-modal-close-btn-color-hover: var(--biel-terms-modal-color); } [data-theme='dark'] { --biel-border-color: #6b6b6b; --biel-tooltip-bg: #2a2a2a; --biel-tooltip-text: var(--biel-white-color); --biel-text-color: #b0b8c4; --biel-scrollbar-color: #555555; --biel-scrollbar-hover-color: #333333; --biel-bot-button-bg-color-active: transparent; --biel-bot-button-icon-color: var(--biel-white-color); --biel-bot-button-text-color: var(--biel-white-color); --biel-header-text-color: var(--biel-white-color); --biel-bot-close-bg-color: transparent; --biel-bot-close-color: var(--biel-white-color); --biel-bot-content-bg-color: var(--biel-dark-color); --biel-bot-content-border-color: rgba(255, 255, 255, 0.1); --biel-bot-content-text-color: var(--biel-text-color); --biel-header-border-color: #363636; --biel-header-powered-by-link-color: var(--biel-white-color); --biel-dropdown-bg-color: var(--biel-message-biel-bg-color); --biel-dropdown-border-color: var(--biel-header-border-color); --biel-dropdown-hover-bg-color: var(--biel-feedback-bg-color); --biel-dropdown-selected-bg-color: var(--biel-feedback-bg-hover-color); --biel-dropdown-selected-hover-bg-color: var(--biel-message-source-bg-hover-color); --biel-dropdown-text-color: var(--biel-white-color); --biel-dropdown-text-secondary-color: var(--biel-text-color); --biel-input-color: var(--biel-white-color); --biel-input-border-color: var(--biel-border-color); --biel-input-border-focus-color: var(--biel-primary-light-color); --biel-input-button-color: var(--biel-white-color); --biel-input-button-bg-color: var(--biel-primary-color); --biel-input-button-border-color: var(--biel-primary-color); --biel-input-button-hover-color: var(--biel-white-color); --biel-input-button-hover-bg-color: var(--biel-primary-hover-color); --biel-input-button-hover-border-color: var(--biel-primary-hover-color); --biel-input-options-button-hover-bg-color: var(--biel-dropdown-hover-bg-color); --biel-input-options-button-focus-border-color: var(--biel-input-border-focus-color); --biel-message-biel-text-color: var(--biel-white-color); --biel-message-biel-bg-color: #2a2a2a; --biel-message-user-text-color: var(--biel-white-color); --biel-message-user-bg-color: #2a2a2a; --biel-message-source-color: var(--biel-white-hover-color); --biel-message-source-bg-color: #3a3a3a; --biel-message-source-bg-hover-color: #4a4a4a; --biel-message-source-text-color: var(--biel-white-color); --biel-message-source-link-color: var(--biel-primary-color); --biel-source-card-bg: var(--biel-message-biel-bg-color); --biel-source-card-border: var(--biel-source-toggle-border); --biel-source-toggle-bg: var(--biel-message-biel-bg-color); --biel-source-toggle-border: var(--biel-input-border-color); --biel-suggested-questions-text-color: var(--biel-white-color); --biel-suggested-questions-bg-color: var(--biel-dark-color); --biel-feedback-bg-color: #3a3a3a; --biel-feedback-bg-hover-color: #4a4a4a; --biel-feedback-text-color: var(--biel-white-color); --biel-search-button-bg-color: var(--biel-dark-color); --biel-search-button-text-color: var(--biel-white-color); --biel-search-button-border-color: var(--biel-primary-color); --biel-search-content-text-color: var(--biel-text-color); --biel-search-content-bg-color: var(--biel-dark-color); --biel-search-content-border-color: rgba(255, 255, 255, 0.1); --biel-search-result-bg-color: transparent; --biel-search-result-bg-hover-color: var(--biel-input-options-button-hover-bg-color); --biel-search-result-bg-selected-color: var(--biel-input-options-button-hover-bg-color); --biel-search-result-border-color: #363636; --biel-search-ask-ai-border-color: var(--biel-search-result-border-color); --biel-search-result-title-color: var(--biel-white-color); --biel-search-result-description-color: var(--biel-text-color); --biel-search-result-mark-color: var(--biel-primary-light-color); --biel-code-snippet-header-text-color: var(--biel-text-color); --biel-code-snippet-text-color: var(--biel-white-color); --biel-search-filter-color: var(--biel-white-color); --biel-search-filter-selected-color: var(--biel-white-color); --biel-search-filter-bg-color: var(--biel-dark-color); --biel-search-filter-selected-bg-color: var(--biel-primary-color); --biel-search-filter-border-color: #3a3a3a; --biel-search-filter-hover-color: #3a3a3a; --biel-search-filter-selected-border-color: var(--biel-primary-color); --biel-terms-modal-bg-color: var(--biel-dark-color); --biel-terms-modal-color: var(--biel-white-color); --biel-terms-modal-close-btn-color: var(--biel-footer-action-color); --biel-terms-modal-close-btn-color-hover: var(--biel-terms-modal-color); --biel-search-toctree-page-bg-color: var(--biel-search-result-bg-hover-color); --biel-search-toctree-page-border-color: var(--biel-search-result-border-color); --biel-search-toctree-page-text-color: var(--biel-white-color); --biel-search-toctree-count-color: var(--biel-text-color); --biel-search-toctree-border-color: var(--biel-search-result-border-color); } @media (min-width: 768px) { :root { --biel-search-button-text-display: block; --biel-search-button-ctrl-k-display: block; --biel-search-button-padding: 8px 15px; --biel-search-button-icon-margin-right: 5px; --biel-search-content-max-height: 80dvh; --biel-search-body-max-height: 50dvh; } } ``` ## CSS parts For fine-grained control, the widget exposes CSS parts that let you style elements inside the Shadow DOM using the `::part()` pseudo-element. **Syntax:** ```css /* Styling a component's own parts */ component-name::part(part-name) { /* your styles */ } /* Styling nested component parts (with prefix) */ parent-component::part(child-component-part-name) { /* your styles */ } ``` **Naming conventions:** - **Direct parts** use simple names: `biel-bot::part(modal)`, `biel-button::part(button)` - **Nested parts** use prefixed names: `biel-bot::part(biel-message-bubble)`, `biel-search::part(biel-search-result-title)` ### Finding available parts 1. Right-click the widget and select **Inspect**. 2. Expand the `#shadow-root` inside the component tag. 3. Look for elements with `part="..."` attributes. ### Examples #### Custom biel button ```css /* Square button with custom color */ biel-button::part(button) { border-radius: 8px; background-color: #ff5722; color: white; box-shadow: 0 4px 12px rgba(255, 87, 34, 0.3); transition: all 0.2s ease; } /* Hover effect */ biel-button::part(button):hover { background-color: #f4511e; transform: translateY(-2px); } ``` --- ## Suggested questions Suggested questions are clickable prompts that appear when a user opens the assistant. Use them to surface common queries so users don't have to type from scratch. :::important Only **Administrator** or **Maintainer** roles can manage projects. See [Manage roles](https://docs.biel.ai/administration/roles.md). ::: ## Add suggested questions 1. In the [Biel.ai dashboard](https://app.biel.ai), select your project. 2. Click **Settings**. 3. Open **Assistant** in the left sidebar and, under **Conversation** > **Suggested questions**, enter your questions. Click **Add question** to add more. 4. Click **Save** on the Conversation card. Open the assistant on your site to verify the suggested questions appear as clickable options. --- ## Web search (beta) Augment assistant answers with real-time results from the internet when your documentation does not fully cover a question. :::warning Enabling web search means your assistant can return answers your team did not write, review, or approve. Responses may be inaccurate, outdated, or inconsistent with your product's terminology and tone, and you have limited control over which sources are used. ::: ## How it works When web search is enabled, the assistant first looks for an answer in your documentation. If the documentation is not enough, it searches the web and combines both sources in the response. A web search is triggered when the assistant decides it needs outside information. Running the web search adds five interactions to the question's base usage, even if it returns no usable content. An Auto or Instant question with web search therefore uses six interactions. Think mode can use more. Web-search interactions count toward your team's included allowance. With [extra usage](https://docs.biel.ai/administration/subscription.md#extra-usage) enabled, interactions beyond that allowance cost $0.05 each. ## Before you enable web search Web search is a fallback, not a substitute for good documentation. Before turning it on, consider whether the gap is better closed by improving your docs: - **Accuracy:** Web sources may contradict your documentation, reference outdated versions of your product, or surface answers from competitors and unofficial forums. - **Brand voice:** Answers pulled from the web will not match your product's terminology, tone, or style. - **Support burden:** Incorrect answers sourced from the web can generate support tickets that are harder to trace, since the source is not under your control. In most cases, expanding your documentation is the safer long-term choice. Web search is most appropriate for narrow, well-defined gaps such as third-party integrations or ecosystem topics that are not worth maintaining in your own docs. You can constrain web search behavior by extending your project's prompt, for example by restricting which topics the assistant should answer from the web, instructing it to prefer official sources, or requiring it to flag when an answer comes from outside your documentation. See [Custom prompt](https://docs.biel.ai/customization/custom-prompt.md) for details. ## Enable web search :::important Only **Administrator** or **Maintainer** roles can manage projects. See [Manage roles](https://docs.biel.ai/administration/roles.md). ::: 1. In the [Biel.ai dashboard](https://app.biel.ai), select your project. 2. Click **Settings**. 3. Open **Assistant** in the left sidebar and, under **AI model and instructions**, check **Enable web search**. ![Enable web search in the AI model and instructions section](./images/settings-chatbot-enable-web-search.jpg) 4. Click **Save** on the AI model and instructions card. --- ## Workflows (Enterprise) # Workflows (Agentic RAG for Documentation) :::info Archived guide This page preserves a historical workflow overview. Its builder, routing, and deployment instructions do not describe the current Biel.ai dashboard. To configure your assistant today, use [Projects](https://docs.biel.ai/administration/projects.md) and [Actions](https://docs.biel.ai/customization/actions.md). For enterprise orchestration requirements, [contact us](https://biel.ai/contact). ::: Workflows connect multiple Biel.ai projects into a single assistant interface. Each project covers a specific domain, and a router directs queries to the most appropriate one. Projects maintain their own sources, model configuration, and custom prompts. :::important This feature is available exclusively on **Enterprise** plans. [Contact us](https://biel.ai/contact) to learn more about enterprise solutions. ::: ## How workflows work **Single project:** ```mermaid graph LR A[User Query] --> B[Single Knowledge Base] B --> C[LLM] C --> D[Response] ``` **Workflow with routing and actions:** ```mermaid graph TB A[User Query] --> B[Router Agent] B -->|Routes to| C[Python Docs Agent] B -->|Routes to| D[Java Docs Agent] B -->|Routes to| E[API Reference Agent] C --> F[Response] D --> F E --> F F --> G[Action Triggers] G -->|Optional| H[Create Ticket] G -->|Optional| I[Send to Slack] G -->|Optional| J[Schedule Meeting] ``` The router analyzes each query and directs it to the appropriate agent. Agents can also trigger external actions (tickets, notifications, etc.) based on conversation context. ## When to use workflows | Scenario | Example | Why workflows help | |----------|---------|-------------------| | Multiple languages/SDKs | Python, JavaScript, Java docs | Users only see relevant examples | | Multiple products | Product A (analytics), Product B (collaboration) | Focused responses without cross-contamination | | Different doc types | API reference, user guides, admin docs | Routes technical queries to API docs, UI questions to guides | | Large doc sets (1000+ pages) | Enterprise documentation | Splitting by domain improves accuracy | | Custom actions | Bug reports → Zendesk, demo requests → Calendly | Trigger integrations based on conversation context | Use a single project instead if your docs are under 1000 pages, cover one cohesive topic, and don't need external integrations. ## Setting up a workflow :::tip Enterprise setup included As part of your enterprise agreement, our team handles the initial workflow configuration to ensure everything works correctly from the start. We'll work with you to define routing rules, configure integrations, and test the setup before going live. ::: ### Prerequisites - At least two existing projects with indexed content. - (Optional) Webhook endpoints for custom actions. ### Create your workflow 1. In the [Biel.ai dashboard](https://app.biel.ai), click **Workflows** > **Create workflow**. 2. Enter a **Name** and optional **Description**. 3. Click **Create**. ### Add projects 1. In your workflow settings, navigate to the **Projects** section. 2. Click **Add project**. 3. Select a project from your existing projects. 4. Define when this project should be used: - **Keywords**: Terms that indicate this project should handle the query - **Topics**: High-level categories this project covers - **Priority**: Ranking when multiple projects could match 5. Repeat for each project you want to include. 6. Click **Save**. ### Configure routing rules 1. Navigate to **Routing rules** in your workflow settings. 2. Click **Add rule**. 3. Define your rule: ``` Name: API Questions Condition: Query contains ["API", "endpoint", "authentication", "integration"] Action: Route to "Developer Documentation" project Priority: High ``` 4. Add multiple rules to cover different scenarios. 5. Set a fallback strategy: - **Query all projects**: Combines responses from all relevant projects - **Default project**: Routes to a general knowledge project - **Request clarification**: Asks the user to rephrase 6. Click **Save**. ### Set up custom actions (optional) 1. Navigate to **Actions** in your workflow settings. 2. Click **Add action**. 3. Configure your action: - **Action type**: Slack, Microsoft Teams, Email, Zendesk, Webhook, or other available integrations. - **Trigger condition**: When this action should fire. - **Configuration**: Credentials and integration details. 4. Click **Save**. ## Test your workflow 1. In the workflow dashboard, click **Test**. 2. Enter sample queries that should trigger different projects, including edge cases and action triggers. 3. Review routing decisions and responses. 4. Adjust rules and priorities as needed. ## Deploy your workflow 1. In your workflow settings, navigate to **Deployment**. 2. Copy the embed code and add it to your website. ## Supported integrations | Category | Platforms | |----------|-----------| | Communication | Slack, Microsoft Teams, Email, Discord | | Ticketing | Zendesk, Jira, ServiceNow, Freshdesk | | CRM | Salesforce, HubSpot | | Scheduling | Calendly, Cal.com | | Analytics | Segment, Mixpanel, Google Analytics | | Custom | Any HTTP endpoint via webhooks | --- ## Customization Configure the Biel.ai widget appearance, behavior, and AI settings.
Widget Configure widget properties and positioning
Styles Customize colors, fonts, and CSS
Dark mode Enable dark mode support
Initial message Set the assistant greeting message
Suggested questions Add clickable question prompts
Actions Define clickable action buttons based on conversation triggers
Models Choose the AI model
Prompt Configure AI behavior and response style
Reasoning modes Control reasoning depth (Auto, Instant, Think)
Chat progress Choose the progress spinner or loading dots
Web search Augment answers with real-time results from the internet
Data privacy PII redaction, IP collection, Terms & Conditions
Search Configure search ranking and metadata
Search filters Add category filters to search results
Embedded mode Render the assistant inline in your page
--- ## Ask AI assistant widget for Antora Add an [AI assistant](https://biel.ai) or [AI search widget](https://biel.ai/ai-search-for-docs) to your Antora documentation using Biel.ai's web components. ## Prerequisites - A **Biel.ai account**. If you don't have one, [sign up for free](https://app.biel.ai/accounts/signup/). - **A project created in your Biel.ai dashboard**. Follow the [Quickstart guide](https://docs.biel.ai/quickstart.md) to create one. - **An Antora documentation site** ready to install Biel.ai. ## Add the assistant widget {#add-the-chatbot-widget} ![Assistant widget for docs](./images/biel-widget-docs.jpg) 1. Modify the UI bundle: * If you're using a custom UI bundle for your Antora project, navigate to the UI bundle's directory. * Otherwise, clone Antora's default UI bundle with the following command: ```bash git clone https://gitlab.com/antora/antora-ui-default.git ``` 1. Locate the `head.hbs` file, which is usually under `src/partials`, and insert the following code: ```html ``` 1. Locate the `footer.hbs` or the specific file where you'd like the assistant to appear. Just before the closing tags in that file, add the following snippet: ```html Ask AI ``` Replace `` with your project's ID from the [Biel.ai dashboard](https://docs.biel.ai/quickstart.md#2-create-a-project). 1. Build and verify your project: * Re-bundle your custom UI and run the Antora build command. * If using the default UI, you'd have to integrate it as a local UI and then run Antora with the `--ui-bundle-url` flag to point to your modified local UI bundle. * Once built, ensure the assistant is functioning correctly on your site. ## Next steps - [Customize](https://docs.biel.ai/customization.md) the widget's appearance, behavior, and tone. - [Connect integrations](https://docs.biel.ai/integrations.md) like GitHub Actions, MCP, or Zapier. --- ## Ask AI assistant widget for Astro Add an [AI assistant](https://biel.ai) or [AI search widget](https://biel.ai/ai-search-for-docs) to your Astro site using the `astro-biel` integration. :::tip Building with Starlight? Use the dedicated [Starlight plugin](https://docs.biel.ai/installation/starlight.md) instead. ::: ## Prerequisites - A [Biel.ai account](https://app.biel.ai/accounts/signup/). - A [project](https://docs.biel.ai/quickstart.md#2-create-a-project) with indexed content. - An Astro site. - Node.js installed. ## Add the assistant widget {#add-the-chatbot-widget} The `astro-biel` integration adds a floating chat button to every page. It works with any template or UI framework and survives client-side navigation with Astro's ClientRouter. ![Assistant widget for docs](./images/biel-widget-docs.jpg) 1. Install the integration: ```console npm install astro-biel ``` 2. Add it to your `astro.config.mjs`: ```js export default defineConfig({ integrations: [ biel({ project: '', headerTitle: 'Biel.ai assistant', }), ], }) ``` Replace `` with your project's ID from the [Biel.ai dashboard](https://docs.biel.ai/quickstart.md#2-create-a-project). 3. Run `npm run dev` and verify the chat button appears in the bottom-right corner. ## Customization Pass [layout options](https://docs.biel.ai/customization/layout.md) to the integration as camelCase properties: ```js biel({ project: '', bielButtonText: 'Ask AI', buttonPosition: 'bottom-right', modalPosition: 'bottom-right', buttonStyle: 'dark', headerTitle: 'Documentation AI', }) ``` Set `enable: false` to turn the widget off without removing the configuration. ## Add the search widget The search widget renders an AI search input you can place anywhere in your layout. The `astro-biel` integration loads the required assets. ![Biel search](./images/biel-search-widget.jpg) Install and configure the integration: ```console npm install astro-biel ``` In `astro.config.mjs`, append Biel to your existing integrations: ```js export default defineConfig({ integrations: [biel({ project: '' })], }) ``` Add the element to your layout's header (or any component): ```html Search ``` Replace `` with your project's ID from the [Biel.ai dashboard](https://docs.biel.ai/quickstart.md#2-create-a-project). ## Alternative: layout tags If you prefer not to use the integration, add the tags to your layout manually. 1. Locate the `src/layouts/Layout.astro` file (or any layout file that wraps your pages) and insert the following code within the **head** section: ```html ``` 2. Just before the closing **body** tag of your layout file, add the following snippet: ```html Ask AI ``` Replace `` with your project's ID from the [Biel.ai dashboard](https://docs.biel.ai/quickstart.md#2-create-a-project). 3. Open the website in a web browser to verify the assistant appears and works correctly. ## Next steps - [View the `astro-biel` source and releases](https://github.com/TechDocsStudio/astro-biel). - [Customize](https://docs.biel.ai/customization.md) the widget's appearance, behavior, and tone. - [Connect integrations](https://docs.biel.ai/integrations.md) like GitHub Actions, MCP, or Zapier. --- ## Basic installation Add a Biel.ai [AI assistant](https://biel.ai) or [AI search widget](https://biel.ai/ai-search-for-docs) to any HTML site. This method uses CDN-hosted components — no build tools or package managers required. ## Prerequisites - A [Biel.ai account](https://app.biel.ai/accounts/signup/). - A [project](https://docs.biel.ai/quickstart.md#2-create-a-project) with indexed content. ## Add the assistant widget {#add-the-chatbot-widget} The `` component adds a floating chat button to your site. ![Assistant widget for docs](./images/biel-widget-docs.jpg) 1. Add the following inside the **head** section of your HTML: ```html ``` 2. Add the following just before the closing **body** tag: ```html Ask AI ``` Replace `` with your project's ID from the [Biel.ai dashboard](https://docs.biel.ai/quickstart.md#2-create-a-project). 3. Open the page in a browser to verify the assistant appears in the bottom-right corner. ## Add the search widget The `` component adds an AI-powered search bar instead of (or alongside) the assistant. ![Biel search](./images/biel-search-widget.jpg) 1. Add the following inside the **head** section of your HTML: ```html ``` 2. Add the following where you want the search button to appear: ```html Search ``` Replace `` with your project's ID from the [Biel.ai dashboard](https://docs.biel.ai/quickstart.md#2-create-a-project). 3. Open the page in a browser to verify the search widget works. ## Select a widget version The links above omit a version, which is equivalent to `biel-search@latest`. The browser loads the latest published npm release from jsDelivr. It can change without rebuilding your site, although CDN caching means a new release may not appear immediately. To use a specific release, include the same version in both asset URLs: ```html ``` Replace `0.1.93` with your chosen release. Remove the version, or use `@latest`, to follow new releases again. See jsDelivr's [versioning](https://github.com/jsdelivr/jsdelivr#npm) and [caching](https://github.com/jsdelivr/jsdelivr#caching) documentation. ## Next steps - [Customize](https://docs.biel.ai/customization.md) the widget's appearance, behavior, and tone. - [Connect integrations](https://docs.biel.ai/integrations.md) like GitHub Actions, MCP, or Zapier. --- ## Ask AI assistant widget for Confluence Use a Biel.ai [AI assistant](https://biel.ai) or [AI search widget](https://biel.ai/ai-search-for-docs) to answer questions from indexed Confluence content on a website you control. ## Prerequisites - A [Biel.ai account](https://app.biel.ai/accounts/signup/) and a [project](https://docs.biel.ai/quickstart.md). - A Confluence Cloud space and credentials for pages you want to index. - A website that allows custom JavaScript to host the widget. ## Add the assistant widget {#add-the-chatbot-widget} ![Assistant widget for docs](./images/biel-widget-docs.jpg) Confluence Cloud has no native **Custom HTML** setting for injecting these scripts. Atlassian's [Custom HTML feature request](https://jira.atlassian.com/browse/CONFCLOUD-72750) documents this limitation. 1. Connect your space using [Confluence as a data source](https://docs.biel.ai/customization/data-sources/confluence.md). Save the source and click **Refresh sources** to index it. 2. On your external website, add these dependencies inside the **head**: ```html ``` 3. Add the assistant before the closing **body** tag: ```html Ask AI ``` Replace `` with your project's ID from the Biel.ai installation code. 4. Publish the external page and test a question about your indexed Confluence content. Link to that page from your space. ## Limitations - Indexing Confluence content does not install a widget inside Confluence Cloud. - Confluence page permissions are not inherited by the external widget. Configure [access control](https://docs.biel.ai/customization/data-sources/private-content.md) for its readers. - Confluence Data Center customization is a separate setup and is not covered by this Cloud guide. ## Troubleshooting **Custom HTML not available** This is expected in Confluence Cloud. Host the widget on a site that permits custom JavaScript. **Assistant not answering questions** Check the project dashboard's loading status and **Logs**. Verify that the source credentials can read the pages you want indexed. **Assistant not appearing on the external site** Check that its CSS and JavaScript load, and that the project ID matches the installation code. ## Next steps - [Customize](https://docs.biel.ai/customization.md) the widget's appearance, behavior, and tone. - [Connect integrations](https://docs.biel.ai/integrations.md) like GitHub Actions, MCP, or Zapier. --- ## Ask AI assistant widget for Docusaurus Add a Biel.ai [AI assistant](https://biel.ai) or [AI search widget](https://biel.ai/ai-search-for-docs) to your Docusaurus v3 site using the `docusaurus-biel` plugin. ## Prerequisites - A [Biel.ai account](https://app.biel.ai/accounts/signup/). - A [project](https://docs.biel.ai/quickstart.md#2-create-a-project) with indexed content. - A Docusaurus v3 site. - Node.js installed. ## Add the assistant widget {#add-the-chatbot-widget} The `docusaurus-biel` plugin adds a floating chat button to your site. ![Assistant widget for docs](./images/biel-widget-docs.jpg) 1. Install the plugin: ```console npm install docusaurus-biel ``` 2. Add the plugin to `docusaurus.config.js`: ```js plugins: [ [ 'docusaurus-biel',{ project: '', headerTitle: 'Biel.ai assistant', version: 'latest' } ] ], ``` Replace `` with your project's ID from the [Biel.ai dashboard](https://docs.biel.ai/quickstart.md#2-create-a-project). 3. Run `npm start` and verify the assistant appears on your site. ## Select a widget version The plugin loads the widget's JavaScript and CSS from the CDN using `latest` by default. You do not need to install `biel-search` separately. This follows the latest published widget release, independently of your npm lockfile. To use a specific release, set `version` in `docusaurus.config.js` and rebuild your site: ```js plugins: [ ['docusaurus-biel', { project: '', version: '0.1.93', }], ], ``` Replace `0.1.93` with your chosen release. Use `version: 'latest'` to follow new releases again. See [CDN version selection](https://docs.biel.ai/installation/cdn.md#select-a-widget-version) for how caching affects `latest`. ## Customization Pass [layout options](https://docs.biel.ai/customization/layout.md) to the plugin as camelCase properties: ```js plugins: [ [ 'docusaurus-biel',{ enable: true, project: '', bielButtonText: 'ASK AI', buttonPosition: 'center-right', modalPosition: 'sidebar-right', headerTitle: 'Biel.ai assistant', buttonStyle: 'dark', } ] ], ``` To override the widget's styles (colors, fonts, etc.), add CSS custom properties to your `src/css/custom.css` file: ```css :root { --biel-primary-color: #FF0000; } ``` See [Styles](https://docs.biel.ai/customization/styles.md) for the full list of CSS properties. :::tip[Docusaurus not loading your custom CSS?] Make sure `custom.css` is referenced in `docusaurus.config.js` under the `classic` preset: ```js presets: [ [ 'classic', { theme: { customCss: require.resolve('./src/css/custom.css'), }, }, ], ], ``` ::: ## Add the search widget The search widget replaces the default Docusaurus search bar with Biel.ai's AI-powered search. ![Biel search](./images/biel-search-widget.jpg) 1. Install the plugin: ```console npm install docusaurus-biel ``` 2. Register the plugin in `docusaurus.config.js` to load the widget assets: ```js plugins: [ [ 'docusaurus-biel', { project: '', headerTitle: 'Documentation AI', version: 'latest', enable: false, }, ], ], ``` Replace `` with your project ID. `enable: false` hides the floating assistant button while keeping the assets available for search. Set it to `true` to use both widgets. 3. Eject the `SearchBar` component using [swizzling](https://docusaurus.io/docs/swizzling): ```console npm run swizzle @docusaurus/theme-classic SearchBar ``` When prompted, choose **TypeScript** and **Eject**. 4. Open `src/theme/SearchBar.tsx` and replace its content with: ```tsx export default function SearchBar() { const projectId = ''; const headerTitle = 'Documentation assistant'; // @ts-ignore: Not a React component return Search; } ``` Replace `` with your project's ID from the [Biel.ai dashboard](https://docs.biel.ai/quickstart.md#2-create-a-project). 5. Run `npm start` and verify the search widget appears in the navbar. :::tip[Using search without the assistant?] Set `enable: false` in the `docusaurus-biel` plugin config to hide the floating chat button: ```js plugins: [ [ 'docusaurus-biel', { enable: false, project: '', headerTitle: 'Biel.ai assistant', version: 'latest' } ] ], ``` ::: ## Multilingual support If your Docusaurus site uses [i18n](https://docusaurus.io/docs/i18n/tutorial), you can localize the assistant's UI strings per locale. This approach uses `biel-react` instead of the `docusaurus-biel` plugin. ![Assistant widget i18n](./images/biel-i18n.jpg) 1. Install `biel-react`: ```bash npm install biel-react ``` :::tip[Already using docusaurus-biel?] This setup replaces it. Run `npm uninstall docusaurus-biel` to remove the plugin. ::: 2. Wrap the Footer component using [swizzling](https://docusaurus.io/docs/swizzling) to inject the assistant before the closing **body** tag: ```bash npm run swizzle @docusaurus/theme-classic Footer ``` When prompted, choose **Wrap**. 3. Open `src/theme/Footer/index.js` and replace its content with: ```js function BielWidget() { const { i18n } = useDocusaurusContext(); const language = i18n.currentLocale; const projectId = ''; // Replace with your actual project ID const placeholders = { en: { bielButtonText: "Ask AI", sendButtonText: 'Send', inputPlaceholderText: 'Type your message', error403: 'Oops! The request URL does not match the one defined for this project.', error404: 'Oops! We could not find the provided project ID.', errorDefault: 'Oops! Please try again later.', headerTitle: 'Need help?', footerText: 'AI generated answers. Always verify the sources before using them.', sourcesText: 'Sources', suggestedQuestions: JSON.stringify(["What is Biel.ai?", "How to install in Docusaurus?"]), suggestedQuestionsTitle: 'Suggested questions', termsTitle: 'Assistant Terms & Conditions', termsDescription: "Please review our Terms & Conditions before proceeding.", termsCheckboxText: 'I have read and agree to the Terms & Conditions.', welcomeMessage: 'Hello! How can I help you today?' }, es: { bielButtonText: "Pregúntame", sendButtonText: 'Enviar', inputPlaceholderText: 'Escribe tu mensaje', error403: '¡Ups! La URL de solicitud no coincide con la definida para este proyecto.', error404: '¡Ups! No pudimos encontrar el ID de proyecto proporcionado.', errorDefault: '¡Ups! Por favor, intenta de nuevo más tarde.', headerTitle: '¿Necesitas ayuda?', footerText: 'Respuestas generadas por IA. Verifica siempre las fuentes antes de usarlas.', sourcesText: 'Fuentes', suggestedQuestions: JSON.stringify(["¿Qué es Biel.ai?", "¿Cómo instalar en Docusaurus?"]), suggestedQuestionsTitle: 'Preguntas sugeridas', termsTitle: 'Términos y condiciones del asistente', termsDescription: "Por favor revisa nuestros Términos y Condiciones antes de continuar.", termsCheckboxText: 'He leído y acepto los Términos y Condiciones.', welcomeMessage: '¡Hola! ¿En qué puedo ayudarte hoy?' } }; const { bielButtonText, error403, error404, errorDefault, footerText, headerTitle, inputPlaceholderText, sendButtonText, sourcesText, suggestedQuestions, suggestedQuestionsTitle, termsCheckboxText, termsDescription, termsTitle, welcomeMessage, } = placeholders[language] || placeholders.en; useEffect(() => { if (typeof window !== 'undefined') { defineCustomElements(window); } }, []); return ( {bielButtonText} ); } export default function FooterWrapper(props) { return ( <>