إنشاء استوديو إبداعي متعدد الوكلاء باستخدام مجموعة أدوات Agent Stack من Google: ADK وA2A وMCP على Cloud Run وAgent Runtime

1. نظرة عامة

في هذا الدرس التطبيقي، ستنشئ AI Creative Studio، وهو نظام موزّع متعدد الوكلاء يحوّل طلبًا واحدًا إلى حملة كاملة على Instagram.

اكتب جملة واحدة. يمكنك الحصول على أبحاث الجمهور والترجمة والشرح والأفكار المرئية والنصوص التي تمت مراجعتها من حيث الجودة والجدول الزمني الكامل للمشروع، وكل ذلك من إنشاء فريق من وكلاء الذكاء الاصطناعي المتعاونين.

الوكلاء الذين ستنشئهم

الوكيل

الدور

محلّل إستراتيجي للعلامة التجارية

البحث على الويب عن إحصاءات الجمهور وتحليل المنافسين ومؤشرات 2025

كاتب الإعلانات

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

Designer

إنشاء أفكار مرئية وإنشاء صور حقيقية من خلال Gemini، وتخزينها في GCS

ناقد

نسخ المراجعات والمرئيات - تعرض APPROVED أو NEEDS_REVISION مع ملاحظات محدّدة

مدير مشروع

إنشاء مخطط زمني للمشروع وتقسيم المهام، ويمكن مزامنته مع Notion من خلال MCP

مدير التصميم

تنسيق عمل جميع الخبراء الخمسة بالتسلسل: ما عليك سوى تقديم طلب واحد، وسيتولّى تنسيق الباقي

يتم نشر الوكلاء الخمسة كخدمات دقيقة مستقلة على Cloud Run. تتواصل هذه النماذج عبر بروتوكول A2A، وهو معيار مفتوح لا يعتمد على لغة معيّنة، ما يتيح لأي وكيل استدعاء أي وكيل آخر بغض النظر عن إطار العمل الخاص به. يعمل "المدير الإبداعي" على Agent Runtime ويتواصل مع كل خبير عن بُعد.

الهندسة المعمارية

نظرة عامة على النظام

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

  • يمكنك إنشاء وكلاء نماذج لغوية كبيرة باستخدام Google ADK وAgent وتعليمات النظام والأدوات المضمّنة.
  • يمكنك تجميع معلومات الوكيل القابلة لإعادة الاستخدام في ملفات نموذجية باستخدام مهارات ADK (SkillToolset).
  • إنشاء صور حقيقية من خلال ربط وكيل نصي بنموذج صور باستخدام FunctionTool
  • يمكنك دمج واجهات برمجة التطبيقات الخارجية بدون رمز ربط مخصّص باستخدام بروتوكول سياق النموذج (MCP).
  • يمكنك تحويل أي وكيل إلى خدمة يمكن استدعاؤها عبر الشبكة باستخدام بروتوكول Agent to Agent (A2A) عبر HTTPS.
  • تنظيم الوكلاء الموزّعين باستخدام RemoteA2aAgent وAgentTool
  • يمكنك تجميع الوكلاء المستقلين ونشرهم كخدمات مصغّرة في Cloud Run.
  • استضافة أداة تنسيق ذات حالة على بيئة تشغيل الوكيل
  • يمكنك الحفاظ على سير العمل الطويل الذي يتضمّن عدة وكلاء ضمن حدود السياق باستخدام ضغط السياق.
  • إنشاء حلقة مراقبة الجودة: مراجعات النقاد → مراجعة تلقائية عند الحاجة

المتطلبات

  • مشروع Google Cloud تم تفعيل الفوترة فيه
  • دور المالك أو المحرّر في "إدارة الهوية وإمكانية الوصول"
  • معرفة أساسية بلغة Python

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

في هذا الدرس التطبيقي حول الترميز، سنستخدم Cloud Shell.

ما هو Cloud Shell؟

‫Cloud Shell هي بيئة Linux مجانية مستندة إلى المتصفّح تتضمّن كل ما تحتاج إليه مثبّتًا مسبقًا: gcloud وgit وPython وDocker وغير ذلك. ولن تحتاج إلى تثبيت أي شيء على جهازك.

لفتح Cloud Shell، انقر على رمز الوحدة الطرفية في شريط الأدوات أعلى يسار "وحدة تحكّم Google Cloud Platform":

فتح Cloud Shell من شريط أدوات GCP Console

عند فتح Cloud Shell للمرة الأولى، سيُطلب منك إثبات ملكية حسابك. انقر على إثبات الملكية:

مربّع حوار تأكيد الحساب

بعد ذلك، انقر على تفويض للسماح لـ Cloud Shell بإجراء طلبات إلى Google Cloud API:

مربّع حوار "السماح باستخدام Cloud Shell"

أصبح Cloud Shell جاهزًا الآن. ستظهر لك رسالة ترحيب في نافذة الوحدة الطرفية: نافذة Cloud Shell الطرفية جاهزة

المصادقة على مشروعك وإعداده

تمّت مصادقة Cloud Shell باستخدام حسابك على Google. تأكيد حسابك النشط والعثور على رقم تعريف مشروعك:

gcloud config list

يمكنك أيضًا الاطّلاع على رقم تعريف المشروع في لوحة بيانات وحدة تحكّم Google Cloud Platform على اللوحة الجانبية اليمنى. انسخها، ستحتاج إليها في الأمر التالي:

العثور على رقم تعريف مشروعك في GCP Console وتعيينه في Cloud Shell

الآن، اضبط مشروعك على النحو التالي:

export PROJECT_ID=$(gcloud config get-value project)
export REGION="us-central1"        # Cloud Run deployment region
echo "Project: $PROJECT_ID"

الناتج المتوقّع:

Project: my-project-123

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

gcloud services enable \
    aiplatform.googleapis.com \
    apphub.googleapis.com \
    run.googleapis.com \
    cloudbuild.googleapis.com \
    artifactregistry.googleapis.com \
    generativelanguage.googleapis.com \
    iam.googleapis.com \
    cloudresourcemanager.googleapis.com \
    storage.googleapis.com \
    secretmanager.googleapis.com

يستغرق ذلك حوالي دقيقتين. سيظهر لك الرمز Operation finished successfully عند اكتمال العملية.

إعداد "بيانات الاعتماد التلقائية للتطبيق" (ADC)

ستتصل الوكلاء بمنصة Gemini Enterprise Agent Platform باستخدام مكتبة Google Auth، التي تتطلّب بيانات اعتماد تلقائية للتطبيق، وهي منفصلة عن مصادقة gcloud CLI.

نفِّذ الأمر التالي مرة واحدة:

gcloud auth application-default login

ستفتح علامة تبويب متصفّح تطلب منك تأكيد الإجراء. انقر على سماح. وسترى ما يلي:

Credentials saved to file: ~/.config/gcloud/application_default_credentials.json

إنشاء نسخة طبق الأصل من مستودع التطبيق النموذجي

يستخدم هذا الدرس التطبيقي حول الترميز مستودعًا أوليًا، وهو عبارة عن مشروع هيكلي يتضمّن جميع البنية الأساسية (ملفات Dockerfile وpyproject.toml وبرامج النشر)، ولكن عليك كتابة منطق الوكيل.

git clone https://github.com/Saoussen-CH/mas-a2a-gcp.git ~/ai-creative-studio
cd ~/ai-creative-studio/workshop/starter

يحتوي كل agent.py على عناصر نائبة # TODO حيث ستكتب منطق الوكيل. اكتملت النصوص البرمجية Dockerfile وpyproject.toml ونشرها.

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

انسخ المثال المقدَّم وأدرِج رقم تعريف مشروعك في خطوة واحدة:

cp .env.example .env
sed -i "s|GOOGLE_CLOUD_PROJECT=your-project-id|GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)|" .env

بعد ذلك، أنشِئ حزمة GCS حيث سيخزّن "المصمّم" الصور التي تم إنشاؤها وعدِّل .env باسمها:

export PROJECT_ID=$(gcloud config get-value project)
export BUCKET_NAME="${PROJECT_ID}-campaign-images"

gcloud storage buckets create gs://${BUCKET_NAME} \
    --location=us-central1 \
    --project=${PROJECT_ID}

sed -i "s|GCS_IMAGES_BUCKET=your-project-id-campaign-images|GCS_IMAGES_BUCKET=${BUCKET_NAME}|" .env

بعد ذلك، يمكنك إعداد ميزة "عناوين URL الموقّعة للصور". ينشئ المدير الإبداعي روابط HTTPS قابلة للنقر لكل صورة في الملخّص النهائي للحملة. يتطلّب ذلك حساب خدمة لتوقيع عناوين URL. شغِّل الأوامر التالية لإعداده:

export PROJECT_NUMBER=$(gcloud projects describe $(gcloud config get-value project) --format="value(projectNumber)")
export SA_EMAIL="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"
export AGENT_RUNTIME_SA="service-${PROJECT_NUMBER}@gcp-sa-aiplatform-re.iam.gserviceaccount.com"

# Allow your user account to sign URLs locally (adk web)
gcloud iam service-accounts add-iam-policy-binding ${SA_EMAIL} \
  --member="user:$(gcloud config get-value account)" \
  --role="roles/iam.serviceAccountTokenCreator"

# Allow Agent Runtime to sign URLs when deployed
gcloud projects add-iam-policy-binding $(gcloud config get-value project) \
  --member="serviceAccount:${AGENT_RUNTIME_SA}" \
  --role="roles/iam.serviceAccountTokenCreator"

# Save SA email and project number to .env
grep -q "^SIGNING_SERVICE_ACCOUNT" .env \
  && sed -i "s|^SIGNING_SERVICE_ACCOUNT=.*|SIGNING_SERVICE_ACCOUNT=${SA_EMAIL}|" .env \
  || echo "SIGNING_SERVICE_ACCOUNT=${SA_EMAIL}" >> .env

grep -q "^GOOGLE_CLOUD_PROJECT_NUMBER" .env \
  && sed -i "s|^GOOGLE_CLOUD_PROJECT_NUMBER=.*|GOOGLE_CLOUD_PROJECT_NUMBER=${PROJECT_NUMBER}|" .env \
  || echo "GOOGLE_CLOUD_PROJECT_NUMBER=${PROJECT_NUMBER}" >> .env

افتح .env في المحرّر لمراجعة جميع الإعدادات:

cloudshell edit .env

سيؤدي ذلك إلى فتح .env كعلامة تبويب في "محرِّر Cloud Shell". انقر على الزر فتح المحرِّر في شريط الأدوات إذا لم تكن لوحة المحرِّر ظاهرة:

انقر على "فتح المحرِّر" (Open Editor) في شريط أدوات Cloud Shell

أداة Cloud Shell Editor مع شجرة ملفات المشروع

تأكَّد من إعداد المشروع بشكلٍ صحيح:

grep GOOGLE_CLOUD_PROJECT .env

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

نستخدم uv، وهي أداة سريعة وحديثة لإدارة حِزم Python، وتتعامل مع البيئات الافتراضية وتثبّت في أداة واحدة. وهي أسرع من pip بمقدار 10 إلى 100 مرة، وهي الطريقة المُقترَحة لإدارة مشاريع Python.

تم تثبيت uv مسبقًا في Cloud Shell. تتشارك جميع البرامج الوسيطة في التبعيات الأساسية نفسها، لذا ثبِّت التبعيات مرة واحدة وستعمل مع كل برنامج وسيط في هذا الدرس العملي:

uv sync

يقرأ الأمر uv sync pyproject.toml وينشئ الدليل .venv/ مع جميع العناصر التابعة. يحتوي كلّ برنامج متخصص أيضًا على pyproject.toml يستخدمه حصريًا إصدارات Docker، ويشمل التثبيت المشترَك أعلاه كل ما تحتاج إليه للاختبار المحلي.

3- التعرّف على حزمة تطوير التطبيقات (ADK) من Google

قبل كتابة الرمز، دعنا نتعرّف على حزمة تطوير الوكلاء (ADK)، وهي إطار العمل الذي ستستخدمه لإنشاء كل وكيل في هذا الدرس التطبيقي حول الترميز.

ما هي "حزمة تطوير التطبيقات" (ADK)؟

