1. نظرة عامة
تعرض معظم تطبيقات الوكلاء نصًا عاديًا. يغيّر بروتوكول A2UI ذلك. فهو بروتوكول يتضمّن 18 وحدة أساسية تصريحية لواجهة المستخدم تتيح للوكيل إنشاء واجهات تفاعلية منسّقة. ويعرضها العميل بشكل أصلي. ولست بحاجة إلى أي رمز جديد للواجهة الأمامية لكل تصميم.
يستخدم هذا الدرس التطبيقي حول الترميز حزمة تطوير الوكلاء (ADK) لإنشاء الوكيل وبروتوكول A2UI لإنشاء واجهة المستخدم.
ما ستنشئه
لوحة بيانات وهمية للبنية التحتية السحابية في ثلاث مراحل:
- وكيل عادي يعرض بيانات الموارد كنص عادي
- وكيل A2UI يعرض البيانات نفسها بتنسيق JSON المنظَّم لبروتوكول A2UI
- وكيل معروض يعرض JSON الخاص ببروتوكول A2UI كمكوّنات تفاعلية لواجهة المستخدم في واجهة مستخدم المطوّرين في حزمة ADK

أهداف الدورة التعليمية
- كيفية عمل بروتوكول A2UI: 18 وحدة أساسية و3 أنواع من الرسائل ونموذج مكوّنات مسطّح
- كيفية استخدام حزمة A2UI SDK لطلب إنشاء JSON الخاص ببروتوكول A2UI من وكيل ADK
- كيفية عرض مكوّنات A2UI في
adk web
المتطلبات
- مشروع على Google Cloud تم تفعيل الفوترة له
- متصفّح ويب، مثل Chrome
- الإصدار 3.12 من Python أو إصدار أحدث
هذا الدرس التطبيقي حول الترميز مخصّص للمطوّرين ذوي الخبرة المتوسطة الذين لديهم بعض المعرفة بلغة Python وGoogle Cloud.
يستغرق إكمال هذا الدرس التطبيقي حول الترميز من 15 إلى 20 دقيقة تقريبًا.
يجب أن تكلّف الموارد التي تم إنشاؤها في هذا الدرس التطبيقي حول الترميز أقل من 5 دولارات أمريكية.
2. إعداد البيئة
إنشاء مشروع على Google Cloud
- في Google Cloud Console، في صفحة اختيار المشروع، اختَر مشروعًا على Google Cloud أو أنشِئ مشروعًا.
- تأكَّد من أنّ الفوترة مفعَّلة لمشروعك على السحابة الإلكترونية. كيفية التحقّق مما إذا كانت الفوترة مفعَّلة في مشروع.
بدء محرِّر Cloud Shell
لبدء جلسة Cloud Shell من Google Cloud Console، انقر على تفعيل Cloud Shell في Google Cloud Console.
يؤدي ذلك إلى بدء جلسة في اللوحة السفلية من Google Cloud Console.
لبدء المحرِّر، انقر على فتح المحرِّر في شريط أدوات نافذة Cloud Shell.
ضبط متغيّرات البيئة
في شريط أدوات محرِّر Cloud Shell، انقر على الوحدة الطرفية ثم على وحدة طرفية جديدة ، ثم شغِّل الأوامر التالية لضبط مشروعك وموقعك الجغرافي وإعداد حزمة 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 واجهة مستخدم للمطوّرين يمكنك استخدامها للتفاعل مع وكيلك وإرسال طلبات إليه في متصفّح لأغراض الاختبار.
بدء واجهة مستخدم المطوّرين في حزمة ADK
في الوحدة الطرفية لمحرِّر Cloud Shell، شغِّل الأمر التالي لبدء واجهة مستخدم المطوّرين في حزمة ADK:
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 في متصفّحك من خلال النقر على عنوان URL للاختبار المحلي مع الضغط على Ctrl أو Cmd ، أو من خلال النقر على الزر معاينة الويب واختيار المعاينة على المنفذ 8080.
بعد عرض واجهة مستخدم المطوّرين في حزمة ADK، اختَر a2ui_agent من القائمة المنسدلة.
إرسال طلبات نموذجية
أرسِل طلبًا نموذجيًا إلى الوكيل:
What's running in my project?
جرِّب الآن طلبًا نموذجيًا آخر وستحصل على المزيد من الناتج النصي:
Does anything need my attention?
من المفترض أن تبدو محادثتك مشابهة لما يلي:

ستحصل على الكثير من النص. وهو دقيق، ولكن تجربة المستخدم ليست رائعة.
5. إنشاء JSON الخاص ببروتوكول A2UI
ماذا لو كان بإمكان الوكيل وصف واجهة مستخدم بدلاً من عرض النص؟ بروتوكول A2UI هو بروتوكول يتيح للوكلاء إنشاء واجهات تفاعلية من كتالوج يتضمّن 18 وحدة أساسية. ويعرضها العميل بشكل أصلي.
تتضمّن حزمة A2UI Python SDK مدير مخطط ينشئ لك طلبات النظام. ويعلّم النموذج اللغوي الكبير كتالوج مكوّنات 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() بين وصف دورك ومخطط JSON الكامل لبروتوكول A2UI وأمثلة قليلة، لذا يعرف النموذج اللغوي الكبير كيفية تنسيق الناتج بالضبط. ولست بحاجة إلى كتابة كتالوج المكوّنات يدويًا.
6. اختبار الناتج بتنسيق JSON
إذا كانت واجهة مستخدم المطوّرين في حزمة ADK لا تزال قيد التشغيل من وقت سابق، من المفترض أن تعيد تحميل التغييرات التي أجريتها على وكيلك تلقائيًا.
اختَر a2ui_agent، وابدأ جلسة جديدة من خلال النقر على +جلسة جديدة في أعلى يسار واجهة مستخدم المطوّرين في حزمة ADK، ثم أرسِل الطلب نفسه كما كان من قبل:
What's running in my project?
في هذه المرة، يردّ الوكيل باستخدام JSON الخاص ببروتوكول A2UI بدلاً من النص العادي. ستظهر لك رسائل منظَّمة تحتوي على beginRendering وsurfaceUpdate وdataModelUpdate في ناتج المحادثة.

يصف 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
الفئة | المكونات |
التصميم | البطاقة والعمود والصف والقائمة وعلامات التبويب والفاصل والنافذة المنبثقة |
العرض | النص والصورة والرمز والفيديو ومشغّل الصوت |
الإدخال | حقل النص وإدخال التاريخ والوقت والاختيار من بين خيارات متعدّدة ومربّع الاختيار وشريط التمرير |
الإجراء | زرّ |
ينشئ الوكيل تصاميم مختلفة من الكتالوج نفسه. اطّلِع على مرجع المكوّنات للحصول على تفاصيل كاملة عن كل وحدة أساسية. تستخدم كل من طريقة عرض التصفّح ولوحة البيانات حسب الأولوية ونموذج الضبط هذه الوحدات الأساسية الـ 18 نفسها. ولست بحاجة إلى مكوّنات جديدة للواجهة الأمامية.
8. عرض مكوّنات A2UI
ينشئ الوكيل JSON صالحًا لبروتوكول A2UI، ولكن يعرضه adk web كنص عادي. لعرضه كمكوّنات فعلية لواجهة المستخدم، أنت بحاجة إلى أداة صغيرة تحوّل ناتج JSON الخاص ببروتوكول A2UI من الوكيل إلى التنسيق الذي يتوقّعه العارض المضمّن في 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
تنفّذ هذه الأداة إجراءَين:
- تستخرج JSON الخاص ببروتوكول A2UI من الناتج النصي للوكيل
- تغلّف كل رسالة 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 كواجهة مستخدم فعلية: بطاقات تحتوي على مؤشرات الحالة وتفاصيل الموارد وأزرار الإجراءات.

جرِّب طلبًا مختلفًا للاطّلاع على كيفية إنشاء الوكيل لواجهة مستخدم مختلفة من المجموعة نفسها من الوحدات الأساسية:
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 SDK طلبات النظام التي تعلّم النموذج اللغوي الكبير كتالوج المكوّنات
- ينشئ الوكيل والأداة والوحدات الأساسية نفسها واجهات مستخدم مختلفة لأغراض مختلفة
- يمكن عرض مكوّنات A2UI مباشرةً في
adk webأثناء التطوير
إنشاء واجهة أمامية للإنتاج
في هذا الدرس التطبيقي حول الترميز، عرضت بروتوكول A2UI داخل adk web لأغراض التطوير والاختبار.
لأغراض الإنتاج، يمكنك إنشاء واجهة أمامية باستخدام أحد عارضات A2UI الرسمية:
النظام الأساسي | العارض | تثبيت |
الويب (React) |
|
|
الويب (Lit) |
|
|
الويب (Angular) |
|
|
الأجهزة الجوّالة/أجهزة الكمبيوتر | حزمة Flutter GenUI SDK |