-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Ge a2ui v09 examples #2086
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Ge a2ui v09 examples #2086
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
7 changes: 7 additions & 0 deletions
7
samples/community/agent/adk/gemini_enterprise/v0_9/.env.example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # Copy this file to .env and fill in your API key | ||
| # Get your API key at: https://aistudio.google.com/apikey | ||
|
|
||
| GEMINI_API_KEY=your_gemini_api_key_here | ||
|
|
||
| # Optional: Use Vertex AI instead of Gemini API | ||
| # GOOGLE_GENAI_USE_VERTEXAI=TRUE |
15 changes: 15 additions & 0 deletions
15
samples/community/agent/adk/gemini_enterprise/v0_9/.gcloudignore
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # Ignore common Python build artifacts | ||
| __pycache__/ | ||
| *.pyc | ||
| *.pyo | ||
| build/ | ||
| dist/ | ||
| *.egg-info/ | ||
| .venv/ | ||
| venv/ | ||
|
|
||
| .adk/ | ||
|
|
||
| # Do not upload local environment / secrets | ||
| .env | ||
| .env.example |
20 changes: 20 additions & 0 deletions
20
samples/community/agent/adk/gemini_enterprise/v0_9/.gitignore
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| # Local environment / secrets — never commit | ||
| .env | ||
|
|
||
| # Python build artifacts | ||
| __pycache__/ | ||
| *.pyc | ||
| *.pyo | ||
| build/ | ||
| dist/ | ||
| *.egg-info/ | ||
|
|
||
| # Virtual environments | ||
| .venv/ | ||
| venv/ | ||
|
|
||
| # ADK local state | ||
| .adk/ | ||
|
|
||
| # Generated prompt dump (from `python prompt_builder.py`) | ||
| generated_prompt.txt |
121 changes: 121 additions & 0 deletions
121
samples/community/agent/adk/gemini_enterprise/v0_9/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| # A2UI v0.9 Demo agent sample | ||
|
|
||
| This sample uses the Agent Development Kit (ADK) and A2UI SDK to | ||
| create an "A2UI v0.9 Demo" agent that can be deployed to GCP Cloud Run. The agent | ||
| showcases what can be built with Gemini Enterprise A2UI v0.9, rendering rich, | ||
| interactive UIs from the Material component catalog and the Gemini Enterprise | ||
| custom components (`Canvas`, `IFrameSrcdoc`, `IFrameUrl`). | ||
|
|
||
| Ask the agent **"what can you do?"** and it renders an A2UI `Canvas` listing the available demos. It can demo: | ||
|
|
||
| - **Material components**: cards, text, buttons, icons, images, badges. | ||
| - **Forms & inputs**: `MaterialInput`, `MaterialSelect`, `MaterialCheckbox`, | ||
| `MaterialRadioButton`, `MaterialSlideToggle`, `MaterialSlider`, | ||
| `MaterialChips`, `MaterialButtonToggle`, `MaterialDatepicker`, | ||
| `MaterialTimepicker`. | ||
| - **Tabs & layout**: `MaterialTabs`, `MaterialExpansionPanel`, | ||
| `MaterialGridList`, `MaterialRow`, `MaterialColumn`. | ||
| - **Data display**: `MaterialTable`, `MaterialProgressBar`, | ||
| `MaterialProgressSpinner`. | ||
| - **Dialogs & menus**: `MaterialDialog`, `MaterialMenu`. | ||
| - **Canvas**: render content in a resizable side panel (`Canvas` root). | ||
| - **Iframe**: `IFrameSrcdoc` (sandboxed agent-supplied HTML) and `IFrameUrl` | ||
| (allowlisted embedded URL). | ||
| - **Restaurant finder**: find restaurants and book a table. | ||
|
|
||
| This started as a port of the upstream | ||
| [A2UI restaurant_finder sample](https://github.com/a2ui-project/a2ui/tree/main/samples/agent/adk/restaurant_finder) | ||
| with these notable differences: | ||
|
|
||
| 1. **A2UI v0.9 only.** Support for A2UI v0.8 has been removed. The agent only | ||
| advertises and serves the A2UI v0.9 extension. | ||
| 2. **Gemini Enterprise composite catalog.** Instead of the bundled | ||
| `BasicCatalog`, the agent uses the A2UI v0.9 Gemini Enterprise composite | ||
| catalog (`gemini_enterprise_composite_catalog.json`), which unions the | ||
| standard Material catalog, the basic catalog, and the Gemini Enterprise | ||
| custom components (`Canvas`, `IFrameSrcdoc`, `IFrameUrl`). Example UI | ||
| templates under `examples/0.9/` use `Material*`, `Canvas`, and `IFrame*` | ||
| components. | ||
| 3. **Generic demo.** The agent is no longer restaurant-specific; it generates | ||
| whichever UI best demonstrates the components requested. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - Python 3.14 or higher | ||
| - [uv](https://docs.astral.sh/uv/) | ||
| - Access to an LLM and API key | ||
|
|
||
| ## Running the Sample | ||
|
|
||
| 1. Create an environment file with your API key: | ||
|
|
||
| `cp .env.example .env` | ||
|
|
||
| Edit `.env` with your actual API key (do not commit .env) | ||
|
|
||
| 2. Run the agent server: | ||
|
|
||
| `uv run .` | ||
|
|
||
| 3. In another terminal window: | ||
|
|
||
| - verify that the agent is available via A2A: | ||
|
|
||
| ``` | ||
| curl http://localhost:10002/.well-known/agent-card.json | ||
| ``` | ||
|
|
||
| - send a message to the agent: | ||
|
|
||
| ``` | ||
| curl http://localhost:10002 \ | ||
| -H 'Content-Type: application/json' \ | ||
| -d '{ | ||
| "jsonrpc": "2.0", | ||
| "id": 1, | ||
| "method": "message/send", | ||
| "params": { | ||
| "message": { | ||
| "role": "user", | ||
| "parts": [{"text": "What can you do?"}], | ||
| "messageId": "1" | ||
| } | ||
| } | ||
| }' | ||
| ``` | ||
|
|
||
| ## Deploying to Cloud Run | ||
|
|
||
| `deploy.sh` deploys the agent to Cloud Run from source: | ||
|
|
||
| ``` | ||
| ./deploy.sh <PROJECT_ID> <SERVICE_NAME> [MODEL_NAME] | ||
| ``` | ||
|
|
||
| ## Updating the component catalog | ||
|
|
||
| `gemini_enterprise_composite_catalog.json` is a copy of the public A2UI v0.9 | ||
| Gemini Enterprise composite catalog: | ||
|
|
||
| ``` | ||
| https://www.gstatic.com/vertexaisearch/a2ui/v0_9/gemini_enterprise_composite_catalog.json | ||
| ``` | ||
|
|
||
| If the catalog adds or removes components, also update the example templates in | ||
| `examples/0.9/` so they continue to validate (the agent loads examples with | ||
| `validate_examples=True`). | ||
|
|
||
| ## Disclaimer | ||
|
|
||
| Important: The sample code provided is for demonstration purposes and | ||
| illustrates the mechanics of A2UI and the Agent-to-Agent (A2A) protocol. When | ||
| building production applications, it is critical to treat any agent operating | ||
| outside of your direct control as a potentially untrusted entity. | ||
|
|
||
| All operational data received from an external agent—including its AgentCard, | ||
| messages, artifacts, and task statuses—should be handled as untrusted input. Any | ||
| UI definition or data stream received must be treated as untrusted. Developers | ||
| are responsible for implementing appropriate security measures—such as input | ||
| sanitization, Content Security Policies (CSP), strict isolation for optional | ||
| embedded content, and secure credential handling—to protect their systems and | ||
| users. | ||
15 changes: 15 additions & 0 deletions
15
samples/community/agent/adk/gemini_enterprise/v0_9/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # Copyright 2025 Google LLC | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # https://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| from . import agent |
98 changes: 98 additions & 0 deletions
98
samples/community/agent/adk/gemini_enterprise/v0_9/__main__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| # Copyright 2025 Google LLC | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # https://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| import logging | ||
| import os | ||
|
|
||
| from a2a.server.apps import A2AStarletteApplication | ||
| from a2a.server.request_handlers import DefaultRequestHandler | ||
| from a2a.server.tasks import InMemoryTaskStore | ||
| from agent import A2uiDemoAgent | ||
| from agent_executor import A2uiDemoAgentExecutor | ||
| import click | ||
| from dotenv import load_dotenv | ||
| from starlette.middleware.cors import CORSMiddleware | ||
| from starlette.staticfiles import StaticFiles | ||
|
|
||
| load_dotenv() | ||
|
|
||
| logging.basicConfig(level=logging.INFO) | ||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| class MissingAPIKeyError(Exception): | ||
| """Exception for missing API key.""" | ||
|
|
||
|
|
||
| @click.command() | ||
| @click.option("--host", default="localhost") | ||
| @click.option("--port", default=10002) | ||
| def main(host, port): | ||
| try: | ||
| # Check for API key only if Vertex AI is not configured | ||
| if not os.getenv("GOOGLE_GENAI_USE_VERTEXAI") == "TRUE": | ||
| if not os.getenv("GEMINI_API_KEY"): | ||
| raise MissingAPIKeyError( | ||
| "GEMINI_API_KEY environment variable not set and" | ||
| " GOOGLE_GENAI_USE_VERTEXAI is not TRUE." | ||
| ) | ||
|
|
||
| base_url = f"http://{host}:{port}" | ||
|
|
||
| agent = A2uiDemoAgent(base_url=base_url) | ||
|
|
||
| agent_executor = A2uiDemoAgentExecutor(agent) | ||
|
|
||
| request_handler = DefaultRequestHandler( | ||
| agent_executor=agent_executor, | ||
| task_store=InMemoryTaskStore(), | ||
| ) | ||
| server = A2AStarletteApplication( | ||
| agent_card=agent.agent_card, http_handler=request_handler | ||
| ) | ||
| import uvicorn | ||
|
|
||
| app = server.build() | ||
|
|
||
| app.add_middleware( | ||
| CORSMiddleware, | ||
| allow_origin_regex=r"http://localhost:\d+", | ||
| allow_credentials=True, | ||
| allow_methods=["*"], | ||
| allow_headers=["*"], | ||
| ) | ||
|
|
||
| # Serve restaurant images from the local `images/` directory if | ||
| # present. The directory only contains binary image assets and may be | ||
| # omitted; the server still starts (image URLs will simply 404). | ||
| images_dir = os.path.join(os.path.dirname(__file__), "images") | ||
| if os.path.isdir(images_dir): | ||
| app.mount("/static", StaticFiles(directory=images_dir), name="static") | ||
| else: | ||
| logger.warning( | ||
| "No 'images' directory found at %s; /static will not be served.", | ||
| images_dir, | ||
| ) | ||
|
|
||
| uvicorn.run(app, host=host, port=port) | ||
| except MissingAPIKeyError as e: | ||
| logger.error(f"Error: {e}") | ||
| exit(1) | ||
| except Exception as e: | ||
| logger.error(f"An error occurred during server startup: {e}") | ||
| exit(1) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.