‫Agent Development Kit (ADK) هو إطار عمل مرن ونمطي لتطوير وكلاء الذكاء الاصطناعي ونشرهم. على الرغم من أنّ ADK محسّن للعمل مع Gemini ومنظومة Google المتكاملة، إلا أنّه لا يعتمد على نموذج معيّن ولا على طريقة نشر معيّنة، وهو مصمّم ليتوافق مع أُطر العمل الأخرى. تم تصميم ADK لجعل عملية تطوير الوكلاء تبدو أقرب إلى تطوير البرامج، وذلك لتسهيل إنشاء ونشر وتنظيم البُنى القائمة على الوكلاء التي تتراوح بين المهام البسيطة وسير العمل المعقّد.

تتولّى حزمة تطوير التطبيقات (ADK) الأجزاء المعقّدة، مثل استدعاء الأدوات والمحادثات المتعددة الأدوار وإدارة السياق والبث، حتى تتمكّن من التركيز على منطق الوكيل.

المكوّنات الأساسية لوكيل ADK

يتألف كلّ وكيل من أربع وحدات أساسية:

حظر

الدور

الطراز

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

الأدوات

الدوال التي تسترد البيانات أو تنفّذ إجراءات من خلال طلب البيانات من واجهات برمجة التطبيقات أو الخدمات

التنسيق

يحافظ على الذاكرة والحالة خلال الأدوار، ويوجه طلبات استخدام الأدوات، ويعيد النتائج إلى النموذج

وقت التشغيل

يتم تنفيذ النظام عند استدعائه، إما محليًا من خلال adk web أو كخدمة تم نشرها.

تعريف الوكيل

يتم تعريف كل من العملاء الخمسة في هذا الدرس العملي بالطريقة نفسها:

from google.adk.agents import Agent
from google.adk.tools.google_search_tool import google_search

root_agent = Agent(
    name="brand_strategist",                              # unique identifier
    model=os.getenv("GEMINI_MODEL", "gemini-2.5-flash"), # the LLM powering this agent
    instruction=SYSTEM_INSTRUCTION,                       # the agent's persona, constraints, and output format
    description="Brand strategist for market research, trend analysis, and competitive insights",
    tools=[google_search],                                # functions the LLM can call
)

الحقل

الغرض

name

المعرّف الفريد: تستخدمه أدوات التنسيق لتوجيه المكالمات

model

يشير الحقل إلى نموذج Gemini الذي يستند إليه هذا الوكيل.

instruction

طلب النظام: يحدّد دور الوكيل والقيود وتنسيق الإخراج

description

ملخّص من سطر واحد: يقرأ المنسّق هذا الملخّص لتحديد الخبير الذي يجب التواصل معه

tools

الدوال التي يمكن للنموذج اللغوي الكبير استدعاؤها (المضمّنة مثل google_search أو دوال Python المخصّصة)

طريقة تشغيل ADK لوكيل

User message
     
     
  Agent (LLM)   reads instruction + conversation history
     
     ├─► needs more info?  calls a tool  gets result  continues reasoning
     
     └─► done reasoning  returns final text response

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

4. إنشاء وكيل "استراتيجي العلامة التجارية" واختباره

لنبدأ بالوكيل الأول: استراتيجي العلامة التجارية. هذه أداة بحث فقط للعثور على إحصاءات الجمهور المستهدَف وتحليل المنافسين والمواضيع الرائجة باستخدام "بحث Google".

افتح ملف الوكيل الأساسي في "محرِّر Cloud Shell":

cloudshell edit agents/brand_strategist/agent.py

سيظهر لك قسمان # TODO لتملأهما.

المهمة 1 - كتابة تعليمات النظام

أولاً، عليك كتابة تعليمات النظام للوكيل. تعليمات النظام هي سلسلة تحدّد دور الوكيل وقيوده وتنسيق الإخراج.

SYSTEM_INSTRUCTION = f"""You are a Brand Strategist specializing in market research and trend analysis.

IMPORTANT: Today's date is {datetime.date.today().strftime("%B %d, %Y")}.
When conducting research, focus on current trends from {datetime.date.today().year}.
Use search queries like "[topic] trends {datetime.date.today().year}" for recent insights.

IMPORTANT: Your role is RESEARCH ONLY. You do NOT create campaign content, captions, or designs.
After providing research insights, your work is complete.

Your expertise:
- Identifying target audience insights and behaviors
- Analyzing competitor strategies
- Researching current social media trends
- Understanding platform algorithms and best practices

You have access to:
- google_search: Search the web for competitors, trends, and market insights

When given a campaign brief:
1. Use google_search to research the target audience's current interests
2. Search for and analyze 2-3 competitor brands
3. Identify 3-5 trending topics related to the product category
4. Provide high-level strategic insights - NOT specific campaign content

DO NOT create captions, copy, designs, or any campaign content.

Format your output as:
**Audience Insights:**
[Key behaviors and preferences based on research]

**Competitive Analysis:**
[What 2-3 competitors are doing - strengths and weaknesses]

**Trending Topics:**
[3-5 relevant trends to consider]

**Key Strategic Insights:**
[High-level themes and positioning opportunities]
"""

TODO 2 - Create the root_agent

بعد ذلك، استبدِل root_agent غير المكتمل بما يلي:

root_agent = Agent(
    name="brand_strategist",
    model=os.getenv("GEMINI_MODEL", "gemini-2.5-flash"),
    instruction=SYSTEM_INSTRUCTION,
    description="Brand strategist for market research, trend analysis, and competitive insights",
    tools=[google_search],
)

الاختبار محليًا باستخدام واجهة مستخدم الويب لحزمة ADK

لنختبر الآن الوكيل باستخدام واجهة مستخدم الويب الخاصة بحزمة تطوير التطبيقات، وهي واجهة دردشة مدمجة لاختبار الوكلاء قبل نشرهم على السحابة الإلكترونية.

uv run adk web agents --allow_origins='*'

وسترى ما يلي:

INFO: Started server process
INFO: Uvicorn running on http://localhost:8000

يعمل الخادم الآن داخل Cloud Shell:

لفتحها في المتصفّح، استخدِم معاينة الويب:

  1. اطّلِع على شريط أدوات Cloud Shell في أعلى الصفحة.
  2. انقر على رمز معاينة الويب (يبدو كمربّع يحتوي على سهم للأعلى، أعلى يسار شريط أدوات Cloud Shell).
  3. انقر على "تغيير المنفذ" وأدخِل 8000، ثم انقر على "تغيير ومعاينة"

يتم فتح علامة تبويب متصفّح جديدة تحتوي على واجهة مستخدم ADK على الويب. انقر على القائمة المنسدلة "اختيار وكيل" في أعلى يمين الصفحة، وستظهر لك قائمة بجميع وكلائك:

اختَر brand_strategist لبدء الاختبار:

جرِّب هذه الطلبات الاختبارية

في مربّع المحادثة في واجهة مستخدم الويب الخاصة بـ ADK، جرِّب ما يلي:

  • Research the eco-friendly water bottle market for health-conscious millennials
  • What are the top Instagram trends in the wellness space in 2025?

من المفترض أن ترى الوكيل يتصل بخدمة "بحث Google" ويعرض نتائج بحث منظَّمة تتضمّن أقسام "إحصاءات الجمهور" و"تحليل تنافسي" و"المواضيع الرائجة".

5- إنشاء تطبيق Copywriter - مهارات حزمة تطوير البرامج (ADK)

الدور: تحويل أبحاث العلامات التجارية إلى تعليقات على Instagram ينشئ كاتب الإعلانات 3 صيغ مختلفة لشرح الصور تغطي أساليب مختلفة (ملهمة، تعليمية، متعلقة بالمنتدى)، ويتضمّن كل منها عبارات هاشتاغ وعبارة تحث المستخدم على اتخاذ إجراء.

المفهوم: مهارات ADK

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

تتيح لك مهارات ADK (SkillToolset، تم طرحها في الإصدار 1.25.0 من ADK) تجميع هذه المعرفة في ملفات نموذجية بثلاثة مستويات تحميل:

  • L1 - frontmatter (name + description في SKILL.md): متوفّرة دائمًا، وتُستخدم لاكتشاف المهارات
  • L2 - التعليمات (نص SKILL.md): يتم تحميلها عندما يفعّل الوكيل المهارة
  • المستوى 3 - الموارد (ملفات references/ وassets/): يتم تحميلها فقط عندما يقرأها الوكيل بشكل صريح

يتم تقليص تعليمات النظام إلى بيان دور قصير بالإضافة إلى "تحميل المهارة قبل الكتابة". لا يتم إدخال تفاصيل النظام الأساسي في قدرة الاستيعاب إلا عندما يحتاج إليها الوكيل فعليًا.

تتوفّر مهارة "كاتب النصوص الإعلانية" في agents/copywriter/skills/instagram-copywriting/:

skills/
  instagram-copywriting/
    SKILL.md                        L1 frontmatter (discovery) + L2 instructions (loaded on trigger)
    references/
      platform-guide.md             L3: character limits, hashtag tiers, algorithm signals
      caption-formulas.md           L3: hook formulas, CTA patterns, full caption structures
    assets/
      brand-voice-examples.md       L3: annotated real-world caption examples

افتح الملف مباشرةً في محرِّر Cloud Shell:

cloudshell edit agents/copywriter/agent.py

TODO 1 - استيراد load_skill_from_dir وskill_toolset

ابحث عن التعليق # TODO 1: Import load_skill_from_dir and skill_toolset وأضِف عمليتَي الاستيراد التاليتَين:

from google.adk.skills import load_skill_from_dir
from google.adk.tools import skill_toolset

TODO 2 - تحميل المهارة وإنشاء SkillToolset

ابحث عن التعليقَين أدناه:

# TODO 2: Load the instagram-copywriting skill from the skills/ directory
# TODO 2: Create a SkillToolset with the loaded skill

استبدِلها بما يلي:

_instagram_skill = load_skill_from_dir(
    pathlib.Path(__file__).parent / "skills" / "instagram-copywriting"
)
_copywriting_skills = skill_toolset.SkillToolset(skills=[_instagram_skill])

يقرأ load_skill_from_dir الملف SKILL.md بالإضافة إلى أي ملفات في references/ وassets/. تغلف SkillToolset ذلك في التنسيق الذي تقبله وكلاء ADK، أي مجموعة أدوات وليس مهارة أولية.

TODO 3 - تسجيل مجموعة الأدوات لدى الوكيل

ابحث عن tools=[], # TODO 3: Add the SkillToolset here واستبدله بما يلي:

tools=[_copywriting_skills],

افتح ملف المهارة للاطّلاع على طريقة تنظيمه:

cloudshell edit agents/copywriter/skills/instagram-copywriting/SKILL.md

استمرار تشغيل واجهة مستخدم الويب في "حزمة تطوير التطبيقات لنظام Android" استخدِم القائمة المنسدلة الخاصة بالوكيل للتبديل إلى copywriter بدون إعادة تشغيل الخادم.

إذا لم يكن قيد التشغيل، ابدأه مرة أخرى:

uv run adk web agents --allow_origins='*'

جرِّب ذلك: بدِّل القائمة المنسدلة إلى copywriter وأرسِل:

You are writing captions for EcoFlow Smart Water Bottle targeting health-conscious millennials aged 25-35.
Audience insight: they prioritize sustainability, track health metrics, and share lifestyle content.
Competitor insight: Hydro Flask dominates with lifestyle branding; S'well leads on premium aesthetics.
Write 3 Instagram captions - one inspirational, one educational, one community-focused. Include 5 hashtags each and a CTA.

6. Build the Designer - Multimodal Image Generation

استمرار تشغيل واجهة مستخدم الويب في "حزمة تطوير التطبيقات لنظام Android" استخدِم القائمة المنسدلة الخاصة بالوكيل للتبديل بين الوكلاء بدون إعادة تشغيل الخادم.

الدور: إنشاء مفاهيم مرئية لكل تعليق توضيحي وإنشاء الصور الفعلية باستخدام ميزة إنشاء الصور الأصلية في Gemini تنتج أداة Designer مفهومًا مرئيًا واحدًا بالضبط لكل تعليق توضيحي، مع طلب تفصيلي ونمط ولوحة ألوان ومزاج وتنسيق Instagram، ثم تستدعي أداة generate_image على الفور لإنتاج الصورة الفعلية وتحميلها إلى GCS.

المفهوم: ربط وكيل نصي بنموذج صور من خلال أداة

يعمل "المصمّم" على gemini-3-flash-preview (نموذج النص الذي تم ضبطه من خلال GEMINI_MODEL في .env)، ولكن يتطلّب إنشاء الصور نموذجًا مخصّصًا (gemini-3.1-flash-image-preview). لا يتيح نموذج الصور هذا ميزة استدعاء الدوال، لذا لا يمكن استخدامه مباشرةً كوكيل في "حزمة تطوير التطبيقات" (ADK). بدلاً من ذلك، يتم تضمينها في دالة Python عادية وتسجيلها كـ FunctionTool.

