Pengalaman Frontend dengan ADK dan A2UI

1. Ringkasan

Sebagian besar aplikasi agen menampilkan teks biasa. A2UI mengubah hal tersebut. Ini adalah protokol dengan 18 primitif UI deklaratif yang memungkinkan agen Anda menyusun antarmuka interaktif yang kaya. Klien merendernya secara native. Tidak ada kode frontend baru yang diperlukan per tata letak.

Codelab ini menggunakan Agent Development Kit (ADK) untuk membangun agen dan A2UI untuk membuat UI.

Yang akan Anda build

Dasbor infrastruktur cloud dalam tiga tahap:

  1. Agen standar yang menampilkan data resource sebagai teks biasa
  2. Agen A2UI yang menampilkan data yang sama dengan JSON A2UI terstruktur
  3. Agen yang dirender yang menampilkan JSON A2UI sebagai komponen UI interaktif di UI pengembangan ADK

Agen A2UI ADK

Yang akan Anda pelajari

  • Cara kerja A2UI: 18 primitif, 3 jenis pesan, model komponen datar
  • Cara menggunakan A2UI SDK untuk meminta agen ADK membuat JSON A2UI
  • Cara merender komponen A2UI di adk web

Yang Anda butuhkan

  • Project Google Cloud yang mengaktifkan penagihan
  • Browser web seperti Chrome
  • Python 3.12+

Codelab ini ditujukan bagi developer tingkat menengah yang sudah memahami Python dan Google Cloud.

Codelab ini membutuhkan waktu sekitar 15-20 menit untuk diselesaikan.

Resource yang dibuat dalam codelab ini seharusnya berbiaya kurang dari $5.

2. Menyiapkan lingkungan Anda

Buat Project Google Cloud

  1. Di Konsol Google Cloud, di halaman pemilih project, pilih atau buat project Google Cloud.
  2. Pastikan penagihan diaktifkan untuk project Cloud Anda. Pelajari cara memeriksa apakah penagihan telah diaktifkan pada suatu project.

Mulai Cloud Shell Editor

Untuk meluncurkan sesi Cloud Shell dari konsol Google Cloud, klik Activate Cloud Shell di konsol Google Cloud Anda.

Tindakan ini akan meluncurkan sesi di panel bawah konsol Google Cloud.

Untuk meluncurkan editor, klik Open Editor di toolbar jendela Cloud Shell.

Menetapkan variabel lingkungan

Di toolbar Cloud Shell Editor, klik Terminal dan New Terminal, lalu jalankan perintah berikut untuk menyetel project, lokasi, dan mengonfigurasi ADK agar menggunakan Gemini di Vertex AI.

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

Mengaktifkan API

Di terminal, jalankan perintah berikut untuk mengaktifkan API yang diperlukan:

gcloud services enable aiplatform.googleapis.com

Menginstal dependensi

Di terminal, jalankan perintah berikut untuk menginstal Agent Development Kit (ADK) versi terbaru:

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

3. Membangun agen

Mulai dengan agen ADK standar yang menampilkan teks biasa. Seperti inilah tampilan sebagian besar aplikasi agen saat ini.

Buat folder agen

Buat folder bernama a2ui_agent yang akan berisi kode sumber untuk agen dan alat Anda.

Menentukan alat dan data tiruan

Buat a2ui_agent/resources.py dengan konten berikut. Alat ini menampilkan daftar resource cloud beserta statusnya.

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

Menentukan agen

Buat a2ui_agent/agent.py dengan konten berikut:

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. Menguji agen

ADK menyertakan UI dev yang dapat Anda gunakan untuk berinteraksi dengan dan mengirim perintah ke agen Anda di browser untuk pengujian.

Mulai UI dev ADK

Di terminal Cloud Shell Editor, jalankan perintah berikut untuk memulai UI dev ADK:

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

Anda akan melihat pesan yang mirip dengan berikut ini:

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

Membuka UI dev ADK

Anda dapat membuka UI dev ADK di browser dengan mengklik Ctrl atau Cmd pada URL pengujian lokal, atau dengan mengklik tombol Web Preview dan memilih Preview on Port 8080.

Setelah Anda melihat UI dev ADK, pilih a2ui_agent dari menu drop-down.

Mengirim contoh perintah

Kirim perintah contoh ke agen:

What's running in my project?

Sekarang coba perintah contoh lain dan Anda akan mendapatkan lebih banyak output teks:

Does anything need my attention?

Percakapan Anda akan terlihat seperti berikut:

Agen Teks ADK

Anda akan melihat teks yang sangat panjang. Akurat, tetapi bukan pengalaman pengguna yang baik.

5. Membuat JSON A2UI

Bagaimana jika agen dapat mendeskripsikan UI, bukan membuang teks? A2UI adalah protokol yang memungkinkan agen menyusun antarmuka interaktif dari katalog 18 elemen dasar. Klien merendernya secara native.

A2UI Python SDK menyertakan pengelola skema yang membuat perintah sistem untuk Anda. Hal ini mengajarkan katalog komponen A2UI lengkap, nama dan jenis properti yang benar, serta struktur JSON kepada LLM.

Memperbarui agen

Ganti konten a2ui_agent/agent.py dengan konten berikut:

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

Metode generate_system_prompt() menggabungkan deskripsi peran Anda dengan skema JSON A2UI lengkap dan contoh few-shot, sehingga LLM mengetahui persis cara memformat outputnya. Anda tidak perlu menulis katalog komponen secara manual.

6. Menguji output JSON

