a2ui-project / a2ui-project/a2ui

[v0.10] Configuration Schemas for Data-Bound Components

オープン
#989 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る
component: specification component: standard catalog specification P2 status: needs review type: feature/enhancement
主要言語
TypeScript
スター
16.4k
フォーク
1.3k
平均マージ
2日 13時間
マージ済み PR(30日)
134

説明

## Problem

The A2UI spec cleanly separates component structure (`updateComponents`) from component data (`updateDataModel`). Components bind to data model values via `DataBinding` — a JSON Pointer path into the data model.

However, **the data model is completely untyped**. The `updateDataModel` message accepts any JSON value at any path:

```json
"updateDataModel": {
"surfaceId": "string",
"path": "string",
"value": "any" // ← no schema, no constraints
}
```

This works fine for simple components with inline properties (like `Text` or `Button` in the basic catalog). But for **complex data-bound components** — where a component binds to a rich configuration object via `DataBinding` — there is no spec-level way for a catalog to declare what shape of data the component expects.

### Why this matters

- **LLM agents** generate data model values with no schema guidance. Common errors include missing required fields, wrong types, broken enum values, and malformed nested structures. These errors are only caught at the client renderer — too late for the agent to self-correct.
- **Validators** check component tree topology (IDs, cycles, orphans, recursion limits, path syntax) but have zero visibility into data model content. Invalid data passes all 5 validation levels.
- **Clients** receive `updateDataModel` payloads with no way to validate before rendering.
- **Catalog authors** can define complex data expectations but must resort to description strings or proprietary extensions — nothing machine-readable.
- **Tooling** (TypeScript generators, mock data generators, documentation tools) cannot extract data shape information from catalogs.

### Example

A catalog defines a `ContactCard` component that binds to a config object:

```json
"ContactCard": {
"properties": {
"component": { "const": "ContactCard" },
"configuration": {
"$ref": "common_types.json#/$defs/DataBinding",
"description": "Path to a ContactCardConfig object in the data model."
}
}
}
```

The component expects an object with `name` (string), `email` (string, format: email), and `role` (enum) at the bound path — but that expectation lives only in a description string. The spec has no mechanism to express it formally.

---

## Proposed Solution

Two additions to the catalog format, with no wire protocol changes:

### 1. `configSchemas` — a new top-level catalog section

A map of schema name to JSON Schema (Draft 2020-12), declaring the expected shapes of data model values:

```json
{
"catalogId": "urn:example:my-catalog:v1",
"components": { ... },
"functions": { ... },
"configSchemas": {
"ContactCardConfig": {
"type": "object",
"properties": {
"name": { "type": "string" },
"email": { "type": "string", "format": "email" },
"role": { "type": "string", "enum": ["engineer", "manager", "designer"] }
},
"required": ["name", "email", "role"]
}
}
}
```

### 2. `expectedSchema` — an annotation on DataBinding properties

A machine-readable link from a component's binding property to its expected data shape:

```json
"ContactCard": {
"allOf": [
{ "$ref": "common_types.json#/$defs/ComponentCommon" },
{
"properties": {
"component": { "const": "ContactCard" },
"configuration": {
"$ref": "common_types.json#/$defs/DataBinding",
"expectedSchema": { "$ref": "#/configSchemas/ContactCardConfig" }
}
},
"required": ["component", "configuration"]
}
]
}
```

### What this enables

- **Data model validation** — validators can check `updateDataModel` values against the expected schema, adding a new validation level alongside the existing 5
- **LLM self-correction** — agents can validate generated data before sending to the client, and feed structured errors back to the LLM for retry
- **Prompt generation** — schema managers can automatically produce data shape documentation for LLM prompts, instead of relying on prose descriptions
- **Client-side validation** — clients can optionally validate incoming data before rendering
- **Type generation** — tooling can produce TypeScript interfaces from `configSchemas`

### What this does NOT change

- **No wire protocol changes** — `createSurface`, `updateComponents`, `updateDataModel`, `deleteSurface` are unchanged
- **No mandatory validation** — `configSchemas` and `expectedSchema` are optional; validators MAY check them
- **Fully backward compatible** — catalogs without `configSchemas` work exactly as before; validators that don't understand `expectedSchema` skip it

---

## Design Rationale

**Why a top-level section, not inline in components?**
Multiple components may share config schema fragments (e.g., a shared header object used across several components). A top-level section with `$ref` support enables reuse. It also separates UI structure concerns from data shape concerns.

**Why annotate the property, not the DataBinding type?**
`DataBinding` is a runtime type that appears in `updateComponents` payloads. Adding schema metadata to it would bloat every runtime message. `expectedSchema` is catalog metadata — it belongs on the component schema, not the runtime value.

**Why not a `dataModelSchema` on `createSurface`?**
A surface-level schema requires the agent to know the full data shape upfront, conflicts with incremental/streaming updates, and creates a monolithic schema instead of per-component contracts.

コントリビューションガイド

コントリビューションガイドを開く

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。