One conversation surface on every page
Release notes 2026-09-15 — the agent conversation is now a dock beside every dashboard page, open by default on a record, carrying the page you are on as context. The floating bubble is gone.

Shipped: merged to vocion-core main on 2026-09-09 as 336fddd9, with 7591b8ea and 0a03f37c; included in the 2026-09-15 deploy. Part of the 2026-09-15 release notes.
The outcome
An operator reading a mission run, a briefing or an agent's profile should be able to ask about it without leaving it, and the answer should be about that page. Three presentations of the conversation — a dock on lead pages, a draggable bubble with its own history everywhere else, and the full page — became two. The commit deletes ChatBubble.tsx, ChatBubbleHeader.tsx, ChatBubbleHistoryPanel.tsx and useDraggablePosition (with their tests) and adds PageDock.tsx — the diff stat is in 336fddd9.
What it is
The dock is the conversation on every page except the full-page chat, mounted once by the app shell beside the page content (packages/core/src/features/dashboard/AppShell.tsx → features/dashboard/chat/PageDock.tsx). Open, it takes a third of the viewport with a 384px floor — DOCK_WIDTH_CLASS = 'w-[max(24rem,33.333vw)]' in ChatDock.tsx — and below 1200px it becomes a fixed panel over the page (the max-[1199px]:fixed classes on the same <aside>). Its header renders the same ChatMenu as the full page: new chat, recent threads, which agent answers.
PageDock decides per route (PageDock.tsx, OWN_DOCK_ROUTES and RECORD_ROUTES):
- nothing on
/dashboard/chat— the full page is the conversation — and on routes that mount their own scoped dock; - open by default on single records: mission runs, missions, objects, agents, connectors, eval runs, adoption detail, learning steps — a person on one record came to work on it;
- collapsed to a button everywhere else.
Each turn carries the page the person is on — route and title — as page_context on the request. withPageContext() appends a short "where I am" note to the message the model sees; the stream route passes the note to the agent and stores the message as typed, so the transcript never shows it (the commit message states the rule; pageContext.test.ts pins the format). A stored collapse choice wins over the page default and applies across pages.
Two follow-ups landed with it: the guided review cards live in the transcript rather than a separate panel, and the composer is the dock's bottom edge.
What did not change
The stream protocol. Every turn already emits typed events — tool start and end, a hierarchical trace of reasoning, tool and delegate nodes, retrieval progress, recommended-action cards, human-in-the-loop gates, usage (packages/core/src/services/agents/types.ts, AgentEvent) — and the trace is persisted on the message row — traceJson in Schema.ts (conversation_message.trace_json). A finished message collapses to "Worked it out · N steps" (WorkTimeline.tsx, headerText); expand it to read every call the agent made.
What is next
The dock is the spine for the persistent rail: resizable width, tool rows visible while the turn streams, collapsible reasoning, in-app link chips, thumbs feedback that feeds learning, conversation search, structured record context beyond route and title, and an expanded view with working artifacts beside the conversation. That work is in progress; nothing in it is merged.
The screenshot is the activity feed on a local workspace with fictional data, with the dock collapsed to its button.
Where this lives in the repo
- Shell mount and route rules:
features/dashboard/AppShell.tsx,features/dashboard/chat/PageDock.tsx(OWN_DOCK_ROUTES,RECORD_ROUTES,isChatPage,isRecordRoute), tests inPageDock.test.tsx - The dock:
features/dashboard/chat/ChatDock.tsx(DOCK_WIDTH_CLASS = 'w-[max(24rem,33.333vw)]', the collapse keyvocion_chat_dock_collapsed) - Page context on the wire and in the prompt:
services/chat/pageContext.ts(+ test), consumed inapp/[locale]/rpc/agent/stream/route.ts - The stream's event union and trace nodes:
services/agents/types.ts(AgentEvent,TraceNodeEvent); rendering after the turn infeatures/dashboard/chat/WorkTimeline.tsx - Commits:
336fddd9(the dock),7591b8ea(guided cards in the transcript, composer as the dock's bottom edge),0a03f37c