Skip to content
Kura

Trace Waterfall

beta

Span tree on a shared time axis for agent runs: nested agent, LLM, tool and retrieval spans, live bars, a details row and keyboard tree navigation.

@kura-ui/react/trace-waterfallCopy for agentsMarkdownRegistry JSON

A finished turn

minimal
Trace14.2s
Kura
Plan the fix
read_file
Write the patch
Trace complete, 14.2s

Replay of a run

The 12-minute auth-client migration replayed on a controlled clock: subagents, a failing pnpm test (selected, with its error), the fix, review and PR. The axis rescales as the run grows.

full
Trace4m 40s
Kura
Plan the migration
read_file
search_code
Draft the client patch
edit_file
edit_file
test-writer
Write session tests
edit_file

Live, from a wall clock

A subagent that is still running: `startedAt` makes running bars grow in real time.

state
test-writer25.2s
test-writer
read_file
search_code
Write session tests
edit_file
bash

Custom details

`renderDetails` shows the edit a tool made as a CodeBlock.

composition
Tool calls9.3s
Fix token refresh
Diagnose the failure
edit_file
src/auth/client.tsts
if (res.status === 401 && session.refreshToken) { session = await auth.refresh(session.refreshToken) return retry(req, session)}
bash
Trace complete, 9.3s

Installation

npx shadcn@latest add https://kuro.abstergo.fyi/r/trace-waterfall.json

Copies the source into components/kura/trace-waterfall with its dependencies (kura-theme, kura-format, status-glyph, use-controllable-state, use-elapsed, utils). Tokens come from the kura-theme item.

When to use it

Use it for

  • Show where the time (and tokens, and money) went in an agent run: which model calls, tool calls and subagents ran, nested, and when.
  • Debug a slow or failed run: spot the long LLM call, the failed `pnpm test`, the subagent that ran in parallel.
  • Watch a run live: running spans grow against the axis and a 'now' line moves (pass `startedAt` or drive `now`).
  • Inspect one span's input, output, error, model, tokens and cost inline by selecting it.

Reach for something else when

  • The agent's plan or todo list (what it intends to do) — use task-list.
  • A narrative of steps with tool calls attached — use agent-timeline.
  • Parallel subagents as a live roster with activity and progress — use agent-fleet.
  • A single tool invocation — use tool-call.

Props

PropTypeDefaultDescription
spans*readonly TraceSpan[]—Root spans (usually one agent span). TraceSpan = { id, name, kind: "agent" | "llm" | "tool" | "retrieval", start (ms since run start), end? (omit while running), status: AgentStatus, meta? (mono hint: path, command), model?, tokens? { input, output }, cost? (USD), input?, output?, error?, children? }.
titleReact.ReactNode"Trace"Header title.
actionsReact.ReactNode—Controls on the right of the header (e.g. a replay or open-in-LangSmith button).
nownumber—Current run time in ms since start (a controlled clock). Running spans end here and the 'now' line sits here. Use it for replays and server-driven clocks.
startedAtDate | number—Wall-clock start of the run. When given (and `now` isn't), running spans grow live, ticking every 250ms. Without either, running spans end at the latest known time.
selectedIdstring | null—Selected span (controlled). Its details row opens under it.
defaultSelectedIdstring | nullnullInitially selected span when uncontrolled. May name a span that doesn't exist yet; it opens when the span appears.
onSelectedIdChange(id: string | null) => void—Called when a span is selected, or with null when the selection is cleared.
defaultCollapsedIdsreadonly string[]—Spans whose subtrees start collapsed (e.g. noisy subagents).
renderDetails(span: TraceSpan) => React.ReactNode—Replace the details row body for a span (e.g. a CodeBlock with the diff a tool wrote). Return null to use the default stats + input/output.
emptyReact.ReactNode—Rendered when there are no spans. Default: 'No spans yet'.
labelstring"Trace"Accessible name of the tree.

All native attributes of the root element, className and ref pass through.

Anatomy

  1. TraceWaterfallRoot panel, a container-query context. `data-state="running" | "idle"`; contains a polite status region.data-slot="trace-waterfall"
  2. Headerh-10 header: title, summary, actions.data-slot="trace-waterfall-header"
  3. SummaryMono: span count · total duration · tokens · cost. Count/tokens/cost hide on narrow containers.data-slot="trace-waterfall-summary"
  4. AxisSticky row with 'Span / Duration' over the tree and nice tick labels (0, 2m, 4m…) over the bars.data-slot="trace-waterfall-axis"
  5. BodyScroll container. Give the root a height (e.g. `h-[480px]`) to scroll long traces under the sticky axis.data-slot="trace-waterfall-body"
  6. Spanrole="treeitem" with `data-kind`, `data-status`, `data-selected`; wraps the row and, when selected, its details.data-slot="trace-waterfall-span"
  7. Rowh-8 grid row: indented tree cell (chevron, kind icon, name, mono meta, glyph for running/failed/waiting, duration) and the bar cell.data-slot="trace-waterfall-row"
  8. ToggleChevron that collapses a subtree (pointer only; ArrowLeft/Right on the keyboard).data-slot="trace-waterfall-toggle"
  9. BarPositioned on the shared axis. Neutral greys by kind (LLM darkest), thin for agent spans; blue while running, red failed, amber waiting, ink when selected.data-slot="trace-waterfall-bar"
  10. NowHairline at the current time while any span is running.data-slot="trace-waterfall-now"
  11. DetailsSunken row under the selected span: kind, start, duration, model, tokens, cost, then input and output/error.data-slot="trace-waterfall-details"
  12. DurationMono, tabular, width-reserved; ticks while the span runs.data-slot="trace-waterfall-duration"
  13. EmptyRendered when there are no spans.data-slot="trace-waterfall-empty"

Accessibility

  • Role: tree
  • A WAI-ARIA tree: each span is a treeitem with aria-level/posinset/setsize, aria-expanded for subtrees and aria-selected; one roving tab stop.
  • Each treeitem is labelled “bash pnpm test, tool, 38.4s, failed” — status is spoken, never colour-only. The selected span is described by its details row.
  • A polite status region announces failures and “Trace complete, 11m 52s” — ticking durations are not announced.
  • The axis, grid lines, bars and now-line are decorative (aria-hidden or inside labelled items).
  • Reduced motion: Bars and the now-line jump to their new positions instead of easing; the chevron turns instantly; rows and details only fade.
KeysAction
ArrowDown / ArrowUpMoves focus to the next / previous visible span.
ArrowRightExpands a collapsed span; on an expanded span moves to its first child.
ArrowLeftCollapses an expanded span; otherwise moves to the parent span.
Home / EndFirst / last visible span.
Enter / SpaceSelects the focused span (opens details); again to close.
EscapeClears the selection.

Notes for agents

  • Times are ms relative to the run start, not timestamps: convert with `span.start = +new Date(event.ts) - runStart`.
  • Omit `end` (and set status running) for unfinished spans; pass `startedAt` (wall clock) or `now` so they grow.
  • Put tokens/cost on leaf spans only. If every root span carries totals, the header uses the roots instead of summing.
  • Ids must be unique across the whole tree; they drive selection, collapse state and focus.
  • Give the root a fixed height for long traces; the axis stays sticky while the body scrolls.