affectUI › Components › Agents

Trace Waterfall

Where the time and money of an agent run go – every LLM call, tool call and sub-agent as a bar on a live timeline, with tokens and cost per step, the slowest call marked and branches that fold into their parent.

Part of affectUI Pro. Install: npx shadcn@latest add https://www.affectui.com/r/trace-waterfall.json · Import from @/components/ui/trace-waterfall

When to use

  • Debugging an agent run: how long each step took, where the time and the money went, which call is slow
  • A run view next to a chat or a log – every LLM call, tool call and sub-agent as a bar on one timeline
  • Live runs, where you want to watch spans start, grow and finish while the agent works

When not to use

  • Who started whom, at a glance – use Agent Tree
  • Several agents side by side over the last half hour – use Agent Lanes
  • One agent's plan as a checklist – use Agent Plan

Usage

import { TraceWaterfall, type TraceSpan } from "@/components/ui/trace-waterfall";

const run: TraceSpan = {
  id: "run", name: "Orchestrator", kind: "agent", status: "running", start: 0,
  input: "Launch the new pricing page",
  children: [
    { id: "plan", name: "Plan the launch", kind: "llm", model: "Opus 5.5", detail: "Opus 5.5", status: "done",
      start: 900, end: 7800, tokensIn: 3240, tokensOut: 880, cost: 0.115 },
    { id: "search", name: "web_search", kind: "tool", detail: "Linear pricing", status: "running", start: 8100 },
  ],
};

export function Run({ startedAt }: { startedAt: number }) {
  // Times are ms from the start of the run; with startedAt the component keeps its own clock while it runs
  return <TraceWaterfall root={run} startedAt={startedAt} />;
}

Props

NameTypeDefaultDescription
rootTraceSpan{ id, name, kind, status, start, end?, detail?, icon?, model?, tokensIn?, tokensOut?, cost?, input?, output?, error?, children? } – the whole run as a tree, rebuilt as it goes on
kind"agent" | "subagent" | "llm" | "tool"Per span – picks the bar's tint: agents slate, LLM calls violet, tool calls teal; failed spans are red
status"running" | "done" | "failed"Per span – a running span has no end yet and grows into "now"
start / endnumberPer span, in ms from the start of the run; leave end out while it runs
detailstringPer span – a few muted words after the name, e.g. the model or the query
iconReactNodePer span – a small mark, e.g. the model maker's or the tool's logo; defaults to a swatch in the kind's color
cost / tokensIn / tokensOutnumberPer span, its own – agents add up their children, so don't pre-sum
input / output / errorstringPer span – short previews shown in the details window
nownumberThe clock in ms from the start of the run – e.g. a faster one for a demo or a replay
startedAtnumberWhen the run started (epoch ms) – without now, the component ticks its own clock from here while a span runs
collapsed / defaultCollapsedstring[][]Ids of folded spans, controlled or uncontrolled
onCollapsedChange(collapsed: string[]) => voidA span was folded or opened
openId / defaultOpenIdstring | nullnullThe span whose details are open, controlled or uncontrolled
onOpenChange(id: string | null, span?: TraceSpan) => voidDetails opened (with the span) or closed
markSlowestbooleantrueMarks the slowest finished LLM or tool call with a small "Slowest" tag
minRangenumber10000The shortest time the axis shows, in ms – it grows in round steps as the run gets longer
formatCost(amount: number) => stringdollars, e.g. "$0.042"Formats every cost
titlestring"Trace"Heading of the bar; next to it the root's input (or name)
classNamestringExtra class on the root

Keyboard

  • Tab: Moves into the waterfall (one row is in the tab order) and on to the details window
  • ArrowUp / ArrowDown: Moves between the rows; Home and End jump to the first and the last
  • ArrowRight: Opens a folded span, or moves to its first child
  • ArrowLeft: Folds an open span, or moves to its parent
  • Enter / Space: Opens or closes the details of the focused span
  • Esc: Closes the details

Accessibility

  • The rows are a tree: every span is a treeitem with its level, labelled with name, kind, status, duration and cost; aria-expanded on spans with children
  • Roving focus – only one row is in the tab order, so the waterfall is a single stop
  • The details window is a dialog labelled with the span's name, with a close button; Esc closes it and returns focus to the row
  • The run's state in the bar (Live, Done, Failed) is announced politely when it changes
  • Ticks, grid lines and the "now" line are decoration and hidden from assistive tech

Responsive

  • Built on a container query: wide, the span tree sits on the left and the timeline on the right
  • Under 560px each row stacks – name, duration and cost on one line, the bar across the whole width under it; the numbers wrap to three columns
  • Under 360px the muted detail after each name drops out, so names keep their room
  • Dark mode built in: switches when an ancestor (usually <html>) has the class dark or data-theme="dark"

Requirements

  • React 19

Related

  • Agent Tree – Who started whom – an orchestrator and its sub-agents as a live tree, with status, cost and time on every card, costs rolling up each branch, and branches that fold to one line
  • Agent Lanes – Where every agent is right now – a live timeline with a lane per agent, tasks growing into “now”, hand-offs drawn between agents and approvals right on the block
  • Agent Plan – An agent's step-by-step plan to review before it runs – rename, drag to reorder, remove or add steps, then watch each one run with live timers and retry from a failed step
  • Agent Steering – Steer an agent while it works – queue a note for the next step and watch it glide into the plan when the agent picks it up, or interrupt right away

Guides