تجربیات فرانت‌اند با ADK و A2UI

۱. مرور کلی

اکثر برنامه‌های عامل، متن ساده را برمی‌گردانند. A2UI این را تغییر می‌دهد. این یک پروتکل با ۱۸ عنصر رابط کاربری اعلانی است که به عامل شما اجازه می‌دهد رابط‌های غنی و تعاملی ایجاد کند. کلاینت آنها را به صورت بومی رندر می‌کند. برای هر طرح‌بندی، به کد frontend جدیدی نیاز نیست.

این آزمایشگاه کد از کیت توسعه عامل (ADK) برای ساخت عامل و از A2UI برای تولید رابط کاربری استفاده می‌کند.

آنچه خواهید ساخت

داشبورد زیرساخت ابری در سه مرحله:

  1. یک عامل استاندارد که داده‌های منابع را به صورت متن ساده برمی‌گرداند
  2. یک عامل A2UI که همان داده‌های A2UI JSON ساختاریافته را برمی‌گرداند.
  3. یک عامل رندر شده که A2UI JSON را به عنوان اجزای رابط کاربری تعاملی در رابط کاربری توسعه‌یافته ADK نمایش می‌دهد.

عامل ADK A2UI

آنچه یاد خواهید گرفت

  • نحوه کار A2UI: ۱۸ عنصر اولیه، ۳ نوع پیام، مدل کامپوننت مسطح
  • نحوه استفاده از A2UI SDK برای وادار کردن یک عامل ADK به تولید A2UI JSON
  • نحوه رندر کردن کامپوننت‌های A2UI در adk web

آنچه نیاز دارید

  • یک پروژه گوگل کلود با قابلیت پرداخت صورتحساب
  • یک مرورگر وب مانند کروم
  • پایتون ۳.۱۲+

این آزمایشگاه کد برای توسعه‌دهندگان سطح متوسط ​​است که با پایتون و گوگل کلود آشنایی دارند.

تکمیل این آزمایشگاه کد تقریباً ۱۵ تا ۲۰ دقیقه طول می‌کشد.

منابع ایجاد شده در این آزمایشگاه کد باید کمتر از ۵ دلار هزینه داشته باشند.

۲. محیط خود را آماده کنید

ایجاد یک پروژه ابری گوگل

  1. در کنسول گوگل کلود ، در صفحه انتخاب پروژه، یک پروژه گوگل کلود را انتخاب یا ایجاد کنید .
  2. مطمئن شوید که صورتحساب برای پروژه ابری شما فعال است. یاد بگیرید که چگونه بررسی کنید که آیا صورتحساب در یک پروژه فعال است یا خیر .

ویرایشگر Cloud Shell را شروع کنید

برای راه‌اندازی یک جلسه Cloud Shell از کنسول Google Cloud، روی Activate Cloud Shell در کنسول Google Cloud خود کلیک کنید.

این یک جلسه در پنل پایین کنسول Google Cloud شما راه‌اندازی می‌کند.

برای اجرای ویرایشگر، روی گزینه Open Editor در نوار ابزار پنجره Cloud Shell کلیک کنید.

تنظیم متغیرهای محیطی

در نوار ابزار Cloud Shell Editor، روی Terminal و New Terminal کلیک کنید، سپس دستورات زیر را برای تنظیم پروژه، مکان و پیکربندی ADK برای استفاده از Gemini در Vertex AI اجرا کنید.

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

فعال کردن APIها

در ترمینال، دستور زیر را برای فعال کردن API های مورد نیاز اجرا کنید:

gcloud services enable aiplatform.googleapis.com

نصب وابستگی‌ها

در ترمینال، دستور زیر را برای نصب آخرین نسخه Agent Development Kit (ADK) اجرا کنید:

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

۳. عامل را بسازید

با یک عامل ADK استاندارد که متن ساده را برمی‌گرداند شروع کنید. این چیزی است که اکثر برنامه‌های عامل امروزی به آن شبیه هستند.

ایجاد پوشه عامل

پوشه‌ای به نام a2ui_agent ایجاد کنید که شامل کد منبع برای عامل و ابزارهای شما باشد.

تعریف ابزار و داده‌های شبیه‌سازی‌شده

a2ui_agent/resources.py را با محتوای زیر ایجاد کنید. این ابزار فهرستی از منابع ابری به همراه وضعیت آنها را برمی‌گرداند.

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

عامل را تعریف کنید

a2ui_agent/agent.py را با محتوای زیر ایجاد کنید:

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

۴. عامل را آزمایش کنید

ADK شامل یک رابط کاربری توسعه‌دهنده است که می‌توانید از آن برای تعامل و ارسال پیام به عامل خود در مرورگر برای آزمایش استفاده کنید.

رابط کاربری ADK dev را شروع کنید

در ترمینال ویرایشگر Cloud Shell خود، دستور زیر را برای شروع رابط کاربری ADK dev اجرا کنید:

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