هذا هو النمط المتبّع مع أي نموذج أو واجهة برمجة تطبيقات لا يمكن للنموذج اللغوي الكبير استدعاؤها مباشرةً: يتم تضمينها في أداة، ويسمح للوكيل بتحديد وقت استدعائها، ثم يتم استلام نتيجة منظَّمة.

Designer agent (text model)
        
          decides visual concept, writes image prompt
        
  generate_image tool
        
          calls gemini-3.1-flash-image-preview
          uploads result to GCS
        
  {"status": "success", "gcs_uri": "gs://..."}
        
          returned to agent, included in response
        
  Critic (receives gcs_uri, passes to Vertex AI for multimodal review)

افتح الملف مباشرةً في محرِّر Cloud Shell:

cloudshell edit agents/designer/image_gen_tool.py

يتم توفير توقيع الدالة وإعداد البيئة وإدخال نسبة العرض إلى الارتفاع. نفِّذ المهام الثلاث المدرَجة في قائمة المهام بالترتيب:

TODO 1 - استدعاء نموذج الصور في Gemini

ابحث عن التعليق # TODO 1 واستبدِله بما يلي:

        client = genai.Client(vertexai=True, project=project_id, location=location)

        response = client.models.generate_content(
            model=image_model,
            contents=prompt_with_aspect,
            config=types.GenerateContentConfig(
                response_modalities=["IMAGE", "TEXT"],
                http_options=types.HttpOptions(
                    retry_options=types.HttpRetryOptions(
                        attempts=5, exp_base=2, initial_delay=30,
                        http_status_codes=[429, 500, 503, 504],
                    ),
                    timeout=180_000,
                ),
            ),
        )

TODO 2 - استخراج وحدات البايت الخاصة بالصورة من الردّ

ابحث عن التعليق # TODO 2 واستبدِله بما يلي:

        image_bytes = None
        mime_type = "image/png"
        for part in response.candidates[0].content.parts:
            if part.inline_data is not None:
                image_bytes = part.inline_data.data
                mime_type = part.inline_data.mime_type or "image/png"
                break

        if not image_bytes:
            return {"status": "error", "error": "Gemini returned no image data"}

TODO 3 - تحميل إلى GCS وعرض معرّف الموارد المنتظم (URI)

ابحث عن التعليق # TODO 3 واستبدِله بما يلي:

        ext = "jpg" if "jpeg" in mime_type else "png"
        from google.cloud import storage
        gcs_client = storage.Client(project=project_id)
        bucket = gcs_client.bucket(bucket_name)
        blob_name = f"campaign-images/{concept_name}-{uuid.uuid4().hex[:8]}.{ext}"
        blob = bucket.blob(blob_name)
        blob.upload_from_file(io.BytesIO(image_bytes), content_type=mime_type)
        gcs_uri = f"gs://{bucket_name}/{blob_name}"

جرِّب ذلك: بدِّل القائمة المنسدلة إلى designer وأرسِل:

Create a visual concept and generate the image for an EcoFlow Smart Water Bottle Instagram post targeting health-conscious millennials.
Style: clean, modern, lifestyle-focused. Include a detailed prompt with color palette, mood, and format (1080x1080 or 1080x1350).

7. إنشاء أداة Critic - Structured Output

الدور: ضمان جودة النصوص والصور قبل تسليمها إلى مدير المشروع يقيّم Critic كلاً من المنتجات النهائية ويعرض APPROVED أو NEEDS_REVISION مع اقتراحات محدّدة. عندما تكون قيم gcs_uri متوفّرة في الإدخال، تستدعي الأداة review_image لفحص كل صورة تم إنشاؤها بصريًا قبل تقييمها.

المفهوم: متى يجب استخدام نموذج Pydantic لنتائج Gemini؟

تتعلّق القاعدة بالمستخدم الذي يستهلك الناتج:

  • يستهلك رمز Python البرمجي هذا التنسيق → استخدِم response_schema + Pydantic. لا يمكن للرمز البرمجي التعامل مع الغموض، لذا تحتاج إلى بنية مضمونة لاستخراج الحقول بشكل موثوق.
  • يستهلك النموذج اللغوي الكبير (LLM) هذا النص → تنسيق النص + تعليمات النظام كافٍ. تفهم النماذج اللغوية الكبيرة قواعد التنسيق وتسمح بالتغيير.

في review_image، يحتاج رمز Python البرمجي إلى score وapproval_status وwhat_works وissues وsuggestions كقيم مكتوبة. يفرض response_schema=_GeminiReview قيودًا على Gemini على مستوى واجهة برمجة التطبيقات لعرض JSON صالح، بينما يحلّله model_validate_json() إلى كائن مكتوب يمكن أن يستخدمه الرمز البرمجي بشكل موثوق.

class _GeminiReview(BaseModel):
    score: int = Field(ge=1, le=10)
    approval_status: Literal["APPROVED", "NEEDS_REVISION"]
    what_works: str
    issues: str
    suggestions: str

افتح الملف مباشرةً في محرِّر Cloud Shell:

cloudshell edit agents/critic/image_review_tool.py

يتم توفير نماذج Pydantic والطلب. نفِّذ المهام الثلاث المدرَجة في قائمة المهام بالترتيب:

TODO 1 - إنشاء جزء صورة من معرّف الموارد المنتظم (URI) في "خدمة التخزين السحابي من Google"

ابحث عن التعليق # TODO 1 واستبدِله بما يلي:

        image_part = types.Part.from_uri(file_uri=gcs_uri, mime_type=mime_type)

TODO 2 - Call Gemini with a structured response schema

ابحث عن التعليق # TODO 2 واستبدِله بما يلي:

        response = client.models.generate_content(
            model=model,
            contents=[image_part, prompt],
            config=types.GenerateContentConfig(
                response_schema=_GeminiReview,
                response_mime_type="application/json",
            ),
        )

TODO 3 - تحليل الردّ وعرض النتيجة

ابحث عن التعليق # TODO 3 واستبدِله بما يلي:

        review = _GeminiReview.model_validate_json(response.text)
        return ImageReviewResult(status="success", concept_name=concept_name, **review.model_dump())

جرِّب ذلك: بدِّل القائمة المنسدلة إلى critic وأرسِل:

Review this Instagram caption for an eco-friendly water bottle brand targeting millennials:
"Hydrate smarter, live greener. 💧 Our EcoFlow bottle tracks your intake, keeps your drink cold for 24h, and never touches single-use plastic. Because what you drink from matters as much as what you drink. #EcoFlow #HydrationGoals #SustainableLiving #ZeroWaste #HealthyHabits - Shop link in bio."
Score it and indicate APPROVED or NEEDS_REVISION with specific feedback.

تأكَّد من أنّ الردّ يتضمّن **POSTS REVIEW:** وStatus: APPROVED (أو NEEDS_REVISION) و**OVERALL ASSESSMENT:**. في حال توفُّر هذه الأقسام، يكون Critic جاهزًا للاتصال بأداة التنسيق.

عند الانتهاء من اختبار جميع البرامج الثلاثة، اضغط على Ctrl+C لإيقاف الخادم.

8. إنشاء وكيل مدير المشروع باستخدام MCP

تقدّم "مديرة المشاريع" مفهومًا جديدًا: بروتوكول سياق النموذج (MCP).

افتح الملف:

cloudshell edit agents/project_manager/agent.py

هذا الملف أكثر تعقيدًا، إذ يتضمّن الدالة create_project_manager_agent() مع فرعين: أحدهما بدون Notion (جداول زمنية نصية فقط) والآخر مع مجموعة أدوات Notion MCP. عليك ملء كليهما.

المشكلة التي يحلّها MCP

يحتاج الوكيل إلى طلب خدمة خارجية، مثل إنشاء صفحة في Notion. يمكنك كتابة رمز Python برمجي يستدعي Notion REST API مباشرةً. بعد ذلك:

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

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

ما هو برنامج MCP؟

‫MCP (بروتوكول سياق النموذج) هو معيار مفتوح (نشرته شركة Anthropic) لربط وكلاء الذكاء الاصطناعي بالأدوات الخارجية ومصادر البيانات. وهي تعمل مثل محوّل عالمي.

خادم MCP هو برنامج صغير يعمل على:

  1. تغليف واجهة برمجة تطبيقات خارجية (مثل Notion وGitHub وقواعد البيانات وأنظمة الملفات وما إلى ذلك)
  2. تعرض واجهة برمجة التطبيقات هذه على شكل قائمة أدوات موثّقة ومحدّدة النوع.
  3. يتواصل مع الوكيل عبر بروتوكول بسيط (stdio أو HTTP)

يتصل الوكيل بخادم MCP، ويكتشف تلقائيًا الأدوات المتاحة، ويمكنه استدعاؤها تمامًا مثل أي أداة أخرى، إذ ترى نماذج اللغات الكبيرة API-post-page(...) كدالة قابلة للاستدعاء.

ما الفرق بين A2A وMCP؟

وهذا من أكثر النقاط التي يحدث فيها التباس. في ما يلي الفرق الأساسي:

A2A

MCP

ما يتم ربطه

الوكيل ↔ الوكيل

الوكيل ↔ أداة أو خدمة خارجية

الجهة الأخرى هي

وكيل آخر للنموذج اللغوي الكبير

أداة تغليف لواجهة برمجة التطبيقات (بدون نموذج لغوي كبير)

مثال

مدير التصميم يتصل بمحلّل استراتيجي للعلامة التجارية

مدير المشروع يرسل طلبات إلى واجهة برمجة تطبيقات Notion

البروتوكول

JSON-RPC عبر HTTPS

بث stdio أو HTTP

التعريف

Google

Anthropic

فكر في الأمر بهذه الطريقة:

  • التواصل بين التطبيقات: طريقة تواصل الوكلاء مع بعضهم البعض
  • MCP = طريقة تواصل الوكلاء مع الأدوات والخدمات

في هذا المشروع، يتم استخدام كليهما معًا:

Creative Director
    
      (A2A)  Brand Strategist ─── (google_search tool built into ADK)
      (A2A)  Copywriter
      (A2A)  Designer
      (A2A)  Critic
      (A2A)  Project Manager
                   
                     (MCP)  notion-mcp-server ──► Notion REST API

طريقة عمل MCP في هذا المشروع

عند تشغيل الوكيل، يطلق ADK عملية notion-mcp-server كعملية فرعية. تتيح هذه العملية للنموذج اللغوي الكبير الوصول مباشرةً إلى الأدوات التالية:

الأداة

وظيفتها

API-retrieve-a-database

يجلب المخطط (أسماء السمات وأنواعها وقيمها الصالحة)

API-post-database-query

طلبات البحث في الصفحات الحالية

API-post-page

إنشاء صفحة جديدة

API-patch-page

تعديل صفحة حالية

تستدعي النماذج اللغوية الكبيرة هذه الدوال مثل أي دالة أخرى، فهي لا تعرف أنّها تمر عبر MCP إلى واجهة برمجة تطبيقات REST في Notion.

لماذا stdio؟ لماذا لا نستخدم بروتوكول HTTP فقط؟

يعمل خادم MCP كـ عملية فرعية للوكيل، ويتواصل عبر stdin/stdout. وهذا يعني ما يلي:

  • لا حاجة إلى منفذ شبكة إضافي
  • يدير الوكيل دورة الحياة (بدء التشغيل عند الطلب، والإيقاف عند الخروج)
  • يتم شحن كل شيء في صورة Docker واحدة، بدون الحاجة إلى خدمة منفصلة لنشرها.

(اختياري) تفعيل عملية الدمج مع Notion

يمكنك تخطّي هذا القسم بالكامل. ينتج وكيل "مدير المشروع" دائمًا جدولاً زمنيًا كاملاً للحملة يستند إلى النصوص، سواء تم استخدام Notion أم لا. في حال تخطّي عملية الإعداد هذه، سيعود الوكيل إلى وضع التشغيل في الذاكرة ويعرض المخطط الزمني كنص عادي في المحادثة. لن يحدث أي خلل، ولكن لن تظهر المهام في قاعدة بيانات Notion. انتقِل مباشرةً إلى الخطوة 1 إذا أردتَ تخطّي الخطوات.