Jika Anda masih menjalankan UI dev ADK dari sebelumnya, UI tersebut akan otomatis memuat ulang perubahan yang Anda lakukan pada agen.

Pilih a2ui_agent, mulai sesi baru dengan mengklik +New Session di kanan atas UI dev ADK, lalu kirim perintah yang sama seperti sebelumnya:

What's running in my project?

Kali ini, agen merespons dengan JSON A2UI, bukan teks biasa. Anda akan melihat pesan terstruktur yang berisi beginRendering, surfaceUpdate, dan dataModelUpdate di output chat.

JSON A2UI ADK

JSON menjelaskan UI lengkap dengan kartu, ikon, dan tombol, tetapi adk web menampilkannya sebagai teks mentah. Pada langkah berikutnya, Anda akan membuatnya dirender sebagai komponen UI yang sebenarnya.

7. Memahami A2UI

Lihat JSON yang baru saja dihasilkan agen Anda. Anda akan melihat bahwa pesan ini berisi tiga jenis pesan. Setiap respons A2UI mengikuti struktur yang sama:

1. beginRendering

Membuat platform rendering dan memberi nama komponen root:

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

2. surfaceUpdate

Mengirimkan hierarki komponen sebagai daftar datar dengan referensi ID (tidak bertingkat):

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

Mengirim data secara terpisah dari struktur:

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

Komponen terikat ke data menggunakan {"path": "key"}. Anda dapat memperbarui data tanpa mengirim ulang hierarki komponen.

18 primitif

Kategori

Komponen

Tata letak

Kartu, Kolom, Baris, Daftar, Tab, Pemisah, Modal

Display

Teks, Gambar, Ikon, Video, AudioPlayer

Input

TextField, DateTimeInput, MultipleChoice, CheckBox, Slider

Tindakan

Tombol

Agen menyusun tata letak yang berbeda dari katalog yang sama. Lihat referensi komponen untuk mengetahui detail lengkap tentang setiap elemen dasar. Tampilan penjelajahan, dasbor prioritas, dan formulir konfigurasi semuanya menggunakan 18 elemen dasar yang sama ini. Tidak ada komponen frontend baru yang diperlukan.

8. Merender komponen A2UI

Agen menghasilkan JSON A2UI yang valid, tetapi adk web menampilkannya sebagai teks mentah. Untuk merendernya sebagai komponen UI sebenarnya, Anda memerlukan utilitas kecil yang mengonversi output JSON A2UI agen ke dalam format yang diharapkan oleh perender bawaan adk web.

Membuat utilitas rendering A2UI

Buat a2ui_agent/a2ui_utils.py dengan konten berikut:

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

Utilitas ini melakukan dua hal:

  1. Mengekstrak JSON A2UI dari output teks agen
  2. Membungkus setiap pesan A2UI dalam format yang diharapkan oleh perender A2UI bawaan adk web

Memperbarui agen

Ganti konten a2ui_agent/agent.py dengan konten berikut. Satu-satunya perubahan dari langkah sebelumnya adalah impor a2ui_callback dan parameter after_model_callback pada agen:

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. Menguji UI yang dirender

Jika Anda masih menjalankan UI dev ADK dari sebelumnya, UI tersebut akan otomatis memuat ulang perubahan yang Anda lakukan pada agen.

Muat ulang tab browser, pilih a2ui_agent, lalu mulai sesi baru dengan mengklik +New Session di kanan atas UI dev ADK dan kirim perintah yang sama seperti sebelumnya:

What's running in my project?

Kali ini, adk web merender komponen A2UI sebagai UI sebenarnya: kartu dengan indikator status, detail resource, dan tombol tindakan.

Agen A2UI ADK

Coba perintah yang berbeda untuk melihat cara agen menyusun UI yang berbeda dari kumpulan primitif yang sama:

Does anything need my attention?

Terakhir, coba perintah lain untuk menghasilkan UI yang berbeda guna men-deploy layanan baru:

I need to deploy a new service

Setiap perintah ditujukan ke agen, alat, dan 18 primitif yang sama. Namun, setiap perintah menghasilkan UI yang berbeda untuk maksud yang berbeda.

10. Pembersihan

Untuk menghindari server lokal tetap berjalan, bersihkan resource:

  • Di terminal yang menjalankan adk web, tekan Ctrl+C untuk menghentikan server agen.

Jika Anda membuat project khusus untuk codelab ini, Anda dapat menghapus seluruh project tersebut:

gcloud projects delete ${GOOGLE_CLOUD_PROJECT}

11. Selamat

Anda telah membuat agen ADK yang menghasilkan UI interaktif yang kaya menggunakan A2UI.

Yang telah Anda pelajari

  • A2UI adalah protokol dengan 18 primitif deklaratif dan 3 jenis pesan
  • A2UI SDK menghasilkan perintah sistem yang mengajarkan katalog komponen LLM
  • Agen, alat, dan elemen dasar yang sama menyusun UI yang berbeda untuk maksud yang berbeda
  • Komponen A2UI dapat dirender langsung di adk web selama pengembangan

Membangun frontend produksi

Dalam codelab ini, Anda merender A2UI di dalam adk web untuk pengembangan dan pengujian.

Untuk produksi, Anda akan membuat frontend menggunakan salah satu perender A2UI resmi:

Platform

Perender

Instal

Web (React)

@a2ui/react

npm install @a2ui/react

Web (Lit)

@a2ui/lit

npm install @a2ui/lit

Web (Angular)

@a2ui/angular

npm install @a2ui/angular

Seluler/Desktop

Flutter GenUI SDK

Memulai

Dokumen referensi