Skip to content

Repository files navigation

a2ui-bindjs

CI

An A2UI (Agent-to-UI) renderer built on BindJS, with native rendering across web, Apple, and Android platforms using React, SwiftUI, and Jetpack Compose.

Flight search, a custom FlightCard component, drawn by SwiftUI on an iPhone and by Jetpack Compose on a Pixel

One BindJS FlightCard source and one set of A2UI messages, from examples/ios/custom-catalog and examples/android/custom-catalog.

A tour of the examples on both phones, from the catalog to the custom components:

a2ui-bindjs.mp4

Why BindJS

BindJS is the open component language for agent UI: write a component once in JavaScript, with its logic, and render it with React, SwiftUI or Jetpack Compose. It uses an API modeled on SwiftUI, with a runtime that turns component definitions into a JSON AST for each platform to render as native views. The same defineComponent source can produce a UISegmentedControl on iOS and a <select> on the web.

This fits well with A2UI. A2UI describes components and binds them to data, leaving their appearance to a catalog. With BindJS, that catalog can be shared across all three platforms.

  • One shared catalog. The 18 components in core/src/catalog/basic power the web examples, the SwiftUI app, and the Compose app in this repo. Changes to those components apply across all three.
  • Native rendering. On Apple and Android platforms, components render through SwiftUI and Jetpack Compose, with native gestures, animations, and typography.
  • A shared protocol engine. The TypeScript interpreter bundles into a single dependency-free file, about 34 KB gzipped. Native apps embed it to handle parsing, data, functions, and diffing without implementing the protocol themselves.
  • Catalog updates at runtime. Hosts can fetch and register updated component definitions without an app release. examples/web/metabind loads a catalog from a Metabind project, while examples/web/custom-catalog shows how to override individual components.

Protocol support

Version Support Notes
v1.0 Full Rendered and validated against the vendored schemas
v0.9.1 Full Same components and functions, so one catalog answers to both

Messages

Message Direction Support
createSurface agent → renderer Web, iOS, Android
updateComponents agent → renderer Web, iOS, Android
updateDataModel agent → renderer Web, iOS, Android
deleteSurface agent → renderer Web, iOS, Android
callRendererFunction agent → renderer Parsed and dispatched as a store event for hosts to subscribe to
agentFunctionResponse agent → renderer Parsed and dispatched as a store event for hosts to subscribe to
action renderer → agent Web, iOS, Android
error renderer → agent Web, iOS, Android (opt-in, per validate)

Basic catalog

Components Support
AudioPlayer Button Card CheckBox ChoicePicker Column DateTimeInput Divider Icon Image List Modal Row Tabs Text TextField Video Slider Web, iOS, Android

Functions

Functions Support
and or not length required numeric email regex pluralize formatString formatNumber formatCurrency formatDate openUrl Web, iOS, Android

Conformance

Suite Result
Official conformance suite (vendor/conformance/) 20 passed, 0 known gaps
43 official spec examples, v1.0 Rendered and schema-validated
43 official spec examples, v0.9 Rendered
Both example sets again on iOS and Android Decoded into native view trees

Installing

React

Install the renderer and the core package its message types come from:

pnpm add @metabindai/a2ui-bindjs @metabindai/a2ui-bindjs-react

For a step-by-step walk through a Vite + React app, chips and a component override included, see Getting started.

iOS and macOS

Add the package to your Package.swift, then depend on the A2UI product:

.package(url: "https://github.com/metabindai/a2ui-bindjs.git", from: "0.1.0")

Android

Add the artifact to your module's dependencies:

implementation("ai.metabind:a2ui-bindjs-android:0.1.0")

Note

The artifact is served from GitHub Packages, which requires a token even to read. See Consuming the artifact for the repository configuration, the minimum SDK, and the compile settings the AAR expects.

Layout

The top level splits by platform. vendor/spec/ is the protocol itself.

