Skip to content

feat: add specification for A2UI web app iframe component (v0.9) - #2123

Merged
sugoi-yuzuru merged 14 commits into
mainfrom
webframe
Jul 30, 2026
Merged

feat: add specification for A2UI web app iframe component (v0.9)#2123
sugoi-yuzuru merged 14 commits into
mainfrom
webframe

Conversation

@sugoi-yuzuru

@sugoi-yuzuru sugoi-yuzuru commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Description

This PR introduces the new URL-based web application iframe component (web-app-frame-url) for the A2UI protocol, adding a secure and isolated method to embed external web applications via URL. It also includes a new "Pong" community sample application to demonstrate its usage.

https://screencast.googleplex.com/cast/NDU2Njg0MjA3MTg0MjgxNnxjNzRjZjIyZS0zOA

🌟 Key Features & Additions

  • Web App Frame URL Component (web-app-frame-url):

    • Component Implementation: Added web-app-frame-url.ts to the Angular client to handle rendering external web apps inside a sandboxed iframe.
    • Specification & Documentation: Authored web-frame-component_spec.md to define the component's API, two-way data binding handshake behavior, and strict security considerations.
    • Catalog Updates: Registered the new component and its configuration in mcp_app_catalog.json.
    • Sandboxing: Introduced sandbox-url.html and updated sandbox.ts to facilitate secure postMessage cross-origin communications while strictly defining <meta> tag requirements and Content-Security-Policy limits for URL-based frames.
  • Pong Web Sample:

    • New Web App: Created the samples/community/web/pong/ sample app.
    • A2UI Bridge: Includes pong_web_frame_bridge.js, which handles the client-side postMessage handshake, state synchronization (player/cpu scores), and function calls with the A2UI host.
    • Server Implementation: Built a standalone Python HTTP server (pong_server.py) to serve the application and inject the bridge script seamlessly.
  • Python ADK Integration:

    • Added necessary tool abstractions in mcp_app_proxy/tools.py and agent.py to allow the proxy agent to interact with and render the new Pong game component.

📝 Notes for Reviewers

  • Please review the CSP rules and Origin verification logic detailed in web-frame-component_spec.md and sandbox-url.html to ensure the cross-origin communication remains completely secure.
  • The Pong server is an independent application—ensure uv is configured properly if testing the sample locally, as per the uv.lock and pyproject.toml configurations.

Pre-launch Checklist

One time:

For this PR:

  • I have updated the relevant CHANGELOG.md file.
  • I updated/added relevant documentation.
  • My code changes (if any) have tests.
  • If my branch is on a fork, I have verified that scripts/e2e_test.sh passes.

If you need help, consider asking for advice on the discussion board.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the WebAppFrameUrl component to support rendering external web applications inside a sandboxed iframe, alongside a detailed specification document for the WebApp Iframe Component (v0.9). It also adds a local Python server and a bridge script to serve and integrate a web-based Pong game. The review feedback highlights critical security concerns that must be addressed before merging: specifically, the use of wildcard origins ('') for postMessage target origins and expected origin validation, which exposes the application to message interception, and an overly permissive CORS header (Access-Control-Allow-Origin: '') on the local server.

Comment thread samples/community/web/pong/pong_web_frame_bridge.js Outdated
Comment thread samples/community/web/pong/pong_server.py Outdated
@sugoi-yuzuru
sugoi-yuzuru force-pushed the webframe branch 3 times, most recently from 9657e63 to 2c3de18 Compare July 29, 2026 15:38
@sugoi-yuzuru sugoi-yuzuru changed the title docs: add specification for A2UI web app iframe component (v0.9) feat: add specification for A2UI web app iframe component (v0.9) Jul 29, 2026

This specification document defines the A2UI Iframe Component (v0.9) for the secure, sandboxed rendering of rich interactive web applications and model-generated HTML content. This document serves two primary purposes:

1. **Platform Implementation Blueprint:** It provides client-side platform developers with a strict, standard set of instructions to implement compliant `WebAppFrameUrl` and `WebAppFrameSrcdoc` components in any native programming language (e.g., TypeScript/Web, Kotlin/Android, Swift/iOS, or Dart/Flutter) while maintaining identical security and sandboxing guarantees.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work on, e.g., Android? Unless you're embedding a browser view, there's no such thing as frames like this what there is present in the web.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the specification is written primarily using web terminology (iframes, srcdoc, postMessage), it serves as a blueprint for configuring native WebView and WKWebView components to behave securely and communicate identically.

And you are correct, this is assuming that you are serving a web-application so the native app will display this by a browser widget.


# 4. Component catalog definition

The two web frame components, _WebAppFrameUrl_ and _WebAppFrameSrcdoc_, shall be registered as distinct options in the A2UI v0.9 Component Catalog.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need 2 components in the catalog? Isn't the fact that we use two iframes an implementation detail that could be encapsulated by one A2UI component?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That’s a great question, and it highlights a subtle but important distinction in the architecture.

You are correct that the double-iframe sandbox pattern (an outer proxy iframe wrapping an inner sandbox iframe) is strictly an implementation detail that is completely hidden from the A2UI agent.

However, the reason there are two distinct components in the catalog (WebAppFrameUrl and WebAppFrameSrcdoc) has nothing to do with the double-iframe implementation. In fact, both components use the double-iframe setup under the hood.

