Experiencias de frontend con ADK y A2UI

1. Descripción general

La mayoría de las apps del agente devuelven texto sin formato. A2UI cambia eso. Es un protocolo con 18 primitivas de IU declarativas que permiten que tu agente cree interfaces interactivas y enriquecidas. El cliente los renderiza de forma nativa. No se necesita código de frontend nuevo por diseño.

En este codelab, se usa el Kit de desarrollo de agentes (ADK) para compilar el agente y A2UI para generar la IU.

Qué compilarás

Un panel simulado de infraestructura de nube en tres etapas:

  1. Un agente estándar que devuelve datos de recursos como texto sin formato
  2. Un agente de A2UI que devuelve los mismos datos que el JSON estructurado de A2UI
  3. Un agente renderizado que muestra el JSON de la A2UI como componentes interactivos de la IU en la IU de desarrollo del ADK

Agente de A2UI del ADK

Qué aprenderás

  • Cómo funciona A2UI: 18 primitivas, 3 tipos de mensajes, modelo de componentes plano
  • Cómo usar el SDK de A2UI para solicitar a un agente del ADK que genere JSON de A2UI
  • Cómo renderizar componentes de A2UI en adk web

Requisitos

  • Un proyecto de Google Cloud con la facturación habilitada.
  • Un navegador web, como Chrome
  • Python 3.12 o versiones posteriores

Este codelab es para desarrolladores intermedios que tienen cierta familiaridad con Python y Google Cloud.

Este codelab tarda entre 15 y 20 minutos en completarse.

Los recursos creados en este codelab deberían costar menos de USD 5.

2. Configura tu entorno

Crea un proyecto de Google Cloud

  1. En la consola de Google Cloud, en la página del selector de proyectos, selecciona o crea un proyecto de Google Cloud.
  2. Asegúrate de que la facturación esté habilitada para tu proyecto de Cloud. Obtén información para verificar si la facturación está habilitada en un proyecto.

Inicia el editor de Cloud Shell

Para iniciar una sesión de Cloud Shell desde la consola de Google Cloud, haz clic en Activar Cloud Shell en la consola de Google Cloud.

Esto inicia una sesión en el panel inferior de la consola de Google Cloud.

Para iniciar el editor, haz clic en Abrir editor en la barra de herramientas de la ventana de Cloud Shell.

Configura las variables de entorno

En la barra de herramientas del editor de Cloud Shell, haz clic en Terminal y Nueva terminal. Luego, ejecuta los siguientes comandos para configurar tu proyecto y ubicación, y configurar el ADK para usar Gemini en Vertex AI.

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

Habilitar APIs

En la terminal, ejecuta el siguiente comando para habilitar las APIs requeridas:

gcloud services enable aiplatform.googleapis.com

Instala dependencias

En la terminal, ejecuta el siguiente comando para instalar la versión más reciente del Kit de desarrollo de agentes (ADK):

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

3. Compila el agente

Comienza con un agente estándar del ADK que devuelva texto sin formato. Así se ven la mayoría de las apps de agentes hoy en día.

Crea la carpeta del agente

Crea una carpeta llamada a2ui_agent que contendrá el código fuente de tu agente y tus herramientas.

Define la herramienta y los datos simulados

Crea a2ui_agent/resources.py con el siguiente contenido. Esta herramienta muestra una lista de los recursos de la nube con su estado.

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

Define el agente

Crea a2ui_agent/agent.py con el siguiente contenido:

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. Prueba el agente

El ADK incluye una IU de desarrollo que puedes usar para interactuar con tu agente y enviarle instrucciones en un navegador para realizar pruebas.

Inicia la IU de desarrollo del ADK

En la terminal del Editor de Cloud Shell, ejecuta el siguiente comando para iniciar la IU de desarrollo del ADK:

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

Deberías ver un mensaje similar al siguiente:

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

Abre la IU de desarrollo del ADK

Para abrir la IU de desarrollo del ADK en tu navegador, haz clic con Ctrl o Cmd en la URL de prueba local, o bien haz clic en el botón Vista previa en la Web y selecciona Vista previa en el puerto 8080.

Una vez que veas la IU para desarrolladores del ADK, selecciona a2ui_agent en el menú desplegable.

Envía instrucciones de ejemplo

Envía una instrucción de muestra al agente:

What's running in my project?

Ahora prueba con otra instrucción de ejemplo y obtendrás más texto como resultado:

Does anything need my attention?

Tu conversación debería ser similar a la siguiente:

Agente de texto del ADK

Verás una gran cantidad de texto. Es precisa, pero no ofrece una buena experiencia del usuario.

5. Genera JSON de A2UI

¿Qué pasaría si el agente pudiera describir una IU en lugar de volcar texto? A2UI es un protocolo que permite a los agentes componer interfaces interactivas a partir de un catálogo de 18 elementos primitivos. El cliente los renderiza de forma nativa.

El SDK de Python de A2UI incluye un administrador de esquemas que genera instrucciones del sistema para ti. Le enseña al LLM el catálogo completo de componentes de A2UI, los nombres y tipos de propiedades correctos, y la estructura JSON.

Actualiza el agente

Reemplaza el contenido de a2ui_agent/agent.py por lo siguiente:

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],
)

El método generate_system_prompt() combina la descripción de tu rol con el esquema JSON completo de A2UI y algunos ejemplos, por lo que el LLM sabe exactamente cómo dar formato a su resultado. No es necesario que escribas el catálogo de componentes de forma manual.

