Esperienze frontend con ADK e A2UI

1. Panoramica

La maggior parte delle app di agenti restituisce testo normale. A2UI cambia tutto. È un protocollo con 18 primitive UI dichiarative che consente all'agente di comporre interfacce interattive e avanzate. Il client le esegue il rendering in modo nativo. Non è necessario nuovo codice frontend per layout.

Questo codelab utilizza Agent Development Kit (ADK) per creare l'agente e A2UI per generare l'UI.

Che cosa creerai

Una dashboard dell'infrastruttura cloud in tre fasi:

  1. Un agente standard che restituisce i dati delle risorse come testo normale
  2. Un agente A2UI che restituisce gli stessi dati come JSON A2UI strutturato
  3. Un agente di cui è stato eseguito il rendering che visualizza il JSON A2UI come componenti UI interattivi nell'UI di sviluppo ADK

Agente ADK A2UI

Obiettivi didattici

  • Come funziona A2UI: 18 primitive, 3 tipi di messaggi, modello di componenti flat
  • Come utilizzare l'SDK A2UI per richiedere a un agente ADK di generare JSON A2UI
  • Come eseguire il rendering dei componenti A2UI in adk web

Che cosa ti serve

  • Un progetto cloud Google Cloud con la fatturazione abilitata
  • Un browser web come Chrome
  • Python 3.12 o versioni successive

Questo codelab è destinato a sviluppatori di livello intermedio che hanno una certa familiarità con Python e Google Cloud.

Il completamento di questo codelab richiede circa 15-20 minuti.

Le risorse create in questo codelab dovrebbero costare meno di 5 $.

2. Configura l'ambiente

Crea un progetto Google Cloud

  1. Nella console Google Cloud, nella pagina di selezione del progetto, seleziona o crea un progetto Google Cloud.
  2. Verifica che la fatturazione sia attivata per il tuo progetto Cloud. Scopri come verificare se la fatturazione è abilitata per un progetto.

Avvia l'editor di Cloud Shell

Per avviare una sessione di Cloud Shell dalla console Google Cloud, fai clic su Attiva Cloud Shell nella console Google Cloud.

Viene avviata una sessione nel riquadro inferiore della console Google Cloud.

Per avviare l'editor, fai clic su Apri editor nella barra degli strumenti della finestra di Cloud Shell.

Imposta le variabili di ambiente

Nella barra degli strumenti dell'editor di Cloud Shell, fai clic su Terminale e Nuovo terminale, quindi esegui i seguenti comandi per impostare il progetto, la località e configurare ADK in modo che utilizzi Gemini in Vertex AI.

export GOOGLE_CLOUD_PROJECT=<INSERT_YOUR_GCP_PROJECT_HERE>
export GOOGLE_CLOUD_LOCATION=global
export GOOGLE_GENAI_USE_VERTEXAI=True

Abilita API

Nel terminale, esegui il seguente comando per abilitare le API richieste:

gcloud services enable aiplatform.googleapis.com

Installa le dipendenze

Nel terminale, esegui il seguente comando per installare la versione più recente di Agent Development Kit (ADK):

pip install -U google-adk a2ui-agent-sdk
export PATH="$HOME/.local/bin:$PATH"

3. Crea l'agente

Inizia con un agente ADK standard che restituisce testo normale. Ecco come si presentano la maggior parte delle app di agenti oggi.

Crea la cartella dell'agente

Crea una cartella denominata a2ui_agent che conterrà il codice sorgente dell'agente e degli strumenti.

Definisci lo strumento e i dati simulati

Crea a2ui_agent/resources.py con i seguenti contenuti. Questo strumento restituisce un elenco di risorse cloud con il relativo stato.

