Skip to content

Commit b31928c

Browse files
committed
Add readme.
1 parent 69002aa commit b31928c

File tree

3 files changed

+136
-0
lines changed

3 files changed

+136
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# A2UI Custom Components & Multiple Surfaces Guide
2+
3+
This guide explains how the **Contact Client** and **Contact Multiple Surfaces Agent** work in tandem to deliver rich, custom user interfaces beyond the standard A2UI library.
4+
5+
## Architecture Overview
6+
7+
Unlike standard A2UI agents that rely solely on the core component library, this sample demonstrates a **Client-First Extension Model**:
8+
9+
1. **Client Defines Components**: The web client (`contact` sample) defines custom components (`OrgChart`, `WebFrame`) and their schemas.
10+
2. **Inline Catalog Negotiation**: When the client connects to the agent, it sends these schemas in its connection handshake (Client Event) under `metadata.inlineCatalog`.
11+
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).
12+
4. **Rich Rendering**: The LLM can then instruct the client to render these custom components.
13+
14+
## Key Features
15+
16+
### 1. Multiple Surfaces
17+
The agent manages multiple distinct UI areas ("surfaces") simultaneously:
18+
- **`contact-card`**: The main profile view validation.
19+
- **`org-chart-view`**: A side-by-side organizational chart.
20+
- **`location-surface`**: A transient modal/overlay for map views.
21+
22+
### 2. Custom Components
23+
24+
#### `OrgChart`
25+
A custom LitElement component created in the client that renders a hierarchical view.
26+
- **Schema**: Defined in `samples/client/lit/contact/ui/custom-components`.
27+
- **Usage**: The agent sends a JSON structure matching the schema, and the client renders it natively.
28+
29+
#### `WebFrame` (Iframe Component)
30+
A powerful component that allows embedding external web content or local static HTML files within the A2UI interface.
31+
- **Usage in Sample**: Used to render the "Office Floor Plan".
32+
- **Security**: Uses standard iframe sequencing and sandbox attributes.
33+
- **Interactivity**: Can communicate back to the parent A2UI application (e.g., clicking a desk on the map triggers an A2UI action `chart_node_click`).
34+
35+
## How to Run in Tandem
36+
37+
1. **Start the Agent**:
38+
```bash
39+
cd samples/agent/adk/contact_multiple_surfaces
40+
uv run .
41+
```
42+
*Runs on port 10004.*
43+
44+
2. **Start the Client**:
45+
```bash
46+
cd samples/client/lit/contact
47+
npm run dev
48+
```
49+
*Configured to connect to localhost:10004.*
50+
51+
## Flow Example: "View Location"
52+
53+
1. **User Trigger**: User clicks "Location" on a profile card.
54+
2. **Action**: Client sends standard A2UI action `view_location`.
55+
3. **Agent Response**: Agent detects the intent and returns a message to render the `location-surface`.
56+
4. **Component Payload**:
57+
```json
58+
{
59+
"WebFrame": {
60+
"url": "http://localhost:10004/static/floorplan.html?data=...",
61+
"interactionMode": "interactive"
62+
}
63+
}
64+
```
65+
5. **Rendering**: Client receives the message, creates the surface, and instantiates the `WebFrame` component, loading the static HTML map served by the agent.

samples/agent/adk/contact_multiple_surfaces/agent_executor.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ async def execute(
8686
elif "request" in part.root.data:
8787
logger.info(f" Part {i}: Found 'request' in DataPart.")
8888
query = part.root.data["request"]
89+
90+
# Check for inline catalog
91+
if "metadata" in part.root.data and "inlineCatalog" in part.root.data["metadata"]:
92+
logger.info(f" Part {i}: Found 'inlineCatalog' in DataPart.")
93+
inline_catalog = part.root.data["metadata"]["inlineCatalog"]
94+
catalog_json = json.dumps(inline_catalog)
95+
# Append to query so the agent sees it (simple injection)
96+
query += f"\n\n[SYSTEM: The client supports the following custom components: {catalog_json}]"
8997
else:
9098
logger.info(f" Part {i}: DataPart (data: {part.root.data})")
9199
elif isinstance(part.root, TextPart):
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# A2UI Custom Components & Client Architecture Guide
2+
3+
This guide explains how the **Contact Client** works in tandem with the **Contact Multiple Surfaces Agent** to define and render rich, custom user interfaces.
4+
5+
## Client-First Extension Model
6+
7+
This sample demonstrates a powerful pattern where the **Client** controls the capabilities of the agent:
8+
9+
1. **Component Definition**: This client defines custom components (`OrgChart`, `WebFrame`) in `ui/custom-components/`.
10+
2. **Schema Generation**: Each custom component has an associated JSON schema.
11+
3. **Handshake**: When connecting to the agent, the client sends these schemas in the `metadata.inlineCatalog` field of the initial request.
12+
4. **Dynamic Support**: This allows *any* A2UI agent (that supports inline catalogs) to immediately start using these components without prior knowledge.
13+
14+
## Custom Components Implemented
15+
16+
### 1. `OrgChart`
17+
*Located in: `ui/custom-components/org-chart.ts`*
18+
A visual tree illustrating the organizational hierarchy.
19+
- **Implementation**: A standard LitElement component.
20+
- **Interaction**: Emits `chart_node_click` events when nodes are clicked, which are sent back to the agent as A2UI Actions.
21+
22+
### 2. `WebFrame` (Interactive Iframe)
23+
*Located in: `ui/custom-components/web-frame.ts`*
24+
A tailored iframe wrapper for embedding external content or static HTML tools.
25+
- **Use Case**: Used here to render the "Office Floor Plan" map.
26+
- **Security**: Uses `sandbox` attributes to restrict script execution while allowing necessary interactions.
27+
- **Bridge**: Includes a `postMessage` bridge to allow the embedded content (the map) to trigger A2UI actions in the main application.
28+
29+
## Multiple Surfaces
30+
31+
The client is designed to render multiple A2UI "Surfaces" simultaneously. Instead of a single chat stream, the `contact.ts` shell manages:
32+
33+
- **Main Profile (`contact-card`)**: The primary view.
34+
- **Side Panel (`org-chart-view`)**: A persistent side view for context.
35+
- **Overlay (`location-surface`)**: A temporary surface for specific tasks like map viewing.
36+
37+
## How to Run in Tandem
38+
39+
To see this full experience, you must run this client with the specific `contact_multiple_surfaces` agent.
40+
41+
### 1. Start the Agent
42+
The agent serves the backend logic and the static assets (like the floor plan HTML).
43+
```bash
44+
cd ../../../agent/adk/contact_multiple_surfaces
45+
uv run .
46+
```
47+
*Runs on port 10004.*
48+
49+
### 2. Start this Client
50+
The client connects to the agent and renders the UI.
51+
```bash
52+
# In this directory (samples/client/lit/contact)
53+
npm install
54+
npm run dev
55+
```
56+
*The client acts as a shell, connecting to localhost:10004 by default.*
57+
58+
## Configuration
59+
60+
The connection to the agent is configured in `middleware/a2a.ts`. If you need to change the agent port, update the URL in that file:
61+
```typescript
62+
const agentUrl = "http://localhost:10004";
63+
```

0 commit comments

Comments
 (0)