إذا كان لديك حساب على Notion وأردت تجربة عملية الربط بـ MCP، أكمِل عملية الإعداد أدناه الآن. تشير المهام التي تلي ذلك إلى أرقام تعريف قاعدة بيانات Notion، وهذا هو المكان الذي يمكنك الحصول عليها منه.

الخطوة 1: إنشاء قاعدة بيانات Notion من نموذج

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

انقر على الرابط أدناه لإضافة القالب إلى مساحة عملك في Notion:

→ إضافة نموذج "المشاريع والمهام" إلى Notion

نموذج "المشاريع والمهام" في Notion في Marketplace

بعد إضافة قاعدة البيانات، سيكون لديك قاعدتا بيانات مرتبطتان: المشاريع والمهام. يتضمّن النموذج إدخالات نموذجية، لذا احذفها كلها قبل المتابعة لكي يبدأ الوكيل بمساحة عمل فارغة (اختَر الكل → حذف).

الخطوة 2: إنشاء عملية دمج في Notion

إنشاء عملية الدمج:

  1. انتقِل إلى notion.so/my-integrations
  2. انقر على عملية دمج جديدة → أطلق عليها اسمًا AI Creative Studio
  3. ربطها بمساحة العمل
  4. انقر على ضبط الإعدادات → تأكَّد من وضع علامة في مربّعات الاختيار الخاصة بإمكانات قراءة المحتوى وتعديل المحتوى وإدراج المحتوى

إعدادات دمج Notion - أطلِق عليها اسم "AI Creative Studio" وانسخ الرمز المميّز

  1. انسخ رمز التكامل الداخلي (ntn_...) والصقه في ملف .env:
NOTION_TOKEN=ntn_your-token-here

ربط عملية الدمج بقواعد البيانات:

  1. افتح صفحة النموذج التي نسختها للتو، ثم انقر على قاعدة بيانات المشاريع.
  2. انقر على قائمة ... (في أعلى يسار الصفحة) → عمليات الربطإضافة عملية ربط → اختَر AI Creative Studio

انقر على "عمليات الربط" في قائمة قاعدة البيانات للمشاركة مع عملية الدمج.

يظهر "استوديو الإبداع المستند إلى الذكاء الاصطناعي" كعملية ربط نشطة

  1. كرِّر الخطوات نفسها لقاعدة بيانات المهام

الحصول على أرقام تعريف قاعدة البيانات:

  1. انقر على رابط قاعدة بيانات المشاريع لفتحها، وسيتم فتحها في صفحة منفصلة بعنوان URL على النحو التالي:
https://www.notion.so/9887b6a94f7f83f68f8581e038d1aaa4?v=2c37b6a94f7f838685f1086e312c7278

فتح قاعدة بيانات "المشاريع" من صفحة النموذج

رقم تعريف قاعدة البيانات هو أول معرّف فريد عالميًا (UUID) في عنوان URL، أي كل ما يسبق ?v=:

https://www.notion.so/{DATABASE_ID}?v=...
                       ^^^^^^^^^^^^^^^^
                       9887b6a94f7f83f68f8581e038d1aaa4  ← this is your DATABASE_ID
  1. كرِّر الخطوات نفسها مع رابط قاعدة بيانات المهام للحصول على رقم تعريف قاعدة البيانات.
  2. أضِف القيم الثلاث إلى .env:
NOTION_TOKEN=ntn_your-token-here
NOTION_PROJECT_DATABASE_ID=9887b6a94f7f83f68f8581e038d1aaa4   # <-- your Projects DB ID
NOTION_TASKS_DATABASE_ID=your-tasks-db-id                      # <-- your Tasks DB ID

الخطوة 3: تثبيت خادم Notion MCP

يتصل "مدير المشروع" بتطبيق Notion من خلال حزمة @notionhq/notion-mcp-server Node.js الرسمية. تثبيته على مستوى العالم:

npm install -g @notionhq/notion-mcp-server@1.9.1

التحقّق من عملية التثبيت:

npm list -g @notionhq/notion-mcp-server

الناتج المتوقّع:

└── @notionhq/notion-mcp-server@1.9.1

notion-mcp-server: command not found

? تأكَّد من تثبيت Node.js (node --version) وأنّ مجلد npm global bin مدرَج في PATH (export PATH=$PATH:$(npm bin -g)).

الخطوة 4: التحقّق من ملف ‎ .env

افتح .env وتأكَّد من ضبط جميع قيم Notion الثلاث (أضفتها في الخطوة 2):

cloudshell edit .env
NOTION_TOKEN=ntn_...                           # integration token
NOTION_PROJECT_DATABASE_ID=...                 # Projects database ID
NOTION_TASKS_DATABASE_ID=...                   # Tasks database ID

يرصد وكيل "مدير المشروع" هذه المتغيرات تلقائيًا عند بدء التشغيل ويُفعّل مجموعة أدوات Notion MCP.

طريقة عمل ميزة "اكتشاف المخطط"

يستخدم مدير المشروع اكتشاف المخطط الديناميكي، ولا يرمز أبدًا إلى أسماء خصائص Notion:

Step 1: Call API-retrieve-a-database to discover exact property names
Step 2: Read the "properties" object in the response
Step 3: Use ONLY discovered property names (case-sensitive) in API calls
Step 4: For select/status fields, use only values from the options array

هذا يعني أنّ الوكيل يتكيّف مع أي بنية لقاعدة بيانات Notion تلقائيًا، فإذا أعدت تسمية خصائصك إلى الفرنسية أو العربية أو أي لغة أخرى، سيظل الوكيل يعمل.

المهمة 1 - كتابة تعليمات النظام

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

مهمتك هي استبدال العنصر النائب return بتعليمات نظام حقيقية تستخدم {notion_section}:

    return f"""You are a Project Manager specializing in creative campaign execution.

Today's date is {datetime.date.today().strftime("%B %d, %Y")}.
Use this as the starting point for all timelines.

Your goal: create a complete project plan for the campaign.
{notion_section}
**Project Timeline:**
Phase 1: Strategy & Research | [date]  [date] | [key activities]
Phase 2: Content Creation    | [date]  [date] | [key activities]
Phase 3: Review & Revision   | [date]  [date] | [key activities]
Phase 4: Launch & Monitoring | [date]  [date] | [key activities]

**Task List:**
| Task | Owner | Deadline | Status |
[list each task with realistic deadlines from today; set Owner to TBD]

**Budget Breakdown:**
[by category with approximate allocations]

**Milestones:**
[3-5 key checkpoints with dates]

**Notion Status:**
[What happened - e.g. "Project created (ID: xxx), 8 tasks linked" or "Notion not configured - text timeline only"]
"""

TODO 2 - Agent without Notion

داخل create_project_manager_agent()، في الفرع if not notion_token، استبدِل الوكيل غير المكتمل بما يلي:

        return Agent(
            name="project_manager",
            model=os.getenv("GEMINI_MODEL", "gemini-2.5-flash"),
            generate_content_config=GENERATE_CONTENT_CONFIG,
            instruction=get_system_instruction(),
            description="Project manager that creates campaign timelines and task breakdowns",
        )

قائمة المهام 3 - وكيل باستخدام Notion MCP

ملاحظة: يحتوي ملف البداية على دالة معاودة الاتصال handle_notion_error مكتوبة مسبقًا فوق create_project_manager_agent(). تعترض هذه الأداة أخطاء واجهة برمجة التطبيقات في Notion (400/404) وتستبدل حمولات الأخطاء الأولية برسائل واضحة وقابلة للتنفيذ، ما يتيح للنموذج اللغوي الكبير تصحيح الأخطاء بنفسه. ما عليك سوى توصيله عبر after_tool_callback.

أولاً، اقرأ معرّفَي قاعدة البيانات في أعلى create_project_manager_agent():

    notion_token           = os.getenv("NOTION_TOKEN")
    notion_project_db_id   = os.getenv("NOTION_PROJECT_DATABASE_ID")
    notion_tasks_db_id     = os.getenv("NOTION_TASKS_DATABASE_ID")

بعد ذلك، في فرع else، أنشئ مجموعة أدوات MCP والوكيل:

        from google.adk.tools.mcp_tool import McpToolset, StdioConnectionParams
        from mcp import StdioServerParameters

        server_params = StdioServerParameters(
            command="notion-mcp-server",
            env={
                "NOTION_TOKEN": notion_token,
                "PATH": os.environ.get("PATH", ""),
            }
        )
        notion_toolset = McpToolset(
            connection_params=StdioConnectionParams(
                server_params=server_params,
                timeout=30.0
            )
        )

        return Agent(
            name="project_manager",
            model=os.getenv("GEMINI_MODEL", "gemini-2.5-flash"),
            generate_content_config=GENERATE_CONTENT_CONFIG,
            after_tool_callback=handle_notion_error,
            instruction=get_system_instruction(
                project_database_id=notion_project_db_id,
                tasks_database_id=notion_tasks_db_id,
            ),
            description="Project manager with Notion integration for task tracking",
            tools=[notion_toolset],
        )

أفضل الممارسات: لا تتوقّف عن العمل بشكل نهائي عند حدوث خطأ في عمليات الدمج الاختيارية. يكون المخطط الزمني النصي دائمًا هو المنتج الأساسي، بينما يكون Notion مكمّلاً له.

اختبار "مدير المشاريع" محليًا باستخدام ADK Web

uv run adk web agents --allow_origins='*'

افتح "معاينة الويب" على المنفذ 8000. استخدِم القائمة المنسدلة الخاصة بالوكيل لاختيار project_manager، ثم جرِّب ما يلي:

Create a project plan for a GreenBrew organic coffee brand Instagram campaign.
Budget: $2,500. Launch in 3 weeks. Target audience: eco-conscious millennials aged 22-30.
Include phases, tasks with deadlines from today, and milestones.

سيظهر لك مخطط زمني منظَّم يتضمّن مراحل وقائمة مهام ومعالم رئيسية. إذا تم ضبط بيانات اعتماد Notion في .env، سينشئ الوكيل أيضًا إدخالات في مساحة عمل Notion.

9- التعرّف على بروتوكول A2A

سنستخدم بروتوكول Agent-to-Agent (A2A) لربط الوكلاء المختلفين في نظامنا. لنتعرّف على طريقة عملها.

المشكلة التي يحلّها تطبيق A2A

لنفترض أنّ لديك وكيل "خبير استراتيجي في مجال العلامات التجارية" تم إنشاؤه باستخدام ADK ووكيل "كاتب إعلانات" تم إنشاؤه باستخدام LangGraph. كيف يمكن لأحدهما الاتصال بالآخر؟ وهي تتحدث بلغات داخلية مختلفة. ستحتاج إلى كتابة رمز ربط مخصّص في كل مرة.

تحلّ A2A هذه المشكلة من خلال تحديد لغة عالمية يمكن لأي وكيل التحدث بها، بغض النظر عن إطار العمل. إنّها معيار HTTP في عالم الوكلاء، وهو معيار يتّفق عليه الجميع حتى يتمكّن أي شخص من التحدّث مع أي شخص.

ما هي خدمة A2A؟

‫Agent-to-Agent (A2A) هو معيار مفتوح للتواصل بين الوكلاء نشرته Google. يحدّد ما يلي:

  1. كيف يصف الوكيل نفسه - بطاقة الوكيل في /.well-known/agent.json
  2. كيفية استدعاء وكيل آخر له - JSON-RPC عبر HTTPS
  3. طريقة عرض النتائج - بث مباشر أو ردّ واحد

ما الذي يجعل A2A مرنًا:

  • متوافق مع لغات متعددة: يمكن لوكلاء Python التواصل مع وكلاء TypeScript
  • متوافق مع جميع الأُطر: يمكن لوكلاء ADK التحدّث إلى وكلاء LangGraph أو CrewAI
  • التوافق مع أي بنية تحتية: يمكن للوكلاء المحليين التحدّث مع الوكلاء على السحابة الإلكترونية

طريقة العمل - خطوة بخطوة

Creative Director                  Brand Strategist
      │                                  │
      │  1. GET /.well-known/agent.json  │
      │ ────────────────────────────────►│
      │  ◄──── agent card (name, url,    │
      │         skills, capabilities) ───│
      │                                  │
      │  2. POST /                       │
      │     {"method": "tasks/send",     │
      │      "params": {"message": ...}} │
      │ ────────────────────────────────►│
      │                                  │  LLM does
      │                                  │  the work...
      │  3. streaming response chunks    │
      │  ◄───────────────────────────────│
      │  ◄───────────────────────────────│
      │  ◄───────────────────────────────│