RESOURCES = [
    {
        "name": "auth-service",
        "type": "Cloud Run",
        "region": "us-west1",
        "status": "healthy",
        "cpu": "2 vCPU",
        "memory": "1 GiB",
        "instances": 3,
        "url": "https://auth-service-abc123.run.app",
        "last_deployed": "2026-04-18T14:22:00Z",
    },
    {
        "name": "events-db",
        "type": "Cloud SQL",
        "region": "us-east1",
        "status": "warning",
        "tier": "db-custom-8-32768",
        "storage": "500 GB SSD",
        "connections": 195,
        "version": "PostgreSQL 16",
        "issue": "Storage usage at 92%",
    },
    {
        "name": "analytics-pipeline",
        "type": "Cloud Run",
        "region": "us-west1",
        "status": "error",
        "cpu": "2 vCPU",
        "memory": "4 GiB",
        "instances": 0,
        "url": "https://analytics-pipeline-ghi789.run.app",
        "last_deployed": "2026-04-10T16:45:00Z",
        "issue": "CrashLoopBackOff: OOM killed",
    },
]

def get_resources() -> list[dict]:
    """Get all cloud resources in the current project.
    Returns a list of cloud infrastructure resources including their
    name, type, region, status, and type-specific details.
    Status is one of: healthy, warning, error. Resources with
    warning or error status include an 'issue' field describing
    the problem.
    """
    return RESOURCES

Definisci l'agente

Crea a2ui_agent/agent.py con i seguenti contenuti:

from google.adk.agents import Agent
from .resources import get_resources

root_agent = Agent(
    model="gemini-3-flash-preview",
    name="cloud_dashboard",
    description="A cloud infrastructure assistant that reports on project resources.",
    instruction=(
        "You are a cloud infrastructure assistant. When users ask about their "
        "cloud resources, use the get_resources tool to fetch the current state. "
        "Summarize the results clearly in plain text."
    ),
    tools=[get_resources],
)

4. Testa l'agente

ADK include un'UI di sviluppo che puoi utilizzare per interagire con l'agente e inviargli prompt in un browser per i test.

Avvia l'UI di sviluppo ADK

Nel terminale dell'editor di Cloud Shell, esegui il seguente comando per avviare l'UI di sviluppo ADK:

adk web --port 8080 --allow_origins "*" --reload_agents

Dovresti visualizzare un messaggio simile al seguente:

+-----------------------------------------------------------------------------+
| ADK Web Server started                                                      |
|                                                                             |
| For local testing, access at http://127.0.0.1:8080.                         |
+-----------------------------------------------------------------------------+

Apri l'UI di sviluppo ADK

Puoi aprire l'UI di sviluppo ADK nel browser facendo clic con il tasto Ctrl o Cmd sull'URL di test locale oppure facendo clic sul pulsante Anteprima web e selezionando Anteprima sulla porta 8080.

Una volta visualizzata l'UI di sviluppo ADK, seleziona a2ui_agent dal menu a discesa.

Invia prompt di esempio

Invia un prompt di esempio all'agente:

What's running in my project?

Ora prova un altro prompt di esempio e otterrai più output di testo:

Does anything need my attention?

La conversazione dovrebbe essere simile alla seguente:

Agente di testo ADK

Visualizzerai una grande quantità di testo. È accurato, ma l'esperienza utente non è ottimale.

5. Genera JSON A2UI

E se l'agente potesse descrivere un'UI anziché scaricare testo? A2UI è un protocollo che consente agli agenti di comporre interfacce interattive da un catalogo di 18 primitive. Il client le esegue il rendering in modo nativo.

L'SDK Python A2UI include un gestore di schemi che genera prompt di sistema per te. Insegna all'LLM l'intero catalogo di componenti A2UI, i nomi e i tipi di proprietà corretti e la struttura JSON.

Aggiorna l'agente

Sostituisci i contenuti di a2ui_agent/agent.py con i seguenti:

from google.adk.agents import Agent
from a2ui.schema.manager import A2uiSchemaManager
from a2ui.basic_catalog.provider import BasicCatalog
from .resources import get_resources

