Reasoning Trace

Pro

Reasoning-summary display for a reasoning model. Streams token by token, stays open while the model thinks, then collapses itself to a summary chip the moment it finishes — the lifecycle that separates it from a timeline. Four variants: inline chip, numbered steps, streaming and nested. Per-step kind, status, latency, tokens and attributed confidence; sub-thoughts render recursively; content goes through sv-streaming-markdown so nothing reaches the DOM as markup. `[disclosure]` governs what a viewer may see, and a step’s verbatim provider reasoning is off unless asked for by name.

</>sv-reasoning-trace reasoningreasoning-summaryagentthinkingtracellm
import { SvReasoningTraceComponent } from '@styloviz-pro/reasoning-trace';

Demo & usage

Basic usage

Pro

Usage example — open the gallery for the full interactive demo.

Pro

An interactive demo for this component lives in the gallery.

Open live demo

More examples

Inline in a chat message

Pro

Resolves to one chip — "Thought for 3.5s · 6 steps" — that expands on demand.

Live, then self-collapsing

Pro

Open with a caret while thinking; collapses itself the moment streaming ends.

Reasoning as the subject of the page

Pro

Turn auto-collapse off when the trace is the content rather than an aside.

Sub-thoughts with attributed confidence

Pro

Nested branches render recursively; the meter says what its figure is, so a self-report does not read as a calibrated probability.

When to use

  • Showing a reasoning model's thinking beside its answer, without letting it dominate the thread.
  • Debugging why an agent chose one path over another — the reflection steps are usually where it went wrong.
  • Giving a reviewer the model's stated confidence per step before they act on the output.
  • Rendering a live "thinking" state that resolves into something compact when it completes.

Async states

  • loading
  • error
  • retry
  • offline

Item identity & owned state

Restorable state
  • openStepIds

Bind these to put a saved view back — the open sections, the hidden columns, the selected rows — and read their Change events to store what the user does.

Inputs

NameTypeDefaultDescription
loadingbooleanfalseTrue while the data is being fetched.
errorSvDataError | string | nullnullLoad failure. Use `toSvDataError()` from `@styloviz/core` to normalize an `HttpErrorResponse`.
stepsreadonly ReasoningStep[][]The reasoning steps, in order.
connectionSvConnectionState'idle'State of your `EventSource` / WebSocket. A trace that stops growing looks the same whether the model is still thinking or the socket died, and `streaming` alone cannot tell those apart.
reconnectablebooleanfalseOffer a manual reconnect while the feed is down.
summarystring | nullnullReplace the generated collapsed summary with your own wording.
variantReasoningTraceVariant'steps'Presentation preset.
streamingbooleanfalseThe model is thinking right now — keeps the trace open and shows a cursor.
autoCollapsebooleantrueCollapse to the summary chip when `streaming` goes false. This is the component's whole reason to exist; turn it off only when the trace *is* the page rather than an aside in a thread.
defaultExpandedbooleanfalseStart expanded. Ignored once the reader toggles, and by `inline`.
showTimingbooleantrueShow per-step duration and token chips.
showConfidencebooleanfalseShow the confidence meter on steps that report one.
confidenceBasisstring | nullnullWhat the confidence figure actually is. A PER-STEP CONFIDENCE WITH NO METHOD BEHIND IT IS A DECORATIVE NUMBER ON AN UNVERIFIABLE CLAIM. "80%" reads as calibrated; it is usually the model asked to rate its own certainty, which is a different quantity from a token-probability mean and not comparable across models, prompts or runs. One phrase — "self-reported by the model", "mean token logprob" — is the whole fix. With `showConfidence` on and no basis, the figure still renders and says "no method recorded". Hiding the number a host already shows would be a silent regression; saying what it is not is the honest move.
disclosureReasoningDisclosure'steps'How much of the trace this viewer may see. THE FIELD THIS EXISTS FOR IS `raw` — a step's verbatim provider reasoning, which several providers' terms prohibit displaying. It is rendered only at `'full'`, so the unsafe thing is off unless somebody asks for it by name. THE DEFAULT IS `'steps'`, NOT `'summary'`. Defaulting a component whose whole purpose is showing reasoning steps to "hide the steps" would be a silent breaking change dressed as a safety fix. The model's narration is what this was built to show and what every existing host renders; `raw` is the new, dangerous field, and it starts hidden.
maxHeightstring'24rem'Max height of the step list before it scrolls, as a CSS length.
headingOffsetnumber3Heading level offset for Markdown inside a step.
ariaLabelstring'Model reasoning'Accessible label for the trace region.
openStepIdsReadonlySet<string> (two-way)new Set()Step ids the reader opened (two-way). A `model` so a host can restore or persist which steps were open. A step still being written is shown open regardless, so it is not listed here unless the reader opened it.

Outputs

EventPayload typeDescription
retryvoidThe host should re-run the failed load.
reconnectvoidThe user asked to re-open the feed.
toggledReasoningTraceToggleEmits whenever the trace opens or closes, and whether it did so by itself.
stepToggledReasoningStepToggleEmits when a single step is expanded or collapsed.
stepClickReasoningStepEmits the step the reader activated.
openStepIdsChangeReadonlySet<string>Emits the new `openStepIds` whenever it changes — the output half of `[(openStepIds)]`.

