← All posts

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.

Vocion Teamvocion-v2.69.0

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):

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