schema_manager = A2uiSchemaManager(
    version="0.8",
    catalogs=[BasicCatalog.get_config("0.8")],
)

instruction = schema_manager.generate_system_prompt(
    role_description=(
        "You are a cloud infrastructure assistant. When users ask about "
        "their cloud resources, use the get_resources tool to fetch the "
        "current state."
    ),
    workflow_description=(
        "Analyze the user's request and return structured UI when appropriate."
    ),
    ui_description=(
        "Use cards for resource summaries, rows and columns for comparisons, "
        "icons for status indicators, and buttons for drill-down actions. "
        "Do NOT use markdown formatting in text values. Use the usageHint "
        "property for heading levels instead. "
        "Respond ONLY with the A2UI JSON array. Do NOT include any text "
        "outside the JSON. Put all explanations into Text components."
    ),
    include_schema=True,
    include_examples=True,
)

root_agent = Agent(
    model="gemini-3-flash-preview",
    name="cloud_dashboard",
    description="A cloud infrastructure assistant that renders rich A2UI interfaces.",
    instruction=instruction,
    tools=[get_resources],
)

Il metodo generate_system_prompt() combina la descrizione del ruolo con lo schema JSON A2UI completo e alcuni esempi, in modo che l'LLM sappia esattamente come formattare l'output. Non è necessario scrivere il catalogo dei componenti a mano.

6. Testa l'output JSON

Se l'UI di sviluppo ADK è ancora in esecuzione dalla procedura precedente, dovrebbe ricaricare automaticamente le modifiche apportate all'agente.

Seleziona a2ui_agent, avvia una nuova sessione facendo clic su +Nuova sessione in alto a destra nell'UI di sviluppo ADK, quindi invia lo stesso prompt di prima:

What's running in my project?

Questa volta, l'agente risponde con JSON A2UI anziché testo normale. Nell'output della chat vedrai messaggi strutturati contenenti beginRendering, surfaceUpdate e dataModelUpdate.

ADK A2UI JSON

Il JSON descrive un'UI avanzata con schede, icone e pulsanti, ma adk web la visualizza come testo non elaborato. Nel passaggio successivo, eseguirai il rendering come componenti UI effettivi.

7. Informazioni su A2UI

Esamina il JSON appena generato dall'agente. Noterai che contiene tre tipi di messaggi. Ogni risposta A2UI segue la stessa struttura:

1. beginRendering

Crea una superficie di rendering e assegna un nome al componente principale:

{"beginRendering": {"surfaceId": "default", "root": "main-column"}}

2. surfaceUpdate

Invia l'albero dei componenti come elenco flat con riferimenti ID (non nidificati):

{"surfaceUpdate": {"surfaceId": "default", "components": [
  {"id": "main-column", "component": {"Column": {"children": {"explicitList": ["title", "card1"]}}}},
  {"id": "title", "component": {"Text": {"text": {"literalString": "My Resources"}, "usageHint": "h1"}}},
  {"id": "card1", "component": {"Card": {"child": "card1-content"}}},
  {"id": "card1-content", "component": {"Text": {"text": {"path": "service_name"}}}}
]}}

3. dataModelUpdate

Invia i dati separatamente dalla struttura:

{"dataModelUpdate": {"surfaceId": "default", "contents": [
  {"key": "service_name", "valueString": "auth-service"},
  {"key": "status", "valueString": "healthy"}
]}}

I componenti si legano ai dati utilizzando {"path": "key"}. Puoi aggiornare i dati senza inviare di nuovo l'albero dei componenti.

Le 18 primitive

Categoria

Componenti

Layout

Card, Column, Row, List, Tabs, Divider, Modal

Display

Text, Image, Icon, Video, AudioPlayer

Input

TextField, DateTimeInput, MultipleChoice, CheckBox, Slider

Azione

Button

