Repository navigation
[iFrame] Add the iframe catalog schema #2795
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
Draft
Draft
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
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
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
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,32 @@ | ||
| # A2UI iframe catalog | ||
|
|
||
| The A2UI iframe catalog lets A2UI surfaces embed sandboxed web applications, from remote widgets to model-generated HTML, next to regular components. It defines the `WebAppFrameUrl` and `WebAppFrameSrcdoc` components, which render an iframe and connect it to the surface through a message protocol, so the embedded application can dispatch actions, share data model state in both directions, call host functions and request its own size. | ||
|
|
||
| ## Catalog specification | ||
|
|
||
| The catalog ID is `https://a2ui.org/specification/v1_0/catalogs/iframe/catalog.json`. | ||
|
|
||
| The catalog declares two components in [catalog.json](catalog.json) and no functions: | ||
|
|
||
| | Component | Content | Description | | ||
| | :------------------ | :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------ | | ||
| | `WebAppFrameUrl` | `url` (`DynamicString`, required) | Loads an external http or https application in a sandboxed iframe. The remote server is responsible for its Content Security Policy. | | ||
| | `WebAppFrameSrcdoc` | `htmlContent` (`string`, required) | Renders inline HTML through `srcdoc` in a sandboxed iframe without network access. The host injects a strict Content Security Policy. | | ||
|
|
||
| Both components share the properties below. | ||
|
|
||
| | Property | Type | Description | | ||
| | :------------------------ | :----------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| | `height` | `DynamicNumber` | The height of the iframe in pixels. | | ||
| | `config` | `object` | Static key-value settings passed once to the application, in the handshake. | | ||
| | `data.paths` | `object` of `string` | A map of state keys to JSON Pointer paths in the data model. The host sends the current values in the handshake and pushes every later change. | | ||
| | `allowedEvents` | `object` of JSON Schemas | The actions the application may dispatch, each mapped to the schema of its payload. | | ||
| | `allowedFunctions` | `object` of JSON Schemas | The catalog functions the application may call, each mapped to the schema of its arguments. | | ||
| | `mutableData` | `object` of JSON Schemas | The `data.paths` keys the application may write back, each mapped to the schema of the allowed values. | | ||
| | `disableSchemaValidation` | `boolean` | Skips the schema validation of the three allowlists above. Reserved for trusted first-party applications; the allowlists themselves still apply. | | ||
|
|
||
| The allowlists deny by default: the host drops any action, function call or data change that is not listed or whose payload fails validation. The messages exchanged between the host and the embedded application (`a2ui_app_frame_ready`, `a2ui_app_frame_init`, `a2ui_action`, `a2ui_data_model_change`, `a2ui_function_call`, `a2ui_size_changed` and their host-to-app counterparts) are defined in the [WebApp iframe component specification](web_app_frame_specification.md). | ||
|
|
||
| ## Implementations | ||
|
|
||
| The components originated in the [Angular MCP calculator sample](../../samples/community/client/angular/projects/mcp_calculator/src/a2ui-catalog/), which implements a v0.9 predecessor of this catalog under its own sample catalog ID. |
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,162 @@ | ||
| { | ||
| "$schema": "https://json-schema.org/draft/2020-12/schema", | ||
| "$id": "https://a2ui.org/specification/v1_0/catalogs/iframe/catalog.json", | ||
| "protocolVersion": "1.0", | ||
| "title": "A2UI iframe catalog", | ||
| "description": "A2UI catalog for embedding sandboxed web applications in a surface. `WebAppFrameUrl` loads an external URL and `WebAppFrameSrcdoc` renders inline HTML. Both components exchange `a2ui_*` messages with the host over a dedicated MessagePort to dispatch actions, keep bound data in sync in both directions, call host functions and request frame resizes. See web_app_frame_specification.md for the protocol and the security controls.", | ||
| "catalogId": "https://a2ui.org/specification/v1_0/catalogs/iframe/catalog.json", | ||
| "components": { | ||
| "WebAppFrameUrl": { | ||
| "type": "object", | ||
| "description": "Renders an external web application, loaded from an http or https URL, in a sandboxed iframe. The remote server is responsible for the application's Content Security Policy.", | ||
| "properties": { | ||
| "component": { | ||
| "const": "WebAppFrameUrl" | ||
| }, | ||
| "url": { | ||
| "$ref": "common_types.json#/$defs/DynamicString", | ||
| "description": "The external URL to load inside the iframe. Only http and https URLs are loaded. The host appends its own origin as the `origin` query parameter so the application can address its messages to the host." | ||
| }, | ||
| "height": { | ||
| "$ref": "common_types.json#/$defs/DynamicNumber", | ||
| "description": "The height of the iframe in pixels." | ||
| }, | ||
| "config": { | ||
| "type": "object", | ||
| "description": "A dictionary of static key-value initialization properties passed to the embedded application once, in the `a2ui_app_frame_init` handshake, without reactive data model binding." | ||
| }, | ||
| "data": { | ||
| "type": "object", | ||
| "description": "Data binding configuration for the component.", | ||
| "properties": { | ||
| "paths": { | ||
| "type": "object", | ||
| "description": "A dictionary mapping custom state keys to distinct JSON Pointer paths in the data model. The host sends the current value of every path in the handshake and pushes an `a2ui_data_model_update` message whenever one changes.", | ||
| "additionalProperties": { | ||
| "type": "string" | ||
| } | ||
| } | ||
| }, | ||
| "required": ["paths"], | ||
| "additionalProperties": false | ||
| }, | ||
| "allowedEvents": { | ||
| "type": "object", | ||
| "description": "A map of authorized action names to JSON Schemas describing the expected `data` payload. The host silently drops an `a2ui_action` message whose action is not listed or whose data fails validation.", | ||
| "additionalProperties": { | ||
| "type": "object", | ||
| "description": "A JSON Schema. The host validates the matching payload against it before acting on the message; an empty object accepts any value." | ||
| } | ||
| }, | ||
| "allowedFunctions": { | ||
| "type": "object", | ||
| "description": "A map of authorized host client function names to JSON Schemas describing their expected arguments. The host rejects an `a2ui_function_call` message whose function is not listed or whose arguments fail validation. The functions must exist in the surface's catalog.", | ||
| "additionalProperties": { | ||
| "type": "object", | ||
| "description": "A JSON Schema. The host validates the matching payload against it before acting on the message; an empty object accepts any value." | ||
| } | ||
| }, | ||
| "mutableData": { | ||
| "type": "object", | ||
| "description": "A map of state keys, as declared in `data.paths`, that the embedded application is authorized to mutate in the parent data model, each mapped to a JSON Schema describing the allowed values. The host drops an `a2ui_data_model_change` message whose key is not listed or whose value fails validation.", | ||
| "additionalProperties": { | ||
| "type": "object", | ||
| "description": "A JSON Schema. The host validates the matching payload against it before acting on the message; an empty object accepts any value." | ||
| } | ||
| }, | ||
| "disableSchemaValidation": { | ||
| "type": "boolean", | ||
| "description": "If true, the host skips the JSON Schema validation of `allowedEvents`, `allowedFunctions` and `mutableData` payloads and forwards them as they arrive. Source checks, payload limits and the allowlists still apply. Reserve it for trusted first-party applications; the agent backend must not set it for untrusted content.", | ||
| "default": false | ||
| } | ||
| }, | ||
| "required": ["component", "url"] | ||
| }, | ||
| "WebAppFrameSrcdoc": { | ||
| "type": "object", | ||
| "description": "Renders inline HTML, such as a model-generated application, in a sandboxed iframe with no network access. The host injects a strict Content Security Policy into the markup before rendering it.", | ||
| "properties": { | ||
| "component": { | ||
| "const": "WebAppFrameSrcdoc" | ||
| }, | ||
| "htmlContent": { | ||
| "type": "string", | ||
| "description": "The raw HTML string to render via srcdoc. A value prefixed with `url_encoded:` is decoded with decodeURIComponent before rendering." | ||
| }, | ||
| "height": { | ||
| "$ref": "common_types.json#/$defs/DynamicNumber", | ||
| "description": "The height of the iframe in pixels." | ||
| }, | ||
| "config": { | ||
| "type": "object", | ||
| "description": "A dictionary of static key-value initialization properties passed to the embedded application once, in the `a2ui_app_frame_init` handshake, without reactive data model binding." | ||
| }, | ||
| "data": { | ||
| "type": "object", | ||
| "description": "Data binding configuration for the component.", | ||
| "properties": { | ||
| "paths": { | ||
| "type": "object", | ||
| "description": "A dictionary mapping custom state keys to distinct JSON Pointer paths in the data model. The host sends the current value of every path in the handshake and pushes an `a2ui_data_model_update` message whenever one changes.", | ||
| "additionalProperties": { | ||
| "type": "string" | ||
| } | ||
| } | ||
| }, | ||
| "required": ["paths"], | ||
| "additionalProperties": false | ||
| }, | ||
| "allowedEvents": { | ||
| "type": "object", | ||
| "description": "A map of authorized action names to JSON Schemas describing the expected `data` payload. The host silently drops an `a2ui_action` message whose action is not listed or whose data fails validation.", | ||
| "additionalProperties": { | ||
| "type": "object", | ||
| "description": "A JSON Schema. The host validates the matching payload against it before acting on the message; an empty object accepts any value." | ||
| } | ||
| }, | ||
| "allowedFunctions": { | ||
| "type": "object", | ||
| "description": "A map of authorized host client function names to JSON Schemas describing their expected arguments. The host rejects an `a2ui_function_call` message whose function is not listed or whose arguments fail validation. The functions must exist in the surface's catalog.", | ||
| "additionalProperties": { | ||
| "type": "object", | ||
| "description": "A JSON Schema. The host validates the matching payload against it before acting on the message; an empty object accepts any value." | ||
| } | ||
| }, | ||
| "mutableData": { | ||
| "type": "object", | ||
| "description": "A map of state keys, as declared in `data.paths`, that the embedded application is authorized to mutate in the parent data model, each mapped to a JSON Schema describing the allowed values. The host drops an `a2ui_data_model_change` message whose key is not listed or whose value fails validation.", | ||
| "additionalProperties": { | ||
| "type": "object", | ||
| "description": "A JSON Schema. The host validates the matching payload against it before acting on the message; an empty object accepts any value." | ||
| } | ||
| }, | ||
| "disableSchemaValidation": { | ||
| "type": "boolean", | ||
| "description": "If true, the host skips the JSON Schema validation of `allowedEvents`, `allowedFunctions` and `mutableData` payloads and forwards them as they arrive. Source checks, payload limits and the allowlists still apply. Reserve it for trusted first-party applications; the agent backend must not set it for untrusted content.", | ||
| "default": false | ||
| } | ||
| }, | ||
| "required": ["component", "htmlContent"] | ||
| } | ||
| }, | ||
| "functions": {}, | ||
| "$defs": { | ||
| "anyComponent": { | ||
| "oneOf": [ | ||
| { | ||
| "$ref": "#/components/WebAppFrameUrl" | ||
| }, | ||
| { | ||
| "$ref": "#/components/WebAppFrameSrcdoc" | ||
| } | ||
| ], | ||
| "discriminator": { | ||
| "propertyName": "component" | ||
| } | ||
| }, | ||
| "anyFunction": { | ||
| "description": "This catalog declares no functions, so no function call validates against it.", | ||
| "not": {} | ||
| } | ||
| } | ||
| } | ||
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.