TraceViewer

AG-UI React Hierarchical execution traces — LLM calls, tool calls, state transitions, errors. Tree view with expand/collapse, waterfall timeline, inline payload viewer, and live event streaming.

idle
AG-UI events: Streams RUN_STARTED → SPAN_STARTED/TOOL_CALL_START → SPAN_ENDED/TOOL_CALL_END → RUN_FINISHED. Toggle "Inject error" to trigger an ERROR event mid-stream.
① Live streaming trace (via TraceViewerContainer)
② Multi-agent trace with nested tool calls (tree view)
③ Same trace — waterfall view
④ Empty state + error trace
Empty (no spans)
Error trace (3 spans + error)

Copy-paste snippet

// Controlled mode — pass spans array directly
import { TraceViewer } from './TraceViewer.jsx';

const spans = [
  { id: 's1', name: 'plan', type: 'llm',  status: 'done',   startTime: 0,        endTime: 1200, duration: 1200 },
  { id: 's2', parentId: 's1', name: 'search', type: 'tool',  status: 'done',   startTime: 1200, endTime: 2300, duration: 1100,
    payload: { args: { query: 'sales data' }, result: { count: 42 } } },
  { id: 's3', name: 'Rate limit exceeded', type: 'error', status: 'error',  startTime: 2300, error: '429 Too Many Requests' },
];

return <TraceViewer
  spans={spans}
  mode="tree"           // or "waterfall"
  theme="light"          // "dark" | "auto"
  filterType="all"        // "llm" | "tool" | "state" | "error"
  filterStatus="all"      // "done" | "error" | "running"
  search=""
  startTime={0}             // ms epoch, for waterfall offset
/>;

// AG-UI stream mode — auto-wired to event bus
import { TraceViewerContainer } from './TraceViewer.jsx';

const bus = new EventTarget();

// Your agent runtime dispatches these events:
bus.dispatchEvent(new CustomEvent('RUN_STARTED',       { detail: { traceId: 'run-001' } }));
bus.dispatchEvent(new CustomEvent('SPAN_STARTED',      { detail: { spanId: 'plan', name: 'Plan LLM', type: 'llm', startTime: Date.now() } }));
bus.dispatchEvent(new CustomEvent('TOOL_CALL_START',  { detail: { spanId: 'search', parentSpanId: 'plan', tool: 'web_search', args: { q: 'Q1 revenue' }, startTime: Date.now() } }));
bus.dispatchEvent(new CustomEvent('TOOL_CALL_END',    { detail: { spanId: 'search', result: { items: 12 }, duration: 800 } }));
bus.dispatchEvent(new CustomEvent('SPAN_ENDED',        { detail: { spanId: 'plan', status: 'done', duration: 2400 } }));
bus.dispatchEvent(new CustomEvent('RUN_FINISHED',      { detail: { outcome: 'success' } }));

// Span types: llm | tool | state | error
// Status: running | done | error