L'agente compone layout diversi dallo stesso catalogo. Per informazioni dettagliate su ogni primitiva, consulta la guida di riferimento per i componenti. Una visualizzazione di navigazione, una dashboard delle priorità e un modulo di configurazione utilizzano tutte queste 18 primitive. Non sono necessari nuovi componenti frontend.

8. Esegui il rendering dei componenti A2UI

L'agente genera JSON A2UI valido, ma adk web lo visualizza come testo non elaborato. Per eseguirne il rendering come componenti UI effettivi, è necessario un piccolo strumento che converta l'output JSON A2UI dell'agente nel formato previsto dal renderer integrato di adk web.

Crea l'utilità di rendering A2UI

Crea a2ui_agent/a2ui_utils.py con i seguenti contenuti:

import json
import re
from google.genai import types
from google.adk.agents.callback_context import CallbackContext
from google.adk.models.llm_response import LlmResponse

def _wrap_a2ui_part(a2ui_message: dict) -> types.Part:
    """Wrap a single A2UI message for rendering in adk web."""
    datapart_json = json.dumps({
        "kind": "data",
        "metadata": {"mimeType": "application/json+a2ui"},
        "data": a2ui_message,
    })
    blob_data = (
        b"<a2a_datapart_json>"
        + datapart_json.encode("utf-8")
        + b"</a2a_datapart_json>"
    )
    return types.Part(
        inline_data=types.Blob(
            data=blob_data,
            mime_type="text/plain",
        )
    )

def a2ui_callback(
    callback_context: CallbackContext,
    llm_response: LlmResponse,
) -> LlmResponse | None:
    """Convert A2UI JSON in text output to rendered components."""
    if not llm_response.content or not llm_response.content.parts:
        return None
    for part in llm_response.content.parts:
        if not part.text:
            continue
        text = part.text.strip()
        if not text:
            continue
        if not any(k in text for k in ("beginRendering", "surfaceUpdate", "dataModelUpdate")):
            continue
        # Strip markdown fences
        if text.startswith("```"):
            text = text.split("\n", 1)[-1]
            if text.endswith("```"):
                text = text[:-3].strip()
        # Find where JSON starts (skip conversational prefix)
        json_start = None
        for i, ch in enumerate(text):
            if ch in ("[", "{"):
                json_start = i
                break
        if json_start is None:
            continue
        json_text = text[json_start:]
        # raw_decode parses JSON and ignores trailing text
        try:
            parsed, _ = json.JSONDecoder().raw_decode(json_text)
        except json.JSONDecodeError:
            # Handle concatenated JSON objects: {"a":1} {"b":2}
            try:
                fixed = "[" + re.sub(r'\}\s*\{', '},{', json_text) + "]"
                parsed, _ = json.JSONDecoder().raw_decode(fixed)
            except json.JSONDecodeError:
                continue
        if not isinstance(parsed, list):
            parsed = [parsed]
        a2ui_keys = {"beginRendering", "surfaceUpdate", "dataModelUpdate", "deleteSurface"}
        a2ui_messages = [msg for msg in parsed if isinstance(msg, dict) and any(k in msg for k in a2ui_keys)]
        if not a2ui_messages:
            continue
        new_parts = [_wrap_a2ui_part(msg) for msg in a2ui_messages]
        return LlmResponse(
            content=types.Content(role="model", parts=new_parts),
            custom_metadata={"a2a:response": "true"},
        )
    return None

Questa utilità esegue due operazioni:

  1. Estrae il JSON A2UI dall'output di testo dell'agente
  2. Esegue il wrapping di ogni messaggio A2UI nel formato previsto dal renderer A2UI integrato di adk web

Aggiorna l'agente

Sostituisci i contenuti di a2ui_agent/agent.py con i seguenti. L'unica modifica rispetto al passaggio precedente è l'importazione di a2ui_callback e il parametro after_model_callback nell'agente:

