Skip to content
Scrim UI

AI Research Assistant

A research flow that shows search tool calls, reasoning, sources and a cited final answer.

research-assistant.tsx159 lines4 componentsReact + Tailwind + shadcn/ui

npx shadcn@latest add @scrimui/research-assistant
Agent promptClaude Code · Cursor · any agent
Add the AI Research Assistant pattern from the Scrim UI registry to this project — a complete screen, not a single component.

AI Research Assistant — A research flow that shows search tool calls, reasoning, sources and a cited final answer.

## 1. Install

```bash
npx shadcn@latest add @scrimui/research-assistant
```

This writes the screen to `components/blocks/research-assistant.tsx` and pulls in the components it is built from, each landing at `components/ui/`. Everything is plain React + Tailwind with no runtime dependencies. The imports in the block already point at those paths, so it compiles as installed.

## 2. What it is made of

- `search-tool-call` — Search Tool Call
- `reasoning` — Reasoning
- `citation-ui` — Citation UI
- `source-card` — Source Card

Each is a separate file you can edit or replace on its own; the block is the arrangement, not a monolith.

## 3. Rules this layout depends on

Keep these when adapting the screen — they are the reasons it works, and they are easy to break while restyling:

- Show search and reasoning as they happen — research credibility comes from transparency.
- Keep sources persistent in a sidebar while the answer streams in the main column.
- Distinguish 'final answer' from intermediate reasoning visually.
- Let users verify any claim by clicking its citation.
- Collapse the search/tool trail once the answer lands so it doesn't dominate.

## 4. Do not do these

- Hiding the tool trail after answering — users can't audit how you got there.
- Answering before all searches complete, then revising confusingly.
- No way to see the full source, only a truncated snippet.
- Auto-scrolling the sources panel on every token, making it unreadable.

The demo content in the file — messages, file names, model names — is placeholder. Replace it with this project's real data and wire the handlers to real state rather than shipping the stubs.

Reference: https://scrimui.dev/patterns/research-assistant

Installs the screen and every component it is built from, and carries the layout rules from this page so an agent does not restyle them away.

Live Preview

Research Question

Which Claude 5 model is most cost-effective for a high-volume support bot?

  1. 1

    Parsed the question

    The user asks for the latest Claude 5 tier and its pricing.

  2. 2

    Formulated queries

    Ran two searches: model capabilities and per-tier pricing.

  3. 3

    Cross-checked sources

    Matched official docs against release notes.

  4. 4

    Synthesized the answer

    Combined 3 sources into a single recommendation.

Built from these components

Pattern code

This file composes the components above. Copy each component from its page, then this pattern file wires them together.

research-assistant.tsx
"use client";

import { Card } from "@/components/ui/card";
import * as React from "react";
import { SearchToolCall, type SearchResult } from "../../search-tool-call/search-tool-call";
import { Reasoning } from "../../reasoning/reasoning";
import { SourceCard } from "../../source-card/source-card";
import { InlineCitation, CitationList, type Citation } from "../../citation-ui/citation-ui";

/* ------------------------------------------------------------------ */
/* Data                                                                */
/* ------------------------------------------------------------------ */

const SEARCH_RESULTS: SearchResult[] = [
  {
    title: "Claude Fable 5 and Mythos 5 — Anthropic",
    url: "https://www.anthropic.com/news/claude-fable-5-mythos-5",
    snippet: "Fable 5 is the most advanced generally available Claude model to date.",
  },
  {
    title: "Claude 5 family: model overview",
    url: "https://docs.anthropic.com/models/overview",
    snippet: "Capabilities, context windows and pricing for the Claude 5 line.",
  },
  {
    title: "Anthropic model pricing",
    url: "https://docs.anthropic.com/pricing",
    snippet: "Per-token pricing for Opus, Sonnet and Haiku tiers.",
  },
];

const REASONING_STEPS = [
  {
    title: "Parsed the question",
    detail: "The user asks for the latest Claude 5 tier and its pricing.",
  },
  {
    title: "Formulated queries",
    detail: "Ran two searches: model capabilities and per-tier pricing.",
  },
  {
    title: "Cross-checked sources",
    detail: "Matched official docs against release notes.",
  },
  {
    title: "Synthesized the answer",
    detail: "Combined 3 sources into a single recommendation.",
  },
];

const SOURCES: Citation[] = [
  {
    id: 1,
    title: "Claude Fable 5 and Mythos 5",
    url: "https://www.anthropic.com/news/claude-fable-5-mythos-5",
    domain: "anthropic.com",
    snippet: "Fable 5 is the most advanced generally available Claude model.",
  },
  {
    id: 2,
    title: "Claude 5 family: model overview",
    url: "https://docs.anthropic.com/models/overview",
    domain: "docs.anthropic.com",
  },
  {
    id: 3,
    title: "Anthropic model pricing",
    url: "https://docs.anthropic.com/pricing",
    domain: "docs.anthropic.com",
  },
];

/* ------------------------------------------------------------------ */
/* ResearchAssistantPattern                                            */
/* ------------------------------------------------------------------ */

