A2UI-Oberflächen in Ihrer App rendern

Wenn Sie den Jetpack Compose-Renderer für die Kommunikation zwischen KI-Agent und Benutzeroberfläche (A2UI) verwenden, sendet ein KI-Agent Nachrichten, in denen UI-Strukturen, Komponenteneigenschaften und Datenaktualisierungen beschrieben werden. Wenn Sie diese Oberflächen nativ in Ihrer App anzeigen möchten, hosten und rendern Sie eine A2UI-Oberfläche in der Jetpack Compose-Hierarchie Ihrer App.

Der Compose A2UI-Renderer koordiniert das Parsen von Nachrichten, die reaktive Snapshot-Statusverwaltung und animierte Statusübergänge von Oberflächen. Der Core-Renderer ist unabhängig von einem bestimmten Designsystem, bietet aber durch den bereitgestellten Basic Catalog eine sofort einsatzbereite Integration mit Material Design 3.

Compose-basierte Datenschicht initialisieren

Der A2UI-Renderer unterstützt Snapshot-fähigen Status in der Datenschicht Ihrer App, sodass die Benutzeroberfläche Ihrer App auf inkrementelle Updates vom Agent reagieren kann. Um diese Unterstützung hinzuzufügen, initialisieren Sie den Parser und den Prozessor mit den Factory-Funktionen A2uiMessageParser und A2uiMessageProcessor in Ihrem ViewModel, wie im folgenden Code-Snippet gezeigt:

class AgenticUiViewModel : ViewModel() {
    // Create a parser that leverages the built-in JSON parser.
    private val parser = A2uiMessageParser()

    // Create an A2UI message processor with your catalog and optional
    // action interceptor (implementing A2uiActionInterceptor).
    private val processor = A2uiMessageProcessor(
        // You can also use the provided Material catalog instead of
        // a custom one.
        catalogs = listOf(CustomDesignSystemCatalog)
    )

    // Expose active surfaces to the UI as a StateFlow.
    val a2uiSurfaces: StateFlow<List<A2uiSurfaceModel>> =
        processor.activeSurfaces

    init {
        // Collect messages on a background thread tied to the ViewModel lifecycle.
        viewModelScope.launch(Dispatchers.Default) {
            processor.collectMessages()
        }

        // Add support for two-way communication with the agent.
        viewModelScope.launch(start = CoroutineStart.UNDISPATCHED) {
            processor.outboundEvents.collect(::handleOutboundA2uiEvent)
        }
    }

    // Called by your app's networking layer or business logic whenever
    // a new A2UI protocol message arrives from the AI agent.
    fun onNetworkMessage(json: String) {
        processor.processInput(parser, json)
    }
}

Oberflächen mit dem Basiskatalog (Material 3) rendern

Wenn Sie Oberflächen mit der bereitgestellten Basic Catalog-Implementierung (androidx.compose.material3:material3-a2ui) rendern, können Sie eine vollständig formatierte Material 3-Oberfläche rendern, einschließlich integrierter Unterstützung für Ladeanzeigen, Fehlergrenzen und animierte Übergänge. Verwenden Sie dazu den zusammensetzbaren Einstiegspunkt A2uiSurface:

@Composable
fun AgenticUiScreen(viewModel: AgenticUiViewModel) {
    // Observe active surfaces managed by the data layer.
    val surfaces by viewModel.a2uiSurfaces.collectAsStateWithLifecycle()

    Column(Modifier.fillMaxSize()) {
        surfaces.forEach { surface ->
            key(surface.id) {
                A2uiSurface(
                    surfaceModel = surface,
                    // Add your surface's custom modifiers here.
                )
            }
        }
    }
}

Oberflächenstatus und animierte Übergänge verarbeiten

A2uiSurface koordiniert die Auflösung des Status der Stammkomponente und wendet AnimatedContent-Übergänge für die Status „Wird geladen“, „Fehler“ und „Erfolg“ an:

@Composable
fun CustomStyledSurface(surface: A2uiSurfaceModel) {
    A2uiSurface(
        surfaceModel = surface,
        modifier = Modifier.fillMaxSize(),
        loadingContent = {
            Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                CircularProgressIndicator()
            }
        },
        errorContent = { exception ->
            Text(
                text = "Failed to load: ${exception.message}",
                color = MaterialTheme.colorScheme.error,
                // Add your custom error styling, such as modifiers, here.
            )
        },
        transitionSpec = {
            (fadeIn(animationSpec = tween(600)) togetherWith
                    fadeOut(animationSpec = tween(600)))
                .using(SizeTransform(clip = false))
        },
    )
}

Oberflächenrendering auf niedriger Ebene mit benutzerdefinierten Routern

Sie können den Status der Surface-Root-Komponente direkt mit observeA2uiComponentState beobachten und das Rendern an A2uiComponent delegieren:

@Composable
fun RawSurfaceCoordinator(surface: A2uiSurfaceModel) {
    // Extract the catalog to provide its readiness evaluator to the
    // composition. This lets components wait for their dynamic data bindings
    // before they're rendered.
    val coreSurface = surface as? A2uiCoreSurfaceModel
        ?: throw IllegalArgumentException(
            "Surface must implement A2uiCoreSurfaceModel")
    val composeCatalog = coreSurface.catalog as? A2uiCatalog
        ?: throw IllegalArgumentException("Catalog must implement A2uiCatalog")
    val readinessEvaluator = remember(composeCatalog) {
        composeCatalog.asReadinessEvaluator() }

    CompositionLocalProvider(
        LocalA2uiReadinessEvaluator provides readinessEvaluator
    ) {
        val rootState = observeA2uiComponentState(surface = surface)
        when (rootState) {
            is A2uiComponentState.Loading -> {
                LoadingSpinner()
            }
            is A2uiComponentState.Error -> {
                ErrorBanner(rootState.exception)
            }
            is A2uiComponentState.Success -> {
                // Delegate component routing to the Compose A2UI router.
                A2uiComponent(
                    component = rootState.component,
                    // Add your custom modifiers here.
                )
            }
        }
    }
}

Details zur Implementierung

Der Agent-to-UI-Renderer verarbeitet die Auflösung des Oberflächenstatus und die defensiven Fehlergrenzen.

Defensive Fehlergrenzen und Behandlung von Halluzinationen bei Agenten

Da A2UI-Oberflächen von generativen LLM-Agents gesteuert werden, können eingehende Nutzlasten fehlerhaft sein oder auf unbekannte Komponententypen verweisen.

Der Renderer legt die folgenden defensiven Grenzen fest, um die Wahrscheinlichkeit von Abstürzen zu minimieren:

  • Fehlerbehebung für die Selbstkorrektur des Agent: Fehler werden als ausgehende Clientnachrichten gesendet, sodass der Agent sich in nachfolgenden Interaktionsrunden selbst korrigieren kann. Es gibt auch eine API, mit der Komponentenimplementierungen Fehler an den Agenten senden können, wenn die API zur Renderzeit komponentenbezogene Fehler erkennt.
  • Unbekannte Komponenten: Wenn ein unbekannter Komponententyp erkannt wird, wird er abgefangen, bevor er den UI-Baum erreicht. Er wird als Fehlerstatus gekennzeichnet und zur Selbstkorrektur an den Agent zurückgemeldet.
  • Fehler bei der Schemavalidierung: Nutzlasten werden anhand von Komponentenschemas (A2uiSchema) validiert. Falsch formatierte Eigenschaften sollten niemals Compose-UI-Layouts erreichen.
  • Schutz vor dünnbesetzten Arrays: Wenn sehr große Listenindexe empfangen werden, wechselt das Datenmodell von einer dichten Liste zu einer adaptiven dünnbesetzten Map, wodurch Speicherfehler vermieden werden.