← All posts

Chat UI v2 — streaming, keepalives, and tool legibility

vocion-v0.3.0 ships ChatShell — a server-sent-events chat surface with 15s keepalives, thinking summaries, and inline tool calls. Here's how to use it and what's behind it.

Vocion Teamvocion-v0.3.0

Staleness note, added 2026-09-08. This post documents the ChatShell UI as it shipped in core v0.3.0. The streaming/keepalive/tool-legibility mechanics described below are unchanged, but the support-reply walkthrough describes the demo's draft_reply capability as an operations/ skill with a config-level requiresApproval flag. As of core v2.20.0 (commit 1daee5b2), the operations/{skill.yaml,prompt.md} shape is gone — the equivalent capability lives at skills/<slug>/SKILL.md, and approval gating is a plugin-contract concern, not a field an author sets in skill frontmatter; see docs/entities/skill.md. The walkthrough steps themselves (URLs, sign-in, chat flow) still describe the demo's current shape.

vocion-v0.3.0 swaps the dashboard's /chat over to ChatShell: a server-sent-events surface designed for long-running agent runs that don't sit comfortably inside a 30-second request window. If you've been running anything that does retrieval, tool use, or multi-step reasoning, this is the change you'll feel first.

What's new

Why we built it

Two problems with the old chat surface, both surfaced by the deepagents + Langfuse work in the prior release:

  1. Long runs died silently. A 2-minute retrieval + draft would stall against the Vercel edge proxy at 30s. Users saw a frozen UI; the run kept going on the backend and the result was lost.
  2. Tool calls were invisible. When the agent invoked search_emails or add_learning, those calls flowed into the same text stream as the assistant's prose. You couldn't tell the model from its tools, which made debugging painful and reviewing harder.

ChatShell separates the concerns: streaming envelope (durable), reasoning surface (collapsed), tool calls (structured), citations (structured), feedback (audited).

How to use it

The chat lives at /dashboard/chat. After you sign in to either local instance (http://localhost:3000 for the umbrella dashboard, http://localhost:3001 for the support-reply demo), it's the first thing the dashboard sidebar links to.

A concrete walkthrough — drafting a reply to a support ticket on the demo instance:

Stale as of core v2.20.0 — "Tool call: draft_reply (Sonnet, requires approval)" below describes the demo's now-removed operations/ shape; see the note above.

1. Open http://localhost:3001/sign-in
   (Banner autofills demo@example.com / demo123)
2. Click "Sign in" → lands in /dashboard
3. Sidebar → Chat → type:
   "Draft a reply to this ticket: 'Order #42 hasn't shipped, ETA?'"
4. Watch the run unfold:
   - "Thinking…" chip (expand to see the plan)
   - Tool call: summarize_ticket (Haiku, ~400ms)
   - Tool call: draft_reply (Sonnet, requires approval)
   - Streamed reply text
   - Sources panel: which playbook / learnings fed the draft
5. Hit thumbs-up or thumbs-down → leaves a note → committed to the audit trail

If you're wiring a custom agent into the same shell, point your stream handler at /rpc/agent/stream and emit the SSE event types defined in packages/core/src/features/dashboard/chat/. The shell auto-renders thinking chips for event: thinking, tool cards for event: tool_call, source cards for event: source, and the assistant body for event: text.

What's next