They exist as two separate components in the catalog for two primary reasons:

  1. Different JSON Schemas for the Agent
    The A2UI Component Catalog dictates the JSON structure the LLM agent must generate. These two components take fundamentally different inputs:

WebAppFrameUrl requires a url property (a string pointing to a remote server).
WebAppFrameSrcdoc requires an htmlContent property (a potentially massive string of raw HTML/JS/CSS generated dynamically by the model).
2. Divergent Security Threat Models (CSP Enforcement)
As detailed in Section 5 of the specification, because the source of the content differs, the client renderer must apply completely different security pipelines before rendering the iframe:

For WebAppFrameUrl: The client is loading an external URL via the src attribute. It cannot manipulate the HTML of the remote site, so it must rely on the remote server's HTTP headers to provide the Content Security Policy (CSP). The client's primary security duty here is checking the URL against a strict Domain Allowlist.
For WebAppFrameSrcdoc: The client receives a raw HTML string generated by the LLM. Because LLM output can be unpredictable or maliciously prompted, the client must treat it as untrusted. The client must intercept this HTML, strip out any model-generated CSP tags, and forcibly inject a strict, network-free CSP tag into the before rendering it as srcdoc.
Summary
While the double-iframe sandbox is indeed an encapsulated implementation detail, the agent does need to know whether it is passing a URL or raw HTML. Because they have different schemas and require the client to apply completely different security parsing rules, they are modeled as two separate components in the protocol catalog.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I'll read over the docs again to see if I missed this or if there's something that could be added.

Comment thread samples/community/web/pong/pong_web_frame_bridge.js Outdated
@sugoi-yuzuru
sugoi-yuzuru requested a review from jgindin July 29, 2026 23:45
@sugoi-yuzuru
sugoi-yuzuru force-pushed the webframe branch 2 times, most recently from 96a3afe to 72b342d Compare July 30, 2026 01:00
Comment thread samples/community/agent/adk/mcp_app_proxy/catalogs/0.9/mcp_app_catalog.json Outdated
},
{
"type": "object",
"properties": {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could it make sense to also have a way to pass arbitrary static data to the embedded app as a property, rather than needing to pass it via the data model?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love the idea.

I have introduced a new property config to allow static data assignment to embedded app.
Please check this commit.

  1. I have updated the spec document to discuss about it. In addition to the spec update, I added a section to discuss the difference between the 3 flavors of data: config, data without mutableData, and data with mutableData.
  2. I have updated the component catalog and implementation.
  3. I have updated the WebAppFrameUrl example Pong game to leverage this config to define the "matching-score" of the game. Previously, it was hard-coded to announce a winner who scored 3 points first. Now, the Agent will return a config to set the exact score to call the winner (5).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if you think config is not the right design here.


```json
{
"type": "a2ui_function_call",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these the same or similar as the API for MCP apps to interact with A2UI? Could we unify them somehow?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are very similar. However, I have made a conscious decision to keep them distinct. I have a table in the document https://screenshot-v2.corp.google.com/FCmW9CWE3CgfkeK showing how the mapping works.

While there are some opportunities to mirror them, I believe partial mirroring will make things further convoluted and hard to pin-point which version of an app is implemented.

Furthermore, mirroring the MCP Apps protocols could put us in a situation where we will need to keep updating our implementation to match resulting in additional workload to maintain the synchrony.

By keeping them completely distinct, I believe it gives us more consistency for the A2UI Iframe (WebAppFrame) protocol and a more room to make independent feature evolution paths.

{name: 'McpApp', component: McpApp, schema: McpAppSchema},
{name: 'PongScoreBoard', component: PongScoreBoard, schema: PongScoreBoardSchema},
{name: 'PongLayout', component: PongLayout, schema: PongLayoutSchema},
{name: 'WebAppFrameUrl', component: WebAppFrameUrl, schema: WebAppFrameUrlSchema},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josemontesp is there some way in Angular that we the application developer could pass some configuration data to the Component when installing it in a catalog?

I think it could be great for a developer to be able to set some static domain allowlist for these apps here, to statically protect the client against loading apps at arbitrary domains.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oooo

This would be cool.

Maintaining an allowlist on the client-side catalog would be a nice protection against Agent hallucination and compromised A2UI payloads coming from Agent/MCP servers.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Angular we could use injection tokens that are provided at the app root level, with an optional type-safe configuration. The component can then inject that configuration directly into the component class.


Used to load standalone, sandboxed, model-generated HTML/JS layouts.

```json

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a thought -- take it or leave it...

WebAppFrameSrcdoc and WebAppFrameUrl are quite similar. If we expect them to remain this way, maybe extract the common properties into a new WebApp schema, and then include that in both?

The WebApp schema would have all the properties that are common between the two.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a reasonable POV.
But I will leave it until I have an implementation of the 2 versions completed.

We already had some spec updates through this review cycle and prematurely refactoring them might make us less agile to polish implementation or identify new ideas.

@sugoi-yuzuru

Copy link
Copy Markdown
Collaborator Author

Hi all,

If there are any more comments, please LMK. I will address them as a follow up!
Will merge this soon.

@sugoi-yuzuru
sugoi-yuzuru merged commit 818eeee into main Jul 30, 2026
23 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in A2UI Jul 30, 2026
@sugoi-yuzuru
sugoi-yuzuru deleted the webframe branch July 30, 2026 18:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants