Algolia-Central

Knowledge/AgentStudio/12-ui-and-instantsearch.md

12 — UI Refactoring & Algolia InstantSearch Adoption

This section addresses a parallel workstream to agent + prompt refactoring: where Algolia's native frontend libraries (InstantSearch, the <Chat> widget, the <FilterSuggestions> widget, the AI SDK UI hooks) should replace our custom frontend code, and what stays custom.

Why this matters

We currently have: - src/hooks/chat/useSpecialist.ts — 652 lines of state machine for specialist (Elena/Bruno) handoff and rendering - src/hooks/chat/useChatStream.ts — 639 lines of state machine for Maverick streaming - lib/agent-studio/stream-adapter.ts — 350 lines that convert Agent Studio's native JSON output to our custom XML format - Frontend XML-tag parsing scattered across src/components/chat/ - Custom paragraph buffering, footnote stripping, tag injection post-processors - ~1,600+ lines of frontend code doing what Algolia's native widgets do natively

That's the cost. The opportunity: replace large swaths of this with <Chat> (which is itself built on useChat from @ai-sdk/react) plus per-tool layoutComponent slots. Lower line count, lower bug surface, native streaming, native tool round-trip — and we get future widget improvements for free.

This is a major frontend refactor. It pairs with the agent refactor — when Elena/Bruno emit XML tags, we need our custom parser. When they emit tool calls, we need layoutComponents. Frontend refactor unlocks once tools replace XML.

What Algolia provides for frontend

Tier 1 — Agent-facing widgets (the focus of this refactor)

Per 04-frontend-widgets.md:

Widget Package What it gives you
<Chat> (React) react-instantsearch Full chat UI: streaming, tool round-trip, history, prompts, error states, suggestions, layouts
chat() (Vanilla JS) instantsearch.js/es/widgets Same as above for non-React
<FilterSuggestions> (React) react-instantsearch AI-suggested facet filters, debounced, integrated with InstantSearch state
filterSuggestions() (Vanilla JS) instantsearch.js/es/widgets Vanilla equivalent

Status: all four are BETA. Pin versions. Read changelogs.

Tier 2 — Search-facing components (potential future use)

Standard InstantSearch React components for non-AI search UIs:

  • <SearchBox>, <Hits>, <RefinementList>, <HierarchicalMenu>, <RangeInput>, <Pagination> — for traditional search interfaces
  • Connectors (useSearchBox, useHits, useRefinementList) for custom UIs over the same data

These are stable, not beta. Use for any non-AI search surfaces (admin tooling, faceted search pages, etc.) Algolia Central might need.

Tier 3 — Hooks and primitives

  • useChat from @ai-sdk/react — what <Chat> is built on. Use directly for custom React UIs needing managed message state + streaming.
  • liteClient as algoliasearch from algoliasearch/lite — lightweight client for browser use. Read-only, smaller bundle.
  • Insights API client — event tracking for personalization and analytics.

What we have today

Our frontend chat surface roughly maps as:

File Lines What it does Native equivalent
src/hooks/chat/useChatStream.ts 639 Maverick streaming state machine useChat hook OR <Chat> widget
src/hooks/chat/useSpecialist.ts 652 Elena/Bruno handoff + XML rendering state <Chat>'s tools prop with per-tool layoutComponent
lib/agent-studio/stream-adapter.ts 350 JSON→XML conversion + paragraph buffering + footnote stripping NOT NEEDED if agents emit tool calls instead of XML
src/components/chat/ChatMessage.tsx unknown XML tag parsing + render switching Per-tool layoutComponent per <Chat>'s tools prop
lib/search/stream_processor.ts unknown Post-generation content mutation, tag injection NOT NEEDED with structured tools
Discovery card UI (Maverick) various Render <discovery_pivot> tag <Chat>'s suggestionsComponent slot + config.suggestions.enabled
Handoff banner UI various Render <specialist_handoff> tag Custom layoutComponent for the handoff_to_specialist tool
Mermaid diagram render unknown Parse <strategic_architecture> tag, render via mermaid.js Custom layoutComponent for the render_architecture_diagram tool
Code block render unknown Parse <production_code> tag, render via syntax highlighter Custom layoutComponent for the render_code_block tool

Total frontend code that becomes simpler or vanishes: roughly 1,600+ lines of state machines and XML parsers + N component-specific tag parsers.

Total NEW frontend code: per-tool layoutComponent (~30-80 lines each) × ~6-8 tools = ~300-500 lines.

Net reduction: ~1,000-1,300 lines.

Migration approach (NOT a big-bang rewrite)

The safest path: migrate one piece at a time, keeping the rest intact.

Phase 1 — Replace useChatStream with <Chat>

Smallest scope: just the Maverick conversation. <Chat agentId={maverickAgentId} /> inside an <InstantSearch> shell. Drop useChatStream.ts (639 lines). Maverick still emits XML tags during this phase — <Chat> can render them via assistantMessageLeadingComponent or a custom message renderer that does the parsing inline.

Output: useChatStream.ts deleted. Maverick UI is now the native widget. ~600 lines of custom code → 0.

Phase 2 — Add tools for Maverick's structured outputs

Define tools for discovery_pivot (or use platform suggestions.enabled), specialist_handoff, analogy_canvas (if kept). Update Maverick prompt to call tools instead of emitting XML. Pass tool definitions to <Chat tools={...} /> with layoutComponent for each.