from google.adk.agents import Agent
from a2ui.schema.manager import A2uiSchemaManager
from a2ui.basic_catalog.provider import BasicCatalog
from .resources import get_resources
from .a2ui_utils import a2ui_callback

schema_manager = A2uiSchemaManager(
    version="0.8",
    catalogs=[BasicCatalog.get_config("0.8")],
)

instruction = schema_manager.generate_system_prompt(
    role_description=(
        "You are a cloud infrastructure assistant. When users ask about "
        "their cloud resources, use the get_resources tool to fetch the "
        "current state."
    ),
    workflow_description=(
        "Analyze the user's request and return structured UI when appropriate."
    ),
    ui_description=(
        "Use cards for resource summaries, rows and columns for comparisons, "
        "icons for status indicators, and buttons for drill-down actions. "
        "Do NOT use markdown formatting in text values. Use the usageHint "
        "property for heading levels instead. "
        "Respond ONLY with the A2UI JSON array. Do NOT include any text "
        "outside the JSON. Put all explanations into Text components."
    ),
    include_schema=True,
    include_examples=True,
)

root_agent = Agent(
    model="gemini-3-flash-preview",
    name="cloud_dashboard",
    description="A cloud infrastructure assistant that renders rich A2UI interfaces.",
    instruction=instruction,
    tools=[get_resources],
    after_model_callback=a2ui_callback,
)

9. Testa l'UI di cui è stato eseguito il rendering

Se l'UI di sviluppo ADK è ancora in esecuzione dalla procedura precedente, dovrebbe ricaricare automaticamente le modifiche apportate all'agente.

Aggiorna la scheda del browser, seleziona a2ui_agent, quindi avvia una nuova sessione facendo clic su +Nuova sessione in alto a destra nell'UI di sviluppo ADK e invia lo stesso prompt di prima:

What's running in my project?

Questa volta, adk web esegue il rendering dei componenti A2UI come UI effettiva: schede con indicatori di stato, dettagli delle risorse e pulsanti di azione.

Agente ADK A2UI

Prova un prompt diverso per vedere come l'agente compone un'UI diversa dallo stesso insieme di primitive:

Does anything need my attention?

Infine, prova un altro prompt per generare un'UI diversa per eseguire il deployment di un nuovo servizio:

I need to deploy a new service

Ogni prompt va allo stesso agente, allo stesso strumento e alle stesse 18 primitive. Tuttavia, ogni prompt genera un'UI diversa per un intento diverso.

10. Elimina

Per evitare di lasciare in esecuzione i server locali, elimina le risorse:

  • Nel terminale in cui è in esecuzione adk web, premi Ctrl+C per arrestare il server dell'agente.

Se hai creato un progetto specifico per questo codelab, puoi eliminare l'intero progetto:

gcloud projects delete ${GOOGLE_CLOUD_PROJECT}

11. Complimenti

Hai creato un agente ADK che genera UI interattive e avanzate utilizzando A2UI.

Che cosa hai imparato

  • A2UI è un protocollo con 18 primitive dichiarative e 3 tipi di messaggi
  • L'SDK A2UI genera prompt di sistema che insegnano all'LLM il catalogo dei componenti
  • Lo stesso agente, lo stesso strumento e le stesse primitive compongono UI diverse per intenti diversi
  • I componenti A2UI possono essere sottoposti a rendering direttamente in adk web durante lo sviluppo

Crea un frontend di produzione

In questo codelab, hai eseguito il rendering di A2UI all'interno di adk web per lo sviluppo e i test.

Per la produzione, devi creare un frontend utilizzando uno dei renderer A2UI ufficiali:

Piattaforma

Renderer

Installa

Web (React)

@a2ui/react

npm install @a2ui/react

Web (Lit)

@a2ui/lit

npm install @a2ui/lit

Web (Angular)

@a2ui/angular

npm install @a2ui/angular

Mobile/Desktop

SDK Flutter GenUI

Come iniziare

Documenti di riferimento