شما باید پیامی مشابه پیام زیر را ببینید:

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

رابط کاربری توسعه ADK را باز کنید

می‌توانید رابط کاربری ADK dev را در مرورگر خود با فشردن کلیدهای Ctrl یا Cmd و کلیک روی آدرس اینترنتی محلیِ در حال آزمایش، یا با کلیک روی دکمه‌ی پیش‌نمایش وب و انتخاب پیش‌نمایش روی پورت ۸۰۸۰، باز کنید.

پس از مشاهده رابط کاربری ADK dev، از منوی کشویی a2ui_agent را انتخاب کنید.

ارسال نمونه سوالات

یک نمونه درخواست برای نماینده ارسال کنید:

What's running in my project?

حالا یک نمونه‌ی دیگر از اعلان را امتحان کنید، خروجی متنی بیشتری دریافت خواهید کرد:

Does anything need my attention?

مکالمه شما باید شبیه به شکل زیر باشد:

عامل متن ADK

شما با دیواری از متن مواجه خواهید شد. دقیق، اما نه یک تجربه کاربری عالی.

۵. تولید A2UI JSON

چه می‌شد اگر عامل می‌توانست به جای نوشتن متن، رابط کاربری را توصیف کند؟ A2UI پروتکلی است که به عامل‌ها اجازه می‌دهد رابط‌های تعاملی را از کاتالوگی متشکل از ۱۸ عنصر اولیه بسازند. کلاینت آنها را به صورت بومی رندر می‌کند.

کیت توسعه نرم‌افزار پایتون A2UI شامل یک مدیر طرحواره است که پیام‌های سیستمی را برای شما تولید می‌کند. این کیت، کاتالوگ کامل کامپوننت‌های A2UI، نام‌ها و انواع صحیح ویژگی‌ها و ساختار JSON را به LLM آموزش می‌دهد.

به‌روزرسانی عامل

محتویات a2ui_agent/agent.py را با موارد زیر جایگزین کنید:

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

متد generate_system_prompt() توضیحات نقش شما را با طرح کامل A2UI JSON و مثال‌های مختصر ترکیب می‌کند، بنابراین LLM دقیقاً می‌داند که چگونه خروجی خود را قالب‌بندی کند. نیازی نیست کاتالوگ کامپوننت را به صورت دستی بنویسید.

۶. خروجی JSON را آزمایش کنید

اگر هنوز رابط کاربری توسعه‌دهنده ADK را از قبل اجرا دارید، باید به‌طور خودکار تغییراتی را که در عامل خود ایجاد کرده‌اید، مجدداً بارگذاری کند.

a2ui_agent را انتخاب کنید، با کلیک روی +New Session در سمت راست بالای رابط کاربری ADK dev، یک جلسه جدید را شروع کنید، سپس همان پیام قبلی را ارسال کنید:

What's running in my project?

این بار، عامل به جای متن ساده، با A2UI JSON پاسخ می‌دهد. پیام‌های ساختاریافته‌ای حاوی beginRendering ، surfaceUpdate و dataModelUpdate را در خروجی چت مشاهده خواهید کرد.

ADK A2UI JSON

JSON یک رابط کاربری غنی با کارت‌ها، آیکون‌ها و دکمه‌ها را توصیف می‌کند، اما adk web آن را به صورت متن خام نمایش می‌دهد. در مرحله بعد، آن را به صورت اجزای واقعی رابط کاربری رندر خواهید کرد.

۷. A2UI را درک کنید

به JSON که عامل شما ایجاد کرده است نگاه کنید. متوجه خواهید شد که شامل سه نوع پیام است. هر پاسخ A2UI از همین ساختار پیروی می‌کند:

۱. شروع رندرینگ

یک سطح رندر ایجاد می‌کند و کامپوننت ریشه را نامگذاری می‌کند:

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

۲. به‌روزرسانی سطح

درخت کامپوننت را به صورت یک لیست مسطح با ارجاعات ID (نه تو در تو) ارسال می‌کند:

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

۳. به‌روزرسانی مدل داده

داده‌ها را جدا از ساختار ارسال می‌کند:

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

کامپوننت‌ها با استفاده از {"path": "key"} به داده‌ها متصل می‌شوند. می‌توانید داده‌ها را بدون ارسال مجدد درخت کامپوننت به‌روزرسانی کنید.

۱۸ موجود اولیه

دسته بندی

قطعات

طرح بندی

کارت، ستون، ردیف، لیست، زبانه‌ها، جداکننده، مودال

نمایش

متن، تصویر، آیکون، ویدئو، پخش‌کننده صوتی

ورودی

فیلد متنی، ورودی تاریخ و زمان، انتخاب چندگانه، چک باکس، اسلایدر

اکشن

دکمه

