Experiências de front-end com ADK e A2UI

1. Visão geral

A maioria dos apps de agente retorna texto simples. O A2UI muda isso. É um protocolo com 18 primitivos de interface declarativa que permite ao agente criar interfaces interativas e avançadas. O cliente os renderiza de forma nativa. Não é necessário um novo código de front-end por layout.

Este codelab usa o Kit de Desenvolvimento de Agente (ADK) para criar o agente e o A2UI para gerar a interface.

O que você vai criar

Um painel de infraestrutura em nuvem em três estágios:

  1. Um agente padrão que retorna dados de recursos como texto simples
  2. Um agente A2UI que retorna os mesmos dados que o JSON A2UI estruturado
  3. Um agente renderizado que mostra o JSON da A2UI como componentes interativos da interface na interface de desenvolvimento do ADK.

Agente A2UI do ADK

O que você vai aprender

  • Como a A2UI funciona: 18 primitivas, 3 tipos de mensagens, modelo de componente simples
  • Como usar o SDK A2UI para solicitar que um agente do ADK gere JSON A2UI
  • Como renderizar componentes A2UI em adk web

O que é necessário

  • Tenha um projeto do Google Cloud com o faturamento ativado.
  • Um navegador da web, como o Chrome
  • Python 3.12 ou mais recente

Este codelab é destinado a desenvolvedores intermediários que têm alguma familiaridade com Python e Google Cloud.

Este codelab leva aproximadamente de 15 a 20 minutos para ser concluído.

Os recursos criados neste codelab custam menos de US $5.

2. Configurar o ambiente

Criar um projeto do Google Cloud

  1. No console do Google Cloud, na página do seletor de projetos, selecione ou crie um projeto na nuvem do Google Cloud.
  2. Verifique se o faturamento está ativado para seu projeto do Cloud. Saiba como verificar se o faturamento está ativado em um projeto.

Iniciar o editor do Cloud Shell

Para iniciar uma sessão do Cloud Shell no console do Google Cloud, clique em Ativar o Cloud Shell no console do Google Cloud.

Isso inicia uma sessão no painel inferior do console do Google Cloud.

Para iniciar o editor, clique em Abrir editor na barra de ferramentas da janela do Cloud Shell.

Defina as variáveis de ambiente

Na barra de ferramentas do editor do Cloud Shell, clique em Terminal e Novo terminal. Em seguida, execute os comandos a seguir para definir o projeto e o local e configurar o ADK para usar o Gemini na Vertex AI.

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

Ativar APIs

No terminal, execute o seguinte comando para ativar as APIs necessárias:

gcloud services enable aiplatform.googleapis.com

Instalar dependências

No terminal, execute o comando a seguir para instalar a versão mais recente do Kit de Desenvolvimento de Agente (ADK):

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

3. Criar o agente

Comece com um agente ADK padrão que retorna texto simples. É assim que a maioria dos apps de agente se parece hoje.

Criar pasta do agente

Crie uma pasta chamada a2ui_agent que vai conter o código-fonte do seu agente e das ferramentas.

Definir ferramenta e dados simulados

Crie a2ui_agent/resources.py com o conteúdo a seguir. Essa ferramenta retorna uma lista de recursos da nuvem com o status deles.

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

Definir o agente

Crie a2ui_agent/agent.py com o conteúdo abaixo:

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. Testar o agente

O ADK inclui uma interface de desenvolvimento que pode ser usada para interagir e enviar comandos ao agente em um navegador para teste.

Iniciar a interface de desenvolvimento do ADK

No terminal do editor do Cloud Shell, execute o comando a seguir para iniciar a interface de desenvolvimento do ADK:

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

Você verá uma mensagem semelhante a esta:

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

Abrir a interface de desenvolvimento do ADK

Para abrir a interface de desenvolvimento do ADK no navegador, Ctrl ou Cmd clique no URL de teste local ou clique no botão Visualização na Web e selecione Visualizar na porta 8080.

Na interface de desenvolvimento do ADK, selecione a2ui_agent no menu suspenso.

Enviar exemplos de comandos

Envie um exemplo de comando para o agente:

What's running in my project?

Agora tente outro comando de exemplo para receber mais texto:

Does anything need my attention?

Sua conversa deve ser semelhante a esta:

Agente de texto do ADK

Você vai receber um textão. Preciso, mas não é uma ótima experiência do usuário.

5. Gerar JSON A2UI

E se o agente pudesse descrever uma interface em vez de despejar texto? O A2UI é um protocolo que permite que os agentes criem interfaces interativas com base em um catálogo de 18 primitivas. O cliente os renderiza de forma nativa.

O SDK Python da A2UI inclui um gerenciador de esquemas que gera comandos do sistema para você. Ele ensina ao LLM o catálogo completo de componentes A2UI, os nomes e tipos de propriedades corretos e a estrutura JSON.

Atualizar o agente

Substitua os conteúdos de a2ui_agent/agent.py pelo seguinte:

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

