AgentSkillsCN

a2ui-core

以 Lit 为基础构建 Agent-to-User Interface (A2UI) 组件的核心技能。定义了“如数据般安全、如代码般富于表现力”的生成式 UI 协议、基类与模式。

SKILL.md
--- frontmatter
name: a2ui-core
description: The foundational skill for building Agent-to-User Interface (A2UI) components with Lit. Defines the protocol, base classes, and patterns for Generative UI that is "Safe Like Data, Expressive Like Code".

A2UI Core: Protocol & Implementation

Overview

A2UI (Agent-to-User Interface) enables AI agents to "speak UI" by transmitting intent and structure rather than executable code. This skill provides the patterns for building compliant Lit components.

Core Philosophy

"Safe Like Data, Expressive Like Code"

PrincipleImplementation
No Executable LogicAgents send JSON component trees, never JavaScript
Trusted CatalogOnly registered components render; unknown types are ignored
Native FidelityComponents inherit host app's design system via CSS variables

Protocol Specification

The Adjacency List Model

Unlike the DOM (nested tree), A2UI uses a flat list with ID references. This:

  • Prevents LLM syntax errors from deep nesting
  • Enables O(1) updates by component ID
  • Allows efficient streaming
json
{
  "surfaceUpdate": {
    "surfaceId": "main-view",
    "components": [
      { "id": "root", "component": { "Column": { "children": { "explicitList": ["header", "content"] } } } },
      { "id": "header", "component": { "Text": { "text": { "literalString": "Title" } } } },
      { "id": "content", "component": { "Text": { "text": { "path": "/data/message" } } } }
    ]
  }
}

Message Verbs

VerbDescription
surfaceUpdateStructural blueprints (component definitions)
dataModelUpdateState patches; triggers Signal reactivity
beginRenderingMount a specific root component
userActionClient → Agent intent (unidirectional)
deleteSurfaceTeardown and cleanup

Data Binding (JSON Pointers - RFC 6901)

Properties can be:

  • Literal: { "label": { "literalString": "Submit" } }
  • Bound: { "value": { "path": "/user/email" } } → Reactive subscription

Implementation with Lit

Base Class: DynamicComponent

All A2UI components extend DynamicComponent (see assets/DynamicComponent.ts):

typescript
// Usage in your component
@customElement('agui-my-widget')
export class MyWidget extends DynamicComponent {
  render() {
    const label = this.resolve(this.componentDefinition.label);
    return html`<span>${label}</span>`;
  }
}

Key Methods:

  • resolve(prop) → Resolves literal values or subscribes to data paths
  • dispatchUserAction(name, context) → Sends intent to agent

Component Registry

The Trusted Catalog pattern (see assets/ComponentRegistry.ts):

typescript
componentRegistry.register('MyWidget', MyWidget, 'agui-my-widget');

If an agent requests an unregistered component, the renderer safely ignores it.

Smart Wrappers

For 3rd-party libraries (Chart.js, D3, etc.), use Smart Wrappers (see assets/ChartWrapper.ts):

  1. Create a container element
  2. Bridge A2UI props to library API in updated()
  3. Clean up in disconnectedCallback()

Component Implementation Checklist

  • Extend DynamicComponent (or LitElement for simple cases)
  • Use @customElement('agui-*') naming convention
  • Use resolve() for all dynamic properties
  • Use dispatchUserAction() for all user interactions
  • Apply styling via CSS custom properties (see a2ui-design-bridge skill)
  • Register in ComponentRegistry if using full A2UI stack

Validation

Run the payload validator to check JSON structure:

bash
python3 scripts/validate_payload.py '<json_payload>'

Assets

FilePurpose
assets/DynamicComponent.tsBase class with signal binding
assets/ComponentRegistry.tsTrusted Catalog singleton
assets/ChartWrapper.tsSmart Wrapper template
scripts/validate_payload.pyJSON structure validator