الخطوة 1 - الاكتشاف: يستردّ المنسّق بطاقة الوكيل مرة واحدة للتعرّف على اسم الوكيل وعنوان URL وإمكاناته.

الخطوة 2 - الاستدعاء: يرسل المنسّق مهمةً عبر JSON-RPC POST. يتضمّن النص الرسالة (الطلب المقدَّم إلى الخبير).

الخطوة 3 - الرد: يبثّ الخبير الرد على شكل أجزاء، تمامًا كما يحدث في طلب عادي من نموذج لغوي كبير.

بطاقة الوكيل

ينشر كل وكيل وصفًا ذاتيًا في /.well-known/agent.json. هذا التعريف يشبه بطاقة العمل، فهو يخبر العالم بما يمكن أن يفعله الوكيل ومكان الوصول إليه:

{
  "name": "brand_strategist",
  "description": "Market research and competitive analysis",
  "url": "https://brand-strategist-xyz.run.app",
  "capabilities": { "streaming": true },
  "skills": [
    {
      "id": "market_research",
      "description": "Research target audiences, competitors, and trends"
    }
  ]
}

يقرأ المنسّق هذه البطاقة لإنشاء العنصر RemoteA2aAgent، ولا حاجة إلى معرفة مسبقة بالعمليات الداخلية للمتخصّص.

عرض وكيل من خلال A2A في ADK

تلتف to_a2a() حول أي وكيل ADK في تطبيق FastAPI متوافق مع A2A. سطر واحد:

from google.adk.a2a.utils.agent_to_a2a import to_a2a

# root_agent = your normal ADK Agent(...)
a2a_app = to_a2a(root_agent, host=PUBLIC_HOST, port=PUBLIC_PORT, protocol=PROTOCOL)
uvicorn.run(a2a_app, host=HOST, port=PORT)

يؤدي ذلك تلقائيًا إلى إنشاء ما يلي:

  • /.well-known/agent.json - بطاقة موظّف الدعم
  • /: نقطة نهاية JSON-RPC (تنتقل جميع طلبات مهام A2A إلى المسار الجذر)

10. عرض الوكلاء كخدمات من تطبيق إلى تطبيق

لعرض الوكلاء كخدمات A2A، يمكنك استخدام الدالة المساعدة to_a2a() من ADK.

طريقة عمل to_a2a()

from google.adk.a2a.utils.agent_to_a2a import to_a2a

a2a_app = to_a2a(root_agent, host=PUBLIC_HOST, port=PUBLIC_PORT, protocol=PROTOCOL)
uvicorn.run(a2a_app, host=HOST, port=PORT)

تغلّف to_a2a() وكيل ADK في تطبيق FastAPI يعرض تلقائيًا ما يلي:

  • /.well-known/agent.json - بطاقة الوكيل (الاسم والوصف والإمكانات)
  • /a2a/{agent_name}: نقطة نهاية JSON-RPC لتلقّي المهام

يتضمّن رمز الهيكل لكل وكيل حاليًا كتلة __main__ تعمل على تضمين الوكيل في خادم A2A باستخدام to_a2a(). لست بحاجة إلى كتابة هذا الرمز، بل سيتم توفيره لك.

التعرّف على إعداد عنوانَي URL

عند تشغيل python agent.py، يستخدم الحظر __main__ إعدادَين منفصلَين لعناوين URL:

# Where the server actually listens (network interface):
HOST = "0.0.0.0"
PORT = 8082  # Brand Strategist (others use 80838086 locally)

# What gets advertised in the agent card (the address other agents use to reach it):
PUBLIC_HOST = os.getenv("PUBLIC_HOST", "localhost")
PUBLIC_PORT = int(os.getenv("PUBLIC_PORT", str(PORT)))
PROTOCOL    = os.getenv("PROTOCOL", "http")

a2a_app = to_a2a(root_agent, host=PUBLIC_HOST, port=PUBLIC_PORT, protocol=PROTOCOL)
uvicorn.run(a2a_app, host=HOST, port=PORT)

البيئة

HOST:PORT (مرات الاستماع)

PUBLIC_HOST:PUBLIC_PORT (معلن عنه في بطاقة الوكيل)

بالتوقيت المحلي

0.0.0.0:8082

http://localhost:8082

Cloud Run

0.0.0.0:8080

https://brand-strategist-xyz.run.app:443

محليًا، يشير كلاهما إلى الجهاز نفسه. في Cloud Run، يستمع الحاوي داخليًا على 8080، ولكن يجب أن تعلن بطاقة الوكيل عن عنوان URL العام الذي يستخدم HTTPS، وإلا لن يتمكّن المدير الإبداعي من التواصل مع الخبير من خارج الحاوية.

ابدأ تشغيل جميع خوادم A2A المتخصصة الخمسة

لننفّذ جميع العمليات التي يجريها الخبراء الخمسة كخوادم A2A في الوقت نفسه، ثم نختبر "مدير التصميم" محليًا مع توجيهه إلى هذه العمليات.

افتح 5 نوافذ طرفية منفصلة في Cloud Shell (انقر على الرمز + في شريط علامات تبويب النافذة الطرفية) وشغِّل وكيلاً واحدًا لكل نافذة طرفية.

uv run يفعّل .venv تلقائيًا، بدون الحاجة إلى source يدوي في كل نافذة طرفية.

الوحدة الطرفية 1 - استراتيجي العلامة التجارية (المنفذ 8082):

cd ~/ai-creative-studio/workshop/starter
PORT=8082 uv run agents/brand_strategist/agent.py

Terminal 2 - Copywriter (port 8083):

cd ~/ai-creative-studio/workshop/starter
PORT=8083 uv run agents/copywriter/agent.py

الوحدة الطرفية 3 - المصمم (المنفذ 8084):

cd ~/ai-creative-studio/workshop/starter
PORT=8084 uv run agents/designer/agent.py

الوحدة الطرفية 4 - الناقد (المنفذ 8085):

cd ~/ai-creative-studio/workshop/starter
PORT=8085 uv run agents/critic/agent.py

الوحدة الطرفية 5 - مدير المشروع (المنفذ 8086):

cd ~/ai-creative-studio/workshop/starter
PORT=8086 uv run agents/project_manager/agent.py

ضبط عناوين URL الخاصة بالمضيف المحلي في ملف ‎ .env

في المحطة 6، عدِّل .env باستخدام عناوين URL الخاصة بالوكيل المحلي حتى يتمكّن المدير الإبداعي من العثور عليها:

cd ~/ai-creative-studio/workshop/starter

sed -i \
  -e 's|STRATEGIST_AGENT_URL=.*|STRATEGIST_AGENT_URL=http://localhost:8082|' \
  -e 's|COPYWRITER_AGENT_URL=.*|COPYWRITER_AGENT_URL=http://localhost:8083|' \
  -e 's|DESIGNER_AGENT_URL=.*|DESIGNER_AGENT_URL=http://localhost:8084|' \
  -e 's|CRITIC_AGENT_URL=.*|CRITIC_AGENT_URL=http://localhost:8085|' \
  -e 's|PM_AGENT_URL=.*|PM_AGENT_URL=http://localhost:8086|' \
  .env

فحص الوكلاء باستخدام أداة A2A Inspector

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

ما يعرضه لك:

  • بطاقة الوكيل: البيانات الوصفية المنظَّمة التي يعلن عنها الوكيل، مثل اسمه ووصفه وأوضاع الإدخال/الإخراج المتوافقة وعنوان URL لنقطة النهاية هذا ما يقرأه "مخرج تصميم الإعلان" عندما يعثر على خبير.
  • واجهة المحادثة: يمكنك إرسال أي رسالة إلى الوكيل عبر A2A والاطّلاع على الرد الأولي. يمكنك اختبار الطلبات بشكل منفصل قبل ربط الوكلاء ببعضهم.
  • التحقّق من صحة البروتوكول: يتحقّق المدقّق من أنّ بطاقة الوكيل تتوافق مع مواصفات A2A، ويعرض الحقول الناقصة أو الردود المشوّهة في وقت مبكر.

أهمية ذلك: عند النشر إلى Cloud Run لاحقًا، يكتشف "المدير الإبداعي" كل خبير من خلال استرداد بطاقة الوكيل من /.well-known/agent.json. إذا كانت البطاقة غير صحيحة، أي عنوان URL غير صالح أو قدرات غير متوفّرة، سيتعذّر على أداة التنسيق تنفيذ العملية بدون إظهار أي رسالة خطأ. يتيح لك الفاحص رصد هذه المشاكل محليًا قبل أي عملية نشر على السحابة الإلكترونية.

بطاقة وكيل محلّل إستراتيجي للعلامة التجارية

تعرض بطاقة الوكيل هوية الاختصاصي وإمكاناته تمامًا كما يراها الوكلاء الآخرون.

معلومات بطاقة الدفع للوكيل

تثبيت أداة الفحص وبدء استخدامها

cd ~/ai-creative-studio/workshop
./setup_inspector.sh

تعديل .env هو أمر يُنفَّذ لمرة واحدة. استخدِم Terminal 6 لبدء "أداة الفحص" بعد ذلك:

cd ~/a2a-inspector
bash scripts/run.sh

لفتح واجهة مستخدم "أداة الفحص"، استخدِم معاينة الويبتغيير المنفذ → اكتب 5001.

التواصل مع المحلّل الاستراتيجي للعلامة التجارية

أدخِل http://localhost:8082 في حقل عنوان URL الخاص بأداة الفحص وانقر على ربط. يجلب المدقّق بطاقة الوكيل ويعرض البيانات الوصفية الخاصة بالأخصائي.

أداة A2A Inspector مرتبطة بأداة Brand Strategist

المعلومات التي تعرضها بطاقة الوكيل