O método generate_system_prompt() combina sua descrição de função com o esquema JSON completo da A2UI e exemplos de poucos disparos para que o LLM saiba exatamente como formatar a saída. Não é necessário escrever o catálogo de componentes manualmente.

6. Testar a saída JSON

Se você ainda tiver a interface de desenvolvimento do ADK em execução, ela vai recarregar automaticamente as mudanças feitas no seu agente.

Selecione a2ui_agent, inicie uma nova sessão clicando em +Nova sessão no canto superior direito da interface de desenvolvimento do ADK e envie o mesmo comando de antes:

What's running in my project?

Desta vez, o agente responde com JSON A2UI em vez de texto simples. Você vai ver mensagens estruturadas com beginRendering, surfaceUpdate e dataModelUpdate na saída do chat.

JSON do ADK A2UI

O JSON descreve uma interface avançada com cards, ícones e botões, mas o adk web mostra como texto bruto. Na próxima etapa, você vai fazer com que ele seja renderizado como componentes reais da interface.

7. Noções básicas sobre o A2UI

Confira o JSON que o agente acabou de gerar. Você vai notar que ele contém três tipos de mensagens. Todas as respostas da A2UI seguem a mesma estrutura:

1. beginRendering

Cria uma superfície de renderização e nomeia o componente raiz:

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

2. surfaceUpdate

Envia a árvore de componentes como uma lista simples com referências de ID (não aninhadas):

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

Envia os dados separadamente da estrutura:

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

Os componentes são vinculados aos dados usando {"path": "key"}. É possível atualizar os dados sem reenviar a árvore de componentes.

Os 18 primitivos

Categoria

Componentes

Layout

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

Display

Texto, imagem, ícone, vídeo, AudioPlayer

Entrada

TextField, DateTimeInput, MultipleChoice, CheckBox, Slider

Ação

Botão

O agente cria layouts diferentes do mesmo catálogo. Consulte a referência de componentes para mais detalhes sobre cada primitiva. Uma visualização de navegação, um painel de prioridade e um formulário de configuração usam essas mesmas 18 primitivas. Não são necessários novos componentes de front-end.

8. Renderizar componentes A2UI

O agente gera um JSON A2UI válido, mas o adk web o mostra como texto bruto. Para renderizar como componentes de interface reais, você precisa de um pequeno utilitário que converta a saída JSON A2UI do agente no formato esperado pelo renderizador integrado do adk web.

Criar o utilitário de renderização A2UI

Crie a2ui_agent/a2ui_utils.py com o conteúdo abaixo:

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

Esse utilitário faz duas coisas:

  1. Extrai o JSON A2UI da saída de texto do agente.
  2. Encapsula cada mensagem A2UI no formato esperado pelo renderizador A2UI integrado do adk web.

Atualizar o agente

Substitua o conteúdo de a2ui_agent/agent.py pelo seguinte: A única mudança em relação à etapa anterior é a importação de a2ui_callback e o parâmetro after_model_callback no 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. Testar a interface renderizada

Se você ainda tiver a interface de desenvolvimento do ADK em execução, ela vai recarregar automaticamente as mudanças feitas no seu agente.

Atualize a guia do navegador, selecione a2ui_agent e inicie uma nova sessão clicando em +Nova sessão no canto superior direito da interface de desenvolvimento do ADK. Envie o mesmo comando de antes:

What's running in my project?

Desta vez, o adk web renderiza os componentes da A2UI como interface real: cards com indicadores de status, detalhes de recursos e botões de ação.

Agente A2UI do ADK

Tente um comando diferente para ver como o agente cria uma interface diferente com o mesmo conjunto de primitivos:

Does anything need my attention?

Por fim, tente outro comando para gerar uma interface diferente e implantar um novo serviço:

I need to deploy a new service

Cada solicitação vai para o mesmo agente, a mesma ferramenta e as mesmas 18 primitivas. Mas cada comando resulta em uma interface diferente para uma intenção diferente.

10. Limpeza

Para evitar deixar servidores locais em execução, limpe os recursos:

  • No terminal que executa adk web, pressione Ctrl+C para interromper o servidor do agente.

Se você criou um projeto especificamente para este codelab, é possível excluir todo o projeto:

gcloud projects delete ${GOOGLE_CLOUD_PROJECT}

11. Parabéns

Você criou um agente do ADK que gera uma interface interativa e avançada usando o A2UI.

O que você aprendeu

  • O A2UI é um protocolo com 18 primitivos declarativos e 3 tipos de mensagens.
  • O SDK A2UI gera comandos do sistema que ensinam ao LLM o catálogo de componentes.
  • O mesmo agente, ferramenta e primitivos compõem diferentes interfaces para diferentes intents
  • Os componentes do A2UI podem ser renderizados diretamente em adk web durante o desenvolvimento.

Criar um front-end de produção

Neste codelab, você renderizou a A2UI dentro de adk web para desenvolvimento e testes.

Para produção, crie um front-end usando um dos renderizadores oficiais da A2UI:

Plataforma

Renderizador

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

Dispositivo móvel/computador

SDK GenUI do Flutter

Primeiros passos

Documentos de referência