AG-UI React Live collapsible hierarchical tree for agent plans. Streams in node-by-node, animates state transitions, supports keyboard nav. When your agent says "I'm going to do X → Y → Z, and Y has 3 substeps" — this is how you render it.
// Controlled mode — pass plan tree directly import { PlanVisualizer } from './PlanVisualizer.jsx'; const plan = { id: 'root', label: 'Research competitor pricing', status: 'in_progress', children: [ { id: 'crawl', label: 'Crawl competitor pages', status: 'completed', result: 'Found 14 pricing pages' }, { id: 'extract', label: 'Extract pricing data', status: 'in_progress', children: [ { id: 'e1', label: 'Parse pricing tables', status: 'completed' }, { id: 'e2', label: 'Normalize currency', status: 'in_progress' }, { id: 'e3', label: 'Detect plan tiers', status: 'proposed' }, ] }, { id: 'report', label: 'Generate report', status: 'proposed' }, ] }; return <PlanVisualizer plan={plan} theme="light" defaultExpanded={true} density="compact" onNodeClick={(node) => console.log(node.id)} />; // AG-UI stream mode — auto-wired to event bus import { PlanVisualizerContainer } from './PlanVisualizer.jsx'; const bus = new EventTarget(); // Agent dispatches plan proposal bus.dispatchEvent(new CustomEvent('PLAN_PROPOSED', { detail: { plan: { id: 'root', label: 'Main task', status: 'proposed', children: [] } } })); // Node streams in under parent bus.dispatchEvent(new CustomEvent('PLAN_NODE_ADDED', { detail: { parentId: 'root', node: { id: 'step-1', label: 'Fetch', status: 'proposed' } } })); // Node starts executing bus.dispatchEvent(new CustomEvent('PLAN_NODE_UPDATED', { detail: { nodeId: 'step-1', patch: { status: 'in_progress', description: 'Fetching from API…' } } })); // Node completes with result bus.dispatchEvent(new CustomEvent('PLAN_NODE_COMPLETED', { detail: { nodeId: 'step-1' } })); bus.dispatchEvent(new CustomEvent('PLAN_NODE_FAILED', { detail: { nodeId: 'step-2' } })); return <PlanVisualizerContainer eventSource={bus} theme="light" defaultExpanded={true} density="compact" />; // PlanNode status values: // 'proposed' → dashed circle + "proposed" badge (awaiting execution) // 'in_progress' → animated dot + "running" badge + soft glow // 'completed' → green check + "done" badge // 'failed' → red × + "failed" badge // 'cancelled' → slash circle + strikethrough label // Keyboard nav: Arrow keys to traverse, Enter/Space to expand/collapse