export function ResearchAssistantPattern() {
  const [phase, setPhase] = React.useState<0 | 1 | 2>(0);

  React.useEffect(() => {
    if (phase !== 0) return;
    const t = window.setTimeout(() => setPhase(1), 3200);
    return () => window.clearTimeout(t);
  }, [phase]);

  React.useEffect(() => {
    if (phase !== 1) return;
    const t = window.setTimeout(() => setPhase(2), 3600);
    return () => window.clearTimeout(t);
  }, [phase]);

  return (
    <Card className="gap-0 py-0 rounded-xl border border-border bg-card">
      {/* Question header */}
      <div className="border-b border-border px-5 py-4">
        <p className="text-xs font-medium text-muted-foreground">Research Question</p>
        <h3 className="mt-1 text-lg font-semibold text-foreground">
          Which Claude 5 model is most cost-effective for a high-volume support bot?
        </h3>
      </div>

      <div className="grid gap-5 p-5 lg:grid-cols-[1fr_260px]">
        {/* Main column */}
        <div className="min-w-0 space-y-4">
          {/* Search tools */}
          <div className="space-y-2">
            <SearchToolCall
              query="Claude 5 model comparison"
              status={phase >= 1 ? "done" : "searching"}
              results={SEARCH_RESULTS.slice(0, 2)}
              elapsed={phase >= 1 ? "2.4s" : "1.4s"}
            />
            <SearchToolCall
              query="Claude 5 pricing per token"
              status={phase >= 1 ? "done" : "searching"}
              results={SEARCH_RESULTS.slice(2)}
              elapsed={phase >= 1 ? "1.9s" : "0.8s"}
            />
          </div>

          {/* Reasoning */}
          <Reasoning steps={REASONING_STEPS} elapsed="3.1s" isThinking={phase === 0} />

          {/* Answer */}
          {phase === 2 && (
            <div className="space-y-3 rounded-xl border border-border p-4">
              <p className="flex items-center gap-1.5 text-xs font-medium text-emerald-700 dark:text-emerald-400">
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" width="12" height="12">
                  <path d="M20 6 9 17l-5-5" />
                </svg>
                Final Answer
              </p>
              <p className="text-sm leading-7 text-foreground">
                For high-volume support traffic, <strong>Claude Haiku 4.5</strong> is the most
                cost-effective tier: it keeps per-token cost a fraction of Opus while still handling
                the routine routing and drafting that support bots handle best{" "}
                <InlineCitation citation={SOURCES[0]} />. Reserve Opus{" "}
                <InlineCitation citation={SOURCES[1]} /> for escalation paths where reasoning quality
                outweighs cost. At scale, streaming with Haiku keeps first-token latency low and the
                bill predictable <InlineCitation citation={SOURCES[2]} />.
              </p>
              <CitationList citations={SOURCES} />
            </div>
          )}
        </div>

        {/* Sources sidebar */}
        <aside className="hidden lg:block">
          <p className="text-xs font-medium text-muted-foreground">Sources</p>
          <div className="mt-2 space-y-2">
            {SEARCH_RESULTS.map((r, i) => (
              <SourceCard key={i} title={r.title} url={r.url} snippet={r.snippet} index={i + 1} />
            ))}
          </div>
        </aside>
      </div>
    </Card>
  );
}

When to use it

  • Show search and reasoning as they happen — research credibility comes from transparency.
  • Keep sources persistent in a sidebar while the answer streams in the main column.
  • Distinguish 'final answer' from intermediate reasoning visually.
  • Let users verify any claim by clicking its citation.
  • Collapse the search/tool trail once the answer lands so it doesn't dominate.

What breaks in production

  • Hiding the tool trail after answering — users can't audit how you got there.
  • Answering before all searches complete, then revising confusingly.
  • No way to see the full source, only a truncated snippet.
  • Auto-scrolling the sources panel on every token, making it unreadable.

More Patterns

AI Chat

The canonical chat interface — sidebar, streaming messages, prompt input with model selector, and sources.

AI Coding Agent

A coding run with agent status, tool calls, diffs and a human-in-the-loop approval gate.

AI Voice Assistant

A voice-first conversation — live waveform states, a recording input, a spoken transcript and a typed fallback.

Model & Memory Preferences

A preferences screen that picks the model, reasoning level and tools, and manages persistent memory.

Artifact Workspace

Chat on the left, generated output on the right — artifacts open from the answer, stream, version, and fail without breaking the conversation.

Document Q&A Workspace

Ask your own documents — upload and parse, cited answers with inspectable passages, an honest not-found state, and a visible context budget.

Structured Extraction & Review

Upload a document, watch fields fill in, then review the flagged ones — per-field confidence, corrections that keep the original, export earned.

Image Generation Studio

A one-screen generation studio — prompt composer and model picker beside a feed of queued, staged, blocked and ready image results with variants.

Multi-agent Ops Console

Watch a fleet of agents at once — parallel statuses, an inspectable handoff, a waiting approval, a failed child run, and per-run plus fleet cost.

Customer Support Copilot

Grounded reply drafts with citations, honest low-confidence answers, inline corrections, an approval gate on refunds, and a rating row on every draft.

Generative UI Dashboard

The model assembles a dashboard from a controlled widget registry — streamed props, an unsupported-request fallback, and widget clicks that re-enter the chat.