Esperienze frontend con ADK e A2UI

1. Panoramica

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

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

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 del JSON A2UI strutturato
  3. Un agente di rendering che mostra il JSON A2UI come componenti UI interattivi nell'interfaccia utente di sviluppo dell'ADK

Agente ADK A2UI

Obiettivi didattici

  • Come funziona A2UI: 18 primitive, 3 tipi di messaggi, modello di componenti piatto
  • Come utilizzare l'SDK A2UI per chiedere 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+

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 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 sulla 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 questi comandi per impostare il progetto, la località e configurare ADK in modo da utilizzare 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 questo comando per abilitare le API richieste:

gcloud services enable aiplatform.googleapis.com

Installa le dipendenze

Nel terminale, esegui questo comando per installare l'ultima versione dell'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 presenta la maggior parte delle app per agenti oggi.

Crea 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 il seguente contenuto. 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 il seguente contenuto:

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. Testare l'agente

L'ADK include una UI per sviluppatori che puoi utilizzare per interagire con il tuo agente e inviargli prompt in un browser per i test.

Avvia l'interfaccia utente di sviluppo ADK

Nel terminale dell'editor di Cloud Shell, esegui questo comando per avviare l'interfaccia utente di sviluppo dell'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 la UI di sviluppo di ADK

Puoi aprire l'interfaccia utente per sviluppatori dell'ADK nel browser facendo clic con 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'interfaccia utente di sviluppo dell'ADK, seleziona a2ui_agent dal menu a discesa.

Inviare 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

Vedrai un blocco di testo. Accurate, ma non offrono un'esperienza utente ottimale.

5. Generare JSON A2UI

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

L'SDK Python A2UI include un gestore di schemi che genera prompt di sistema per te. Insegna all'LLM il catalogo completo dei 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 come segue:

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 few-shot, in modo che l'LLM sappia esattamente come formattare l'output. Non è necessario scrivere manualmente il catalogo dei componenti.

6. Testare l'output JSON

Se l'interfaccia utente di sviluppo dell'ADK è ancora in esecuzione, 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'interfaccia utente per sviluppatori dell'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 file JSON descrive una UI avanzata con schede, icone e pulsanti, ma adk web lo visualizza come testo non formattato. Nel passaggio successivo, lo visualizzerai 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 radice:

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

2. surfaceUpdate

Invia l'albero dei componenti come un elenco piatto 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 vengono associati ai dati utilizzando {"path": "key"}. Puoi aggiornare i dati senza inviare nuovamente l'albero dei componenti.

Le 18 primitive

Categoria

Componenti

Layout

Scheda, Colonna, Riga, Elenco, Schede, Divisore, Modale

Display

Testo, immagine, icona, video, AudioPlayer

Ingresso

TextField, DateTimeInput, MultipleChoice, CheckBox, Slider

Azione

Pulsante

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

8. Esegui il rendering dei componenti A2UI

L'agente genera un JSON A2UI valido, ma adk web lo visualizza come testo non elaborato. Per eseguirne il rendering come componenti UI effettivi, è necessaria una piccola utilità 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 il seguente contenuto:

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à svolge due funzioni:

  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 quanto segue. L'unica modifica rispetto al passaggio precedente è l'importazione di a2ui_callback e del 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 la UI con rendering effettuato

Se l'interfaccia utente di sviluppo dell'ADK è ancora in esecuzione, 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'interfaccia utente di sviluppo dell'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 una UI diversa dallo stesso insieme di primitive:

Does anything need my attention?

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

I need to deploy a new service

Ogni prompt viene inviato allo stesso agente, allo stesso strumento e alle stesse 18 primitive. Tuttavia, ogni prompt genera un'interfaccia utente diversa per un intento diverso.

10. Elimina

Per evitare di lasciare in esecuzione i server locali, libera spazio nelle 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 eliminarlo completamente:

gcloud projects delete ${GOOGLE_CLOUD_PROJECT}

11. Complimenti

Hai creato un agente ADK che genera un'interfaccia utente interattiva e avanzata 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, strumento e primitive compongono UI diverse per intent diversi
  • I componenti A2UI possono essere visualizzati 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 il 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

Dispositivi mobili/computer

SDK Flutter GenUI

Come iniziare

Documenti di riferimento