تجارب الواجهة الأمامية باستخدام ADK وA2UI

1. نظرة عامة

تعرض معظم تطبيقات الوكلاء نصًا عاديًا. تغيّر A2UI ذلك. وهو بروتوكول يتضمّن 18 عنصرًا أساسيًا تعريفيًا لواجهة المستخدم يتيح للوكيل إنشاء واجهات تفاعلية غنية. يعرض العميل هذه العناصر بشكل أصلي. ليست هناك حاجة إلى رمز جديد للواجهة الأمامية لكل تخطيط.

يستخدم هذا الدرس التطبيقي حول الترميز حزمة تطوير الوكلاء (ADK) لإنشاء الوكيل وA2UI لإنشاء واجهة المستخدم.

ما ستنشئه

لوحة بيانات البنية الأساسية على السحابة الإلكترونية في ثلاث مراحل:

  1. وكيل عادي يعرض بيانات الموارد كنص عادي
  2. وكيل A2UI يعرض البيانات نفسها التي يعرضها ترميز JSON الخاص بـ A2UI
  3. وكيل معروض يعرض ملف JSON الخاص بواجهة A2UI كمكوّنات تفاعلية لواجهة المستخدم في واجهة المستخدم الخاصة بمجموعة أدوات تطوير التطبيقات (ADK)

وكيل ADK A2UI

أهداف الدورة التعليمية

  • طريقة عمل A2UI: 18 عنصرًا أساسيًا و3 أنواع من الرسائل ونموذج مكون مسطّح
  • كيفية استخدام حزمة تطوير البرامج (SDK) الخاصة بواجهة A2UI لطلب إنشاء رمز JSON لواجهة A2UI من وكيل ADK
  • كيفية عرض مكوّنات A2UI في adk web

المتطلبات

  • مشروع Google Cloud تم تفعيل الفوترة فيه
  • متصفّح ويب، مثل Chrome
  • ‫Python 3.12 أو إصدار أحدث

هذا الدرس التطبيقي حول الترميز مخصّص للمطوّرين المتوسطي الخبرة الذين لديهم بعض المعرفة بلغة Python وGoogle Cloud.

يستغرق إكمال هذا الدرس العملي حوالي 15 إلى 20 دقيقة.

يجب أن تكون تكلفة الموارد التي تم إنشاؤها في هذا الدرس التطبيقي حول الترميز أقل من 5 دولارات أمريكية.

2. إعداد البيئة

إنشاء مشروع على Google Cloud

  1. في Google Cloud Console، في صفحة اختيار المشروع، اختَر مشروعًا على Google Cloud أو أنشِئ مشروعًا.
  2. تأكَّد من تفعيل الفوترة لمشروعك على السحابة الإلكترونية. كيفية التحقّق مما إذا كانت الفوترة مفعَّلة في مشروع

بدء Cloud Shell Editor

لبدء جلسة Cloud Shell من "وحدة تحكّم Google Cloud"، انقر على تفعيل Cloud Shell في "وحدة تحكّم Google Cloud".

سيؤدي ذلك إلى بدء جلسة في اللوحة السفلية من "وحدة تحكّم Google Cloud".

لتشغيل المحرِّر، انقر على فتح المحرِّر في شريط الأدوات في نافذة Cloud Shell.

ضبط متغيرات البيئة

في شريط أدوات Cloud Shell Editor، انقر على الوحدة الطرفية ثم على وحدة طرفية جديدة، ثم شغِّل الأوامر التالية لضبط مشروعك وموقعك الجغرافي وإعداد ADK لاستخدام Gemini في Vertex AI.

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

تفعيل واجهات برمجة التطبيقات

في الوحدة الطرفية، شغِّل الأمر التالي لتفعيل واجهات برمجة التطبيقات المطلوبة:

gcloud services enable aiplatform.googleapis.com

تثبيت الحِزم التابعة

في الوحدة الطرفية، شغِّل الأمر التالي لتثبيت أحدث إصدار من "حزمة تطوير الوكيل" (ADK):

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

3- إنشاء الوكيل

ابدأ باستخدام وكيل 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],
)

4. اختبار الوكيل

تتضمّن "حزمة تطوير التطبيقات" واجهة مستخدم للمطوّرين يمكنك استخدامها للتفاعل مع وكيلك وإرسال طلبات إليه في المتصفّح بغرض الاختبار.