6. Prueba la salida de JSON

Si aún tienes en ejecución la IU para desarrolladores del ADK, debería volver a cargar automáticamente los cambios que realizaste en tu agente.

Selecciona a2ui_agent, inicia una nueva sesión haciendo clic en + Nueva sesión en la parte superior derecha de la IU de desarrollo del ADK y, luego, envía la misma instrucción que antes:

What's running in my project?

Esta vez, el agente responde con JSON de A2UI en lugar de texto sin formato. Verás mensajes estructurados que contienen beginRendering, surfaceUpdate y dataModelUpdate en el resultado del chat.

JSON de A2UI del ADK

El JSON describe una IU enriquecida con tarjetas, íconos y botones, pero adk web la muestra como texto sin formato. En el siguiente paso, harás que se renderice como componentes de IU reales.

7. Información sobre A2UI

Observa el código JSON que acaba de generar tu agente. Notarás que contiene tres tipos de mensajes. Todas las respuestas de la A2UI siguen la misma estructura:

1. beginRendering

Crea una superficie de renderización y nombra el componente raíz:

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

2. surfaceUpdate

Envía el árbol de componentes como una lista plana con referencias de ID (no anidadas):

{"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

Envía los datos por separado de la estructura:

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

Los componentes se vinculan a los datos con {"path": "key"}. Puedes actualizar los datos sin volver a enviar el árbol de componentes.

Las 18 primitivas

Categoría

Componentes

Diseño

Tarjeta, columna, fila, lista, pestañas, divisor, modal

Pantalla

Texto, imagen, ícono, video y reproductor de audio

Entrada

TextField, DateTimeInput, MultipleChoice, CheckBox, Slider

Acción

Botón

El agente compone diferentes diseños a partir del mismo catálogo. Consulta la referencia de componentes para obtener todos los detalles sobre cada elemento primitivo. Una vista de exploración, un panel de prioridad y un formulario de configuración usan estas mismas 18 primitivas. No se necesitan componentes nuevos de frontend.

8. Renderiza componentes de A2UI

El agente genera JSON de A2UI válido, pero adk web lo muestra como texto sin procesar. Para renderizarlo como componentes de IU reales, necesitas una pequeña utilidad que convierta el resultado JSON de A2UI del agente al formato que espera el renderizador integrado de adk web.

Crea la utilidad de renderización de A2UI

Crea a2ui_agent/a2ui_utils.py con el siguiente contenido:

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

Esta utilidad realiza dos acciones:

  1. Extrae el JSON de A2UI del resultado de texto del agente.
  2. Encapsula cada mensaje de A2UI en el formato que espera el renderizador de A2UI integrado de adk web.

Actualiza el agente

Reemplaza el contenido de a2ui_agent/agent.py con lo siguiente. El único cambio con respecto al paso anterior es la importación de a2ui_callback y el parámetro after_model_callback en el 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. Prueba la IU renderizada

Si aún tienes en ejecución la IU para desarrolladores del ADK, debería volver a cargar automáticamente los cambios que realizaste en tu agente.

Actualiza la pestaña del navegador, selecciona a2ui_agent y, luego, inicia una nueva sesión haciendo clic en + Nueva sesión en la parte superior derecha de la IU de desarrollo del ADK y envía la misma instrucción que antes:

What's running in my project?

Esta vez, adk web renderiza los componentes de A2UI como una IU real: tarjetas con indicadores de estado, detalles de recursos y botones de acción.

Agente de A2UI del ADK

Prueba con otra instrucción para ver cómo el agente compone una IU diferente a partir del mismo conjunto de elementos básicos:

Does anything need my attention?

Por último, prueba con otra instrucción para generar una IU diferente para implementar un servicio nuevo:

I need to deploy a new service

Cada instrucción se envía al mismo agente, a la misma herramienta y a las mismas 18 instrucciones primitivas. Sin embargo, cada instrucción genera una IU diferente para una intención diferente.

10. Limpieza

Para evitar que los servidores locales sigan en ejecución, limpia los recursos:

  • En la terminal que ejecuta adk web, presiona Ctrl + C para detener el servidor del agente.

Si creaste un proyecto específicamente para este codelab, puedes borrarlo por completo:

gcloud projects delete ${GOOGLE_CLOUD_PROJECT}

11. Felicitaciones

Creaste un agente del ADK que genera una IU interactiva y enriquecida con A2UI.

Qué aprendiste

  • A2UI es un protocolo con 18 elementos primitivos declarativos y 3 tipos de mensajes.
  • El SDK de A2UI genera instrucciones del sistema que le enseñan al LLM el catálogo de componentes.
  • El mismo agente, la misma herramienta y las mismas primitivas componen diferentes IU para diferentes intents
  • Los componentes de A2UI se pueden renderizar directamente en adk web durante el desarrollo.

Compila un frontend de producción

En este codelab, renderizaste A2UI dentro de adk web para el desarrollo y las pruebas.

Para la producción, compilarías un frontend con uno de los renderizadores oficiales de A2UI:

Plataforma

Procesador

Instalar

Web (React)

@a2ui/react

npm install @a2ui/react

Web (Lit)

@a2ui/lit

npm install @a2ui/lit

Web (Angular)

@a2ui/angular

npm install @a2ui/angular

Dispositivos móviles y computadoras

SDK de GenUI de Flutter

Primeros pasos

Documentos de referencia