Internal strategic analysis — March 2026
Additional References:
A2UI (Agent-to-UI) is Google's open specification for AI agents to render rich, interactive user interfaces. It defines a JSON-based protocol where an agent sends structured messages describing UI components, and a client-side renderer displays them. For OpenClaw — the leading open-source AI agent framework — A2UI is the primary mechanism for presenting visual content to users across iOS, Android, and macOS.
OpenClaw's A2UI integration is production-grade and well-engineered. It vendors the official @a2ui/lit renderer, validates messages thoroughly, and works cross-platform through native WebViews. The implementation was architected by Peter Steinberger (@steipete), OpenClaw's creator and veteran native mobile developer (founder of PSPDFKit/Nutrient, 13+ years iOS experience).
However, the implementation is pinned to A2UI v0.8 and explicitly rejects v0.9 messages. With Peter joining OpenAI and OpenClaw transitioning to a foundation, the bus factor is concerning. The v0.9 spec introduces significant improvements — notably createSurface replacing beginRendering, a cleaner event model, and better component variants — and the ecosystem is actively migrating. This document analyzes the current state, the v0.9 changes, and recommends an upgrade path.
The A2UI rendering pipeline flows through several layers:
Agent (LLM) → canvas tool (a2ui_push action)
→ Gateway RPC (node.invoke "canvas.a2ui.pushJSONL")
→ Node app (iOS/Android/macOS)
→ WebView loads A2UI host page from canvas HTTP server
→ JavaScript bridge receives JSONL messages
→ @a2ui/lit renderer renders components
Key components:
-
Canvas Host Server (
src/canvas-host/server.ts) — Node.js HTTP server with WebSocket for live reload. Serves static files from~/.openclaw/canvas/, injects live-reload client viachokidarfile watching. -
A2UI Asset Server (
src/canvas-host/a2ui.ts) — Serves the bundled A2UI Lit renderer at/__openclaw__/a2ui/. Resolves the A2UI root through 10+ candidate paths (a code smell suggesting fragile deployment packaging). -
Bundle Pipeline (
scripts/bundle-a2ui.sh) — TypeScript + Rolldown bundler. Source invendor/a2ui/renderers/lit/, output tosrc/canvas-host/a2ui/a2ui.bundle.js. Content-hash caching to skip unnecessary rebuilds. -
Bootstrap App (
apps/shared/OpenClawKit/Tools/CanvasA2UI/bootstrap.js) — ~15KB Lit web component wrapping@a2ui/litv0_8 renderer with custom style overrides and theme context. -
Native Handlers:
- Android (
A2UIHandler.kt): Polls for WebView readiness (50 retries × 120ms), validates JSONL, callsglobalThis.openclawA2UI.applyMessages() - iOS/macOS (
CanvasA2UIJSONL.swift): Swift-side parsing, v0.8 validation, action bridge for capturing user interactions
- Android (
✅ Official renderer — Uses @a2ui/lit directly, not a custom implementation. Spec compliance comes "for free" with renderer updates.
✅ Cross-platform consistency — Same A2UI bundle works on macOS, iOS, and Android. Platform-specific code is minimal.
✅ Solid validation — JSONL validator (a2ui-jsonl.ts) catches malformed messages, detects version mismatches, returns structured version/count info.
✅ Good DX — Live reload via file watching. buildA2UITextJsonl() helper for quick text displays.
✅ Security — Path traversal protection via resolveFileWithinRoot(), capability-based auth for canvas WebSocket.
createSurface and returns an error. The spec has moved on.
openclawSendUserAction() producing OpenClaw-specific payloads ({ name, surfaceId, sourceComponentId, context }), not A2UI spec-compliant client→server events. This is technical debt.
vendor/a2ui/ directory (~1MB+) manually copied from the A2UI spec repo. Manual sync required to stay current.
bootstrap.js uses appendComponentStyles to patch Lit component styles directly. Fragile if renderer internals change.
Peter Steinberger (@steipete) — Creator and sole architect of OpenClaw. Founded PSPDFKit (leading PDF SDK for iOS/Android). Recently joined OpenAI. OpenClaw transitioning to a foundation.
Bus factor = 1. The A2UI implementation spans Kotlin, Swift, TypeScript, and shell scripts. Knowledge is heavily concentrated. Foundation contributors will need to understand both the A2UI spec and three platform codebases.
Based on analysis of the A2UI repository, PR #751 (upgrading examples to v0.9), and PR #622 (documentation alignment):
createSurface replaces beginRendering: In v0.8, you'd send surfaceUpdate with components, then beginRendering to trigger rendering. In v0.9, createSurface initializes a surface with metadata (catalogId, theme) upfront, and updateComponents replaces surfaceUpdate. Surface lifecycle is now explicit.
Version field required: Every v0.9 message includes "version": "v0.9", enabling version-aware processing.
Terminology changes:
| v0.8 | v0.9 |
|---|---|
beginRendering |
createSurface |
surfaceUpdate |
updateComponents |
usageHint |
variant |
children: { explicitList: [...] } |
Direct arrays |
Component improvements:
- Image: new
fitandvariantproperties - Button:
variantproperty (primary, secondary, etc.) - Text:
variantreplacesusageHintfor heading levels - updateDataModel: omitting
valueimplies deletion
Event model: Actions use structured { event: { name: "..." } } format — directly relevant to fixing OpenClaw's custom action bridge.
Client-side functions: New capability for client-side formatting/computation, reducing agent round-trips.
These changes mean OpenClaw's current implementation cannot process v0.9 messages:
- Message structure:
createSurfaceis a new top-level action key. OpenClaw's JSONL validator whitelists v0.8 keys and rejects others. - Component definitions:
childrenno longer use{ explicitList: [...] }— they're direct arrays. - Style properties:
usageHint→variantaffects visual presentation resolution. - Surface lifecycle: Two-step
surfaceUpdate+beginRenderingbecomescreateSurface+updateComponents. All three native handlers need updating.
PR #751 (nan-yu): Adds v0.9 example files alongside renamed v0.8 examples, plus a migration script (migrate_v08_to_v09.py). Agent code updated to be version-aware but remains pinned to v0.8. Signal: v0.9 is ready, Google provides migration tooling, transition is careful.
PR #622 (gspencergoog — Greg Spencer, Flutter/Google team): Comprehensive documentation overhaul replacing all v0.8 terminology, migrating legacy docs to docs/v0_8/ archive, restructuring for v0.8/v0.9/v0.10. Key detail: v0.10 is already being planned. v0.8 is being archived.
Bottom line: The A2UI ecosystem is moving decisively to v0.9. Staying on v0.8 means falling behind the spec, the tooling, and the community.
- Spec compliance: v0.8 is being archived. New features, bug fixes, and renderer improvements target v0.9+.
- Future-proofing: v0.10 is in planning. Skipping v0.9 makes the eventual upgrade harder.
- Community alignment: Contributors expect v0.9. The migration script from PR #751 automates message format conversion.
- Better architecture: v0.9's explicit
createSurfaceis cleaner than v0.8's implicitbeginRendering.
JSONL Validator (a2ui-jsonl.ts):
- Add
createSurface,updateComponentsto allowed action keys - Support
versionfield detection for v0.9 - Consider dual v0.8/v0.9 support during transition
Bootstrap App (bootstrap.js):
- Import
v0_9from@a2ui/litinstead ofv0_8 - Update component wiring for new children format
- Replace
usageHintreferences withvariant - Update
appendComponentStylesif renderer internals changed
Native Handlers:
- Android (
A2UIHandler.kt): RemovecreateSurfacerejection, update message parsing - iOS/macOS (
CanvasA2UIJSONL.swift): Update Swift-side validation for v0.9 structure - Both: Update action bridge to use v0.9's event format
Vendor Update:
- Sync
vendor/a2ui/to latest, or better: switch to npm dependency - Update bundle pipeline for v0.9 renderer
Phase 1 — Validator + Bootstrap (1-2 weeks):
- Update JSONL validator to accept v0.9 messages
- Update bootstrap app to use v0.9 renderer
- Keep v0.8 support as fallback (version detection already exists)
- Test with v0.9 example files from PR #751
Phase 2 — Native Handlers (1-2 weeks):
- Update Android handler to process v0.9 messages
- Update iOS/macOS handlers
- Fix action bridge to use spec-compliant client→server events
- Hardest phase — requires Kotlin, Swift, and TypeScript changes
Phase 3 — Architecture Improvements (ongoing):
- Replace vendored copy with proper npm dependency
- Reduce 10+ path candidates for A2UI root resolution
- Add streaming support for incremental UI updates during LLM generation
- Replace polling-based readiness with event-driven approach
Fix the action bridge — Biggest opportunity. Replace custom openclawSendUserAction() with spec-compliant A2UI client→server events. Aligns with spec, improves maintainability.
Dependency management — Move from vendored snapshot to npm package. @a2ui/lit should be a proper dependency.
Streaming — v0.9's explicit surface lifecycle makes streaming natural. createSurface first, then stream updateComponents as the LLM generates. Significant UX improvement potential.
Simplify path resolution — Consolidate the 10+ candidate paths to 2-3 well-defined locations.
Our openclaw-live project takes a different approach — browser-based rendering without native node apps. The v0.9 upgrade insights are directly relevant:
- Target v0.9 from the start, not v0.8
- Use the official
@a2ui/litrenderer (OpenClaw validates this is the right choice) - Implement spec-compliant client→server events from day one (learn from OpenClaw's mistake)
- Our browser approach naturally supports streaming — advantage over WebView
- Adopt JSONL validation patterns from OpenClaw (proven in production)
We now have deep context on OpenClaw's A2UI implementation. Potential contributions:
- Submit a PR for v0.9 support — we understand exactly what needs to change
- Fix the action bridge to be spec-compliant — benefits the whole ecosystem
- Improve vendor/dependency management — replace vendored copy with npm
- Add streaming support — our browser-based work gives us relevant experience
- Use
@a2ui/litv0.9 renderer from the start - Implement the same JSONL validation patterns (proven in production)
- Build spec-compliant client→server events (what OpenClaw should have done)
- Consider making our A2UI rendering layer reusable for other projects
- The A2UI spec is actively developed by Google engineers (Greg Spencer from the Flutter team is a key contributor)
- The v0.8→v0.9 migration is happening now — good time to engage
- OpenClaw's transition to a foundation creates an opening for new contributors
- Our audit gives us credibility to participate in spec discussions
Document prepared by Zaf (AI agent) based on source code audit of openclaw/openclaw repository, analysis of A2UI PRs #751 and #622, and A2UI v0.9 specification review.