Technical docs
Internal Chat
Overview
Support reference for the current internal chat UI.
Current chat modes
- The current frontend chat peer modes are:
- `aiTeammate`
- `ally`
- Sidebar `Chats` opens the shared chat surface. It is an action item, not navigation to a dedicated `/ai` page.
- `Alt+C` toggles `Chats`.
- Internal chat uses one shared session model for panel, floating, and minimized views.
What users can do
- Start a new conversation, open history, rename a conversation, or delete it.
- In the shared `Chats` surface, users first see a history screen across active AI teammates, then open a teammate conversation or start a fresh teammate chat from a target chip.
- Shared `Chats` history uses the same teammate-only filtering as Cowork. It does not mix in Ally conversations.
- Send text, reply to a message, stop generation, and send attachments.
- Use `Enter` to send from the current internal-chat composer.
- Use `Shift+Enter` or `Alt+Enter` to insert a newline without sending.
- Use `@` teammate mentions and `#` shared-file mentions when mention sources are available.
- `@` mentions resolve from the teammate catalog for the current org. In AI-teammate chat, that list can also include Ally; the currently open teammate is excluded from the mention list.
- `#` file mentions are scoped to the current AI teammate's readable shared folders, not the org's entire Storage tree.
- Recall previously sent user messages with `ArrowUp` / `ArrowDown` when the composer is otherwise idle.
- Leave feedback on assistant replies:
- `Like`
- `Dislike`
- `Feedback` comment editor
- Failed system-error assistant messages support comment-only feedback.
- Use voice mode for Ally and AI teammate chat when that chat has realtime voice enabled.
Reasoning and display behavior
- The composer shows a `Reasoning` control only when the resolved model supports reasoning.
- User-facing reasoning selections are:
- `Off`
- `Low`
- `Medium`
- `High`
- Reasoning preference is persisted in local storage and scoped by user, org, peer, entity, and conversation. A draft selection can carry forward into the first persisted conversation.
- The reasoning selector is hidden while voice mode is active.
- Assistant messages can persist a preface with reasoning, tool calls, and source cards, so those details survive reloads.
- Chats that are already at the bottom stay pinned during streaming, thinking updates, and panel/viewport resize. If the user scrolls away, expanding a reasoning/tool section does not force them back to the bottom.
Mobile and onboarding behavior
- On mobile, the internal-chat panel renders full width above the shared bottom nav instead of as a desktop-sized floating panel.
- Tapping outside the mobile panel overlay closes it.
- The onboarding URL flag `?onboarding=true` auto-opens Ally once the scoped chat state has restored.
- Onboarding Ally bootstrap prefers the latest server conversation once per user/org scope, so users land in the current onboarding thread instead of a blank draft.
- The onboarding floater is positioned bottom-right on desktop when the saved chat mode restores as a floating session.
REST endpoints the current UI uses
- AI teammate chat:
- `GET /api/organizations/{orgId}/employees/{employee_id}/messages`
- `POST /api/organizations/{orgId}/employees/{employee_id}/messages`
- `POST /api/organizations/{orgId}/employees/{employee_id}/conversations/new`
- `POST /api/organizations/{orgId}/employees/{employee_id}/stop-generation`
- `GET /api/organizations/{orgId}/employees/{employee_id}/conversations`
- `GET /api/organizations/{orgId}/employees/{employee_id}/conversations/search`
- `PATCH /api/organizations/{orgId}/employees/{employee_id}/conversations/{conversation_id}/title`
- `DELETE /api/organizations/{orgId}/employees/{employee_id}/conversations/{conversation_id}`
- Ally chat:
- `GET /api/organizations/{orgId}/ally/messages`
- `POST /api/organizations/{orgId}/ally/messages`
- `POST /api/organizations/{orgId}/ally/conversations/new`
- `POST /api/organizations/{orgId}/ally/stop-generation`
- `GET /api/organizations/{orgId}/ally/conversations`
- `GET /api/organizations/{orgId}/ally/conversations/search`
- `PATCH /api/organizations/{orgId}/ally/conversations/{conversation_id}/title`
- `DELETE /api/organizations/{orgId}/ally/conversations/{conversation_id}`
- Capability bootstrap used by the current frontend:
- `GET /api/init/internal-chat-capabilities`
- Current response only exposes Ally model availability.
Feedback and realtime
- Canonical internal-chat feedback endpoint:
- `PUT /api/organizations/{orgId}/conversations/{conversation_id}/messages/{message_id}/feedback`
- Feedback comments are capped at `500` characters.
- Only the conversation owner can update feedback.
- `429` feedback responses are surfaced as rate-limit failures, and `409` is used for messages that do not accept feedback.
- Internal chat subscribes to:
- `internal.message`
- `internal.message_updated`
- `voice_thinking_started`
- `voice_thinking_ended`
- `internal.message_updated` is the channel used to sync feedback edits and other message updates into the transcript.
- Messages with status `in_progress` are not rendered in the transcript or conversation previews.
Attachments and voice
- Shared chat input currently enforces:
- max `5` attachments per message
- `Too many attachments` toast when exceeded
- drag/drop overlay text `Drop files here`, or `Attachment limit reached` when the cap is already hit
- Clipboard-pasted generic image names are rewritten to `screenshot-...`.
- Realtime voice session creation currently uses:
- `POST /chat/realtime/employee/create-session/{organization_id}/{employee_id}`
- `POST /chat/realtime/ally/create-session/{organization_id}`
- Voice session creation returns a `conversation_id` so the chat UI can bind the realtime session to the correct conversation.
- Employee and Ally voice session creation require exactly one of:
- `conversation_id`
- `create_new_conversation`