# Chat

Conversation panel for an AI assistant backed by one of the app's workflows.

## Add it to an app

1. Open the app builder and find **Chat** in the component palette.
2. Insert it into the intended region or container.
3. Set its properties in the inspector. Use a literal for a fixed value or a binding for a value supplied by the app.
4. Connect its events where the app should respond to a user gesture.
5. Preview with representative data and save after resolving validation problems.

The type name in the builder’s code view is `chat`.

## Settings

| Setting | Accepted value | Required | Default | What it controls |
| --- | --- | --- | --- | --- |
| Appearance (`appearance`) | "inline" / "overlay" | No | "overlay" | Literal only; do not use an expression binding. 'overlay' = the Ask-AI launcher + panel in the app shell; 'inline' = in its cell. |
| Content key (`contentKey`) | string | No | "content" | — |
| Empty-state text (`emptyText`) | string | No | Not specified | Supports expression bindings. Falls back to 'Ask a question to get started.' |
| Messages (`messages`) | list of object | No | [] | Supports expression bindings. Conversation records ({ [roleKey], [contentKey] }), oldest first. The listed default is inserted when adding a new component. |
| Pending (`pending`) | boolean | No | Not specified | Supports expression bindings. Truthy shows the working row and blocks sends. |
| Placeholder (`placeholder`) | string | No | "Message" | Supports expression bindings. Composer hint text. The listed default is inserted when adding a new component. |
| Role key (`roleKey`) | string | No | "role" | — |
| Source document key path (`sourceNameKey`) | string | No | "meta.group" | — |
| Source page path (`sourcePageKey`) | string | No | "meta.fragments.0.page_number" | — |
| Sources key (per message) (`sourcesKey`) | string | No | "" | Names each message's retrieval matches; '' = no source chips. |
| Title (`title`) | string | No | "Assistant" | Supports expression bindings. |
| Working status text (`workingText`) | string | No | "Thinking…" | Supports expression bindings. |

## Values available to bindings

| Value | Type | Initial value | Meaning |
| --- | --- | --- | --- |
| `activeCitation` | object or null | null | The clicked source chip's anchor (a document_viewer `anchor`), with a monotonic revision. |
| `draft` | string | "" | The composer text, per keystroke. |
| `lastMessage` | string | "" | The message just sent (the composer clears first). |

Refer to these values through `components.<component-id>.<value>` in a binding. Use the identifier assigned to this instance of Chat, not the component type name.

## Events

- `onCite` — A source chip was clicked, after activeCitation is published.

- `onSend` — A message was sent, after lastMessage is published.

Connect only the actions the app needs. An event can fetch results, run an enabled data source, set state, update another component, show a notification, or navigate where supported.

## Keyboard and accessible labels

Accessible label source: The header `title`, else 'Assistant'; the overlay panel is a dialog.

- Enter sends; Shift+Enter inserts a newline.

- Escape closes the overlay panel.

## Example: Workflow-backed assistant

| Setting | Example value |
| --- | --- |
| `messages` | "{{ dataSources.chat.data }}" |
| `pending` | "{{ dataSources.chat.isRunning }}" |
| `placeholder` | "Ask about your documents…" |
| `title` | "Document Q&A" |

When `onSend` occurs, the example performs:

- `triggerDataSource` with {"dataSourceId":"chat","inputRecords":[{"message":"{{ components.Chat.lastMessage }}"}],"mode":"run"}

## Example: Inline, with source chips that open the viewer

| Setting | Example value |
| --- | --- |
| `appearance` | "inline" |
| `messages` | "{{ dataSources.chat.data }}" |
| `sourcesKey` | "matches" |

When `onCite` occurs, the example performs:

- `setStateValue` with {"key":"activeAnchor","value":"{{ components.Chat.activeCitation }}"}

## If it is empty or unavailable

Check the source binding, the selected item, and the app’s access. A hosted document, table, review, or storage component needs the corresponding app capability; an offline preview cannot supply live private data. A source running with no results is different from an invalid binding. Inspect the app’s workflow and data source before changing the presentation.
