Guide
A2UI adapter
@kimen/adapter-a2ui is Kimen’s first protocol adapter. It translates
declarative A2UI messages into the neutral
UI spec and renders every surface through the
guarded renderer alone. The catalog and the ki-* elements are the durable
assets; the adapter is disposable by design — the exact supported A2UI
version(s) live in the package’s COMPAT.md, protocol churn is absorbed
there, and an unabsorbable break retires the package without touching core.
Why it is safe
Section titled “Why it is safe”The adapter owns no rendering path of its own. It builds a neutral UiSpec
and hands it to renderUiSpec from @kimen/catalog; the guardrail’s four
invariants (only catalog components render, only declared actions dispatch,
unknown props are rejected, no code path executes from message data) are
enforced there, once. Two complementary checks prove the adapter never opens
a side channel: a static module boundary (no other rendering library is
importable) and a runtime guarantee that every render call arrives at the
guarded renderer.
import { createA2uiAdapter } from '@kimen/adapter-a2ui';
const adapter = createA2uiAdapter({ surface: document.querySelector('#genui'), protocolVersion: '0.9.1', onUserAction: (event) => channelToAgent.send(event), // A2UI userAction round-trip onDegradation: (report) => log(report), // unmapped-type gaps, as data});
// A supported A2UI surface update renders as catalog components:const result = adapter.apply({ surfaceUpdate: { surfaceId: 'checkout', root: 'card', components: [ { id: 'card', component: { Card: { children: { explicitList: ['confirm'] } } } }, { id: 'confirm', component: { Button: { label: { literalString: 'Confirm order' }, action: { name: 'confirm-order' } }, }, }, ], },});result.ok; // true — or false with inert diagnostics naming each offenderDegradation rules
Section titled “Degradation rules”An A2UI message is data, never code:
- Unmapped component types degrade per node to a fixed fallback that never carries agent content.
- Forbidden types reject the whole message — a type the compatibility
matrix declares
forbidden(e.g. rawhtml) is never partially rendered. - Unsupported protocol versions are rejected naming the supported set.
- The action set is frozen at first render: incremental
surfaceUpdate/dataModelUpdatemessages revise the surface without discarding it, but no later update can bind an undeclared action.
Transport is caller-owned: the adapter consumes already-delivered A2UI
messages and emits userAction events to the supplied channel.
deleteSurface drops adapter state; the host owns teardown of its surface
element.
The canonical package documentation, including the compatibility policy,
lives in the repository:
packages/adapter-a2ui.