Path Package Role
vendor/spec/ n/a Verbatim A2UI v1.0 schemas and examples. Never edited; the build reads it.
vendor/conformance/ n/a The official A2UI conformance suite, vendored. pnpm test runs it.
core/ @metabindai/a2ui-bindjs Protocol, store, function library, rendering engine, catalog. No React.
react/ @metabindai/a2ui-bindjs-react <A2UIRenderer /> and hooks, on the BindJS web renderer. Depends on core.
ios/ a2ui-bindjs-apple (Swift) A2UIHost and A2UISurfaceView. Embeds core's renderer bundle.
android/ ai.metabind:a2ui-bindjs-android A2UIHost and A2UISurfaceView on Compose. Embeds the same bundle.
examples/ private Grouped by platform: web/, ios/, and android/.

Core is published and React consumes it as a package, so a host that renders natively, or on a platform React never reaches, takes core alone.

Examples

Path What it shows
examples/web/minimal The smallest thing that renders a surface, action round-trip included
examples/web/custom-catalog Two components overridden with sources plus one catalog entry, no runtime needed
examples/web/metabind Catalog components fetched from a Metabind project rather than bundled
examples/web/mcp A2UI over MCP: tools that answer with a UI instead of prose
examples/web/playground Monaco message-stream editor, scrubbable timeline, and the 43 official spec examples
examples/ios/minimal The same protocol drawn in SwiftUI, sharing one BindJS runtime with the host
examples/ios/catalog Every basic-catalog component on its own screen, each a real A2UI surface
examples/ios/custom-catalog A component the app registers and the agent names, using the web example's source unchanged
examples/android/minimal The same surface again, message for message, on Jetpack Compose
examples/android/catalog The catalog screens on Compose, decoded through the sandbox
examples/android/custom-catalog useCatalog on Android, sharing that same Rating source

Build and test everything, then start whichever example you want:

pnpm install
pnpm build                  # every package and example
pnpm test

pnpm dev:minimal            # :5182, start here
pnpm dev:custom-catalog     # :5183
pnpm dev:metabind           # :5184
pnpm dev:mcp                # :5185 + MCP server on :8787
pnpm dev:playground         # :5181 (also `pnpm dev`)

pnpm dev:ios                # the minimal example on an iOS simulator
pnpm dev:ios:catalog        # every catalog component, on a simulator
pnpm dev:ios:custom-catalog # a component the app registers and the agent names
pnpm dev:ios:mac            # the minimal example as a macOS window

pnpm dev:android            # the same three, starting an emulator if none is running
pnpm dev:android:catalog
pnpm dev:android:custom-catalog

Rendering a surface

React

Build a store from the agent's messages, then hand it to the renderer:

import type { ActionMessage, AgentMessage } from '@metabindai/a2ui-bindjs'
import { useA2UIStore, A2UIRenderer } from '@metabindai/a2ui-bindjs-react'

function Surface({ messages, sendToAgent }: { messages: AgentMessage[]; sendToAgent: (action: ActionMessage) => void }) {
    const { store } = useA2UIStore(messages)

    return <A2UIRenderer store={store} onAction={sendToAgent} />
}

iOS

Create a host, subscribe to actions, apply messages, and put the view in a SwiftUI body:

import A2UI

let host = A2UIHost()
host.onAction = { action in
    // send it to the agent
}
host.apply(messagesFromTheAgent)

A2UISurfaceView(host: host)

Android

The same shape on Compose. apply suspends, and A2UISurfaceView is a composable:

import ai.metabind.a2ui.A2UIHost
import ai.metabind.a2ui.A2UISurfaceView

val host = A2UIHost(context)
host.apply(messagesFromTheAgent)

host.actions.collect { action ->
    // send it to the agent
}

A2UISurfaceView(host = host)

License

Apache License 2.0.

About

An A2UI (Agent-to-UI) renderer built on BindJS, with native rendering across web, Apple, and Android platforms using React, SwiftUI, and Jetpack Compose.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages