- Demo is deployed and accessible at
/demos/declarative-gen-uion the dashboard host - Agent backend is healthy (
/api/copilotkit/healthor the host's/api/health);OPENAI_API_KEYis set on Railway;LANGGRAPH_DEPLOYMENT_URLpoints at a LangGraph deployment exposing thea2ui_dynamicgraph (registered as agent namedeclarative-gen-ui— seesrc/app/api/copilotkit-declarative-gen-ui/route.ts) - Note: the demo source contains no
data-testidattributes. Checks below rely on verbatim visible text, DOM structure, and inline-style fingerprints declared insrc/app/demos/declarative-gen-ui/a2ui/renderers.tsx
- Navigate to
/demos/declarative-gen-ui; verify the page renders within 3s and a singleCopilotChatpane is centered (max-width ~896px, rounded-2xl, full-height) - Verify the chat is wired to
runtimeUrl="/api/copilotkit-declarative-gen-ui"andagent="declarative-gen-ui"(DevTools → Network: sending a message hits that endpoint, not/api/copilotkit) - Verify all 4 suggestion pills are visible with verbatim titles:
- "Show a KPI dashboard"
- "Pie chart — sales by region"
- "Bar chart — quarterly revenue"
- "Status report"
- Send "Hello" and verify an assistant text response appears within 10s (no A2UI surface rendered for plain text)
- DevTools → Network: on first tool-driven response, verify the response stream contains an
a2ui_operationscontainer withcatalogId: "declarative-gen-ui-catalog"(matchesCUSTOM_CATALOG_IDinsrc/agents/a2ui_dynamic.pyandcreateCatalog(..., { catalogId: "declarative-gen-ui-catalog" })ina2ui/catalog.ts)
- Click "Show a KPI dashboard"; within 30s verify an A2UI surface renders in-transcript containing at least 3
Metrictiles (each: uppercase label withletterSpacing: 0.12em, large value in 1.5rem/600 weight, optional↑/↓trend arrow — green#189370for up, red#FA5F67for down) - Verify the chat reply text beneath the surface is one short sentence (per
SYSTEM_PROMPT: "Keep chat replies to one short sentence; let the UI do the talking.")
- Click "Pie chart — sales by region"; within 30s verify a pie-chart card renders with:
- a non-empty title (1rem / 600 weight, color
#010507) and description (0.85rem, color#57575B) - a custom SVG donut (inside the card,
<svg>withtransform: scaleX(-1)) containing a grey background<circle>plus one stroked<circle>per slice (at least 2 slices) - a legend with one row per slice: coloured dot, label, comma-formatted value, percentage ending in
%; percentages sum to 100% (rounding-tolerant)
- a non-empty title (1rem / 600 weight, color
- Verify the first slice uses brand color
#BEC2FFand subsequent slices cycle through theCHART_COLORSpalette (#85ECCE,#FFAC4D,#FFF388, …)
- Click "Bar chart — quarterly revenue"; within 30s verify a bar-chart card renders with a title + description and a recharts
ResponsiveContainerat height 280 - Verify at least 2
<rect>bar elements render, X-axis tick labels match the backendlabelvalues, Y-axis ticks are numeric, and the scoped@keyframes barSlideInanimation fires on first paint (bars translate up fromtranslateY(40px)to0) - Verify bar fills cycle through
CHART_COLORSand bars have rounded top corners (radius: [6, 6, 0, 0])
- Click "Status report"; within 30s verify the surface contains at least one
Card(white background, 1px#DBDBE5border, 16px border-radius, 20px padding) with a bold title - Verify at least one
StatusBadgepill renders — uppercase 0.1em-tracked text, rounded-pill (borderRadius: 999), one of the 4 variants (successgreen,warningorange,errorred#FA5F67,infolilac#BEC2FF) - Verify at least one
InfoRowrenders inside a Card: label (0.85rem, color#57575B) on the left, value (0.9rem, 500 weight, color#010507) on the right, separated by a 1px bottom border#E9E9EF - If the agent emits a
PrimaryButton, verify it renders as a black (#010507) pill-rounded button with white text; hovering changes background to#2B2B2B
- Over the 4 suggestion runs above, confirm each catalog component has rendered at least once across the session:
Card,StatusBadge,Metric,InfoRow,PrimaryButton,PieChart,BarChart. If any did not, send a follow-up prompt targeting the missing one (e.g. "give me a one-button call-to-action card" to forcePrimaryButton)
- Send an empty message; verify it is a no-op (no user bubble, no assistant response)
- Send "What is 2+2?"; verify the agent replies in plain text without invoking
generate_a2ui(noa2ui_operationsin the response stream, no surface rendered) - DevTools → Console: walk through all flows above; verify no uncaught errors and no React error #31 ("objects are not valid as a React child"), which would indicate a broken
path-binding on a catalog renderer
- Chat loads within 3s; plain-text response within 10s; A2UI surfaces render within 30s of prompt
render_a2uiis called exactly once per surface-producing prompt; result contains a valida2ui_operationscontainer withcatalogId: "declarative-gen-ui-catalog"- All 7 custom catalog components (Card, StatusBadge, Metric, InfoRow, PrimaryButton, PieChart, BarChart) have been exercised across the suggestion sample
- Rendered UI matches the
myDefinitionsshape (Zod prop names froma2ui/definitions.tsline up with values visible in the DOM) - No UI layout breaks, no flash of unstyled content, no uncaught console errors