بدء واجهة مستخدم تطوير ADK

في نافذة Cloud Shell Editor، نفِّذ الأمر التالي لبدء واجهة مستخدم 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 في المتصفّح من خلال النقر مع الضغط على Ctrl أو Cmd على عنوان URL للاختبار المحلي، أو من خلال النقر على الزر معاينة الويب واختيار المعاينة على المنفذ 8080.

بعد عرض واجهة مستخدم ADK المخصّصة للمطوّرين، انقر على a2ui_agent من القائمة المنسدلة.

إرسال نماذج طلبات

أرسِل طلبًا نموذجيًا إلى الوكيل:

What's running in my project?

جرِّب الآن طلبًا آخر وستحصل على المزيد من النتائج النصية:

Does anything need my attention?

يجب أن تبدو محادثتك مشابهة لما يلي:

وكيل ADK النصي

سيظهر لك الكثير من النصوص. دقيقة، ولكنّها لا تقدّم تجربة مستخدم رائعة.

5- إنشاء ملف JSON لواجهة A2UI

ماذا لو كان بإمكان الوكيل وصف واجهة مستخدم بدلاً من عرض نص؟ ‫A2UI هو بروتوكول يتيح للوكلاء إنشاء واجهات تفاعلية من كتالوج يضم 18 عنصرًا أساسيًا. يعرض العميل هذه العناصر بشكل أصلي.

تتضمّن حزمة تطوير البرامج (SDK) بلغة Python الخاصة بواجهة A2UI أداة لإدارة المخططات تنشئ لك طلبات النظام. تعرض هذه السلسلة لنموذج اللغة الكبير كتالوجًا كاملاً لمكوّنات A2UI، وأسماء الأنواع والخصائص الصحيحة، وبنية JSON.

تعديل الوكيل

استبدِل محتوى 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 الكامل وأمثلة قليلة اللقطات، لكي تعرف النماذج اللغوية الكبيرة كيفية تنسيق الناتج بدقة. لست بحاجة إلى كتابة قائمة المكوّنات يدويًا.

6. اختبار إخراج JSON

إذا كان لا يزال لديك واجهة مستخدم مطوّر ADK قيد التشغيل من قبل، من المفترض أن تعيد تحميل التغييرات التي أجريتها على الوكيل تلقائيًا.

انقر على a2ui_agent، وابدأ جلسة جديدة بالنقر على +جلسة جديدة في أعلى يسار واجهة مستخدم ADK dev، ثم أرسِل الطلب نفسه كما كان من قبل:

What's running in my project?

في هذه المرة، يردّ الوكيل باستخدام A2UI JSON بدلاً من النص العادي. ستظهر لك رسائل منظَّمة تحتوي على beginRendering وsurfaceUpdate وdataModelUpdate في ناتج المحادثة.

ADK A2UI JSON

يصف ملف JSON واجهة مستخدم غنية تتضمّن بطاقات ورموزًا وأزرارًا، ولكن adk web يعرضها كنص عادي. في الخطوة التالية، ستجعلها تعرض كمكوّنات فعلية لواجهة المستخدم.

7. التعرّف على A2UI

اطّلِع على ملف JSON الذي أنشأه الوكيل للتو. ستلاحظ أنّه يحتوي على ثلاثة أنواع من الرسائل. تتّبع كل استجابة من A2UI البنية نفسها:

‫1. beginRendering

ينشئ هذا الرمز مساحة عرض ويسمّي المكوّن الجذر:

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

‫2. surfaceUpdate

إرسال شجرة المكوّنات على شكل قائمة مسطّحة مع مراجع المعرّفات (غير متداخلة):

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

إرسال البيانات بشكل منفصل عن البنية:

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

ترتبط المكوّنات بالبيانات باستخدام {"path": "key"}. يمكنك تعديل البيانات بدون إعادة إرسال شجرة المكوّنات.

الأنواع الأساسية الـ 18

الفئة

المكونات

التصميم

بطاقة، عمود، صف، قائمة، علامات تبويب، فاصل، نافذة مشروطة

الشبكة الإعلانية

Text, Image, Icon, Video, AudioPlayer

الإدخال

TextField وDateTimeInput وMultipleChoice وCheckBox وSlider

الإجراء

زرّ

