Skip to content
Tier

Search trace

Pro

A search an agent ran, as a tool-call row: what it did in plain words, its status and how long it took, and a count of the searches and the sources read. Opened, it lists each query the agent ran and, under it, the sources it read: each one's title and its domain, as text, never a link. When the tool says the agent read more than it listed, a line says how many; when it doesn't say, nothing is guessed. A failed search opens by default and leads with its error, as ToolCall does.

Built on tool-call's data: pass the same ToolCallData your adapter gives you for the search, with the queries and sources read from its input and output.

Markdown
Version 5.2.0· other versions

This page is for 5.2.0, the current release. An earlier release’s page is the Markdown that release published, so the docs match the version you have installed (candor-lock.json records it).

Not in the docs of 1.3.0, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.8.0, 1.8.1, 1.9.0, 1.9.1, 2.0.0, 2.1.0, 2.2.0, 2.3.0, 2.4.0, 2.5.0, 2.5.1, 2.6.0, 2.6.1, 2.6.2, 2.7.0, 2.8.0 and 2.9.0: the page came later, or had another name then.

Docs pages weren’t kept for 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0 and 1.2.1: they are kept from 1.3.0 on, and before that only llms.txt was published.

Preview

Loading the preview

Install

With the Candor CLI

First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/search-trace

Brings in: bidi, chat, citation, collapsible, locale, locked, motion, status, step-list, streaming-text, tokens, utils · npm: lucide-react@^1.67.0

Usage

TSX · The example above
"use client"

import { SearchTrace } from "@/components/candor/search-trace"

export default function Example() {
  return (
    <div className="flex max-w-lg flex-col gap-1">
      {/* Sources show their title and domain as text, never a link; "more" says how many it read beyond those listed. */}
      <SearchTrace
        defaultOpen
        call={{ id: "s1", tool: "web.search", title: "Searched the web", status: "succeeded", duration: "3.1s" }}
        queries={[
          {
            id: "q1",
            query: "card network chargeback time limit 2026",
            sources: [
              { id: "a", title: "Dispute time limits for merchants", address: "https://www.example.com/merchants/disputes" },
              { id: "b", title: "Chargeback reason codes, explained", address: "https://docs.example.org/chargebacks/codes" },
            ],
            more: 4,
          },
          {
            id: "q2",
            query: "refund policy settled orders",
            sources: [{ id: "c", title: "Refunds and returns", origin: "Help centre · Policies", kind: "knowledge" }],
          },
        ]}
      />
      {/* While it runs, nothing is said about a search that has read nothing yet. */}
      <SearchTrace
        call={{ id: "s2", tool: "web.search", title: "Searching the web", status: "running" }}
        queries={[{ id: "q3", query: "carrier delivery exceptions Rotterdam", sources: [] }]}
      />
    </div>
  )
}

<SearchTrace>

PropTypeDefaultDescription
callrequiredToolCallData—The search's tool call: its plain-words title ("Searched the web"), status, duration and error. Its input and output aren't shown; `queries` holds what they said.
queriesrequiredSearchQuery[]—The queries the agent ran, in order, each with the sources it read.
defaultOpenboolean | undefined—Whether it starts open. Defaults to open when the call failed, closed otherwise.
classNamestring | undefined—Extra classes for the outer element.

Functions

sourceDomain(address: string | undefined)

The domain of a source's address, without a leading "www.", as the URL parser reads it; undefined when the address isn't a URL with a host.

Strings

The fixed words, in English by default. Change any of them under searchTrace in <LocaleProvider strings={{ … }}>; the table is exported as searchTraceStrings.

KeyEnglish
lockedNoDetailThis search has no details to show.
searches{ one: "{count} search", other: "{count} searches" }
sources{ one: "{count} source read", other: "{count} sources read" }
status— {status}
domainSeparatorSpoken,
query“{query}”
sourcesForSources read for “{query}”
more{ one: "and {count} more it read", other: "and {count} more it read" }
nothingReadRead nothing for this search

Motion

MomentFamilyWhat it does
openreveal, sizeThe searches open to their full height when the person opens the trace, and the chevron turns with them; closing reverses both. Under reduced motion it snaps open or shut.

Set with --cd-motion-search-trace-<moment>-* in your brand file; the families are in the design reference.

Types

SearchSource
One source the agent read: the page or document's title as the tool reported it, and where it lives, as text.
{ id: string; /** The page's title or the document's name, as the tool reported it. Shown as text. */ title: string; /** * The source's address as the tool reported it. Only its domain is shown ("example.com", without "www."), read by * the browser's own URL parser, so an address that hides its host in a user name shows the real host and an * internationalised one shows its xn-- form. It is never a link. */ address?: string | undefined; /** Where it lives in the app's words, for a source with no web address ("Docs · Refund policy"). Shown when `address` has no domain. */ origin?: string | undefined; /** What kind of source it is, for its icon. Defaults to "web". */ kind?: SourceKind | undefined; }
SearchQuery
One query the agent ran and what it read for it.
{ id: string; /** The query exactly as the agent ran it. Model output: shown as text. */ query: string; /** The sources the agent read for this query, in the order it read them. */ sources: SearchSource[]; /** How many more sources the tool says the agent read for this query than `sources` lists. Left out, nothing is said about more. */ more?: number | undefined; }

Types from other items

The props above take these. Each is defined by another item; import it from the path shown.

ToolCallData from @/lib/candor/chat
{ id: string; /** The tool's name, for people who want it: "metadata.describe". */ tool: string; /** What it did, in plain words: "Read Account's fields". */ title: string; status: RunStatus; /** Shown when expanded. Text only; long values scroll. */ input?: string | undefined; output?: string | undefined; outputLanguage?: PayloadLanguage | undefined; /** e.g. "1.2s". Absent while running; never estimated. */ duration?: string | undefined; /** Required when status is "failed": what went wrong, in a sentence. */ error?: string | undefined; /** * The lines it changed, when it edited files and the tool counted them: shown as "+12 −3". Left out when the tool * doesn't say; never estimated. New in 4.4. */ lines?: { added: number; removed: number; } | undefined; /** * Who let it run, when it needed a go-ahead: a person, or something automatic (a policy, a classifier, a rule). * `note` is why, in the source's words. Left out when it needed none or the source doesn't say. */ approval?: { by: "person" | "automatic"; note?: string | undefined; /** The input as the agent proposed it, when a person edited it before it ran; `input` is then what ran. */ originalInput?: string | undefined; } | undefined; }
SourceKind from @/lib/candor/chat
"document", "web", "query", "code", "data", "workflow", "knowledge", or the app's own; unknown kinds read as "Source".
string
RunStatus from @/lib/candor/status
The status vocabulary every Candor agent component shares. Components take plain data in these shapes rather than an SDK's message objects, so they work with your own LLM drivers, the Vercel AI SDK or anything else; adapters map an SDK's parts onto them.
"idle" // not started | "queued" // accepted, waiting for a worker | "running" // an agent is working on it now | "waiting" // stopped to ask a person (approval, question) | "blocked" // can't start: something it depends on failed or is waiting | "succeeded" | "failed" | "cancelled" | "skipped"
PayloadLanguage from @/lib/candor/chat
The block's language, e.g. "json", "sql", "python", "text". Shown as a label; never executed or highlighted as HTML.
string