Wire it to your API

This component is headless about transport: it renders what you give it and reports what the user asks for. Nothing below requires @styloviz/data — drive it from whatever you already use.

Template

Pro

Bound to the names this component actually exposes.

Host class

Pro

Drive the three async inputs from your own fetch.

  • This component does not emit a query, so it renders what you give it. Fetch on your own trigger and bind `steps`, `loading` and `error`.
  • `connection` reports the state of your `EventSource` or WebSocket. The component cannot infer it: a list that stops growing looks identical whether the feed is quiet or the socket died.
  • Normalize failures with `toSvDataError()` from `@styloviz/core`. It derives `retryable` from the status, so a 404 does not get a "Try again" button that can only fail again.

Full walkthrough: Connecting to a backend.

Customization & theming

  • `[disclosure]`: `summary` (chip and step titles), `steps` (the model’s narration — the default) or `full` (also each step’s verbatim `raw` provider reasoning). The dangerous field is `raw`: several providers’ terms prohibit displaying the hidden reasoning their models emit, and it is the text most likely to contain a user’s own words repeated back — so it is a field of its own, separate from `content`, and it renders only at `full`, with a dev warning when it actually does.
  • The default is `steps`, not `summary`. Defaulting a component whose whole purpose is showing reasoning steps to 'hide the steps' would be a silent breaking change dressed as a safety fix; the thing that needed a safe default was `raw`, which is new and starts hidden.
  • `[confidenceBasis]` names what the confidence figure is — 'self-reported by the model', 'mean token logprob'. A per-step confidence with no method behind it is a decorative number on an unverifiable claim: '80%' reads as calibrated when it is usually the model rating its own certainty, which is not comparable across models, prompts or runs. With the meter on and no basis the figure still renders and says 'no method recorded' — hiding a number the host already shows would be a silent regression — and the console says so too.
  • The prose here says **reasoning summary**, not 'chain-of-thought', deliberately: the older name invites integrators to pipe a provider’s raw hidden reasoning straight to the DOM. The package name and the `sv-reasoning-trace` selector are unchanged — renaming those would break every host for a wording fix.
  • Redaction, from the pack-wide policy (`X-2`): a step's title and body are masked per `provideSvAiPrivacy({ patterns })`, with a note on the step saying something is hidden. Reasoning content quotes the prompt, and the prompt is where the secrets are — a trace is also the thing people screenshot into a bug report.
  • `variant` picks the presentation: `inline` for a chip in a thread, `steps` for a numbered list, `streaming` for live output, `nested` for branch connectors.
  • `summary` replaces the generated chip text when you want domain wording rather than "Thought for 3.5s · 6 steps".
  • `showTiming` and `showConfidence` control the per-step chips; `maxHeight` sets where the list starts scrolling.
  • `headingOffset` (default 3) demotes Markdown headings inside a step so a thought cannot hijack the page outline.
  • Each step's `kind` selects its glyph — observation, plan, thought, reflection, decision — so the shape of the reasoning is readable at a glance.
  • The `summariseTrace` and `flattenSteps` helpers are exported for building your own summary UI over the same model.

Best practices

  • Do: Leave `autoCollapse` on inside a conversation. A finished trace that stays open pushes the actual answer off screen — that behaviour is the reason this component exists.
  • Do: Use `toggled.automatic` to tell the self-collapse apart from a reader's click, so you only re-scroll the thread on the former.
  • Do: Give each step a `title`. The kind label is a fallback, and a list of six steps all reading "Thought" tells the reader nothing.
  • Do: Set `status: 'thinking'` on the step currently being written — it keeps that step open and renders the caret on it.
  • Don't: Do not use it for executed tool calls. Arguments and results belong in Tool Call Card; a completed run's spans belong in AI Agent Activity Log. This is the model's narration between them.
  • Don't: Do not present `confidence` as a probability of being correct. It is the model's self-report, and a confidently wrong step is the most common failure this view exposes.
  • Don't: Do not stream raw reasoning to end users in a regulated flow without review — surface it to operators, or gate it behind a toggle.

Accessibility

  • The trace is a real disclosure: a `button` with `aria-expanded` and `aria-controls` pointing at the step list, and the same wiring again per step.
  • While the model is thinking the region carries `aria-busy="true"` rather than a live region — announcing every token would read the entire monologue aloud.
  • Completion is announced once, via a visually-hidden `role="status"` region carrying the summary.
  • Status is never colour-only: each step's marker is a distinct glyph — clock, spinner, check or warning triangle.
  • The confidence meter is `role="img"` with a spoken label that carries its basis ("Confidence 82% — self-reported by the model", or "— no method recorded"), so it is neither silent to screen readers nor presented to them as a calibrated probability.
  • Sub-thought indentation is capped at four levels, so a deep chain stays reachable rather than running off-screen.

Feedback on Reasoning Trace

Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.

Loads giscus.app and GitHub — nothing is fetched until you click.