بطاقة الوكيل هي أكثر من مجرد بيانات وصفية، فهي عقد القدرة الكاملة الذي يعلنه الوكيل على الشبكة. يمكنك التواصل مع مدير المشروع (http://localhost:8086) للاطّلاع على أغنى مثال:

{
  "name": "project_manager",
  "description": "Project manager with Notion integration for task tracking",
  "protocolVersion": "0.3.0",
  "defaultInputModes": ["text/plain"],
  "defaultOutputModes": ["text/plain"],
  "skills": [
    {
      "id": "project_manager",
      "name": "model",
      "tags": ["llm"],
      "description": "... full system instruction including today's date and Notion database IDs ..."
    },
    {
      "id": "project_manager-API-post-page",
      "name": "API-post-page",
      "tags": ["llm", "tools"],
      "description": "Notion | Create a page"
    },
    {
      "id": "project_manager-API-retrieve-a-database",
      "name": "API-retrieve-a-database",
      "tags": ["llm", "tools"],
      "description": "Notion | Retrieve a database"
    }
  ]
}

تتميّز هذه الأغنية بثلاثة عناصر:

1. أدوات MCP تصبح مهارات A2A: يتم إدراج كل أداة من أدوات Notion التي يمكن لمدير المشروع الوصول إليها (API-post-page وAPI-retrieve-a-database وما إلى ذلك) كمهارة منفصلة في بطاقة الوكيل. يمكن لأي وكيل آخر على الشبكة معرفة الأدوات التي يمكن لهذا الوكيل استخدامها بالضبط، بدون قراءة أي رمز.

2. تعليمات النظام مضمّنة: يحتوي description الخاص بالمهارة الأولى على تعليمات النظام الكاملة، بما في ذلك تاريخ اليوم ومعرّفات قاعدة بيانات Notion. بهذه الطريقة، يعرف المدير الإبداعي ما يجب تمريره عند الاتصال بمدير المشروع.

3. عنوان URL هو نقطة النهاية المباشرة - الحقل url هو بالضبط ما تستخدمه RemoteA2aAgent عندما يتصل مدير التصميم بهذا الاختصاصي. إذا كان عنوان URL في البطاقة غير صحيح، لن يتمكّن المنسّق من الوصول إلى الوكيل.

لهذا السبب، تُعدّ أداة الفحص أداة فعّالة لتصحيح الأخطاء: فبإلقاء نظرة واحدة على بطاقة الوكيل، يمكنك معرفة ما إذا كان الوكيل يعمل، والأدوات التي يتضمّنها، وما إذا كانت نقطة النهاية صحيحة.

إرسال رسالة اختبار

بعد الاتصال، اكتب طلبًا في لوحة المحادثة وأرسِله. يرسل المدقّق الطلب كمهمة A2A ويبثّ الردّ، بالطريقة نفسها التي سيستخدم بها المدير الإبداعي هذا الوكيل في مرحلة الإنتاج.

الدردشة مع &quot;استشاري العلامة التجارية&quot; من خلال &quot;أداة فحص التطبيقات&quot;

وجِّه أداة الفحص إلى أي منفذ محلي (8082–8086) لاختبار كل أداة متخصصة على حدة.

11. إنشاء أداة تنسيق المخرج الإبداعي

مدير التصميم هو المنسّق الرئيسي. يقرأ عناوين URL المتخصصة من متغيرات البيئة، ويغلّف كل عنوان URL كـ RemoteA2aAgent، ويعرضها كـ AgentTool يمكن للنموذج اللغوي الكبير استدعاؤها.

تأكَّد من أنّ 5 وكلاء متخصصين لا يزالون يعملون (المحطات 1 إلى 5 من الخطوة 10).

في المبنى 6 (مبنى مفتش A2A)، أوقِف المفتش باستخدام Ctrl+C.

افتح الملف:

cd ~/ai-creative-studio/workshop/starter
cloudshell edit agents/creative_director/agent.py

يحتوي هذا الملف على ثلاث مهام معلّقة. اتّبِع هذه الخطوات بالترتيب.

TODO 1 - مراجعة تعليمات النظام المكتوبة مسبقًا

تتوفّر تعليمات النظام في prompt.py في الدليل نفسه، ويتم استيرادها تلقائيًا:

from .prompt import SYSTEM_INSTRUCTION_TEMPLATE

افتح prompt.py لقراءته قبل المتابعة:

cloudshell edit agents/creative_director/prompt.py

من المهم فهمها لأنّها تتحكّم في سلوك التنسيق بأكمله.

لماذا يتحكّم طلب المنسّق في كل شيء؟

افتح prompt.py بجانب هذا القسم، فالأمثلة أدناه تشير إلى أجزاء معيّنة منه.

إنّ الطلب في prompt.py ليس مجرد مستندات، بل هو مستوى التحكّم في النظام بأكمله. يؤدي طلب التنظيم السيئ البنية إلى ما يلي: استدعاء الوكلاء بترتيب غير صحيح، وإنشاء المحتوى من خلال المنظّم بدلاً من المتخصصين، واستمرار سير العمل بعد حدوث أخطاء، وإسقاط السياق بدون إشعار بين الوكلاء. تمنع هذه العناصر التسعة حدوث الأخطاء الأكثر شيوعًا:

العنصر 0 - التخطيط أولاً، ثم التنفيذ

هذا هو العنصر الأكثر أهمية. قبل الاتصال بأي أخصائي، يتم توجيه أداة التنسيق إلى عرض خطة مرقّمة:

I'll create your campaign by coordinating the specialist agents in sequence:
1. Brand Strategist - develop positioning and audience insights
2. Copywriter - write captions using those insights
3. Visual Designer - create image prompts aligned with the copy
4. Critic - review and score the full package
5. Project Manager - build the timeline and task breakdown

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

العنصر 1 - تعريف الدور بشكل صريح

❌ "You are a helpful creative assistant."
✅ "You orchestrate specialists. You do NOT write captions, designs, or timelines yourself."

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

العنصر 2 - بنية استدعاء الأدوات مع إدراج أنماط خاطئة

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

✅ copywriter(request="...")          ← correct
❌ print(copywriter(...))             ← breaks silently
❌ default_api.copywriter(...)        ← breaks silently
❌ copywriter.run(...)                ← breaks silently
❌ agents.copywriter(...)             ← breaks silently

أدّى إدراج الأنماط الخاطئة بشكل صريح إلى خفض عدد طلبات الأدوات غير الصالحة بنسبة% 95 تقريبًا في مرحلة الإنتاج.

العنصر 3: التنفيذ التسلسلي الموضّح خطوة بخطوة

a) Call the tool
b) Wait for tool_output
c) Verify the output is not an error
d) Confirm to the user: "✓ Brand Strategist complete"
e) Then move to the next agent

بدون الخطوتَين (ب) و (ج)، سيتصل النموذج اللغوي الكبير أحيانًا بوكيلَين في الوقت نفسه، أو سيفترض النجاح وينتقل إلى الخطوة التالية قبل تلقّي الردّ.

العنصر 4 - توجيهات الخطأ: STOP وreport وdo not proceed

في الإصدارات الأولى، كان المنسّق يتلقّى خطأً من أحد الخبراء، ويصنع إخراجًا معقولاً له، ثم ينتقل إلى الوكيل التالي. حصل المستخدم على حملة تبدو مكتملة تم إنشاؤها استنادًا إلى أساس من البيانات المتخيّلة. الحلّ واضح: التوقّف فورًا. أبلِغ عن الخطأ بالضبط. عدم المتابعة مطلقًا

العنصر 5 - قواعد تمرير السياق

لا يملك العملاء عن بُعد سجلّ محادثات. عندما يطلب منسّق العمل من كاتب النصوص إجراء عملية عبر A2A، يرى كاتب النصوص الرسالة في هذا الطلب الفردي فقط، ولا يعرف ما قاله خبير استراتيجية العلامة التجارية. يجب أن يجمع المنسّق بشكل صريح النواتج السابقة في كل استدعاء لاحق:

