Agent Graph Viz
A teaching component for the production multi-agent pattern that won: a single
supervisor agent routes a compound user query to specialist agents, passes a
trimmed context across each handoff boundary, and aggregates the results into
a single response. The visitor steps through the happy path — observe → routing → parallel → aggregating → complete — watches the per-hop token
budget drop on the right-hand ladder, then flips on Show failures to probe
three production failure modes (routing error, conflicting actions, context
loss). An insight callout fires once the visitor has seen both paths.
A user sends a compound request. The supervisor must figure out which specialists to involve and in what order.
Installation
npx shadcn@latest add https://craftbits.dev/r/agent-graph-viz.jsonUsage
import { AgentGraphViz } from "@craft-bits/viz/agent-graph-viz";
<AgentGraphViz />Re-target at a different compound query:
<AgentGraphViz userQuery="Cancel my subscription and export my data" />Tighten the per-hop context loss to model a structured-handoff system:
<AgentGraphViz handoffLoss={0.1} />Drive the step index from outside (controlled mode):
const [step, setStep] = useState(0);
<AgentGraphViz stepIndex={step} onStepChange={setStep} />Understanding the component
- Hub-and-spoke SVG graph. A
Supervisorsits in the centre withRefund,Account, andEscalationspecialists around it and aUsernode above. Edge geometry shortens each line so it never passes under a node circle, and arrowheads orient from the inferred angle between endpoints. - Step-driven phase machine.
stepIndexindexes into the five-entrySTEPSarray (observe → routing → parallel → aggregating → complete). The currentphasedecides which edges and nodes are active, which message bubbles render, and which colour the narration paragraph tints to. - Per-hop token ladder. The right-hand panel renders four bars (
Hop 0 → Hop 3) representing the compounding token loss across handoff boundaries. Each bar reveals on its corresponding phase, with a-N% losttag underneath every non-initial hop. - Edge-aligned token badges. While an edge is active, a small rounded rect renders at its midpoint with the remaining token count. The badge fades out when the phase advances.
- Failure-mode toggle. Tapping
Show failuresswitchesphaseto a dedicatedfailurestate, recolouring the affected edge, dropping a!glyph at its midpoint, and replacing the narration with the active failure's prose. - Insight callout. Once the visitor has both completed the happy path and seen at least one failure mode, an
AnimatePresence-mounted callout reveals the punchline (hub-and-spoke = bounded depth, but even two hops compound to ~51% loss at the defaulthandoffLoss = 0.3). - Keyboard. The root is focusable (
tabIndex={0}).ArrowRight/ Space advance,ArrowLeftretreats; the buttons mirror the same actions for pointer users. A sr-only live region narrates the active phase without spamming on every render. - Reduced motion. Under
prefers-reduced-motion: reduce, every spring collapses to instant, the per-edge dot animation disables, and the sonar pulse on active nodes does not mount.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
userQuery | string | "I need a refund AND my account is locked" | Banner query and User node's outgoing message. |
initialTokens | number | 1000 | Token budget on the original query. |
handoffLoss | number | 0.3 | Fractional context lost at each handoff boundary, in [0, 1]. |
stepIndex | number | — | Controlled step index into the happy-path STEPS array. Pair with onStepChange. |
defaultStepIndex | number | 0 | Uncontrolled initial step index. |
onStepChange | (next: number) => void | — | Fires on every step advance, retreat, or jump. |
transition | Transition | SPRINGS.snap | Override the spring used for node / edge state transitions. |
className | string | — | Merged onto the root via cn(). |
Accessibility
- The SVG is
role="img"with anaria-labelsummarising the layout; agent labels and message bubbles arearia-hiddenso the live region drives the story for screen readers. - The container is focusable with a visible
:focus-visiblering and supportsArrowLeft/ArrowRight/ Space for step navigation. - A polite live region announces the active step (
Step N of M: <label>. <narration>) or the active failure mode whenever either changes. - Colour is never the only signal — failure edges add a dashed stroke and a
!glyph, the misrouted specialist gets a dashed outline, and the token ladder labels the percentage as text. - All buttons (step pips, prev/next, reset, failure toggle, failure cards) have visible labels, hit ≥ 32px height, are reachable in tab order, and show a focus ring.
- Motion respects
prefers-reduced-motion: reduce— every spring collapses to instant attribute sets, the travelling dot disables, and the active-node sonar pulse does not mount.
Credits
- Extracted from:
craftingattention(app/src/lessons/primitives/systems/AgentGraphViz.tsx). The source was a lesson component tightly bound to per-track CSS palette tokens (--color-ink-*,--color-accent-400,--color-success-400) and inline per-agent OKLCH hexes, embedded inlineSPRINGS.snappy/SPRINGS.bouncy/SPRINGS.gentle/STAGGER.tightfrom CA'slib/motion, and ended on a lesson-styledca-narrationparagraph. The viz extract remaps every palette tovar(--cb-*)semantic tokens, re-keys motion to the canonicalSPRINGS.snap/SPRINGS.bouncy/SPRINGS.smoothand scalarSTAGGERfrom@craft-bits/core/motion, surfaces the step index as a controlled-or-uncontrolled Radix-style prop (stepIndex/defaultStepIndex/onStepChange), parameterisesuserQuery,initialTokens, andhandoffLoss, and replaces the lesson narration chrome with a token-styled paragraph.