این عامل، طرح‌بندی‌های مختلفی را از یک کاتالوگ واحد می‌سازد. برای جزئیات کامل در مورد هر جزء اولیه، به مرجع اجزا مراجعه کنید. نمای مرور، داشبورد اولویت‌دار و فرم پیکربندی، همگی از همین ۱۸ جزء اولیه استفاده می‌کنند. هیچ جزء جدیدی برای frontend مورد نیاز نیست.

۸. رندر کردن کامپوننت‌های A2UI

عامل، A2UI JSON معتبر تولید می‌کند، اما adk web آن را به صورت متن خام نمایش می‌دهد. برای رندر کردن آن به صورت اجزای رابط کاربری واقعی، به یک ابزار کوچک نیاز دارید که خروجی A2UI JSON عامل را به فرمتی که رندرکننده داخلی adk web انتظار دارد، تبدیل کند.

ابزار رندر A2UI را ایجاد کنید

a2ui_agent/a2ui_utils.py را با محتوای زیر ایجاد کنید:

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

این ابزار دو کار انجام می‌دهد:

  1. A2UI JSON را از خروجی متنی عامل استخراج می‌کند.
  2. هر پیام A2UI را در قالبی که رندرکننده‌ی داخلی A2UI در adk web انتظار دارد، قرار می‌دهد.

به‌روزرسانی عامل

محتویات a2ui_agent/agent.py را با موارد زیر جایگزین کنید. تنها تغییر نسبت به مرحله قبل، ایمپورت a2ui_callback و پارامتر after_model_callback روی agent است:

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

۹. رابط کاربری رندر شده را آزمایش کنید

اگر هنوز رابط کاربری توسعه‌دهنده ADK را از قبل اجرا دارید، باید به‌طور خودکار تغییراتی را که در عامل خود ایجاد کرده‌اید، مجدداً بارگذاری کند.

تب مرورگر را رفرش کنید، a2ui_agent را انتخاب کنید، سپس با کلیک روی +New Session در سمت راست بالای رابط کاربری ADK dev، یک جلسه جدید را شروع کنید و همان اعلان قبلی را ارسال کنید:

What's running in my project?

این بار، adk web اجزای A2UI را به عنوان رابط کاربری واقعی رندر می‌کند: کارت‌هایی با نشانگرهای وضعیت، جزئیات منابع و دکمه‌های عملیاتی.

عامل ADK A2UI

یک اعلان دیگر را امتحان کنید تا ببینید که چگونه عامل، یک رابط کاربری متفاوت را از همان مجموعه اولیه‌ها می‌سازد:

Does anything need my attention?

در نهایت، یک اعلان دیگر را امتحان کنید تا یک رابط کاربری متفاوت برای استقرار یک سرویس جدید ایجاد شود:

I need to deploy a new service

هر اعلان به همان عامل، همان ابزار و همان ۱۸ عنصر اولیه می‌رود. اما هر اعلان منجر به یک رابط کاربری متفاوت برای یک هدف متفاوت می‌شود.

۱۰. تمیز کردن

برای جلوگیری از اجرای سرورهای محلی، منابع را پاک کنید:

  • در ترمینالی که adk web در حال اجرا است، کلیدهای Ctrl+C را فشار دهید تا سرور عامل متوقف شود.

اگر پروژه‌ای را به‌طور خاص برای این آزمایشگاه کد ایجاد کرده‌اید، می‌توانید کل پروژه را حذف کنید:

gcloud projects delete ${GOOGLE_CLOUD_PROJECT}

۱۱. تبریک

شما یک عامل ADK ساختید که با استفاده از A2UI رابط کاربری غنی و تعاملی ایجاد می‌کند.

آنچه آموختید

  • A2UI پروتکلی با ۱۸ نوع داده اولیه اعلانی و ۳ نوع پیام است.
  • کیت توسعه نرم‌افزار A2UI پیام‌های سیستمی تولید می‌کند که کاتالوگ اجزا را به LLM آموزش می‌دهد.
  • عامل، ابزار و عناصر اولیه یکسان، رابط‌های کاربری متفاوتی را برای اهداف مختلف تشکیل می‌دهند.
  • اجزای A2UI می‌توانند در طول توسعه مستقیماً در adk web رندر شوند.

یک رابط کاربری تولید (production frontend) بسازید

در این آزمایشگاه کد، شما A2UI را درون adk web برای توسعه و آزمایش رندر کردید.

برای محیط عملیاتی، شما می‌توانید با استفاده از یکی از رندرکننده‌های رسمی A2UI، یک رابط کاربری (frontend) بسازید:

پلتفرم

رندر کننده

نصب

وب (واکنش)

@a2ui/react

npm install @a2ui/react

وب (ادبیات)

@a2ui/lit

npm install @a2ui/lit

وب (انگولار)

@a2ui/angular

npm install @a2ui/angular

موبایل/دسکتاپ

کیت توسعه نرم‌افزاری GenUI فلاتر

شروع به کار

اسناد مرجع