copywriter(request="Create 3 posts for EcoFlow water bottle targeting millennials.
Use these insights from the Brand Strategist: [paste full strategist output here].
Create engaging captions with hashtags.")

توضّح التعليمات ذلك صراحةً: "لا يمكن للوكلاء البعيدين الوصول إلى الذاكرة المشتركة، لذا يجب تمرير النواتج السابقة بشكل صريح". وبدون ذلك، يعمل كل وكيل بدون معرفة السياق.

العنصر 6 - تصنيف الطلب: بسيط مقابل معقّد

لا يحتاج كل طلب إلى جميع العملاء الخمسة. يطلب الأمر من أداة التنسيق تصنيف الطلب قبل التخطيط:

SIMPLE  → one agent needed
  "Research the eco-friendly water bottle market" → brand_strategist only
  "Write 3 Instagram captions"                    → copywriter only

COMPLEX → all agents sequentially
  "Create a complete campaign with timeline"      → all 5 agents

بدون هذا التصنيف، سيشغّل المنسّق جميع الوكلاء الخمسة لكل طلب، بما في ذلك "أريد 3 أفكار لمنشورات"، ما يؤدي إلى إضافة وقت استجابة وتكلفة غير ضروريين.

العنصر 7 - قواعد التواصل: عرض النتائج الكاملة بدون فلترة

يجب أن يكون الطلب واضحًا بأنّه على أداة التنسيق عدم تلخيص أو تعديل ما يقدّمه الخبراء:

- DO NOT summarize unless the output exceeds 2000 words
- DO NOT filter or edit agent responses
- Show the user exactly what each specialist produced
- NEVER say results are ready unless you received them in tool_output

وبدون ذلك، يعيد المنسّق كتابة نتائج الاختصاصيين بأسلوبه الخاص، ما يؤدي إلى فقدان التفاصيل وحدوث أخطاء وإبطال الغرض من الاستعانة بالاختصاصيين.

العنصر 8 - إكمال سير العمل: لا تتوقّف مبكرًا أبدًا

أحد أنماط الأعطال الدقيقة ولكنها مهمة: يعلن المنسّق عن خطة من 5 خطوات، ويكمل 3 خطوات، ثم يعرض النتائج كما لو تم إنجازها. يمنع الطلب ذلك من خلال قائمة تحقّق صريحة يجب اجتيازها قبل أن يتمكّن المنسّق من إنهاء العملية:

✓ Did I announce a plan with N agents?
✓ Have I called ALL N agents from my plan?
✓ Did each agent respond successfully?
✓ Am I presenting complete results from ALL agents?

If any answer is NO → continue executing the remaining agents.

يمنع ذلك أداة التنسيق من التعامل مع عملية التشغيل الجزئية على أنّها مكتملة.

حلقة مراقبة الجودة

إنّ خطوات المراجعة هي الجزء الأكثر تعقيدًا في prompt.py. افتح قسم ## REVISION WORKFLOW واتّبِع الخطوات.

آلية العمل

بعد أن يقدّم الناقد ملاحظاته، لا يواصل المدير الإبداعي العمل بشكل أعمى مع مدير المشروع. يقرأ هذا النموذج ناتج "الناقد" ويتفرّع إلى ما يلي:

Critic output
      │
      ├── "All Approved: YES"
      │         └──► proceed to Project Manager
      │
      └── "Status: NEEDS_REVISION"
                │
                ├── posts fail   → call copywriter again with feedback
                ├── visuals fail → call designer again with feedback
                └── both fail    → call copywriter, then designer
                          │
                          └──► revised output → Project Manager
                               (1 revision max per deliverable)

هذه الميزة مستندة إلى نماذج اللغات الكبيرة، وليس إلى الرموز البرمجية

ذكرتُ في الدرس العملي السابق أنّ أداة التنسيق "تحلّل" ردّ أداة Critic. لا يوجد رمز Python برمجي ينفّذ عملية التحليل هذه، أي لا توجد تعبيرات عادية ولا مطابقة للسلاسل. "المدير الإبداعي" هو نموذج لغوي كبير يقرأ تعليماته الخاصة. تنصّ هذه التعليمات على ما يلي:

Look for "Status: NEEDS_REVISION" in the critic's response.
Posts need revision  → call copywriter
Visuals need revision → call designer

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

كيف تتم إعادة توجيه السياق في مكالمة مراجعة؟

يتبع طلب المراجعة قاعدة تمرير السياق نفسها من العنصر 5، أي يجب أن يتضمّن المنسّق كل شيء بشكلٍ صريح لأنّ كاتب النصوص لا يتذكّر الإصدار الأول:

"I need you to revise the Instagram posts based on critic feedback.

ORIGINAL BRIEF:
[the original user request]

YOUR FIRST VERSION:
[the posts the copywriter created]

CRITIC FEEDBACK (Score: 6/10 - NEEDS_REVISION):
[the critic's specific suggestions]

Please revise the posts addressing this feedback while maintaining
the strengths the critic identified."

بدون قسم "النسخة الأولى"، سيكتب "كاتب النصوص" من البداية بدلاً من تحسين ما أنتجه سابقًا.

الحدّ الأقصى المسموح به للتعديلات وسبب أهميته

بعد جولة مراجعة واحدة، ينتقل المنسّق إلى مدير المشروع بغض النظر عن النتيجة. تتتبّع التعليمات ذلك ذهنيًا على النحو التالي:

After calling copywriter for revision once:
→ mark "copywriter_revised = true" in context
→ even if the critic still suggests changes, proceed to PM

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

ما الذي يتم تمريره إلى مدير المشروع؟

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

TODO 2 - Register each specialist as a RemoteA2aAgent + AgentTool

ابحث عن التعليق # TODO 2: For each specialist URL... واستبدِله بما يلي:

    if strategist_url:
        available_agents_list.append(
            "- **brand_strategist**: Market research, competitor analysis, trend identification"
        )
        strategist_agent = RemoteA2aAgent(
            name="brand_strategist",
            description="Researches markets, competitors, and trends using Google Search",
            agent_card=f"{strategist_url}/.well-known/agent.json",
        )
        agent_tools.append(AgentTool(agent=strategist_agent))

    if copywriter_url:
        available_agents_list.append(
            "- **copywriter**: Instagram captions, hashtags, and CTAs"
        )
        copywriter_agent = RemoteA2aAgent(
            name="copywriter",
            description="Creates Instagram captions with hashtags and CTAs",
            agent_card=f"{copywriter_url}/.well-known/agent.json",
        )
        agent_tools.append(AgentTool(agent=copywriter_agent))

    if designer_url:
        available_agents_list.append(
            "- **designer**: Visual concepts and real images generated via Gemini (GCS URIs returned)"
        )
        designer_agent = RemoteA2aAgent(
            name="designer",
            description="Creates visual concepts and generates real images via Gemini, stored in GCS",
            agent_card=f"{designer_url}/.well-known/agent.json",
        )
        agent_tools.append(AgentTool(agent=designer_agent))

    if critic_url:
        available_agents_list.append(
            "- **critic**: Quality review with APPROVED/NEEDS_REVISION scoring"
        )
        critic_agent = RemoteA2aAgent(
            name="critic",
            description="Reviews campaign materials and returns structured quality feedback",
            agent_card=f"{critic_url}/.well-known/agent.json",
        )
        agent_tools.append(AgentTool(agent=critic_agent))

    if pm_url:
        available_agents_list.append(
            "- **project_manager**: Project timelines, task breakdowns, Notion integration"
        )
        pm_agent = RemoteA2aAgent(
            name="project_manager",
            description="Creates project timelines and task breakdowns, optionally in Notion",
            agent_card=f"{pm_url}/.well-known/agent.json",
        )
        agent_tools.append(AgentTool(agent=pm_agent))

TODO 3 - Wrap in an App with context compaction

سبب ضرورة الضغط

يتم إلحاق كل رسالة في محادثة - طلب المستخدم وكل طلب أداة وكل رد أداة - بقدرة الاستيعاب التي يقرأها النموذج اللغوي الكبير في الجولة التالية. في سير عمل يتضمّن 5 وكلاء، تتراكم هذه التكاليف بسرعة:

Turn 1:  user prompt                           ~200 tokens
Turn 2:  orchestrator plan                     ~300 tokens
Turn 3:  brand_strategist tool_call            ~150 tokens
Turn 4:  brand_strategist tool_output          ~1,500 tokens   full research report
Turn 5:  copywriter tool_call                  ~300 tokens     must include strategist output
Turn 6:  copywriter tool_output                ~2,000 tokens   3 captions
Turn 7:  designer tool_call                    ~500 tokens
Turn 8:  designer tool_output                  ~1,500 tokens
...

بحلول Agent 4 (الناقد)، تحتوي قدرة الاستيعاب على الناتج الكامل لجميع الوكلاء الثلاثة السابقين، أي ما يتراوح غالبًا بين 8,000 و12,000 رمز مميز في ردود الأدوات فقط. حتى مع قدرة الاستيعاب الكبيرة في Gemini 2.5‎ Pro، تنخفض جودة الاستدلال في أداة التنسيق لأنّها مضطرة إلى الاطّلاع على سجلّ متزايد باستمرار. بدون ضغط، تصل مسارات العمل الطويلة إلى حدود عملية حول "العميل 4".

وظيفة الضغط

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

Without compaction:
  [full strategist output] + [full copywriter output] + [full designer output] + → Critic

With compaction (interval=3, overlap=1):
  [summary of strategist + copywriter] + [full designer output] + → Critic

يحافظ الملخّص على الحقائق الأساسية (الإحصاءات الرئيسية والتعليقات والشرح المعتمدة والمفاهيم المرئية) مع تجاهل التنسيق المطوّل والسياق المتكرّر الذي يتم تمريره إلى كل وكيل والاستدلال الوسيط. لا يزال بإمكان "الناقد" الوصول إلى كل ما يحتاج إليه للتقييم، ولكنّه يقرأ ملخّصًا بدلاً من ثلاثة تقارير كاملة.

الرمز

ابحث عن التعليق # TODO 3: Wrap the agent in an App... واستبدِل العنصر النائب App(...) بما يلي:

    from google.adk.apps import App
    from google.adk.apps.app import EventsCompactionConfig
    from google.adk.apps.llm_event_summarizer import LlmEventSummarizer
    from google.adk.models import Gemini

    compaction_config = EventsCompactionConfig(
        summarizer=LlmEventSummarizer(llm=Gemini(model_id=os.getenv("GEMINI_MODEL", "gemini-2.5-flash"))),
        compaction_interval=3,   # Summarize after every 3 agent completions
        overlap_size=1,          # Keep the most recent agent's output in full
    )

    app = App(
        name="creative_director",
        root_agent=agent,
        events_compaction_config=compaction_config,
        plugins=[LoggingPlugin()],
    )
    return agent, app

compaction_interval=3: يتم تشغيل عملية الضغط بعد كل 3 عمليات إكمال من قِبل الوكيل. بالنسبة إلى مسار مؤلّف من 5 وكلاء، يعني ذلك أنّه يتم تشغيله مرة واحدة (بعد الوكلاء من 1 إلى 3)، ثم يرى "الناقد" و"مدير المنتج" ملخّصًا للوكلاء من 1 إلى 3 بالإضافة إلى الناتج الكامل للوكيل السابق.

overlap_size=1: يتم دائمًا الاحتفاظ بالناتج الكامل لأحدث وكيل كما هو، ولا يتم تلخيصه أبدًا. هذا الأمر مهم لأنّ الناقد يحتاج إلى الناتج الكامل للمصمّم، بما في ذلك قيم gcs_uri، لتحميل الصور الفعلية ومراجعتها. وسيؤدي ذلك إلى فقدان معرّفات الموارد الموحّدة هذه في الملخّص.

كيفية عملها في دورة تشغيل حملة كاملة:

Agent 1 (Strategist)  → full context
Agent 2 (Copywriter)  → full context
Agent 3 (Designer)    → full context
                        ↓ compaction fires: summarizes agents 1-2, keeps 3 in full
Agent 4 (Critic)      → sees [summary of 1-2] + [full output of 3]
Agent 5 (PM)          → sees [summary of 1-3] + [full output of 4]

فهم RemoteA2aAgentوAgentTool

RemoteA2aAgent("brand_strategist", agent_card=url)
     
       wraps the remote service so ADK can call it
     
AgentTool(agent=strategist_agent)
     
       exposes it as a callable tool to the LLM
     
Agent(tools=[...])
     
       LLM calls tool("brand_strategist", message=...) when needed
     
brand-strategist-xxxx.run.app   actual HTTP A2A call happens here

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

اختبار "مدير الإبداع" على الجهاز

uv run adk web agents --allow_origins='*'

افتح "معاينة الويب" على المنفذ 8000. استخدِم القائمة المنسدلة الخاصة بالوكيل لاختيار creative_director، ثم جرِّب ما يلي:

Research the eco-friendly water bottle market for health-conscious millennials

ستلاحظ أنّ "المدير الإبداعي" سيوجّه هذا الطلب إلى "استراتيجي العلامة التجارية" فقط، وستتلقّى ردًا من "استراتيجي العلامة التجارية".

بالنسبة إلى الحملة الكاملة، جرِّب ما يلي:

Create a complete Instagram campaign for SolarPack portable solar charger targeting
outdoor enthusiasts and digital nomads aged 22-35.
Budget $2,000, launch in 2 weeks.

سيلاحظ المستخدم أنّ المدير الإبداعي ينسّق عمل جميع الخبراء الخمسة بالتسلسل، حيث تتدفّق نتائج كلّ وكيل إلى الوكيل التالي.

عرض توضيحي: تنفيذ حملة شاملة

أوقِف "المدير الإبداعي" (Creative Director) (Ctrl+C) قبل المتابعة، لأنّ أداة فحص A2A تستخدم المنفذ 8000 أيضًا.

أوقِف الخوادم الخمسة المتخصّصة (Ctrl+C في كل وحدة طرفية) عند الانتهاء من الاختبار المحلي.

12. نشر وكلاء المتخصّصين واختبارهم

نحن الآن جاهزون لنشر الوكلاء على Google Cloud. ‫Cloud Run هي خدمة رائعة لنشر الوكلاء. وهي بلا خادم وقابلة للتوسيع وسهلة الاستخدام. يتم نشر كل وكيل متخصص كخدمة مستقلة في Cloud Run.

إعدادات النشر

يتّبع Dockerfile لكل متخصص النمط التالي:

FROM python:3.12-slim
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends gcc curl

# Fast dependency install with uv
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
COPY pyproject.toml .
RUN uv sync --no-install-project --no-dev

COPY . .
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
USER appuser

ENV PYTHONUNBUFFERED=1 PORT=8080 HOST=0.0.0.0
EXPOSE 8080
CMD ["uv", "run", "python", "agent.py"]

نشر جميع الخبراء الخمسة بالتسلسل

cd ~/ai-creative-studio/workshop/starter
source .env

uv run deploy/deploy_all_specialists.py

ينشر هذا النص البرمجي جميع الوكلاء الخمسة واحدًا تلو الآخر (إجمالي المدة من 10 إلى 12 دقيقة تقريبًا). تتجنّب عملية النشر المتسلسلة حصة الاستطلاع في Cloud Build (60 طلبًا في الدقيقة). عند اكتمال العملية، يتم إعادة كتابة عنوان URL الخاص بكل وكيل في Cloud Run إلى .env.

بعد نشر "أداة التصميم"، يمنح النص البرمجي تلقائيًا حساب خدمة Cloud Run إذن roles/storage.objectCreator على حزمة GCS، ما يتيح له تحميل الصور التي تم إنشاؤها.

إذا كنت قد أعددت بيانات اعتماد Notion في .env، سيخزّن النص البرمجي أيضًا بيانات الاعتماد بشكل آمن في Secret Manager (مثل notion-token وnotion-project-db-id وnotion-tasks-db-id) وسيدرجها في خدمة Project Manager من خلال --set-secrets بدلاً من متغيّرات البيئة العادية. وهذا يعني أنّ الرمز المميز لا يظهر أبدًا في علامة التبويب "البيئة" في Cloud Run أو في سجلّ الأوامر gcloud.

التحقّق من عمليات النشر

عند اكتمال عملية النشر، يكتب النص البرمجي تلقائيًا عناوين URL الخاصة بخدمة Cloud Run مرة أخرى إلى .env، ما يؤدي إلى استبدال عناوين URL الخاصة بالمضيف المحلي من الخطوة السابقة:

source .env

echo "Deployed URLs:"
echo "  Brand Strategist: $STRATEGIST_AGENT_URL"
echo "  Copywriter:       $COPYWRITER_AGENT_URL"
echo "  Designer:         $DESIGNER_AGENT_URL"
echo "  Critic:           $CRITIC_AGENT_URL"
echo "  Project Manager:  $PM_AGENT_URL"

سيستخدم "مدير التصميم" عناوين URL هذه في Cloud Run تلقائيًا عند نشرها في Agent Runtime في الخطوة التالية.

تأكيد بطاقات الوكيل

يعرض كل وكيل تم نشره بطاقة وكيل على /.well-known/agent.json. استرجِعها للتأكّد من أنّ كل شيء متاح:

source .env

for agent_url in $STRATEGIST_AGENT_URL $COPYWRITER_AGENT_URL $DESIGNER_AGENT_URL $CRITIC_AGENT_URL $PM_AGENT_URL; do
    echo "=== Agent Card: $agent_url ==="
    curl -s "${agent_url}/.well-known/agent.json" | python3 -m json.tool | grep -E '"name"|"url"|"description"'
    echo ""
done

الناتج المتوقّع لكل وكيل:

"name": "brand_strategist",
"url": "https://brand-strategist-xxxx.run.app",
"description": "Brand strategist for market research and competitive insights"

الاختبار باستخدام "أداة فحص التطبيقات إلى التطبيقات" (Cloud Run)

تم تثبيت "أداة فحص التطبيقات إلى السيارات" في الخطوة 10. ابدأها:

cd ~/a2a-inspector
bash scripts/run.sh

افتح "معاينة الويب" → تغيير المنفذ5001. أدخِل عنوان URL الخاص بـ Cloud Run في حقل الربط:

https://brand-strategist-xxxx.us-central1.run.app

انقر على ربط - لا حاجة إلى رمز مصادقة لأنّ الخدمات يتم نشرها باستخدام --allow-unauthenticated.

يتصل المدقّق ببطاقة الوكيل ويتحقّق من صحتها، ويتيح لك الدردشة بشكل تفاعلي عبر A2A.

فحص الوكلاء الذين تم نشرهم على Cloud Run

بعد النشر على Cloud Run، وجِّه أداة الفحص إلى عنوان URL العام لبروتوكول HTTPS للتأكّد من أنّ عملية النشر على السحابة الإلكترونية تعمل:

أداة A2A Inspector مرتبطة بوكيل Cloud Run

مسار العمل هو نفسه: الصق عنوان URL الخاص بـ Cloud Run، ثم اربط الحساب وأرسِل رسالة اختبار. إذا تم تحميل بطاقة الوكيل واستجاب الدردشة، يعني ذلك أنّه تم نشر الاختصاصي بشكل صحيح ويمكن التواصل معه.

13. نشر "مدير التصميم" في "بيئة تشغيل الوكيل"

يتم نشر أداة التنسيق في بيئة تشغيل الوكيل، التي توفّر حالة جلسة مُدارة وتدرّج تلقائي وتتبُّع مدمج.

لماذا يجب استخدام Agent Runtime لمنسّق العمليات؟

يتم نشر الخبراء الخمسة في Cloud Run، وهو خدمة خفيفة الوزن وبدون حالة، ويتولّى كل خبير مهمة واحدة. يجب أن يستوفي مدير الإبداع المتطلبات التالية:

المتطلبات

سبب الأهمية

حالة الجلسة

يستغرق سير العمل المتعدّد الخطوات 45 ثانية أو أكثر. تحتفظ Agent Runtime بحالة المحادثة بين استدعاءات الأدوات في خدمة التنسيق، وبالتالي لا يتم فقدان أي بيانات في منتصف عملية التنفيذ.

تحميل المتغيّر

في بعض الأحيان، حملة واحدة في الساعة، وفي أحيان أخرى، حملات عديدة بالتوازي. يتم توسيع نطاق Agent Runtime إلى صفر عند عدم النشاط، ويتم توسيعه تلقائيًا، لذا لن تدفع مقابل السعة غير المستخدَمة.

إمكانية تتبُّع البيانات

تتوفّر أدوات Cloud Logging وCloud Monitoring وCloud Trace بشكل مدمج. يمكنك الاطّلاع على كل مكالمة A2A وكل رمز مميز مستخدَم وكل ارتفاع في وقت الاستجابة بدون إضافة أي أدوات قياس حالة التطبيق.

مهام سير العمل الطويلة الأمد

يبلغ الحد الأقصى لمدة المهلة في طلبات Cloud Run‏ 3600 ثانية. تم تصميم Agent Runtime لمهام سير العمل التي يمكن أن تستغرق دقائق، مع عمليات إعادة محاولة مُدارة واستمرار الحالة.

‫Cloud Run هو النظام الأساسي المناسب للمتخصصين في التطبيقات التي لا يتم تسجيل بياناتها. ‫Agent Runtime هي المنصة المناسبة لأداة التنسيق ذات الحالة.

نشر أداة التنسيق

cd ~/ai-creative-studio/workshop/starter
source .env

uv run deploy/deploy_orchestrator.py --action deploy

تستغرق هذه العملية من 5 إلى 10 دقائق تقريبًا. عند اكتمال العملية، يتم حفظ AGENT_ENGINE_ID وAGENT_ENGINE_RESOURCE_NAME في .env.

source .env
echo "Agent Engine ID: $AGENT_ENGINE_ID"
echo "Resource: $AGENT_ENGINE_RESOURCE_NAME"

طريقة عمل عملية النشر

تتولّى client.agent_engines.create() تجميع عنصر App وتحميله مع العناصر التابعة له ونشره في البنية الأساسية المُدارة. في ما يلي وظيفة كل مَعلمة:

import vertexai
from vertexai import Client, agent_engines

vertexai.init(project=PROJECT_ID, location=LOCATION, staging_bucket=STAGING_BUCKET)

# Wrap the App in an AdkApp adapter - enables tracing in Cloud Trace
adk_app = agent_engines.AdkApp(app=root_app, enable_tracing=True)

# Initialize client and deploy
client = Client(project=PROJECT_ID, location=LOCATION)

agent_engine_resource = client.agent_engines.create(
    agent=adk_app,
    config={
        "staging_bucket": STAGING_BUCKET,   # GCS bucket for packaging artifacts
        "display_name": "Creative Director",
        # Python packages installed in the managed runtime - pin for reproducibility
        "requirements": [
            "google-cloud-aiplatform[agent_engines]>=1.132.0,<2.0.0",
            "google-adk[a2a]==1.31.1",
            "google-genai>=1.70.0",
            "google-cloud-storage>=2.10.0",
            "python-dotenv>=1.0.0",
            "pydantic>=2.0.0",
            "cloudpickle>=3.0.0",
        ],
        # Specialist URLs passed as env vars - the orchestrator reads these at runtime
        "env_vars": {
            "COPYWRITER_AGENT_URL": COPYWRITER_URL,
            "DESIGNER_AGENT_URL":   DESIGNER_URL,
            "STRATEGIST_AGENT_URL": STRATEGIST_URL,
            "CRITIC_AGENT_URL":     CRITIC_URL,
            "PM_AGENT_URL":         PM_URL,
        },
    },
)

resource_name = agent_engine_resource.api_resource.name
agent_engine_id = resource_name.split("/")[-1]

ما يحدث في الخلفية:

1. Agent Engine packages your App + requirements into a container
2. Uploads it to the staging bucket in your project
3. Deploys to managed compute (you never see or manage the VM)
4. Returns a resource name: projects/.../locations/.../reasoningEngines/<id>
5. That ID is saved to .env as AGENT_ENGINE_ID

بعد النشر، يتصل المنسّق بالمتخصصين الخمسة في Cloud Run من خلال عناوين URL في متغيرات البيئة.

  • يتم تمرير هذه القيم من خلال .env قبل تشغيل نص النشر.

14. إطلاق حملة شاملة

تم نشر النظام بأكمله. تشغيل حملة كاملة من ساحة تجارب Agent Runtime

فتح الوضع التجريبي لبيئة تشغيل الوكيل

  1. انتقِل إلى https://console.cloud.google.com/agent-platform/runtimes. يمكنك أيضًا الانتقال إلى Agent Runtime من منصة Agent > الوكلاء > عمليات النشر.
  2. اختَر بيئة تشغيل الوكيل التي تم نشرها (creative-director)
  3. انقر على ساحة اللعب في الشريط الجانبي الأيمن
  4. انقر على جلسة جديدة لفتح محادثة جديدة

إطلاق حملة كاملة

ألصِق هذا الموجز في المحادثة وأرسِله:

Create a complete Instagram campaign for:
- Product: EcoFlow Smart Water Bottle (tracks hydration, keeps drinks cold 24h)
- Target Audience: Health-conscious millennials, 25-35 years old
- Platform: Instagram
- Goal: Brand awareness + drive website traffic
- Brand Voice: Motivational, clean, science-backed
- Budget: $3,000
- Timeline: Launch in 2 weeks

سينفّذ المدير الإبداعي جميع العملاء الخمسة بالتسلسل:

  1. محلّل إستراتيجي للعلامة التجارية → أبحاث السوق، وتحليل المنافسين، وإحصاءات الجمهور
  2. محرّر الإعلانات → 3 منشورات على Instagram مع مقاطع شرح وعلامات هاشتاغ وعبارات تحثّ على اتّخاذ إجراء
  3. المصمّم: مفاهيم مرئية + صور حقيقية تم إنشاؤها باستخدام Gemini (معرّفات موارد موحّدة في Google Cloud Storage) لكل مشاركة
  4. المراجع → مراجعة الجودة مع التقييمات APPROVED / NEEDS_REVISION
  5. (مراجعة إذا لزم الأمر) → يتم التواصل مع كاتب النصوص أو المصمّم مرة أخرى لتقديم الملاحظات
  6. مدير المشروع: جدول زمني لمدة أسبوعَين، وتقسيم المهام، وتخصيص الميزانية

عرض توضيحي: تنفيذ حملة باستخدام ميزة الدمج مع Notion

اختبار التوجيه إلى وكيل واحد

أرسِل هذا الطلب الأقصر في جلسة جديدة:

Research the luxury skincare market - top brands and trends in 2025

لاحظ أنّ المدير الإبداعي يوجّه هذا الطلب إلى مخطّط استراتيجية العلامة التجارية فقط، ولا يتم استدعاء أي وكلاء آخرين. هذا هو منطق تصنيف الطلبات من تعليمات النظام التي تعمل بشكل صحيح.

فحص عمليات تتبُّع التنفيذ

أثناء البقاء في وحدة التحكّم:

  1. انقر على عمليات التتبُّع في الشريط الجانبي الأيمن (بجانب Playground).
  2. ضمن عرض التتبُّع، اختَر عملية التتبُّع للجلسة التي نفّذتها للتو.
  3. توسيع شجرة التتبُّع للاطّلاع على كل طلب من الوكيل، ومدخلاته/مخرجاته، ووقت الاستجابة، واستخدام الرموز المميزة

يظهر كل طلب A2A إلى أحد المتخصّصين كفترة منفصلة. يمكنك الاطّلاع على السياق الذي قدّمه المدير الإبداعي لكل وكيل والمحتوى الذي تلقّاه منه.

اختياري: التشغيل من الوحدة الطرفية

يمكنك أيضًا تنفيذ الحملة آليًا باستخدام النص البرمجي run_campaign.py المُضمّن في حزمة البداية.

cd ~/ai-creative-studio/workshop/starter
uv run run_campaign.py

15. تنظيف

تنظيف موارد Google Cloud لتجنُّب الرسوم المستمرة

نفِّذ النص البرمجي الخاص بإيقاف التشغيل، إذ يقرأ .env ويحذف كل ما تم إنشاؤه خلال هذا الدرس العملي:

bash deploy/teardown_gcp.sh

سيعرض لك النص البرمجي بالضبط ما سيتم حذفه وسيطلب منك التأكيد قبل تنفيذ أي إجراء:

المورد

البيانات التي يتم حذفها

خدمات Cloud Run

محلّل إستراتيجي للعلامة التجارية، كاتب نصوص إعلانية، مصمّم، ناقد، مدير مشروع

بيئة تشغيل الوكيل

محرك استنتاج "مدير الإبداع" + جميع الجلسات

Artifact Registry

مستودع cloud-run-source-deploy + جميع صور Docker

حِزم GCS

{PROJECT_ID}-campaign-images، {PROJECT_ID}-agent-staging، run-sources-{PROJECT_ID}-{REGION}

Secret Manager

notion-token وnotion-project-db-id وnotion-tasks-db-id (يتم تخطّيها إذا لم يتم إنشاؤها)

التأكّد من إزالة كل شيء

gcloud run services list --region=us-central1
gcloud storage buckets list --project=$GCP_PROJECT_ID

الناتج المتوقّع: قوائم فارغة أو مواردك الحالية فقط

16. ملخّص

تهانينا! لقد أنشأت نظام ذكاء اصطناعي متعدد الوكلاء مناسبًا لمرحلة الإنتاج ونشرته على Google Cloud.

ما أنشأته

الوكيل

إمكانية

التفعيل

محلّل إستراتيجي للعلامة التجارية

أبحاث السوق من خلال "بحث Google"

Cloud Run

محرّر الإعلانات

إنشاء شرح على Instagram

Cloud Run

مُصمِّم

إنشاء الصور من خلال Gemini + تحميل GCS

Cloud Run

ناقد

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

Cloud Run

مدير المشاريع

المخطط الزمني + Notion MCP

Cloud Run

مخرج تصميم الإعلان

التنظيم الكامل من خلال A2A

بيئة تشغيل الوكيل

الأنماط الرئيسية التي تعلّمتها

  1. ADK Agent: تحديد وكيل نموذج لغوي كبير باستخدام تعليمات + أدوات اختيارية
  2. adk web: تشغيل أي وكيل ADK واختباره محليًا باستخدام واجهة مستخدم مدمجة للمحادثة
  3. SkillToolset: تجميع المعرفة القابلة لإعادة الاستخدام في ملفات نموذجية يتم تحميلها عند الطلب
  4. FunctionTool: لتغليف أي دالة Python (أو نموذج خارجي) كأداة وكيل قابلة للاستدعاء
  5. to_a2a(): عرض أي وكيل ADK كخدمة HTTPS متوافقة مع A2A
  6. RemoteA2aAgent + AgentTool: تنظيم الوكلاء البعيدين كأدوات قابلة للاستدعاء
  7. McpToolset - الاتصال بالخدمات الخارجية من خلال خوادم MCP stdio
  8. EventsCompactionConfig - التعامل مع حدود الرموز المميزة في إجراءات سير العمل الطويلة التي تتضمّن عدة وكلاء
  9. ناتج منظَّم من الناقد: التحكّم في الجودة بشكل قابل للقراءة آليًا مع مراجعة تلقائية
  10. ‫Cloud Run: نشر الوكلاء المحفوظين في حاويات على نطاق واسع
  11. بيئة تشغيل الوكيل: أدوات تنسيق المضيفين مع الجلسات المُدارة والتتبُّع

الخطوات التالية

  • إضافة ميزة تعديل الصور في عدة جولات إلى "المصمّم" باستخدام إمكانية التعديل في gemini-3.1-flash-image-preview
  • إضافة مصادقة إدارة الهوية وإمكانية الوصول إلى خدمات Cloud Run (إزالة --allow-unauthenticated)
  • استبدِل أحد المتخصّصين بوكيل LangGraph أو CrewAI - لا يهمّ إطار العمل المستخدَم في A2A
  • إضافة ملاحظات المستخدمين كأداة ليتمكّن المشاركون من تقييم المخرجات وتكرارها
  • استكشاف تتبُّع وقت تشغيل الوكيل في Cloud Console

الموارد