A2UI for WordPress
Using the A2UI protocol in WordPress admin
by Pascal Birchler · github.com/swissspidy/a2ui-wp · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/swissspidy/a2ui-wp/archive/refs/heads/main.zipRenders agent-generated A2UI surfaces inside wp-admin with the WordPress component library. Proof of concept.
A2UI (Agent-to-User Interface) is a protocol that lets an agent describe a user interface as a flat, streamable JSON structure that the host renders with its own native components. This plugin is the "native components" half for WordPress: it takes A2UI v0.9.x messages and renders them with @wordpress/components, the same components wp-admin and the block editor use, so agent-generated UI looks and behaves like the rest of the admin.
Quick Start
Install and activate the latest nightly build on your WordPress website, then open Tools → A2UI. Pick one of the bundled example streams, or paste your own, and click Render all. Everything the rendered UI would send back to an agent shows up in the log next to it.
Note: Requires WordPress 7.1+ and PHP 8.0+.
Using WordPress Playground
Use WordPress Playground to try this plugin directly in the browser, without installing it on your site:
How it works
The plugin registers one admin page and one script. The script contains three layers:
src/core/is a framework-agnostic implementation of the A2UI v0.9.1 client side: message processing (createSurface,updateComponents,updateDataModel,deleteSurface), the per-surface data model (RFC 6901 JSON Pointers), data binding ({ "path": ... }), the${...}expression syntax, the basic catalog's client-side functions (formatString,formatCurrency,required,regex,and,openUrl, and the rest),checks, and outgoingactionmessages. It has no dependencies.src/react/is the React layer:<A2UIRenderer>/<A2UISurface>, hooks for catalog components (useDynamicString,useBoundValue,useChecks,useAction), and the component catalog that maps every basic catalog component onto@wordpress/components.src/admin/is the playground page, with the example streams as hard-coded JSON.
The bundle is built with @wordpress/scripts, so @wordpress/components, @wordpress/element and @wordpress/i18n resolve to the copies WordPress already loads rather than being bundled. What ships is the protocol core, the catalog, and the playground.
Component mapping
| A2UI (basic catalog v0.9.1) | @wordpress/components |
|---|---|
Text (h1–h5, body, caption) |
Heading, Text |
Image (icon, avatar, *Feature, header) |
<img> sized per variant |
Icon |
Icon with @wordpress/icons (see src/react/catalog/icons.ts for the name map) |
Video, AudioPlayer |
native <video> / <audio> |
Row, Column |
HStack, VStack (justify and align mapped to flexbox) |
List (static or template children) |
scrollable VStack / HStack |
Card |
Card + CardBody |
Tabs |
TabPanel |
Modal |
Modal, opened by a click on the trigger child |
Divider |
Divider |
Button (default, primary, borderless) |
Button (secondary, primary, tertiary); disabled while its checks fail |
TextField (shortText, longText, number, obscured) |
TextControl, TextareaControl; checks and validationRegexp shown as help text once touched |
CheckBox |
CheckboxControl |
ChoicePicker (mutuallyExclusive / multipleSelection × checkbox / chips, filterable) |
RadioControl, ToggleGroupControl, CheckboxControl list, toggle Buttons, plus SearchControl for filtering |
Slider |
RangeControl |
DateTimeInput |
DatePicker, TimePicker, DateTimePicker inside a Dropdown |
Theme parameters from createSurface are honoured where they map onto something in the design system: primaryColor is applied through --wp-admin-theme-color and the --wp-components-color-accent variables on the surface wrapper, so buttons, focus rings and toggles pick it up.
Using the renderer elsewhere
The a2ui-wp-admin script handle is registered on init, so another screen can enqueue it. The exports in src/index.ts are what the playground itself uses:
import { A2UIProcessor, A2UIRenderer } from '../index';
const processor = new A2UIProcessor();
// Feed it messages from whatever transport you use.
processor.processMessages( messagesFromTheAgent );
// Send user actions back to the agent.
processor.onAction( ( message ) => transport.send( message ) );
<A2UIRenderer processor={ processor } />;
processor.getClientCapabilities() and processor.getClientDataModel() give you the metadata the transport bindings ask for. Catalog components are plain React components receiving { id, props }; createCatalog() adds or replaces them, and custom client-side functions go through new A2UIProcessor( { functions } ).
Architecture notes
wp-admin is the host, not the server. The plugin renders surfaces and produces action messages; it does not run an agent. An external agent reaching a site through the WordPress MCP adapter is a different situation: those hosts speak MCP Apps (ui:// resources rendered in an iframe), not A2UI, so A2UI payloads would be opaque to them. This renderer therefore serves in-admin agents first. The A2UI and MCP Apps patterns leave room for a later bridge that wraps a surface rendered by this plugin as a ui:// resource for external hosts.
Streaming is optional. A2UI is designed for progressive rendering over a stream, but nothing here needs it: processMessages() takes a complete array, which is what a REST round-trip returns. On typical WordPress hosting, where an agent runs in PHP and long-lived responses are awkward, a REST endpoint that returns the whole message list per turn is the pragmatic default. processJsonl() covers hosts that can stream. Out-of-order delivery works either way: components referenced before they are defined render nothing until they arrive, and nothing renders until the root component exists.
No agent yet. The playground renders bundled and pasted streams. Connecting it to an agent running inside WordPress through the AI Client is the intended next step; the processor's API is what that integration would call.
Status and known gaps
- Targets A2UI v0.9.1 (messages tagged
v0.9are accepted too). The v1.0 candidate is not implemented. Textrenders plain text with preserved line breaks; the Markdown subset the reference renderers support is not rendered yet.Modalopens on a click anywhere inside itstrigger, so a triggerButtonalso fires its own action, matching the reference Lit renderer.DateTimeInputstores whatever the WordPress pickers emit (a local ISO-like string without a zone offset).- The icon map covers the basic catalog's names with the closest
@wordpress/iconsequivalent; a few (volume*,print,stop) are approximations. - Component properties are not schema-validated against the catalog JSON; unknown component types render a warning
Notice, missing references render nothing.
License
GPL-2.0-or-later, like WordPress. See LICENSE.
This is an independent implementation of the A2UI protocol written from the published specification; it does not vendor code from the Apache-2.0 licensed a2ui-project/a2ui repository.