a2ui-project / a2ui-project/a2ui
What must a client do when it holds several A2UI surfaces at once?
- Dominant language
- TypeScript
- Stars
- 16.4k
- Forks
- 1.3k
- Avg merge
- 2d 13h
- Merged PRs (30d)
- 134
Description
**Documents:** `docs/public/guides/a2ui_over_mcp.md`,
`specification/v0_9_1/json/client_data_model.json`,
`specification/v0_9_1/json/client_to_server.json`, and the protocol section
"Data model updates: synchronization and convergence"
We build an A2UI client and an A2UI server that talk over MCP. #2321 settled one half of the
multi-surface problem, because an action now names the surface it happened on. Two questions
remain. Both are about a client that holds more than one surface at the same time.
## 1. The reported data model when several surfaces report
The `sendDataModel` property says:
> If true, the renderer will send the full data model of this surface in the metadata of every
> message sent to the agent.
The synchronization section says:
> When `sendDataModel` is set to `true` for a surface, the renderer automatically appends the
> entire data model of that surface to the metadata of every message (such as `action` or user
> query) sent to the agent that created the surface.
`client_data_model.json` carries a map, and both of its fields are required:
> `surfaces`: A map of surface IDs to their current data models.
Two surfaces have `sendDataModel: true`, and the user acts on the first one. Does that message
carry both data models, or only the model of the surface the action came from?
"every message" and the map both read like both surfaces. "this surface" reads like one. Our
client sends one entry today, and we are not sure that this is correct.
The same section also says:
> **Targeted Delivery**: The data model is sent exclusively to the agent that created the
> surface. Data cannot leak to other agents.
Over MCP one client talks to several servers, and each surface belongs to the server that opened
it. Is the client expected to reduce the map to the surfaces of the server it calls? Our client
can do this, because it knows which server it called. We want to confirm that this is the intent.
## 2. Several surfaces from one tool call
`createSurface` says:
> This message signals the renderer to create a new surface and begin rendering it.
and:
> `surfaceId` must be globally unique for the renderer's lifetime.
A server can therefore answer one `tools/call` with two `createSurface` messages, and a client
can hold both.
Is a client required to render every surface that a single call opens? Or can a client declare a
limit, for example one surface for each invocation, and refuse the rest?
If a limit is allowed, what does the client send back? `client_to_server.json` gives
`VALIDATION_FAILED` a fixed shape. The generic arm takes any other code, with `code`, `surfaceId`
and `message`. Is the generic arm the right place for this, and is there a code name you intend?
We ask because the failure is silent today. A client that drops a surface draws nothing for it,
and the server has no way to learn that. This is the same failure mode as #2321.
Either answer works for us. If a limit is allowed, we report it. If it is not, we draw every
surface the call opens.
Contributor guide
Assessment
This issue has not been assessed yet.