Output: Maverick's XML tag parsing in frontend goes away. Discovery questions, handoff banner, analogy hook all rendered via layoutComponent.

Phase 3 — Replace useSpecialist with <Chat> + tool components

Same shape as Phase 1, but for Elena/Bruno. Uses the same <Chat> widget — just a different agentId (Elena's UUID or Bruno's UUID) and a different tool set.

This phase is BLOCKED on the agent refactor: tools have to exist on Elena/Bruno before frontend can render them. Order: 1. (Backend) Add tools to Elena/Bruno (per §10 migration order step 2). 2. (Frontend) Build layoutComponent for each tool. 3. (Frontend) Replace useSpecialist.ts with <Chat>.

Output: useSpecialist.ts deleted (652 lines). XML parser in stream-adapter.ts deleted (350 lines).

Phase 4 — Drop the JSON→XML stream adapter

Once Elena/Bruno emit tool calls instead of XML output, the stream adapter (lib/agent-studio/stream-adapter.ts) has nothing to do. Delete it. Frontend <Chat> consumes tool calls directly.

Output: 350 more lines deleted.

Phase 5 — Adopt platform features

  • Enable config.memory.enabled and config.suggestions.enabled on agents.
  • Replace custom Redis-based conversation history with platform memory (passing id: "alg_cnv_..." and per-message IDs).
  • Replace Maverick's <discovery_pivot> with platform suggestions, rendered via <Chat>'s suggestionsComponent slot.

Output: Custom session continuity logic in the orchestrator becomes much smaller. Redis stays for 8-signal state only.

Phase 6 — Add right-panel artifact rendering (the "Claude Desktop" UX)

Per RC3-BRIEF and the agent UX direction: chat on left, opened artifacts on right. Each render tool's layoutComponent can: - Render inline in the chat (default) - Render a clickable card in the chat that, when clicked, opens the full artifact in a right panel

This is a frontend pattern we build on top of the native widget. The <Chat> layoutComponent prop gives us the slot; the right panel state and routing is custom.

Output: Two-panel UI shipped. Reference architecture for Claude Desktop-style content engagement.

Per-tool layoutComponent — concrete examples

// render_evidence_card layoutComponent
({ message }) => {
  const { source, metric, driver_action_result } = message.input;
  return (
    <div className="evidence-card">
      <span className="source-tag">{source}</span>
      <h4>{metric}</h4>
      <p>{driver_action_result}</p>
    </div>
  );
}

// render_architecture_diagram layoutComponent
({ message, addToolResult }) => {
  const { mermaid_source } = message.input;
  return (
    <div className="architecture-diagram">
      <Mermaid source={mermaid_source} />
      <button onClick={() => openInRightPanel(mermaid_source)}>
        Open full diagram
      </button>
    </div>
  );
}

// suggest_searches layoutComponent (for Maverick)
({ message, indexUiState, setIndexUiState }) => {
  const { suggestions } = message.input;
  return (
    <div className="suggestion-chips">
      {suggestions.map(s => (
        <button onClick={() => runSearch(s.query, s.facets)}>
          {s.label}
        </button>
      ))}
    </div>
  );
}

Each layoutComponent is small and focused. The widget handles the rest (streaming, error states, message threading).

What stays custom

Not everything maps to native. Some things stay code:

What Why it stays
Right panel ("Claude Desktop" two-panel) Native widget ships with inline + overlay layouts only. Two-panel is custom.
Chat history navigation, conversation threading UI Possibly custom, depending on how <Chat> handles multi-conversation switching
Custom branding (avatars, colors, themes) Style overrides via classNames and translations props of <Chat>
Telemetry, audit logging Platform sends usage data; we may want richer custom telemetry
8-signal discovery state extraction (if stays code-based) Algorithmic logic, not UI
Multi-agent routing (Maverick → specialist) If kept, this is custom UX flow (handoff card, transition animation, persona switch) — but the native widget can host all these as layoutComponents
Right-panel artifact viewer (Mermaid full-screen, code editor with copy, comparison tables) Custom components opened from layoutComponent cards

InstantSearch adoption beyond the chat widget

While the focus is the AI chat surface, Algolia Central will likely need search surfaces beyond chat:

  • Admin / merchandising UI — for managing the index content. InstantSearch React components are the standard.
  • Faceted browse pages — if the user wants to browse content without chat. <SearchBox> + <RefinementList> + <HierarchicalMenu> + <Hits> is the canonical recipe.
  • Public marketing / landing pages with embedded search<SearchBox> with <FilterSuggestions> for AI-suggested filters alongside.

For each surface, default to InstantSearch React components unless there's a specific reason to build custom. The library is mature, well-documented, and integrates natively with Algolia's analytics + personalization.

What this section does NOT cover

Open questions for UI workstream

ID Question Impact
Q-UI-1 Which version of react-instantsearch exposes <Chat> stable enough for production? Determines pin version and migration timing
Q-UI-2 Does the two-panel layout work as a layoutComponent wrapper, or do we need a separate frame above <Chat>? Drives Phase 6 architecture
Q-UI-3 Can <Chat> host the multi-agent (Maverick → Elena/Bruno) handoff visually? Drives whether handoff is in-chat (one widget, persona switches) or out-of-chat (multiple widget instances)
Q-UI-4 What's our policy for tracking widget breaking changes through beta? Operational hygiene