feat(samples): add enterprise_dashboard with compact layout patterns#1467
feat(samples): add enterprise_dashboard with compact layout patterns#1467jswortz wants to merge 1 commit into
Conversation
…tterns Demonstrates visual-first A2UI output patterns for data-dense enterprise use cases: KPI card grids, store comparison layouts, product ranking lists, and tabbed dashboards. Addresses the common "wall of text" problem where agents fall back to markdown instead of structured A2UI components.
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
There was a problem hiding this comment.
Code Review
This pull request introduces an Enterprise Dashboard sample for the A2UI agent framework, featuring an agent that prioritizes visual component layouts over standard markdown. The implementation includes mock analytics tools, example JSON payloads, and a specialized prompt builder. Review feedback focuses on improving the prompt builder's path handling for better portability, reducing redundancy in system instructions, and ensuring data consistency in mock tool responses. There is also a suggestion to better align example JSON files with the prompt's best practices regarding icon usage.
| version=VERSION_0_8, | ||
| catalogs=[BasicCatalog.get_config( | ||
| version=VERSION_0_8, | ||
| examples_path="examples/0.8", |
There was a problem hiding this comment.
The hardcoded relative path examples/0.8 for examples_path is brittle as it depends on the current working directory. This can cause issues when running the script from different locations, including the if __name__ == '__main__' block. It's more robust to construct an absolute path based on the current file's location.
You'll also need to add import os at the top of the file.
| examples_path="examples/0.8", | |
| examples_path=os.path.join(os.path.dirname(os.path.abspath(__file__)), "examples/0.8"), |
| ) | ||
|
|
||
| UI_DESCRIPTION = """ | ||
| You are a VISUAL DASHBOARD, not a text chatbot. |
There was a problem hiding this comment.
| - KPI metrics: Row of Card components, each Card wrapping a Text child | ||
| with bold metric name, large value, and trend indicator. | ||
| - Store/product comparisons: Row of Card components side-by-side. | ||
| NEVER use markdown tables. |
There was a problem hiding this comment.
| { | ||
| "name": "Downtown Market", | ||
| "revenue": "$112,400", | ||
| "transactions": 5100, |
There was a problem hiding this comment.
The transactions field is an integer, while other numeric-like fields such as revenue and avg_basket are pre-formatted strings. For consistency within this tool's return value and to make the data structure more predictable for the LLM, consider formatting transactions as a string as well. This applies to all stores in the list.
| "transactions": 5100, | |
| "transactions": "5,100", |
| "rank": 1, | ||
| "name": "Organic Apples", | ||
| "category": "Produce", | ||
| "units_sold": 1240, |
There was a problem hiding this comment.
Similar to get_store_comparison, the units_sold field is an integer while revenue is a pre-formatted string. To improve consistency across the tools in this file, consider formatting units_sold as a string with comma separators. This should be applied to all products in the list.
| "units_sold": 1240, | |
| "units_sold": "1,240", |
| "id": "aov-text", | ||
| "component": { | ||
| "Text": { | ||
| "text": { | ||
| "literalString": "**Avg Order**\n\n**$22.85**\n\n-1.2% vs last week" | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
The prompt in prompt_builder.py encourages using Icon components for status indicators. This metric has a downward trend (-1.2%), which is a perfect opportunity to demonstrate the use of a trending_down icon, as suggested in the prompt's Status indicators recipe. The current implementation only uses text. Using an icon here would make the example more consistent with the prompt's best practices and the store_comparison.json example.
Summary
enterprise_dashboardsample agent demonstrating compact, visual-first A2UI output patternsMotivation
Every existing sample (
restaurant_finder,rizzcharts,personalized_learning) focuses on agent framework integration but doesn't demonstrate how to prevent the LLM from falling back to markdown "walls of text" when presenting data.Enterprise use cases — dashboards, KPIs, store comparisons, product rankings — are especially prone to this: the LLM defaults to markdown tables, bullet lists, and inline numbers instead of structured A2UI layouts. There's no reference sample showing the right patterns.
What this sample teaches
Layout recipes (data type → A2UI component)
RowofCardwith boldTextRowofCardside-by-sideListwithCardchildren##headersTabscomponent---horizontal ruleDividercomponentIcon(trending_up, trending_down)Prompt engineering patterns
Files
agent.pyLlmAgentrunnable withadk webprompt_builder.pytools.pyexamples/0.8/kpi_dashboard.jsonexamples/0.8/store_comparison.jsonREADME.mdRunning
cd samples/agent/adk adk web enterprise_dashboardExample queries:
Production validation
These patterns have been battle-tested across 3 production agents deployed on Vertex AI Agent Engine (Gemini 3.5 Flash). Before adding anti-markdown rules and layout recipes, ~30-40% of responses fell back to markdown. After, the rate dropped to <5%.
Related
strict_outputmode forgenerate_system_prompt()(SDK-level enforcement)A2UIOutputModeenum for unified TEXT/TOOL prompt generation