Render grounded answer citations (Sources list + clickable [n]) #98

Closed
opened 2026-08-02 12:12:22 -07:00 by westfarn · 0 comments
Owner

Problem

Grounded answers already show inline citation markers like [1, 2, 3, 4, 5, 6], but users cannot see what those numbers refer to — no titles, URLs, or dates in the chat UI.

Backend already emits and persists citations (chat_backend#62, shipped in Phases 1–3). Frontend does not handle the frame or Prompt.citations yet.

Related: activity-status frames live in chat_web_app#96 (same WebSocket envelope; citations explicitly out of scope there).

Backend contract (already live)

WebSocket frame after stream end:

{"v": 1, "type": "citations", "data": [
  {"index": 1, "title": "…", "url": "https://…", "published_at": "2026-07-03"}
]}

Also persisted on the assistant Prompt.citations and returned from conversation/prompt APIs so reload can restore Sources.

Proposed UX

  1. Sources block under the assistant bubble when citations exist — numbered list: title (link), optional date, truncated domain/snippet if useful.
  2. Inline markers — style [1] / [1, 2] in the message as links/hover that scroll/highlight the matching Sources row (or open the URL).
  3. Reload — hydrate from Prompt.citations when loading conversation history, not only live WS frames.
  4. Empty / missing — if no citations frame and no stored citations, render nothing (no empty Sources header).
  5. Share the versioned-frame parser path with #96 (MessageContext JSON envelope); ignore unknown types safely.

Acceptance

  • Live grounded turn: after answer streams, Sources list shows with titles linking to URLs matching [n] in the prose
  • Clicking / focusing an inline [n] highlights or opens the corresponding source
  • Reload conversation: Sources still appear from persisted Prompt.citations
  • Non-grounded turns: no Sources UI
  • Theme + mobile safe; external links open safely (rel="noopener noreferrer", new tab)
  • Unit tests: WS citations frame attach; history hydrate; no-citations fallback
  • Frame envelope compatible with #96 status frames (no conflicting type values)

Out of scope

  • Changing how the backend chooses / ranks sources (#62)
  • Activity status labels (#96)
  • Agentic step frames (chat_backend#63)
## Problem Grounded answers already show inline citation markers like `[1, 2, 3, 4, 5, 6]`, but users cannot see what those numbers refer to — no titles, URLs, or dates in the chat UI. Backend already emits and persists citations ([chat_backend#62](https://git.aimloperations.com/ai_ml_operations/chat_backend/issues/62), shipped in Phases 1–3). Frontend does not handle the frame or `Prompt.citations` yet. Related: activity-status frames live in [chat_web_app#96](https://git.aimloperations.com/ai_ml_operations/chat_web_app/issues/96) (same WebSocket envelope; citations explicitly out of scope there). ## Backend contract (already live) WebSocket frame after stream end: ```json {"v": 1, "type": "citations", "data": [ {"index": 1, "title": "…", "url": "https://…", "published_at": "2026-07-03"} ]} ``` Also persisted on the assistant `Prompt.citations` and returned from conversation/prompt APIs so reload can restore Sources. ## Proposed UX 1. **Sources block** under the assistant bubble when citations exist — numbered list: title (link), optional date, truncated domain/snippet if useful. 2. **Inline markers** — style `[1]` / `[1, 2]` in the message as links/hover that scroll/highlight the matching Sources row (or open the URL). 3. **Reload** — hydrate from `Prompt.citations` when loading conversation history, not only live WS frames. 4. **Empty / missing** — if no citations frame and no stored citations, render nothing (no empty Sources header). 5. Share the versioned-frame parser path with #96 (`MessageContext` JSON envelope); ignore unknown types safely. ## Acceptance - [ ] Live grounded turn: after answer streams, Sources list shows with titles linking to URLs matching `[n]` in the prose - [ ] Clicking / focusing an inline `[n]` highlights or opens the corresponding source - [ ] Reload conversation: Sources still appear from persisted `Prompt.citations` - [ ] Non-grounded turns: no Sources UI - [ ] Theme + mobile safe; external links open safely (`rel="noopener noreferrer"`, new tab) - [ ] Unit tests: WS citations frame attach; history hydrate; no-citations fallback - [ ] Frame envelope compatible with #96 status frames (no conflicting `type` values) ## Out of scope - Changing how the backend chooses / ranks sources (#62) - Activity status labels (#96) - Agentic step frames ([chat_backend#63](https://git.aimloperations.com/ai_ml_operations/chat_backend/issues/63))
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ai_ml_operations/chat_web_app#98