Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This sample uses the Agent Development Kit (ADK) along with the A2A protocol to
1. Navigate to the samples directory:

```bash
cd samples/agent/adk/contact_multiple_surfaces
cd samples/agent/adk/custom-components-example
```

2. Create an environment file with your API key:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Unlike standard A2UI agents that rely solely on the core component library, this

1. **Client Defines Components**: The web client (`contact` sample) defines custom components (`OrgChart`, `WebFrame`) and their schemas.
2. **Inline Catalog Negotiation**: When the client connects to the agent, it sends these schemas in its connection handshake (Client Event) under `metadata.inlineCatalog`.
3. **Agent Adaptation**: The agent (`contact_multiple_surfaces`) dynamically reads this catalog and injects the schema into the LLM's system prompt (via `[SYSTEM]` messages).
3. **Agent Adaptation**: The agent (`custom-components-example`) dynamically reads this catalog and injects the schema into the LLM's system prompt (via `[SYSTEM]` messages).
4. **Rich Rendering**: The LLM can then instruct the client to render these custom components.

## Key Features
Expand Down Expand Up @@ -36,7 +36,7 @@ A powerful component that allows embedding external web content or local static

1. **Start the Agent**:
```bash
cd samples/agent/adk/contact_multiple_surfaces
cd samples/agent/adk/custom-components-example
uv run .
```
*Runs on port 10004.*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def get_text_prompt() -> str:
my_version,
catalogs=[
CatalogConfig.from_path(
name="contact_multiple_surfaces_inline_catalog",
name="custom-components-example_inline_catalog",
catalog_path=inline_catalog_path,
examples_path=f"examples/{my_version}",
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.

[project]
name = "a2ui-contact-multiple-surfaces"
name = "a2ui-custom-components-example"
version = "0.1.0"
description = "Sample Google ADK-based Contact Lookup agent that uses a2ui extension and is hosted as an A2A server agent."
readme = "README.md"
Expand Down
2 changes: 1 addition & 1 deletion samples/agent/adk/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ url = "https://pypi.org/simple"
default = true

[tool.uv.workspace]
members = ["contact_lookup", "contact_multiple_surfaces", "orchestrator", "restaurant_finder", "rizzcharts", "mcp_app_proxy"]
members = ["contact_lookup", "custom-components-example", "orchestrator", "restaurant_finder", "rizzcharts", "mcp_app_proxy"]

[tool.uv.sources]
a2ui-agent = { path = "../../../agent_sdks/python", editable = true }
Expand Down
6 changes: 3 additions & 3 deletions samples/agent/adk/tests/test_examples_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@
"validate": False, # Use invalid examples to test retry logic
},
{
"name": "contact_multiple_surfaces",
"path": SAMPLES_DIR / "contact_multiple_surfaces",
"name": "custom-components-example",
"path": SAMPLES_DIR / "custom-components-example",
"catalogs": [
CatalogConfig.from_path(
name="contact_multiple_surfaces_inline_catalog",
name="custom-components-example_inline_catalog",
catalog_path="inline_catalog_0.9.json",
examples_path=f"examples/{VERSION_0_9}",
),
Expand Down
6 changes: 3 additions & 3 deletions samples/agent/adk/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,23 @@ This sample depends on the Lit renderer. Before running this sample, you need to
```

3. **Run the servers:**
- Run the [A2A server](../../../agent/adk/contact_multiple_surfaces/)
- Run the [A2A server](../../../agent/adk/custom-components-example/)
- By default, the server uses the `McpAppsCustomComponent` which wraps MCP Apps in a secure, isolated double-iframe sandbox (`sandbox.html`) communicating strictly via JSON-RPC.
- Optionally run the server using `USE_MCP_SANDBOX=false uv run .` to bypass this security and use the standard `WebFrame` element.
- **Observing the difference**: Search for "Alex Jordan" in the UI and click the Location button to open the floor plan. If you inspect the DOM using your browser's Developer Tools, you will see that `McpAppsCustomComponent` securely points the iframe `src` to the local proxy (`/sandbox.html`). In contrast, `WebFrame` directly injects the untrusted HTML via a data blob/srcdoc, lacking defense-in-depth origin isolation.
- Run the dev server: `npm run dev`

After starting the dev server, you can open http://localhost:5173/ to view the sample.
After starting the dev server, you can open http://localhost:5173/ to view the sample.

## Available Custom Components

This sample showcases several custom components that go beyond standard A2UI rendering:

- **MCP Apps (`mcp-apps-component.ts`)**: Sandboxed UI widgets using the MCP protocol, communicating securely via a JSON-RPC channel.
- **Secure iFrame Web Frame (`web-frame.ts`)**: Powerful component that allows rendering raw HTML in an isolated context (used for the Office Floor Plan).
- **Org Chart (`org-chart.ts`)**: A custom tree structure visualization component.

## Mix and Match A2UI Surfaces

This sample demonstrates how standard A2UI surfaces (such as contact profile cards using standard `Card` and list items) can live on the same canvas as custom extensions.
The A2UI renderer library seamlessly manages the standard component catalog, while custom components (like the Org Chart or iframe-based floor plans) hook into the same event lifecycle. You can swap between standard profile views and rich custom widgets using a unified routing layer.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "@a2ui/contact",
"name": "@a2ui/custom-components-example",
"private": true,
"version": "0.8.1",
"description": "A2UI Contact Demo",
"description": "A2UI Custom Components Example Demo",
"main": "./dist/contact.js",
"types": "./dist/contact.d.ts",
"type": "module",
Expand Down Expand Up @@ -53,7 +53,7 @@
}
},
"repository": {
"directory": "samples/client/lit/contact",
"directory": "samples/client/lit/custom-components-example",
"type": "git",
"url": "git+https://github.com/google/A2UI.git"
},
Expand Down
2 changes: 1 addition & 1 deletion samples/client/lit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"version": "0.8.1",
"description": "A2UI Lit Samples",
"workspaces": [
"contact",
"custom-components-example",
"shell"
],
"scripts": {
Expand Down
Loading