# Knowledge base & forms

> Let users search your knowledge base and submit ticket forms without leaving your app.

Product: Clad Widget SDK
Source: https://docs.useclad.ai/widget/knowledge-base-forms

---

```ts
const articles = await chat.searchArticles("how do I update billing");
await chat.showArticle(articles[0].id);

await chat.showTicketForm("contact", {
  prefill: { summary: "Cannot log in", severity: "high" },
});
```

- `searchArticles` returns only **published**, end‑user‑visible articles.
- **Ticket forms are one‑way intake.** Submitting a form creates an **issue in
  your inbox** (agents triage it like any other ticket) and shows the user a
  **confirmation screen** — it does *not* open a chat thread and never appears in
  the user's conversation list. Since there's no thread for the user to read, the
  agent **"Reply to customer" composer is disabled** for these issues (internal
  notes still work). `form:submitted` fires on submit; unknown prefill fields are
  ignored.

<!--
<div class="img-ph">
  <span class="img-ph__badge">📷 Screenshot needed</span>
  <p class="img-ph__title">Knowledge base in the widget</p>
  <p class="img-ph__desc">The widget showing <strong>knowledge base search results</strong> (and/or an open article), so users can see they can self‑serve answers without leaving your app.</p>
</div>
-->

### AI assistant chat

When **AI answers** are enabled, the in‑widget search becomes a **conversational
AI assistant**. The user types a question, presses Enter, and lands in a
back‑and‑forth chat: the assistant answers from your help center, asks a
clarifying follow‑up when the question is ambiguous, and keeps context as the
user asks more. The source articles it used collapse into a **"Related
articles"** dropdown at the bottom of the chat.

It behaves like a support rep trained on your **public docs** — and is built to
be **honest**:

- Every reply is grounded **only** in your **published, end‑user‑facing** KB
  articles — internal or draft articles are never used and can never leak into a
  reply. Optionally scoped further to the widget's enabled KB collections.
- If the question is unclear, it asks a short **clarifying question** instead of
  guessing.
- If the docs don't cover the question, it says so plainly and offers a
  **"Start a conversation"** button to reach a human.

**Conversations are saved.** Each AI chat (the turns + the asker's identity and
page/locale/device metadata) is persisted server‑side so your team can review
what users ask and where the docs fall short. AI chats are **deflections** — they
do **not** create inbox tickets; only escalating to a human does.

**Enabling it.** The assistant turns on when both
[`features`](#feature-visibility-overrides-features) flags are set (from your
install code or the widget config):

```js
window.SupportChatSettings = {
  workspaceId: "{YOUR_WORKSPACE_ID}",
  widgetId: "{YOUR_WIDGET_ID}",
  features: { knowledgeBase: true, aiAnswers: true }, // search → AI assistant chat
};
```

- `knowledgeBase` provides the articles the assistant is grounded in.
- `aiAnswers` turns the search bar into the assistant chat.
- Set the widget's `ai.mode` to **`human_first`** to disable the assistant and
  route users straight to a human. With `aiAnswers` off, the search bar stays a
  plain published‑article search.

> Replies are generated server‑side; the widget only ever receives the final
> message text and the public article list. (A one‑shot, non‑conversational
> variant is also available programmatically at `POST /widget/v1/ai/answer`.)

### Where ticket forms come from

Ticket forms render **out of the box** in the widget — you don't build any form
UI. They are **data‑driven**: the *content* of a form (its name and fields) is
defined in the dashboard, while *whether and when it shows* can be driven from
code:

- **Define forms in the dashboard:** **Settings → Integrations → Web Widget →
  Ticket forms**. Create/edit/delete forms with a field builder (text, textarea,
  email, select, image), toggle each form on/off, and choose which forms appear.
  One‑click **Bug report** and **Feature request** templates are available.
  (Equivalently via the admin API — `GET/POST/PATCH/DELETE /api/widget-admin/forms`.)
  Form definitions **cannot** be authored from install code.
- **Image uploads (screenshots):** an **`image`** field lets users attach a
  screenshot (e.g. on a bug report). Uploads are **image‑only** and
  **size‑capped**, stored privately, and surfaced on the **agent's issue card**
  via short‑lived signed URLs — not shown back inside the widget.
- **Surface them automatically:** when the `ticketForms` feature is enabled and
  at least one enabled form exists, the widget home shows the forms as **"Quick
  requests"** cards near the top. The **Live chat** entry point ("Send us a
  message") stays anchored to the bottom of the home screen, and **past
  conversations** live on their own page.
- **Or open one from code:** `chat.showTicketForm(slugOrId, { prefill })` opens a
  specific form on demand (e.g. from a button in your app), optionally
  pre‑filling fields. `startConversation({ formId })` is also supported.
- **Control visibility from code:** the
  [`features`](#feature-visibility-overrides-features) override (`ticketForms:
  false`) hides the forms surface for a given page; `ticketForms: true` shows it
  but still only renders forms that exist and are enabled server‑side.

<!--
<div class="img-ph">
  <span class="img-ph__badge">📷 Screenshot needed</span>
  <p class="img-ph__title">A ticket form in the widget</p>
  <p class="img-ph__desc">The widget showing an <strong>embedded ticket form</strong> with a couple of fields (including an image/screenshot upload), to illustrate submitting an async request from inside the messenger.</p>
</div>
-->