ينشئ الوكيل تنسيقات مختلفة من الفهرس نفسه. اطّلِع على مرجع المكوّنات للحصول على التفاصيل الكاملة حول كل عنصر أساسي. تستخدم كلّ من طريقة عرض التصفّح ولوحة بيانات الأولوية ونموذج الإعدادات هذه العناصر الأساسية الـ 18 نفسها. لا حاجة إلى مكوّنات جديدة في الواجهة الأمامية.

8. عرض مكوّنات A2UI

ينشئ الوكيل ملف JSON صالحًا بتنسيق A2UI، ولكن يعرضه 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. يستخرج هذا الإجراء رمز JSON الخاص بواجهة A2UI من الناتج النصي للوكيل
  2. تغليف كل رسالة A2UI بالتنسيق الذي يتوقّعه عارض A2UI المضمّن في adk web

تعديل الوكيل

استبدِل محتوى a2ui_agent/agent.py بما يلي. التغيير الوحيد عن الخطوة السابقة هو استيراد a2ui_callback والمعلَمة after_model_callback في الوكيل:

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- اختبار واجهة المستخدم المعروضة

إذا كان لا يزال لديك واجهة مستخدم مطوّر ADK قيد التشغيل من قبل، من المفترض أن تعيد تحميل التغييرات التي أجريتها على الوكيل تلقائيًا.

أعِد تحميل علامة تبويب المتصفّح، ثم انقر على a2ui_agent، وابدأ جلسة جديدة بالنقر على +جلسة جديدة في أعلى يسار واجهة مستخدم أدوات تطوير ADK وأرسِل الطلب نفسه كما كان من قبل:

What's running in my project?

في هذه المرة، يعرض adk web مكونات A2UI كواجهة مستخدم فعلية: بطاقات تتضمّن مؤشرات الحالة وتفاصيل الموارد وأزرار الإجراءات.

وكيل ADK A2UI

جرِّب طلبًا مختلفًا لمعرفة كيف ينشئ الوكيل واجهة مستخدم مختلفة من المجموعة نفسها من العناصر الأساسية:

Does anything need my attention?

أخيرًا، جرِّب طلبًا آخر لإنشاء واجهة مستخدم مختلفة من أجل نشر خدمة جديدة:

I need to deploy a new service

يتم إرسال كل طلب إلى الوكيل نفسه والأداة نفسها و18 وحدة أولية نفسها. لكنّ كل طلب يؤدي إلى ظهور واجهة مستخدم مختلفة لغرض مختلف.

10. تنظيف

لتجنُّب ترك الخوادم المحلية قيد التشغيل، عليك تنظيف الموارد باتّباع الخطوات التالية:

  • في الوحدة الطرفية التي يتم فيها تشغيل adk web، اضغط على Ctrl+C لإيقاف خادم الوكيل.

إذا أنشأت مشروعًا خصيصًا لهذا الدرس التطبيقي حول الترميز، يمكنك حذف المشروع بأكمله باتّباع الخطوات التالية:

gcloud projects delete ${GOOGLE_CLOUD_PROJECT}

11. تهانينا

لقد أنشأت وكيل ADK ينشئ واجهة مستخدم تفاعلية غنية باستخدام A2UI.

ما تعلّمته

  • ‫A2UI هو بروتوكول يتضمّن 18 عنصرًا أساسيًا تعريفيًا و3 أنواع من الرسائل.
  • تنشئ حزمة تطوير البرامج A2UI طلبات من النظام تعلّم النموذج اللغوي الكبير قائمة المكوّنات
  • يتألف الوكيل والأداة والعناصر الأساسية نفسها من واجهات مستخدم مختلفة لنوايا مختلفة
  • يمكن عرض مكوّنات A2UI مباشرةً في adk web أثناء التطوير

إنشاء واجهة أمامية للإنتاج

في هذا الدرس التطبيقي حول الترميز، عرضت A2UI داخل adk web لأغراض التطوير والاختبار.

بالنسبة إلى مرحلة الإنتاج، يمكنك إنشاء واجهة أمامية باستخدام أحد أدوات العرض الرسمية في A2UI:

النظام الأساسي

العارض

تثبيت

الويب (React)

@a2ui/react

npm install @a2ui/react

الويب (Lit)

@a2ui/lit

npm install @a2ui/lit

الويب (Angular)

@a2ui/angular

npm install @a2ui/angular

الجوّال/الكمبيوتر

Flutter GenUI SDK

البدء

المستندات المرجعية