AI Assistant
The AI Assistant lets users chat with the organization's Agent workflows from any organization screen. It is available as a docked panel and as a full-screen conversation view.
Availability
The header button and docked panel appear when both conditions are met:
- the white label enables
features.enableChat; GET /api/organizations/{organizationId}/ai/modelsreturns at least one agent.
The full-screen route is /[lang]/org/[orgId]/assistant[/sessionId]. It remains reachable without configured agents and displays an empty state in that case.
On wide screens (at least 1100px), the 420px panel docks beside the page content. On narrower screens it overlays the page. Both horizontal and vertical application layouts support it.
Conversations
The client sends turns to POST /api/organizations/{organizationId}/ai/responses and renders the streamed response. Users can:
- select among the organization's Agent workflows;
- start a new conversation or resume a recent session;
- choose Ask or Auto approval mode per conversation;
- approve or decline tool calls that require confirmation;
- open the current conversation in the full-screen view.
The current application URL is sent as conversation context only for recognized organization routes. Conversation state is isolated by agent and is cleared when the user logs out or changes organization.
Screen and dialog context
An app component can declare props.assistantContext to give the assistant structured context for the current page or dialog. The name, data, and suggested questions support the same template expressions as the component layout; form values are available by form name. A declaration is not published until every expression in name resolves to a non-empty value.
props:
assistantContext:
kind: record
name: "Order {{ order.orderNumber }}"
icon: tabler-package
data:
entityType: Order
entityId: "{{ order.orderId }}"
questions:
- "Summarize this order"
- "What needs attention?"
kind is page, record, or dialog; routes default to page and dialogs to dialog. Without a declaration, routes and titled dialogs continue to publish their automatic context. Names are limited to 200 characters, data to 4 KB after template resolution, and questions to five. Empty values are removed from data. A conversation holds at most eight contexts, and contexts with the same kind, name, and entity ID replace their earlier value.
The composer displays active contexts as removable tags. Suggested questions are ordered from the current context, then the other tags, then the agent's configured prompts. Contexts are sent with each user turn as metadata.contexts and restored when a conversation is reopened.
The assistantContext action can add a snapshot from a button or other event instead of publishing live page context.
Files in chat
Users attach files with the paperclip in the composer, or by dropping them onto the panel or the full view — up to 5 per message, 25 MB each: PDF, PNG, JPG, TXT, CSV, JSON, MD, XLSX and XLS. Each file uploads as soon as it is picked and shows as a chip with its progress. A chip shows why a file can't be sent: an unsupported type, over 25 MB, over 5 files, or a PDF or image for an agent whose model can't read them (supports_files from GET .../ai/models). Excel files are made available to workflow tools by name and do not require the model's file-reading capability. Send is disabled while an upload runs or a chip shows an error. A message may be files only; it is then sent as "See the attached file(s)."
The client uploads through the presigned uploadUrl flow and sends the files as input_file / input_image parts; the backend turns them into session attachments — the client never calls createAttachment. Sent messages show their files as image thumbnails or document cards (type, size, download); a reopened chat rebuilds them from the transcript's attachment blocks, where download becomes available again. A download goes through getPresignedUri(uriType: "file", expiresInDays: 1, download: true) (GraphQL: Attachments), so the saved file keeps the attachment's real name instead of its GUID-based storage name.
Files the agent produces
An agent can also hand back a file instead of, or alongside, its text answer — written by the file.create built-in tool, or captured automatically from a workflow tool's own output (see Producing Files). Each one is a session attachment with origin Produced, distinct from a file a person uploaded.
- The reply shows a produced file as a card below the agent's text, as soon as the internal Responses stream sends
response.tms.file_produced— because that event carries the attachment id, Download works immediately rather than waiting for the chat to be reopened. - A
file_createtool step reads "Created file name", taken from the tool's own result rather than from the model's text. - Reopening a chat rebuilds the cards the same way user uploads do, from the transcript's
attachmentblocks — a produced file's block carries"origin": "produced"and sits on the tool's row (see GraphQL: Agent Sessions).
Agents can also produce PDF, Word, Excel and CSV files with the file.create built-in tool or return files from workflow tools. The response stream announces each saved file with response.tms.file_produced, so its card appears below the agent's reply and can be downloaded immediately. The matching tool step reads Created filename. Reopening a conversation restores these cards from transcript attachment blocks whose origin is produced; uploaded files remain on the user's message.
Library
The books button in the chat header opens the Library, with a badge counting the current conversation's files. It lists This Thread and All Threads (every conversation the user may see), filtered by All, Images or Documents. Images show as a thumbnail grid and documents as a list with type, size, agent and time. Every file links back to its conversation — "Uploaded to …" for a file a person attached, "Produced in …" for one the agent wrote or captured — opens a preview (the image, or a PDF's first page) and can be downloaded. Word, Excel and CSV files are download-only. In the panel, the Library replaces the chat area with a back button; in the full view it opens as a 360px column. It refreshes after every turn.
Data comes from the agentSessionAttachments query; previews and downloads use presigned URLs from the attachment query. Downloads request getPresignedUri(..., download: true), which supplies an attachment disposition and preserves the original file name.
Agent display metadata
Configure an Agent workflow's agent.ui object to control its presentation:
| Field | Purpose |
|---|---|
name | Display name in the agent menu and chat header. |
shortDescription | Supporting text in the selector and empty state. |
icon | Tabler icon name without the prefix; defaults to robot. |
color | Theme color; defaults to primary. |
prompts | Up to five suggested opening prompts. |
For the workflow contract, see Agent workflows. For session loading and transcripts, see Agent Sessions GraphQL API.