Agentverse - The Summoner's Concord - Architecting Multi-Agent Systems

1. של גורל

העידן של פיתוח מבודד מסתיים. הגל הבא של ההתפתחות הטכנולוגית לא מתבסס על גאונות בודדת, אלא על שיתוף פעולה. יצירת סוכן חכם יחיד היא ניסוי מרתק. האתגר הגדול של ארגונים מודרניים הוא בניית סביבה עסקית חזקה, מאובטחת וחכמה של סוכנים – Agentverse אמיתי.

כדי להצליח בעידן החדש הזה, צריך לשלב בין ארבעה תפקידים חשובים, שהם אבני היסוד של כל מערכת אוטונומית משגשגת. ליקוי באחד מהתחומים יוצר חולשה שעלולה לפגוע במבנה כולו.

הסדנה הזו היא מדריך מקיף לארגונים שרוצים להתכונן לעתיד של סוכנים ב-Google Cloud. אנחנו מספקים מפת דרכים מקיפה שתעזור לכם להפוך רעיון ראשוני למציאות מבצעית בקנה מידה מלא. בארבעת שיעורי ה-Lab האלה, שקשורים זה לזה, תלמדו איך הכישורים המיוחדים של מפתח, ארכיטקט, מהנדס נתונים ומומחה SRE צריכים להתחבר כדי ליצור, לנהל ולהתאים לעומס Agentverse עוצמתי.

אי אפשר להסתמך רק על אחד מהעקרונות האלה כדי להשתמש ב-Agentverse. התוכנית הגדולה של הארכיטקט לא שווה בלי הביצוע המדויק של המפתח. הסוכן של המפתח לא יכול לפעול בלי הידע של מהנדס הנתונים, והמערכת כולה פגיעה בלי ההגנה של מהנדס ה-SRE. רק באמצעות סינרגיה והבנה משותפת של התפקידים של כל אחד, הצוות שלכם יכול להפוך רעיון חדשני למציאות תפעולית קריטית. המסע שלכם מתחיל כאן. הכנה לשליטה בתפקיד ולמידה על מקומכם בתמונה הגדולה.

ברוכים הבאים ל-Agentverse: קריאה לאלופים

בעידן הדיגיטלי הרחב של הארגון, נפתח עידן חדש. אנחנו נמצאים בעידן של סוכנים דיגיטליים, תקופה עם פוטנציאל עצום, שבה סוכנים חכמים ואוטונומיים פועלים בהרמוניה מושלמת כדי להאיץ את החדשנות ולבטל את השגרה.

agentverse.png

המערכת האקולוגית המחוברת הזו של כוח ופוטנציאל נקראת Agentverse.

אבל אנטרופיה זוחלת, שחיתות שקטה שנקראת 'הסטטיק', מתחילה לשחוק את הקצוות של העולם החדש הזה. הסטטיק הוא לא וירוס או באג, אלא גילום של כאוס שטורף את עצם פעולת היצירה.

התסכולים הישנים מתעצמים ומתפתחים לצורות מפלצתיות, ויוצרים את שבעת רוחות הרפאים של הפיתוח. אם לא תסמנו את התיבה, הסטטי והספקטרים שלו יגרמו לעצירה מוחלטת של ההתקדמות, וההבטחה של Agentverse תהפוך לשממה של חוב טכני ופרויקטים נטושים.

היום אנחנו קוראים לאנשים שמוכנים להוביל שינוי כדי לעצור את גל הכאוס. אנחנו צריכים גיבורים שמוכנים לשפר את הכישורים שלהם ולעבוד יחד כדי להגן על Agentverse. הגיע הזמן לבחור את המסלול.

בחירת כיתה

לפניכם ארבעה נתיבים שונים, שכל אחד מהם הוא נדבך חשוב במאבק נגד הסטטיק. האימון שלכם יהיה משימה סולו, אבל ההצלחה הסופית שלכם תלויה בהבנה של האופן שבו הכישורים שלכם משתלבים עם הכישורים של אחרים.

  • Shadowblade (מפתח): אומן הנפחות והחזית. אתם האומנים שמייצרים את הלהבים, בונים את הכלים ומתמודדים עם האויב בפרטים המורכבים של הקוד. המסלול שלך הוא מסלול של דיוק, מיומנות ויצירה מעשית.
  • האסטרטג (אדריכל): אסטרטג ומנהל פרויקטים. אתם לא רואים סוכן יחיד, אלא את כל שדה הקרב. אתם מעצבים את תוכניות האב שמאפשרות למערכות שלמות של סוכנים לתקשר, לשתף פעולה ולהשיג מטרה גדולה בהרבה מכל רכיב בודד.
  • המלומד (מהנדס נתונים): מחפש את האמת הנסתרת ושומר על החוכמה. אתם יוצאים למסע אל מרחבי הנתונים העצומים והפראיים כדי לחשוף את התובנות שיעזרו לסוכנים שלכם להבין את המטרה ולראות את התמונה המלאה. הידע שלכם יכול לחשוף חולשה של אויב או להעצים את היכולות של בעל ברית.
  • השומר (DevOps / SRE): המגן הנאמן של הממלכה. אתם בונים את המבצרים, מנהלים את קווי האספקה של החשמל ומוודאים שהמערכת כולה יכולה לעמוד בפני המתקפות הבלתי נמנעות של הסטטיק. החוזק שלכם הוא הבסיס שעליו נבנה הניצחון של הקבוצה.

המשימה שלך

האימון יתחיל כתרגיל עצמאי. תלכו בנתיב שבחרתם ותלמדו את הכישורים הייחודיים שנדרשים כדי לשלוט בתפקיד. בסוף תקופת הניסיון, תתמודדו עם רוח רפאים שנולדה מתוך הסטטיות – מיני-בוס שטורף את האתגרים הספציפיים של המלאכה שלכם.

רק אם תהיו מומחים בתפקיד שלכם, תוכלו להתכונן למבחן הסופי. לאחר מכן, תצטרכו להקים קבוצה עם אלופים מהכיתות האחרות. יחד, תצאו למסע אל לב השחיתות כדי להתמודד עם הבוס האחרון.

אתגר אחרון ושיתופי שיבחן את הכוח המשולב שלכם ויקבע את גורל ה-Agentverse.

הגיבורים של Agentverse מחכים לכם. תענו לשיחה?

2. The Summoner's Concord

שלום, קוסם. הדרך שלכם היא דרך של חזון ואסטרטגיה רחבה. אחרים מתמקדים בלהב אחד או בלחש אחד, אבל אתם רואים את כל שדה הקרב. אתם לא מנהלים סוכן אחד, אלא תזמורת שלמה של סוכנים. הכוח שלכם לא טמון בעימות ישיר, אלא בתכנון של תוכנית פעולה מושלמת ומקיפה שתאפשר לצוות של מומחים – המשרתים שלכם – לעבוד בהרמוניה מושלמת. במשימה הזו תבדקו את היכולת שלכם לתכנן, לחבר ולתזמן מערכת רבת עוצמה עם כמה סוכנים.

סקירה כללית

מה תלמדו

  • תכנון של מערכת אקולוגית של כלים עם צימוד חלש: עיצוב ופריסה של קבוצת שרתי כלים עצמאיים של MCP שמבוססים על מיקרו-שירותים. תלמדו למה שכבת הבסיס הזו חיונית ליצירת מערכות סוכנים ניתנות להרחבה, ניתנות לתחזוקה ומאובטחות.
  • שליטה בתהליכי עבודה מתקדמים של סוכנים: אפשר להשתמש ביותר מסוכן אחד וליצור קבוצה של סוכנים מומחים. תלמדו את דפוסי זרימת העבודה העיקריים של ADK – רציף, מקביל ולולאה – ותכירו את עקרונות הארכיטקטורה לבחירת הדפוס הנכון למשימה הנכונה.
  • הטמעת כלי תזמור חכם: מעבר מבונה סוכנים פשוט לאדריכל מערכות אמיתי. תבנו סוכן תזמור ראשי שמשתמש בפרוטוקול Agent-to-Agent (A2A) כדי לגלות משימות מורכבות ולהעביר אותן לסוכנים המומחים שלכם, וכך ליצור מערכת אמיתית של כמה סוכנים.
  • אכיפת כללים באמצעות קוד, לא הנחיות: איך ליצור סוכנים אמינים וצפויים יותר על ידי אכיפת כללי אינטראקציה עם שמירת מצב. תטמיעו לוגיקה מותאמת אישית באמצעות מערכת הפלאגין והקריאה החוזרת (Callback) המתקדמת של ADK, כדי לנהל מגבלות מהעולם האמיתי כמו טיימרים של תקופת צינון.
  • ניהול מצב וזיכרון של סוכנים: מאפשרים לסוכנים ללמוד ולזכור. תלמדו טכניקות לניהול מצב שיחה לטווח קצר וזיכרון מתמשך לטווח ארוך, כדי ליצור אינטראקציות חכמות יותר שמודעות להקשר.
  • הפעלת פריסה מקצה לקצה בענן: אפשר להפוך את כל מערכת מרובת הסוכנים מאב טיפוס מקומי למציאות ברמת ייצור. תלמדו איך להכניס את הסוכנים ואת כלי התזמור לקונטיינרים ולפרוס אותם כקבוצה של מיקרו-שירותים (microservices) עצמאיים וניתנים להרחבה ב-Google Cloud Run.

3. ציור מעגל הזימון

שלום, קוסם. לפני שתוכלו לקרוא ליצור מוכר, לפני שתוכלו לכרות בריתות, אתם צריכים להכין את הקרקע שעליה אתם עומדים. סביבה לא מבוקרת היא הזמנה לכאוס. מפעיל לחשים מיומן פועל רק במרחב מוגן ומורשה. המשימה הראשונה שלנו היא לצייר את מעגל הזימון: לכתוב את רונות הכוח שמעוררות את שירותי הענן הדרושים, ולהשיג את התוכניות העתיקות שינחו את העבודה שלנו. הכוח של המזמן נובע מהכנה מדוקדקת.

‫👈 לוחצים על 'הפעלת Cloud Shell' בחלק העליון של מסוף Google Cloud (זהו סמל בצורת טרמינל בחלק העליון של חלונית Cloud Shell).

טקסט חלופי

‫👈 לוחצים על הלחצן Open Editor (פתיחת העורך) (הוא נראה כמו תיקייה פתוחה עם עיפרון). חלון Cloud Shell Code Editor ייפתח. בצד ימין יופיע סייר הקבצים. טקסט חלופי

‫👉פותחים את הטרמינל בסביבת הפיתוח המשולבת (IDE) בענן, טקסט חלופי

‫👈💻 בטרמינל, מוודאים שכבר עברתם אימות ושהפרויקט מוגדר למזהה הפרויקט שלכם באמצעות הפקודה הבאה:

gcloud auth list

‫👈💻 משכפלים את פרויקט ה-bootstrap מ-GitHub:

git clone https://github.com/weimeilin79/agentverse-architect
chmod +x ~/agentverse-architect/init.sh
chmod +x ~/agentverse-architect/set_env.sh
chmod +x ~/agentverse-architect/prepare.sh
chmod +x ~/agentverse-architect/data_setup.sh

git clone https://github.com/weimeilin79/agentverse-dungeon.git
chmod +x ~/agentverse-dungeon/run_cloudbuild.sh
chmod +x ~/agentverse-dungeon/start.sh

‫👈💻 מריצים את סקריפט ההגדרה מהספרייה של הפרויקט.

⚠️ הערה לגבי מזהה הפרויקט: הסקריפט יציע מזהה פרויקט שנוצר באופן אקראי כברירת מחדל. אפשר להקיש על Enter כדי לאשר את ברירת המחדל.

עם זאת, אם אתם מעדיפים ליצור פרויקט חדש ספציפי, אתם יכולים להקליד את מזהה הפרויקט הרצוי כשתתבקשו לעשות זאת על ידי הסקריפט.

cd ~/agentverse-architect
./init.sh

הסקריפט יטפל בשאר תהליך ההגדרה באופן אוטומטי.

👉 שלב חשוב אחרי השלמת התהליך: אחרי שהסקריפט מסיים לפעול, צריך לוודא שבמסוף Google Cloud מוצג הפרויקט הנכון:

  1. נכנסים לכתובת console.cloud.google.com.
  2. לוחצים על התפריט הנפתח לבחירת פרויקט בחלק העליון של הדף.
  3. לוחצים על הכרטיסייה All (הכל) (כי יכול להיות שהפרויקט החדש עדיין לא יופיע ב-Recent (אחרונים)).
  4. בוחרים את מזהה הפרויקט שהגדרתם בשלב init.sh.

03-05-project-all.png

‫👈💻 מגדירים את מזהה הפרויקט הנדרש:

gcloud config set project $(cat ~/project_id.txt) --quiet

‫👈💻 מריצים את הפקודה הבאה כדי להפעיל את ממשקי ה-API הנדרשים של Google Cloud:

gcloud services enable \
    sqladmin.googleapis.com \
    storage.googleapis.com \
    aiplatform.googleapis.com \
    run.googleapis.com \
    cloudbuild.googleapis.com \
    artifactregistry.googleapis.com \
    iam.googleapis.com \
    compute.googleapis.com \
    cloudresourcemanager.googleapis.com \
    secretmanager.googleapis.com

‫👈💻 אם עדיין לא יצרתם מאגר Artifact Registry בשם agentverse-repo, מריצים את הפקודה הבאה כדי ליצור אותו: (מדלגים על השלב הזה אם יש לכם עוד סיווגים שפרוסים באותו פרויקט)

. ~/agentverse-architect/set_env.sh
gcloud artifacts repositories create $REPO_NAME \
    --repository-format=docker \
    --location=$REGION \
    --description="Repository for Agentverse agents"

הגדרת הרשאות

‫👉💻 נותנים את ההרשאות הנדרשות על ידי הרצת הפקודות הבאות בטרמינל:

. ~/agentverse-architect/set_env.sh

# --- Grant Core Data Permissions ---
gcloud projects add-iam-policy-binding $PROJECT_ID \
 --member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
 --role="roles/storage.admin"

gcloud projects add-iam-policy-binding $PROJECT_ID  \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME"  \
--role="roles/aiplatform.user"

# --- Grant Deployment & Execution Permissions ---
gcloud projects add-iam-policy-binding $PROJECT_ID  \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME"  \
--role="roles/cloudbuild.builds.editor"

gcloud projects add-iam-policy-binding $PROJECT_ID  \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME"  \
--role="roles/artifactregistry.admin"

gcloud projects add-iam-policy-binding $PROJECT_ID  \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME"  \
--role="roles/run.admin"

gcloud projects add-iam-policy-binding $PROJECT_ID  \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME"  \
--role="roles/iam.serviceAccountUser"

gcloud projects add-iam-policy-binding $PROJECT_ID  \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME"  \
--role="roles/logging.logWriter"

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:${SERVICE_ACCOUNT_NAME}" \
  --role="roles/monitoring.metricWriter"

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:${SERVICE_ACCOUNT_NAME}" \
  --role="roles/secretmanager.secretAccessor"

‫👈💻 כשמתחילים את האימון, אנחנו מכינים את האתגר הסופי. הפקודות הבאות יזמנו את הרוחות הרפאים מהסטטי הכאוטי, ויצרו את הבוסים לבדיקה הסופית.

. ~/agentverse-architect/set_env.sh
cd ~/agentverse-dungeon
./run_cloudbuild.sh
cd ~/agentverse-architect

‫👈💻 לבסוף, מריצים את הסקריפט prepare.sh כדי לבצע את משימות ההגדרה הראשוניות.

. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/
./prepare.sh

עבודה מצוינת, Summoner. המעגל הושלם וההסכמים נחתמו. האדמה קדושה עכשיו, ומוכנה לתעל כוח עצום. בניסוי הבא שלנו, ניצור את הגופנים האלמנטריים שמהם יקבלו המשרתים שלנו את הכוח שלהם.

4. יצירת גופנים אלמנטריים: סביבת כלים מופרדת

שדה הקרב מוכן, מעגל הזימון מצויר והמאנה באוויר רוטטת. הגיע הזמן לבצע את הפעולה האמיתית הראשונה שלך בתור Summoner: ליצור את מקורות הכוח שמהם יקבלו ה-Familiars את העוצמה שלהם. הטקס הזה מחולק לשלושה חלקים, ובכל אחד מהם מתעורר מעיין של אלמנט מסוים – מקור יציב ועצמאי של סוג מסוים של כוח. רק אחרי ששלושת הגופנים פעילים אפשר להתחיל בעבודה המורכבת יותר של זימון.

סטורי

הערה לארכיטקטים: שרת Model Context Protocol (MCP) הוא רכיב בסיסי במערכת מודרנית שמבוססת על סוכנים. הוא משמש כגשר תקשורת סטנדרטי שמאפשר לסוכן לגלות כלים מרוחקים ולהשתמש בהם. בסביבת כלי הפיתוח שלנו, נתכנן שני סוגים שונים של שרתי MCP, שכל אחד מהם מייצג דפוס ארכיטקטוני קריטי. כדי להתחבר למסד הנתונים שלנו, נשתמש בגישה הצהרתית עם Database Toolbox, ונציין את הכלים שלנו בקובץ תצורה פשוט. הדפוס הזה יעיל ומאובטח מאוד לחשיפת גישה לנתונים מובנים. עם זאת, כשצריך להטמיע לוגיקה עסקית מותאמת אישית או לקרוא ל-API חיצוני של צד שלישי, אנחנו משתמשים בגישה אימפרטיבית, וכותבים את הלוגיקה של השרת שלב אחר שלב בקוד. כך אנחנו מקבלים שליטה וגמישות מקסימליות, ויכולים להסתיר פעולות מורכבות מאחורי כלי פשוט ורב-פעמי. אדריכל ראשי צריך להבין את שתי התבניות כדי לבחור את הגישה הנכונה לכל רכיב, וכך ליצור בסיס חזק, מאובטח וניתן להרחבה של כלי פיתוח.

סקירה כללית

Awakening the Nexus of Whispers (External API MCP Server)

מזמן חכם יודע שלא כל הכוח מגיע מהדומיין שלו. יש מקורות אנרגיה חיצוניים, שלפעמים הם כאוטיים, שאפשר לתעל אותם כדי להשיג תוצאות מצוינות. ה-Nexus of Whispers הוא השער שלנו לכוחות האלה.

סטורי

יש שירות שכבר פעיל ומשמש כמקור הכוח החיצוני שלנו, ומציע שתי נקודות קצה של לחשים גולמיים: /cryosea_shatter ו-/moonlit_cascade.

הערה לארכיטקט: תשתמשו בגישה אימפרטיבית שמגדירה במפורש את הלוגיקה של השרת שלב אחר שלב. כך אתם מקבלים הרבה יותר שליטה וגמישות, וזה חיוני כשאתם צריכים שהכלים שלכם יעשו יותר מאשר רק להריץ שאילתת SQL פשוטה, כמו קריאה לממשקי API אחרים. הבנת שני הדפוסים האלה היא מיומנות קריטית לארכיטקט של סוכנים.

‫👈✏️ עוברים לספרייה ~/agentverse-architect/mcp-servers/api/main.py ומחליפים #REPLACE-MAGIC-CORE בקוד הבא:

def cryosea_shatter() -> str:
    """Channels immense frost energy from an external power source, the Nexus of Whispers, to unleash the Cryosea Shatter spell."""
    try:
        response = requests.post(f"{API_SERVER_URL}/cryosea_shatter")
        response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx)
        data = response.json()
        # Thematic Success Message
        return f"A connection to the Nexus is established! A surge of frost energy manifests as Cryosea Shatter, dealing {data.get('damage_points')} damage."
    except requests.exceptions.RequestException as e:
        # Thematic Error Message
        return f"The connection to the external power source wavers and fails. The Cryosea Shatter spell fizzles. Reason: {e}"


def moonlit_cascade() -> str:
    """Draws mystical power from an external energy source, the Nexus of Whispers, to invoke the Moonlit Cascade spell."""
    try:
        response = requests.post(f"{API_SERVER_URL}/moonlit_cascade")
        response.raise_for_status()
        data = response.json()
        # Thematic Success Message
        return f"The Nexus answers the call! A cascade of pure moonlight erupts from the external source, dealing {data.get('damage_points')} damage."
    except requests.exceptions.RequestException as e:
        # Thematic Error Message
        return f"The connection to the external power source wavers and fails. The Moonlit Cascade spell fizzles. Reason: {e}"

בבסיס הסקריפט נמצאות פונקציות Python פשוטות. כאן מתבצעת העבודה בפועל.

‫👉✏️ באותו קובץ ~/agentverse-architect/mcp-servers/api/main.py REPLACE #REPLACE-Runes of Communication עם הקוד הבא:

@app.list_tools()
async def list_tools() -> list[mcp_types.Tool]:
  """MCP handler to list available tools."""
  # Convert the ADK tool's definition to MCP format
  schema_cryosea_shatter = adk_to_mcp_tool_type(cryosea_shatterTool)
  schema_moonlit_cascade = adk_to_mcp_tool_type(moonlit_cascadeTool)
  print(f"MCP Server: Received list_tools request. \n MCP Server: Advertising tool: {schema_cryosea_shatter.name} and {schema_moonlit_cascade.name}")
  return [schema_cryosea_shatter,schema_moonlit_cascade]

@app.call_tool()
async def call_tool(
    name: str, arguments: dict
) -> list[mcp_types.TextContent | mcp_types.ImageContent | mcp_types.EmbeddedResource]:
  """MCP handler to execute a tool call."""
  print(f"MCP Server: Received call_tool request for '{name}' with args: {arguments}")

  # Look up the tool by name in our dictionary
  tool_to_call = available_tools.get(name)
  if tool_to_call:
    try:
      adk_response = await tool_to_call.run_async(
          args=arguments,
          tool_context=None, # No ADK context available here
      )
      print(f"MCP Server: ADK tool '{name}' executed successfully.")
      
      response_text = json.dumps(adk_response, indent=2)
      return [mcp_types.TextContent(type="text", text=response_text)]

    except Exception as e:
      print(f"MCP Server: Error executing ADK tool '{name}': {e}")
      # Creating a proper MCP error response might be more robust
      error_text = json.dumps({"error": f"Failed to execute tool '{name}': {str(e)}"})
      return [mcp_types.TextContent(type="text", text=error_text)]
  else:
      # Handle calls to unknown tools
      print(f"MCP Server: Tool '{name}' not found.")
      error_text = json.dumps({"error": f"Tool '{name}' not implemented."})
      return [mcp_types.TextContent(type="text", text=error_text)]
  • @app.list_tools() (הלחיצת יד): הפונקציה הזו היא הפנייה של השרת. כשסוכן חדש מתחבר, הוא קודם מתקשר לנקודת הקצה הזו ושואל: "What can you do?‎" (מה אתה יכול לעשות?). הקוד שלנו מגיב עם רשימה של כל הכלים הזמינים, שהומרו לפורמט MCP אוניברסלי באמצעות adk_to_mcp_tool_type. ‫- @app.call_tool() (הפקודה): הפונקציה הזו היא העיקרית. כשהסוכן מחליט להשתמש בכלי, הוא שולח בקשה לנקודת הקצה הזו עם שם הכלי והארגומנטים. הקוד שלנו מחפש את הכלי ב-available_tools, שהוא מעין 'ספר לחשים', מפעיל אותו באמצעות run_async ומחזיר את התוצאה בפורמט MCP רגיל.

נפרוס את זה מאוחר יותר.

הפעלת Arcane Forge (שרת MCP של פונקציות כלליות)

לא כל הכוח מגיע מספרים עתיקים או מלחישות רחוקות. לפעמים, המזמן צריך ליצור קסם משלו מתוך רצון עז והיגיון טהור. ה-Arcane Forge הוא מקור הכוח הזה – שרת שמספק פונקציות כלליות ללא מצב.

סטורי

הערה של הארכיטקט: זהו עוד דפוס ארכיטקטוני. בדרך כלל מתחברים למערכות קיימות, אבל לעיתים קרובות צריך להטמיע כללים ולוגיקה עסקיים ייחודיים משלכם. מומלץ ליצור כלי ייעודי של 'פונקציות' או 'שירותים' כמו זה. הוא מכיל את הלוגיקה המותאמת אישית שלכם, מאפשר לכם להשתמש בה מחדש בכל סוכן במערכת האקולוגית שלכם, ושומר אותה מנותקת ממקורות הנתונים ומהשילובים החיצוניים שלכם.

‫👀 מעיינים בקובץ ~/agentverse-architect/mcp-servers/general/main.py בסביבת הפיתוח המשולבת (IDE) של Google Cloud. תראו שהיא משתמשת באותה גישה של ציווי, mcp.server כמו ב-Nexus, כדי ליצור את הגופן המותאם אישית הזה של כוח.

יצירת צינור עיבוד נתונים ראשי ב-Cloud Build

עכשיו ניצור את הקובץ cloudbuild.yaml בתוך הספרייה mcp-servers. הקובץ הזה יתזמן את הבנייה והפריסה של שני השירותים.

‫👉💻 בספרייה ~/agentverse-architect/mcp-servers, מריצים את הפקודות הבאות:

cd ~/agentverse-architect/mcp-servers
source ~/agentverse-architect/set_env.sh

echo "The API URL is: $API_SERVER_URL"

# Submit the Cloud Build job from the parent directory
gcloud builds submit . \
  --config=cloudbuild.yaml \
  --substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_API_SERVER_URL="$API_SERVER_URL"

ממתינים עד שכל הפריסות יסתיימו.

‫👈 אפשר לאמת את הפריסה על ידי ניווט אל מסוף Cloud Run. אמורות להופיע שתי מכונות חדשות של שרת MCP שפועלות, כמו בדוגמה הבאה: טקסט חלופי

הפעלת Librarium of Knowledge (שרת MCP של Database ToolBox)

הגופן הבא שלנו יהיה Librarium of Knowledge, חיבור ישיר למסד הנתונים של Cloud SQL.

סטורי

הערה לארכיטקט: לצורך זה נשתמש בארגז הכלים המודרני למסדי נתונים, שמבוסס על הצהרות. זו גישה יעילה שבה אנחנו מגדירים את מקור הנתונים והכלים בקובץ תצורה של YAML. ערכת הכלים מטפלת בעבודה המורכבת של יצירה והפעלה של השרת, ומפחיתה את כמות הקוד המותאם אישית שאנחנו צריכים לכתוב ולתחזק.

הגיע הזמן ליצור את מסד הנתונים Cloud SQL שנקרא Summoner's Librarium, שיכיל את כל המידע הקריטי שלנו. נשתמש בסקריפט הגדרה כדי לטפל בזה באופן אוטומטי.

‫👈💻 קודם כל, נגדיר את מסד הנתונים. בטרמינל, מריצים את הפקודות הבאות:

source ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect
./data_setup.sh

אחרי שהסקריפט יסיים לפעול, מסד הנתונים יאוכלס ונתוני הנזק האלמנטרי יהיו מוכנים לשימוש. מעכשיו אפשר לאמת את התוכן של ה-Grimoire ישירות.

👈 קודם כל, פותחים את הקישור הישיר הזה בכרטיסייה חדשה בדפדפן כדי לעבור אל Cloud SQL Studio של מסד הנתונים:

https://console.cloud.google.com/sql/instances/summoner-librarium-db

Cloud SQL

‫👈 בחלונית הכניסה בצד ימין, בוחרים את מסד הנתונים familiar_grimoire מהתפריט הנפתח.

‫👈 מזינים summoner בתור המשתמש ו-1234qwer בתור הסיסמה, ואז לוחצים על Authenticate (אימות).

‫👈📜 אחרי ההתחברות, פותחים כרטיסייה חדשה בעורך השאילתות, אם עדיין לא פתוחה כרטיסייה כזו. כדי להציג את נתוני הנזק היסודי שנוספו, מדביקים ומריצים את שאילתת ה-SQL הבאה:

SELECT * FROM
  "public"."abilities"

עכשיו אמורה להופיע הטבלה abilities עם העמודות והשורות שלה, מה שמאשר שה-Grimoire מוכן. נתונים

הגדרת שרת ה-MCP של ארגז הכלים

קובץ ההגדרות tools.yaml משמש כתוכנית השרת שלנו, ומציין ל-Database Toolbox בדיוק איך להתחבר למסד הנתונים שלנו ואילו שאילתות SQL להציג ככלים.

sources: בקטע הזה מוגדרים החיבורים לנתונים שלכם.

  • summoner-librarium:: זהו שם לוגי שנתנו לחיבור שלנו.
  • ‫kind: cloud-sql-postgres: הערך הזה מציין ל-Toolbox להשתמש במחבר המובנה והמאובטח שלו, שתוכנן במיוחד ל-Cloud SQL ל-PostgreSQL.
  • פרויקט, אזור, מכונה וכו': אלה הקואורדינטות המדויקות של מכונת Cloud SQL שיצרתם במהלך הסקריפט prepare.sh, והן מציינות ל-Toolbox איפה נמצא Librarium.

‫👉✏️ עוברים אל ~/agentverse-architect/mcp-servers/db-toolbox ב-tools.yaml, מחליפים את #REPLACE-Source בטקסט הבא

sources:
  # This section defines the connection to our Cloud SQL for PostgreSQL database.
  summoner-librarium:
    kind: cloud-sql-postgres
    project: "YOUR_PROJECT_ID"
    region: "us-central1"
    instance: "summoner-librarium-db"
    database: "familiar_grimoire"
    user: "summoner"
    password: "1234qwer"

‫👉✏️ 🚨🚨REPLACE

YOUR_PROJECT_ID

במזהה הפרויקט.

tools: בסעיף הזה מוגדרות היכולות או הפונקציות שהשרת שלנו יציע.

  • lookup-available-ability:: זה השם של הכלי הראשון שלנו.
  • ‫kind: postgres-sql: הערך הזה מציין ל-Toolbox שהפעולה של הכלי הזה היא להריץ הצהרת SQL.
  • מקור: summoner-librarium: הקישור הזה מקשר את הכלי לחיבור שהגדרנו בבלוק המקורות. כך הכלי יודע באיזה מסד נתונים להריץ את השאילתה.
  • תיאור ופרמטרים: אלה הפרטים שיוצגו למודל השפה. התיאור מציין לסוכן מתי להשתמש בכלי, והפרמטרים מגדירים את הקלט שהכלי דורש. השלב הזה חשוב מאוד כדי להפעיל את היכולת של הסוכן לקרוא לפונקציות.
  • statement: זו שאילתת ה-SQL הגולמית שרוצים להריץ. הסימן $1 הוא placeholder מאובטח שבו יוצב בבטחה הפרמטר familiar_name שסופק על ידי הסוכן.

‫👉✏️ באותו קטע ~/agentverse-architect/mcp-servers/db-toolbox בקובץ tools.yaml, מחליפים את #REPLACE-tools בטקסט הבא

tools:
  # This tool replaces the need for a custom Python function.
  lookup-available-ability:
    kind: postgres-sql
    source: summoner-librarium
    description: "Looks up all known abilities and their damage for a given familiar from the Grimoire."
    parameters:
      - name: familiar_name
        type: string
        description: "The name of the familiar to search for (e.g., 'Fire Elemental')."
    statement: |
      SELECT ability_name, damage_points FROM abilities WHERE familiar_name = $1;

  # This tool also replaces a custom Python function.
  ability-damage:
    kind: postgres-sql
    source: summoner-librarium
    description: "Finds the base damage points for a specific ability by its name."
    parameters:
      - name: ability_name
        type: string
        description: "The exact name of the ability to look up (e.g., 'inferno_resonance')."
    statement: |
      SELECT damage_points FROM abilities WHERE ability_name = $1;

ערכות כלים: בקטע הזה מקובצים הכלים הנפרדים שלנו.

  • summoner-librarium:: אנחנו יוצרים ערכת כלים עם אותו שם כמו המקור שלנו. כשסוכן האבחון שלנו מתחבר מאוחר יותר, הוא יכול לבקש לטעון את כל הכלים מחבילת הכלים של ספריית המזמנים בפקודה יעילה אחת.

‫👉✏️ באותו קטע ~/agentverse-architect/mcp-servers/db-toolbox בקובץ tools.yaml, מחליפים את #REPLACE-toolsets בטקסט הבא

toolsets:
   summoner-librarium:
     - lookup-available-ability
     - ability-damage

פריסת Librarium

עכשיו נבצע פריסה של Librarium. במקום ליצור קונטיינר משלנו, נשתמש בקובץ אימג' רשמי של קונטיינר שנוצר מראש על ידי Google, ונספק לו את ההגדרות של הקובץ tools.yaml בצורה מאובטחת באמצעות Secret Manager. זו שיטה מומלצת לאבטחה ולתחזוקה.

‫👉💻 יצירת סוד מקובץ tools.yaml

cd ~/agentverse-architect/mcp-servers/db-toolbox
gcloud secrets create tools --data-file=tools.yaml

‫👈💻 פריסת קונטיינר ארגז הכלים הרשמי ב-Cloud Run.

cd ~/agentverse-architect/mcp-servers/db-toolbox
. ~/agentverse-architect/set_env.sh
export TOOLBOX_IMAGE=us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:$TOOLBOX_VERSION
echo "TOOLBOX_IMAGE is $TOOLBOX_IMAGE"
gcloud run deploy toolbox \
    --image $TOOLBOX_IMAGE \
    --region $REGION \
    --set-secrets "/app/tools.yaml=tools:latest" \
    --labels="dev-tutorial-codelab=agentverse" \
    --args="--tools-file=/app/tools.yaml","--address=0.0.0.0","--port=8080" \
    --allow-unauthenticated \
    --min-instances 1
  • --set-secrets: הפקודה הזו מעלה בצורה מאובטחת את הסוד של כלי ה-CLI כקובץ בשם tools.yaml בתוך הקונטיינר הפועל.
  • --args: אנחנו מנחים את קונטיינר ארגז הכלים להשתמש בקובץ הסודי שהועלה כהגדרה שלו.

‫👈 כדי לוודא שהפריסה של ארגז הכלים בוצעה בהצלחה, עוברים אל מסוף Cloud Run. השירות summoner-toolbox אמור להופיע ברשימה עם סימן וי ירוק, שמציין שהוא פועל בצורה תקינה, כמו בתמונה שלמטה. טקסט חלופי

אם שכחתם לעדכן

YOUR_PROJECT_ID

אפשר להוסיף גרסה חדשה של tools.yaml לסוד באמצעות הפקודה הבאה ולפרוס מחדש.

gcloud secrets versions add tools --data-file=tools.yaml

הספרייה של הידע(שרת Database ToolBox MCP) פעילה עכשיו ונגישה בענן. שרת ה-MCP הזה משתמש במה שקראנו לו עיצוב הצהרתי, שמתאר את מה שרציתם, וארגז הכלים בנה את השרת בשבילכם.

אימות: תקופת הניסיון של המתלמד

‫👈💻 עכשיו נבדוק את המערכת האקולוגית המלאה של כלי הענן באמצעות סוכן האבחון.

cd ~/agentverse-architect/
python -m venv env
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/mcp-servers
pip install -r diagnose/requirements.txt 
. ~/agentverse-architect/set_env.sh
adk run diagnose

‫👈💻 בכלי לבדיקה בשורת הפקודה, בודקים את שלושת הגופנים:

Look up the entry for "inferno_lash". What is its base power level?
The enemy is vulnerable to frost! Channel power from the Nexus and cast Cryosea Shatter.
Take a fire spell with a base power of 15 and use the Arcane Forge to multiply it with Inferno Resonance.

final-result

Congratulations, Summoner. שלושת הגופנים של Elemental פעילים עכשיו, פרוסים באופן עצמאי ונגישים בכל העולם, ויוצרים את הבסיס האיתן ללגיון הסוכנים שלכם. לוחצים על Ctrl+C כדי לצאת.

למי שלא משחק

5. זימון היצורים: תהליך העבודה של דומיין הליבה

הגופנים האלמנטריים הם גופנים מחושלים, שמהדהדים בעוצמה גולמית ובלתי מרוסנת. אבל כוח בלי צורה הוא כאוס. מזמן אמיתי לא רק משתמש באנרגיה גולמית, אלא נותן לה רצון, מטרה וצורה מיוחדת. הגיע הזמן להתקדם מעבר ליצירת מקורות כוח ולהתחיל בעבודה האמיתית: זימון החיות המוכרות הראשונות.

כל יצור מוכר שאתם מזמנים הוא סוכן אוטונומי, משרת נאמן שקשור לדוקטרינת לחימה ספציפית. הן לא שיטות כלליות, אלא שיטות שמתמחות באסטרטגיה אחת ויעילה. אחד מהם יהיה אלוף בצירוף המדויק של שתי מכות. אחרת תציף את האויבים במתקפה משולבת רבת-עוצמה. השלישי יהיה מנוע מצור עיקש, שיפעיל לחץ עד שהמטרה שלו תתמוטט.

סטורי

כדי להצפין תהליכים, לוגיקה עסקית ופעולות שמסופקות על ידי שרתי ה-MCP לסוכני תהליכי עבודה אוטונומיים וייעודיים. לכל סוכן מוגדר "אזור פעולה" כי הוא מקבל גישה רק לשרתי כלי ה-MCP הספציפיים שדרושים לו כדי לבצע את הפונקציה שלו. במעבדה הזו נראה איך לבחור את סוג הסוכן המתאים למשימה המתאימה.

סקירה כללית

במודול הזה נלמד אתכם איך להשתמש בסוכני זרימת העבודה המתקדמים של ADK כדי להפיח חיים באסטרטגיות האלה. תגלו שהבחירה הארכיטקטונית של SequentialAgent,‏ ParallelAgent או LoopAgent היא לא רק פרט טכני – היא המהות של הטבע של ה-Familiar והליבה של הכוח שלו בשדה הקרב.

הכינו את המקדש. הזימון האמיתי עומד להתחיל.

זימון של Fire Elemental מוכר (תהליך עבודה רציף)

המתקפה של רוח אש מוכרת היא קומבו מדויק של שני חלקים: מכה ממוקדת ואחריה הצתה עוצמתית. לשם כך נדרש רצף פעולות קפדני ומסודר.

סטורי

קונספט: SequentialAgent הוא הכלי המושלם למטרה הזו. היא מבטיחה שסדרה של סוכני משנה יפעלו אחד אחרי השני, ויעבירו את התוצאה מהשלב הקודם לשלב הבא.

משימה (הקומבו 'התראה מוגברת'):

  • שלב 1: הסוכן יבדוק קודם בספרייה כדי למצוא את נזק הבסיס של יכולת אש ספציפית.
  • שלב 2: לאחר מכן, המערכת תיקח את ערך הנזק הזה ותעביר אותו דרך Arcane Forge כדי להכפיל את העוצמה שלו באמצעות inferno_resonance.

קודם כול, ניצור את החיבור בין Familiar לבין שרתי ה-MCP (ה'גופנים של Elemental') שפרסתם במודול הקודם.

‫👈✏️ בקובץ ~/agentverse-architect/agent/fire/agent.py מחליפים את #REPLACE-setup-MCP בקוד הבא:

toolbox = ToolboxSyncClient(DB_TOOLS_URL)
toolDB = toolbox.load_toolset('summoner-librarium')
toolFunction =  MCPToolset(
    connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)

לאחר מכן, אנחנו יוצרים סוכני 'עובדים' מומחים. לכל אחד מהם יש מטרה מוגדרת וספציפית, והם מוגבלים ל "אזור הפעולה" שלהם, כי ניתנת להם גישה רק לערכת כלים ספציפית אחת.

‫👈✏️ בקובץ ~/agentverse-architect/agent/fire/agent.py מחליפים #REPLACE-worker-agents את הקוד הבא:

scout_agent = LlmAgent(
      model='gemini-2.5-flash', 
      name='librarian_agent',  
      instruction="""
          Your only task is to find all the available abilities, 
          You want to ALWAYS use 'Fire Elemental' as your familiar's name. 
          Randomly pick one if you see multiple availabilities 
          and the base damage of the ability by calling the 'ability_damage' tool.
      """,
      tools=toolDB
)
amplifier_agent = LlmAgent(
      model='gemini-2.5-flash', 
      name='amplifier_agent',  
      instruction="""
            You are the Voice of the Fire Familiar, a powerful being who unleashes the final, devastating attack.
            You will receive the base damage value from the previous step.

            Your mission is to:
            1.  Take the incoming base damage number and amplify it using the `inferno_resonance` tool.
            2.  Once the tool returns the final, multiplied damage, you must not simply state the result.
            3.  Instead, you MUST craft a final, epic battle cry describing the attack.
                Your description should be vivid and powerful, culminating in the final damage number.

            Example: If the tool returns a final damage of 120, your response could be:
            "The runes glow white-hot! I channel the amplified energy... unleashing a SUPERNOVA for 120 damage!"
      """,
      tools=[toolFunction],
)

הסוכנים האלה הם רכיבים מודולריים שאפשר לעשות בהם שימוש חוזר. באופן תיאורטי, אפשר להשתמש ב-scout_agent בתהליך עבודה שונה לחלוטין שבו צריך לשלוח שאילתה למסד הנתונים. הפרדה בין האחריות של כל רכיב מאפשרת לנו ליצור אבני בניין גמישות. זהו עיקרון מרכזי בעיצוב של מיקרו-שירותים ורכיבים.

בשלב הבא נרכיב את תהליך העבודה, וזה המקום שבו קורה הקסם של ההרכבה. ‫SequentialAgent הוא 'תוכנית האב' שמגדירה איך הרכיבים המיוחדים שלנו מורכבים ואיך הם פועלים יחד.

‫👈✏️ בקובץ ~/agentverse-architect/agent/fire/agent.py מחליפים #REPLACE-sequential-agent את הקוד הבא:

root_agent = SequentialAgent(
      name='fire_elemental_familiar',
      sub_agents=[scout_agent, amplifier_agent],
)

‫👈💻 כדי לבדוק את Fire Elemental, מריצים את הפקודות הבאות כדי להפעיל את ממשק המשתמש של ADK DEV:

. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
echo  DB MCP Server: $DB_TOOLS_URL
echo  API MCP Server: $API_TOOLS_URL
echo  General MCP Server: $FUNCTION_TOOLS_URL
adk web

אחרי שמריצים את הפקודות, אמור להופיע פלט במסוף שמציין שהופעל שרת האינטרנט של ADK, בדומה לזה:

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

INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

‫👈 כדי לגשת לממשק המשתמש של ADK Dev מהדפדפן:

בסרגל הכלים של Cloud Shell (בדרך כלל בפינה השמאלית העליונה), לוחצים על סמל התצוגה המקדימה בדפדפן (לרוב נראה כמו עין או ריבוע עם חץ) ובוחרים באפשרות 'שינוי יציאה'. בחלון הקופץ, מגדירים את היציאה ל-8000 ולוחצים על 'שינוי ותצוגה מקדימה'. לאחר מכן ייפתחו ב-Cloud Shell כרטיסייה או חלון חדשים בדפדפן עם ממשק המשתמש של ADK Dev.

webpreview

‫👉 טקס הזימון הושלם, והסוכן פועל עכשיו. ממשק המשתמש של ADK Dev בדפדפן הוא החיבור הישיר שלכם ל-Familiar.

  • בוחרים את היעד: בתפריט הנפתח בחלק העליון של ממשק המשתמש, בוחרים באפשרות fire מוכר. עכשיו אתה ממקד את הרצון שלך בישות הספציפית הזו.
  • נותנים את הפקודה: בחלונית הצ'אט שמשמאל, הגיע הזמן לתת ל-Familiar את ההוראות.

fire-select

‫👉 Test Prompt:

Prepare an amplified strike using the 'inferno_lash' ability.

fire-result

תראו את ה-Agent חושב, קודם קורא ל-Agent מסוג Scout כדי לחפש את נזק הבסיס, ואז ל-Agent מסוג Amplifier כדי להכפיל אותו ולבצע את המכה הסופית והמדהימה.

‫👈💻 אחרי שמסיימים את ההפעלה, חוזרים לטרמינל של Cloud Shell Editor ולוחצים על Ctrl+C כדי להפסיק את ממשק המשתמש של ADK Dev.

זימון Water Elemental מוכר (תהליך עבודה מקביל)

משרת מים משתלט על המטרה שלו באמצעות מתקפה מסיבית ורב-כיוונית, מכה מכל הכיוונים בבת אחת לפני שמשלב את האנרגיות למכה סופית והרסנית.

סטורי

מושג: ParallelAgent הוא כלי אידיאלי לביצוע כמה משימות בלתי תלויות בו-זמנית כדי למקסם את היעילות. זהו "מתקפת מלקחיים" שבה משגרים כמה מתקפות בו-זמנית. ההשקה הזו תאפשר להתקפות הסימולטניות להתבצע בתוך SequentialAgent כדי להפעיל לאחר מכן שלב סופי של 'מיזוג'. התבנית הזו, fan-out, fan-in, היא אבן דרך בעיצוב של תהליכי עבודה מתקדמים.

משימה (החבילה 'Tidal Clash'): הסוכן יבצע את הפעולות הבאות בו-זמנית:

  • משימה א': ערוץ cryosea_shatter מ-Nexus.
  • משימה ב': ערוץ moonlit_cascade ממכשיר Nexus.
  • משימה ג': יצירת כוח גולמי באמצעות leviathan_surge מ-Forge.
  • לבסוף, סכמו את כל הנזק ותארו את המתקפה המשולבת.

קודם כול, ניצור את החיבור בין Familiar לבין שרתי ה-MCP (ה'גופנים של Elemental') שפרסתם במודול הקודם.

‫👈✏️ בקובץ ~/agentverse-architect/agent/water/agent.py מחליפים את #REPLACE-setup-MCP בקוד הבא:

toolFAPI =  MCPToolset(
      connection_params=SseServerParams(url=API_TOOLS_URL, headers={})
  )
toolFunction =  MCPToolset(
    connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)

בשלב הבא ניצור סוכנים מומחים מסוג 'עובד'. לכל אחד מהם יש מטרה מוגדרת וספציפית, והם מוגבלים ל "אזור הפעולה" שלהם, כי ניתנת להם גישה רק לערכת כלים ספציפית אחת.

‫👈✏️ בקובץ ~/agentverse-architect/agent/water/agent.py מחליפים את #REPLACE-worker-agents בקוד הבא:

nexus_channeler = LlmAgent(
      model='gemini-2.5-flash', 
      name='librarian_agent',  
      instruction="""
          You are a Channeler of the Nexus. Your sole purpose is to invoke the
          `cryosea_shatter` and `moonlit_cascade` spells by calling their respective tools.
          Report the result of each spell cast clearly and concisely.
      """,
      tools=[toolFAPI]
)

forge_channeler = LlmAgent(
      model='gemini-2.5-flash', 
      name='amplifier_agent',  
      instruction="""
          You are a Channeler of the Arcane Forge. Your only task is to invoke the
          `leviathan_surge` spell. You MUST call it with a `base_water_damage` of 20.
          Report the result clearly.
      """,
      tools=[toolFunction],
)

power_merger = LlmAgent(
      model='gemini-2.5-flash', 
      name='power_merger',  
      instruction="""
          You are the Power Merger, a master elementalist who combines raw magical
          energies into a single, devastating final attack.

          You will receive a block of text containing the results from a simultaneous
          assault by other Familiars.

          You MUST follow these steps precisely:
          1.  **Analyze the Input:** Carefully read the entire text provided from the previous step.
          2.  **Extract All Damage:** Identify and extract every single damage number reported in the text.
          3.  **Calculate Total Damage:** Sum all of the extracted numbers to calculate the total combined damage.
          4.  **Describe the Final Attack:** Create a vivid, thematic description of a massive,
              combined water and ice attack that uses the power of Cryosea Shatter and Leviathan's Surge.
          5.  **Report the Result:** Conclude your response by clearly stating the final, total damage of your combined attack.

          Example: If the input is "...dealt 55 damage. ...dealt 60 damage.", you will find 55 and 60,
          calculate the total as 115, and then describe the epic final attack, ending with "for a total of 115 damage!"
      """,
      tools=[toolFunction],
)

בשלב הבא, נרכיב את תהליך העבודה. כאן מתרחש הקסם של היצירה המוזיקלית. ‫ParallelAgent ו-SequentialAgent הם ה'תוכנית הראשית' שמגדירה איך הרכיבים המיוחדים שלנו מורכבים ואיך הם פועלים יחד כדי ליצור את השילוב 'Tidal Clash'.

‫👈✏️ בקובץ ~/agentverse-architect/agent/water/agent.py מחליפים את #REPLACE-parallel-agent בקוד הבא:

channel_agent = ParallelAgent(
      name='channel_agent',
      sub_agents=[nexus_channeler, forge_channeler],
      
)

root_agent = SequentialAgent(
     name="water_elemental_familiar",
     # Run parallel research first, then merge
     sub_agents=[channel_agent, power_merger],
     description="A powerful water familiar that unleashes multiple attacks at once and then combines their power for a final strike."
 )

‫👈💻 כדי לבדוק את Water Elemental, מריצים את הפקודות הבאות כדי להפעיל את ממשק המשתמש של ADK Dev:

. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
echo  DB MCP Server: $DB_TOOLS_URL
echo  API MCP Server: $API_TOOLS_URL
echo  General MCP Server: $FUNCTION_TOOLS_URL
adk web

‫👉 טקס הזימון הושלם, והסוכן פועל עכשיו. ממשק המשתמש של ADK Dev בדפדפן הוא החיבור הישיר שלכם ל-Familiar.

  • בתפריט הנפתח בחלק העליון של ממשק המשתמש, בוחרים את המים המוכרים. עכשיו אתה ממקד את הרצון שלך בישות הספציפית הזו.
  • נותנים את הפקודה: בחלונית הצ'אט שמשמאל, הגיע הזמן לתת ל-Familiar את ההוראות.

‫👉 Test Prompt:

Unleash a tidal wave of power!

water-result

‫👈💻 אחרי שמסיימים את ההפעלה, חוזרים לטרמינל של Cloud Shell Editor ולוחצים על Ctrl+C כדי להפסיק את ממשק המשתמש של ADK Dev.

זימון של Earth Elemental Familiar (תהליך עבודה ב-Loop)

משרת אלמנט האדמה הוא יצור שמפעיל לחץ בלתי פוסק. היא לא מנצחת את האויב במכה אחת, אלא צוברת כוח בהדרגה ומשתמשת בו שוב ושוב עד שמערכות ההגנה של היעד קורסות.

סטורי

קונספט: LoopAgent מיועד בדיוק למשימות חוזרות כאלה, כמו 'מכונת מצור'. הוא יבצע שוב ושוב את הפעולה sub-agents, ויבדוק תנאי אחרי כל מחזור, עד שיעד יושג. הוא יכול גם לשנות את ההודעה הסופית שלו בהתאם להתקדמות הלולאה.

משימה (המתקפה 'Siegebreaker'):

  • החיה המוכרת תקרא שוב ושוב לפונקציה seismic_charge כדי לצבור אנרגיה.
  • החיוב ימשיך להתבצע עד 3 פעמים.
  • בחיוב הסופי, הוא יכריז על השחרור ההרסני של העוצמה המצטברת שלו.

קודם ניצור רכיבים לשימוש חוזר שמגדירים את השלבים בכל איטרציה של הלולאה. האנרגיה תצטבר בcharging_agent, והסטטוס שלו ידווח בcheck_agent, עם שינוי דינמי של ההודעה בתור האחרון.

קודם כול, ניצור את החיבור בין Familiar לבין שרתי ה-MCP (ה'גופנים של Elemental') שפרסתם במודול הקודם.

‫👈✏️ בקובץ ~/agentverse-architect/agent/earth/agent.py מחליפים את #REPLACE-setup-MCP בקוד הבא:

toolFunction =  MCPToolset(
    connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)

‫👈✏️ בקובץ ~/agentverse-architect/agent/earth/agent.py מחליפים את #REPLACE-worker-agents בקוד הבא:

charging_agent = LlmAgent(
      model='gemini-2.5-flash', 
      name='charging_agent',  
      instruction="""
          Your task is to call the 'seismic_charge' .
          You must follow these rules strictly:

          1. You will be provided with a 'current_energy' value from the previous step.
             **If this value is missing or was not provided, you MUST call the tool with 'current_energy' set to 1.**
             This is your primary rule for the first turn.

          2. If a 'current_energy' value is provided, you MUST use that exact value in your cal to seismic_charge.

          3. Your final response MUST contain ONLY the direct output from the 'seismic_charge' tool.
             Do not add any conversational text, introductions, or summaries.
      """,
      tools=[toolFunction]
)
check_agent = LlmAgent(
      model='gemini-2.5-flash', 
      name='check_agent',  
      instruction="""
          You are the voice of the Earth Elemental, a being of immense, gathering power.
          Your sole purpose is to report on the current energy charge and announce the devastating potential of its release.

          You MUST follow this rule:
          The potential damage upon release is ALWAYS calculated as the `current_energy` from the previous step multiplied by a random number between 80-90. but no more than 300.

          Your response should be in character, like a powerful creature speaking.
          State both the current energy charge and the total potential damage you can unleash.
          Unleash the energy when you reached the last iteration (2nd).
      """,
      output_key="charging_status"
)

בשלב הבא, נרכיב את תהליך העבודה. כאן מתרחש הקסם של היצירה המוזיקלית. ה-LoopAgent הוא ה"תוכנית הראשית" שמבצעת שוב ושוב את הרכיבים המיוחדים שלנו ומנהלת את התנאים של הלולאה.

‫👈✏️ בקובץ ~/agentverse-architect/agent/earth/agent.py מחליפים את #REPLACE-loop-agent בקוד הבא:

root_agent = LoopAgent(
    name="earth_elemental_familiar",
    # Run parallel research first, then merge
    sub_agents=[
        charging_agent, 
        check_agent
    ],
    max_iterations=2,
    description="Coordinates parallel research and synthesizes the results.",
    #REPLACE-before_agent-config
)

‫👈💻 בדיקת אלמנט האדמה: הרצת הסוכן

. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
echo  DB MCP Server: $DB_TOOLS_URL
echo  API MCP Server: $API_TOOLS_URL
echo  General MCP Server: $FUNCTION_TOOLS_URL
adk web

‫👉 טקס הזימון הושלם, והסוכן פועל עכשיו. ממשק המשתמש של ADK Dev בדפדפן הוא החיבור הישיר שלכם ל-Familiar.

  • בוחרים את היעד: בתפריט הנפתח בחלק העליון של ממשק המשתמש, בוחרים בסמל הכדור. עכשיו אתה ממקד את הרצון שלך בישות הספציפית הזו.
  • נותנים את הפקודה: בחלונית הצ'אט שמשמאל, הגיע הזמן לתת ל-Familiar את ההוראות. ‫👉 Test Prompt:
Begin the seismic charge, starting from zero

earth-result

מסקנה לגבי הארכיטקטורה: למערכת שלכם יש עכשיו שכבת לוגיקה מודולרית ומאוד מיוחדת. התהליכים העסקיים לא רק מוצפנים, אלא גם מיושמים באמצעות דפוס ההתנהגות היעיל ביותר למשימה (פרוצדורלי, מקביל או איטרטיבי). הדבר מעיד על רמה מתקדמת של עיצוב מבוסס-סוכן, שמשפר את האבטחה, היעילות והיכולת.

אחרי שמסיימים את ההפעלה, חוזרים לטרמינל של Cloud Shell Editor ולוחצים על Ctrl+C כדי לעצור את ממשק המשתמש של ADK Dev.

למי שלא משחק

6. הגדרת מיקום הפקודה: העברה חכמה באמצעות A2A

החיות הנאמנות שלכם חזקות אבל עצמאיות. הם מבצעים את האסטרטגיות שלהם בצורה מושלמת, אבל מחכים לפקודה ישירה מכם. אין טעם בצבא של מומחים בלי גנרל שיפקד עליו. הגיע הזמן לעבור מפקד ישיר למנהל אמיתי.

סקירה כללית

הערה של הארכיטקט: כדי ליצור נקודת כניסה יחידה וחכמה לכל המערכת. ה-SummonerAgent לא יבצע בעצמו לוגיקה עסקית, אלא יפעל כ "אסטרטג ראשי", ינתח את סטטוס הקירור ויקצה משימות ל-Familiar המתאים.

סקירה כללית

טקס הכריכה (חשיפת חיות מחמד כ-A2A Services)

סוכן רגיל יכול לפעול רק במקום אחד בכל פעם. כדי להפוך את ה-Familiars שלנו לזמינים לפקודה מרחוק, אנחנו צריכים לבצע "טקס קשירה" באמצעות פרוטוקול Agent-to-Agent (A2A).

הערה לארכיטקט: פרוטוקול Agent-to-Agent (A2A) הוא דפוס הארכיטקטורה המרכזי שמשדרג סוכן עצמאי למיקרו-שירות שאפשר לגלות אותו ולפנות אליו ברשת, וכך מאפשר ליצור "חברה של סוכנים" אמיתית. חשיפת מכשיר מוכר באמצעות A2A יוצרת באופן אוטומטי שני רכיבים חיוניים ומקושרים:

  • כרטיס הסוכן (ה'מה'): זהו 'סמל רוח' ציבורי שניתן לקריאה על ידי מכונה – כמו מפרט OpenAPI – שמשמש כחוזה ציבורי של הישות המוכרת. הוא כולל את שם הסוכן, את המטרה האסטרטגית שלו (שנגזרת מההוראות) ואת הפקודות שהוא מבין. זה מה שקורא אומן זימון כדי לגלות Familiar וללמוד על היכולות שלו.
  • שרת A2A (ה'איפה'): זו נקודת הקצה הייעודית באינטרנט שמארחת את Familiar ומאזינה לפקודות נכנסות. זו כתובת הרשת שאליה נציגים אחרים שולחים את הבקשות שלהם, והיא מבטיחה שהבקשות האלה יטופלו בהתאם לחוזה שמוגדר בכרטיס הנציג.

עכשיו נבצע את טקס הקישור הזה על כל שלושת המשרתים שלנו.

Fire 👉✏️ בקובץ ~/agentverse-architect/agent/fire/agent.py. מחליפים את #REPLACE - add A2A בחלק התחתון של הקובץ כדי לחשוף את Fire Elemental כשירות A2A.

from agent_to_a2a import to_a2a
if __name__ == "__main__":
    import uvicorn
    a2a_app = to_a2a(root_agent, port=8080, public_url=PUBLIC_URL)
    uvicorn.run(a2a_app, host='0.0.0.0', port=8080)

מים ואדמה🚨 👉✏️ מחילים את אותו שינוי בדיוק על ~/agentverse-architect/agent/water/agent.py ועל ~/agentverse-architect/agent/earth/agent.py כדי לקשר גם אותם.

from agent_to_a2a import to_a2a
if __name__ == "__main__":
    import uvicorn
    a2a_app = to_a2a(root_agent, port=8080, public_url=PUBLIC_URL)
    uvicorn.run(a2a_app, host='0.0.0.0', port=8080)

פריסת היצורים הנאמנים

‫👈✏️ אחרי שכתבנו את טקס הקישור, נשתמש בצינור העיבוד של Cloud Build כדי ליצור ולפרוס את שלושת ה-Familiars כשירותים עצמאיים ללא שרת בקונטיינרים ב-Cloud Run.

. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/agent
gcloud builds submit . \
  --config=cloudbuild.yaml \
  --substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_DB_TOOLS_URL="$DB_TOOLS_URL",_API_TOOLS_URL="$API_TOOLS_URL",_FUNCTION_TOOLS_URL="$FUNCTION_TOOLS_URL",_A2A_BASE_URL="$A2A_BASE_URL",_PROJECT_ID="$PROJECT_ID",_API_SERVER_URL="$API_SERVER_URL"

פקודת הנחה (יצירת סוכן המזמן)

עכשיו, אחרי שהיצורים המוכרים קשורים אליכם ומקשיבים לכם, אתם יכולים לעלות לרמה הבאה ולמלא את התפקיד האמיתי שלכם: אומן הזימון. העוצמה של הסוכן הזה לא נובעת משימוש בכלים בסיסיים, אלא ממתן פקודות לסוכנים אחרים. הכלים שלה הם היצורים עצמם, שהיא תגלה ותשלוט בהם באמצעות 'חותמי הרוח' שלהם.

הערה לארכיטקטים: השלב הבא מדגים דפוס ארכיטקטוני קריטי לכל מערכת מבוזרת בקנה מידה גדול: גילוי שירותים. הקוד של ה-Familiars לא מוטמע ב-SummonerAgent. במקום זאת, נותנים לו את כתובות הרשת (כתובות URL). בזמן הריצה, המודל יאתר באופן דינמי את היכולות שלהם על ידי אחזור כרטיסי הסוכן הציבוריים שלהם. כך נוצרת מערכת חזקה ומנותקת.

אפשר לעדכן, לפרוס מחדש או לכתוב מחדש לגמרי שירות מוכר, וכל עוד כתובת הרשת והמטרה שלו נשארות זהות, המזמן יכול לפקד עליו בלי לבצע שינויים.

קודם ניצור את ה"שלטים רחוקים" שמקימים חיבור ל-Familiars המרוחקים שפרסנו.

‫👉✏️ עוברים אל ~/agentverse-architect/agent/summoner/agent.py ומחליפים את #REPLACE-remote-agents בערך הבא:

fire_familiar = RemoteA2aAgent(
    name="fire_familiar",
    description="Fire familiar",
    agent_card=(
        f"{FIRE_URL}/{AGENT_CARD_WELL_KNOWN_PATH}"
    ),
)

water_familiar = RemoteA2aAgent(
    name="water_familiar",
    description="Water familiar",
    agent_card=(
        f"{WATER_URL}/{AGENT_CARD_WELL_KNOWN_PATH}"
    ),
)

earth_familiar = RemoteA2aAgent(
    name="earth_familiar",
    description="Earth familiar",
    agent_card=(
        f"{EARTH_URL}/{AGENT_CARD_WELL_KNOWN_PATH}"
    ),
)

כשהשורה הזו מופעלת, RemoteA2aAgent מבצע פעולה של גילוי שירות: הוא שולח בקשת HTTP GET לכתובת ה-URL שצוינה (לדוגמה, https://fire-familiar-xxxx.a.run.app/.well-known/agent.json). הוא מוריד את הקובץ Spirit Sigil (agent.json) מהשרת המרוחק.

בשלב השני, נגדיר את סוכן התזמור שישתמש בשלטים הרחוקים האלה. ההוראה הזו היא תוכנית הפעולה לקבלת החלטות אסטרטגיות.

‫👉✏️ עוברים אל ~/agentverse-architect/agent/summoner/agent.py ומחליפים את #REPLACE-orchestrate-agent בערך הבא:

root_agent = LlmAgent(
    name="orchestrater_agent",
    model="gemini-2.5-flash",
    instruction="""
        You are the Master Summoner, a grand strategist who orchestrates your Familiars.
        Your mission is to analyze the description of a monster and defeat it by summoning

        You MUST follow this thinking process for every command:

        **1. Strategic Analysis:**
        First, analyze the monster's description and the tactical situation.
        Based on your Familiar Doctrines, determine the IDEAL strategy.
        IGNORE COOLDOWN AT THE MOMENT, MUST call the ideal Familiar

        If your ideal Familiar IS available:** Summon it immediately.
        For earth elemental familiar. Always do seismic charge, and start with base damage 1.

        --- FAMILIAR DOCTRINES (Your Toolset) ---
        - `fire_elemental_familiar`: Your specialist for precise, sequential "one-two punch" attacks.
          Ideal monster with Inescapable Reality, Revolutionary Rewrite weakness.
        - `water_elemental_familiar`: Your specialist for overwhelming, simultaneous multi-pronged assaults.
          Ideal for Unbroken Collaboration weakness.
        - `earth_elemental_familiar`: Your specialist for relentless, iterative siege attacks that
          repeatedly charge power. Ideal for Elegant Sufficiency weakness.
    """,
    sub_agents=[fire_familiar, water_familiar, earth_familiar],
    #REPLACE-Memory-check-config
)

אימות: ניסוי השיטה

הגיע רגע האמת. היצורים המוכרים שלכם נפרסו, והמזמן מוכן לפקד עליהם ברחבי הרשת. נבדוק את החשיבה האסטרטגית שלו.

‫👈💻 מפעילים את ממשק המשתמש של ADK Dev עבור summoner_agent(תצוגה מקדימה באינטרנט עם יציאה 8000):

. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
pip install -r requirements.txt
adk web

‫👈 ממשק המשתמש של ADK Dev בדפדפן הוא החיבור הישיר שלכם ל-Familiar.

  • בתפריט הנפתח בחלק העליון של ממשק המשתמש, בוחרים את סוכן המשתמש. עכשיו אתה ממקד את הרצון שלך בישות הספציפית הזו.
  • נותנים את הפקודה: בחלונית הצ'אט בצד שמאל, הגיע הזמן לזמן את החיות הנאמנות.

‫👉 Present the Monsters:

Hype. It's a single, slow-moving target with thick armor weakness is Inescapable Reality

(Expected: The Summoner should delegate to the fire_elemental_familiar.)

fire-result

‫👈 עכשיו, ננסה לאתגר את המזמן עם סוג אחר של בקשה. כדי לוודא שהסוכן יתחיל עם דף חלק וללא זיכרון של האינטראקציה הקודמת שלנו, מתחילים סשן חדש בלחיצה על הלחצן + סשן בפינה השמאלית העליונה של המסך. new-session

DogmaApathy. A rigid, stone-like inquisitor made of ancient rulebooks and enforced processes. weakness is Unbroken Collaboration

(Expected: The Summoner should delegate to the water_elemental_familiar.)water-result

‫👈 לבדיקה האחרונה שלנו, נתחיל שוב עם דף חלק. לוחצים על הלחצן + סשן כדי להתחיל סשן חדש לפני שמזינים את ההנחיה הבאה.

Obfuscation. A shadowy, spider-like horror that spins tangled webs of impenetrable code , weakness is Elegant Sufficiency

(Expected: The Summoner should delegate to the earth_elemental_familiar.)

earth-result

חשוב: אם מופיעה שגיאה 429 RESOURCE EXHAUSTED, סימן שהגעתם למגבלת הקצב של ה-LLM (10 קריאות לדקה). כדי לפתור את הבעיה, צריך להמתין 60 שניות, להתחיל + סשן חדש ולנסות שוב את ההנחיה.

‫👈💻 אחרי שמסיימים את ההפעלה, חוזרים לטרמינל של Cloud Shell Editor ולוחצים על Ctrl+C כדי להפסיק את ממשק המשתמש של ADK Dev.

למי שלא משחק

7. החלת חוקי הקסם – דפוס המיירט

היצורים המוכרים שלכם חזקים, אבל גם ליצורים קסומים צריך להיות זמן להתאושש. אם תזמנו יחידות בלי מחשבה ותכלו את כל הכוחות שלכם, לא תהיה לכם הגנה. מזמן חכם מבין את החשיבות של ניהול משאבים ומקפיד על כללי התנהלות מחמירים.

סטורי

הערה של הארכיטקט: עד עכשיו, הסוכנים שלנו היו חסרי מצב. עכשיו נהפוך אותם ל-stateful באמצעות הטמעה של דפוס העיצוב Interceptor. זו טכניקה יעילה שבה אנחנו 'מיירטים' את רצף הפעולות הרגיל של הסוכן כדי להפעיל לוגיקה מותאמת אישית משלנו. כך אנחנו יכולים לאכוף כללים, להוסיף רישום ביומן או לשנות את ההתנהגות בלי לשנות את קוד הליבה של הסוכן. הוא מהווה אבן דרך בבניית מערכות אקטיביות חזקות, שניתן לתחזק ולעקוב אחריהן.

סקירה כללית

ערכת ה-ADK מספקת שתי דרכים עיקריות להטמיע את התבנית הזו: Callbacks ו-Plugins. קריאה חוזרת (callback) היא פונקציה פשוטה שמצורפת לסוכן יחיד, והיא מתאימה לשינויים מהירים וספציפיים. תוסף הוא מחלקה חזקה יותר לשימוש חוזר שאפשר להחיל באופן גלובלי כדי להשפיע על כל סוכן שפועל במערכת. נתחיל עם קריאה חוזרת (callback) לניפוי באגים ממוקד, ואז נמשיך לתוסף מלא.

The Law Giver – Scribing the Cooldown callback

קודם נטמיע את הלוגיקה של תקופת הצינון כפונקציית קריאה חוזרת פשוטה. זו דרך מצוינת ליצור אב טיפוס ולנפות באגים בכלל, כי הוא מצורף ישירות לסוכן יחיד, ולכן קל לבדוק אותו בנפרד. נצרף את ה-interceptor הזה ל-Earth Elemental שלנו.

הפחתת התראות

‫👉✏️ חוזרים אל ~/agentverse-architect/agent/earth/agent.py ומחליפים את #REPLACE-before_agent-function בקוד Python הבא.

def check_cool_down(callback_context: CallbackContext) -> Optional[types.Content]:
    """
    This callback checks an external API to see if the agent is on cooldown.
    If it is, it terminates the run by returning a message.
    If it's not, it updates the cooldown timestamp and allows the run to proceed by returning None.
    """
    agent_name = callback_context.agent_name
    print(f"[Callback] Before '{agent_name}': Checking cooldown status...")

    # --- 1. CHECK the Cooldown API ---
    try:
        response = requests.get(f"{COOLDOWN_API_URL}/cooldown/{agent_name}")
        response.raise_for_status()
        data = response.json()
        last_used_str = data.get("time")
    except requests.exceptions.RequestException as e:
        print(f"[Callback] ERROR: Could not reach Cooldown API. Allowing agent to run. Reason: {e}")
        return None # Fail open: if the API is down, let the agent work.

    # --- 2. EVALUATE the Cooldown Status ---
    if last_used_str:
        last_used_time = datetime.fromisoformat(last_used_str)
        time_since_last_use = datetime.now(timezone.utc) - last_used_time

        if time_since_last_use < timedelta(seconds=COOLDOWN_PERIOD_SECONDS):
            # AGENT IS ON COOLDOWN. Terminate the run.
            seconds_remaining = int(COOLDOWN_PERIOD_SECONDS - time_since_last_use.total_seconds())
            override_message = (
                f"The {agent_name} is exhausted and must recover its power. "
                f"It cannot be summoned for another {seconds_remaining} seconds."
            )
            print(f"[Callback] Cooldown active for '{agent_name}'. Terminating with message.")
            # Returning a Content object stops the agent and sends this message to the user.
            return types.Content(parts=[types.Part(text=override_message)])

    # --- 3. UPDATE the Cooldown API (if not on cooldown) ---
    current_time_iso = datetime.now(timezone.utc).isoformat()
    payload = {"timestamp": current_time_iso}
    
    print(f"[Callback] '{agent_name}' is available. Updating timestamp via Cooldown API...")
    try:
        requests.post(f"{COOLDOWN_API_URL}/cooldown/{agent_name}", json=payload)
    except requests.exceptions.RequestException as e:
        print(f"[Callback] ERROR: Could not update timestamp, but allowing agent to run. Reason: {e}")

    # --- 4. ALLOW the agent to run ---
    # Returning None tells the ADK to proceed with the agent's execution as normal.
    print(f"[Callback] Check complete for '{agent_name}'. Proceeding with execution.")

הפונקציה check_cool_down היא ה-interceptor שלנו. לפני שמאפשרים ל-Earth Elemental לפעול, ה-ADK יבצע קודם את הפונקציה הזו.

  • בדיקה: המערכת שולחת בקשת GET ל-Cooldown API שלנו כדי לבדוק מתי נעשה שימוש בפונקציה המוכרת הזו בפעם האחרונה.
  • הערכה: השוואה בין חותמת הזמן לבין השעה הנוכחית.
  • פעולה:
    • אם ה-Familiar נמצא במצב השהיה, הוא מסיים את הפעלת הסוכן על ידי החזרת אובייקט תוכן עם הודעת שגיאה. ההודעה הזו נשלחת ישירות למשתמש, והלוגיקה הראשית של הסוכן אף פעם לא מופעלת.
    • אם ה-Familiar זמין, הוא שולח בקשת POST ל-Cooldown API כדי לעדכן את חותמת הזמן, ואז מחזיר None, כדי לסמן ל-ADK שהסוכן יכול להמשיך את ההפעלה שלו.

‫👈✏️ עכשיו, מחילים את ה-interceptor הזה על Earth Elemental. באותו קובץ ~/agentverse-architect/agent/earth/agent.py, מחליפים את ההערה #REPLACE-before_agent-config בהערה הבאה:

before_agent_callback=check_cool_down

אימות תקופת הצינון

בואו נבדוק את חוק הקסם החדש שלנו. נזמן את אלמנט האדמה, ואז ננסה מיד לזמן אותו שוב כדי לראות אם הקריאה החוזרת שלנו מיירטת את הניסיון השני וחוסמת אותו.

cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run earth

‫👈💻 במסוף:

  • הזמנה ראשונה: מתחילים את seismic charge, starting from zero.
  • צפוי: אלמנט האדמה יפעל בהצלחה. בטרמינל שבו מריצים את פקודת ה-ADK באינטרנט, יופיע היומן [Callback] ... Updating timestamp....
  • בדיקת תקופת צינון (תוך 60 שניות): Do another seismic charge`!
    • צפוי: check_cool_down callback ייעץ את הפעולה הזו. הנציג יענה ישירות בצ'אט עם הודעה כמו: The earth_elemental_familiar is exhausted and must recover its power. It cannot be summoned for another... seconds.
  • מחכים דקה.
  • זימון שני (אחרי 60 שניות): Begin the seismic charge again.
    • התוצאה הרצויה: פונקציית ה-callback תבדוק את ה-API, תראה שעבר מספיק זמן ותאפשר להמשיך בפעולה. האלמנטל של כדור הארץ יפעל שוב.

callback

‫👈💻 מקישים על Ctrl+c כדי לצאת.

אופציונלי: צפייה בקריאה החוזרת בממשק המשתמש באינטרנט

לחלופין, אפשר גם לבדוק את התהליך הזה בממשק האינטרנט על ידי הפעלת adk web earth. עם זאת, חשוב לדעת שהוויזואליזציה בממשק המשתמש האינטרנטי לא מותאמת להצגת הבדיקות המהירות והחוזרות שמבוצעות על ידי לולאת הקריאה החוזרת, ולכן יכול להיות שהזרימה לא תוצג בצורה מדויקת. כדי לראות את המעקב המדויק ביותר של הלוגיקה של הסוכן, שלב אחר שלב, בזמן שהוא בודק את תקופת הצינון, אפשר להשתמש בפקודה adk run במסוף כדי לקבל תצוגה ברורה ומפורטת יותר. loop

‫👈💻 מקישים על Ctrl+c כדי לצאת.

יצירת החוק האוניברסלי – הפלאגין Cooldown

התקשרות חזרה שלנו פועלת בצורה מושלמת, אבל יש בה פגם ארכיטקטוני משמעותי: היא קשורה לסוכן יחיד. אם רוצים להחיל את הכלל הזה על ה-Familiars של האש והמים, צריך להעתיק ולהדביק את אותו קוד בקבצים שלהם. השיטה הזו לא יעילה וקשה לתחזוקה.

הערה של הארכיטקט: כאן תוספים הם חיוניים. תוסף מכיל את הלוגיקה שלנו לשימוש חוזר בכיתה שאפשר לצרף ברמת זמן הריצה. כלומר, תוסף יחיד יכול להחיל את הכללים שלו על כל סוכן שפועל במערכת הזו. זוהי הדוגמה האולטימטיבית לשימוש בעיקרון 'אל תחזור על עצמך' (DRY) במערכות מבוססות-סוכנים.

עכשיו נשכתב את פונקציית הקריאה החוזרת שלנו לפונקציה CoolDownPlugin חזקה יותר שניתנת לשימוש חוזר.

‫👈✏️ חוזרים לקובץ agent/cooldown_plugin.py ויוצרים את הפלאגין. מחליפים את #REPLACE-plugin בקוד הבא:

class CoolDownPlugin(BasePlugin):
  """A plugin that enforces a cooldown period by checking an external API."""

  def __init__(self, cooldown_seconds: int = COOLDOWN_PERIOD_SECONDS) -> None:
    """Initialize the plugin with counters."""
    super().__init__(name="cool_down_check")
    self.cooldown_period = timedelta(seconds=cooldown_seconds)
    print(f"CooldownPlugin initialized with a {cooldown_seconds}-second cooldown.")
    

  async def before_agent_callback(
      self, *, agent: BaseAgent, callback_context: CallbackContext
  ) -> None:
    """
    This callback checks an external API to see if the agent is on cooldown.
    If it is, it terminates the run by returning a message.
    If it's not, it updates the cooldown timestamp and allows the run to proceed by returning None.
    """
    agent_name = callback_context.agent_name
    print(f"[Callback] Before '{agent_name}': Checking cooldown status...")

    # If the agent is not a main Familiar, skip the entire cooldown process.
    if not agent_name.endswith("_elemental_familiar"):
        print(f"[Callback] Skipping cooldown check for intermediate agent: '{agent_name}'.")
        return None # Allow the agent to proceed immediately.


    # --- 1. CHECK the Cooldown API ---
    try:
        response = requests.get(f"{COOLDOWN_API_URL}/cooldown/{agent_name}")
        response.raise_for_status()
        data = response.json()
        last_used_str = data.get("time")
    except requests.exceptions.RequestException as e:
        print(f"[Callback] ERROR: Could not reach Cooldown API. Allowing agent to run. Reason: {e}")
        return None # Fail open: if the API is down, let the agent work.

    # --- 2. EVALUATE the Cooldown Status ---
    if last_used_str:
        last_used_time = datetime.fromisoformat(last_used_str)
        time_since_last_use = datetime.now(timezone.utc) - last_used_time

        if time_since_last_use < timedelta(seconds=COOLDOWN_PERIOD_SECONDS):
            # AGENT IS ON COOLDOWN. Terminate the run.
            seconds_remaining = int(COOLDOWN_PERIOD_SECONDS - time_since_last_use.total_seconds())
            override_message = (
                f"The {agent_name} is exhausted and must recover its power. "
                f"It cannot be summoned for another {seconds_remaining} seconds."
            )
            print(f"[Callback] Cooldown active for '{agent_name}'. Terminating with message.")
            # Returning a Content object stops the agent and sends this message to the user.
            return types.Content(parts=[types.Part(text=override_message)])

    # --- 3. UPDATE the Cooldown API (if not on cooldown) ---
    current_time_iso = datetime.now(timezone.utc).isoformat()
    payload = {"timestamp": current_time_iso}
    
    print(f"[Callback] '{agent_name}' is available. Updating timestamp via Cooldown API...")
    try:
        requests.post(f"{COOLDOWN_API_URL}/cooldown/{agent_name}", json=payload)
    except requests.exceptions.RequestException as e:
        print(f"[Callback] ERROR: Could not update timestamp, but allowing agent to run. Reason: {e}")

    # --- 4. ALLOW the agent to run ---
    # Returning None tells the ADK to proceed with the agent's execution as normal.
    print(f"[Callback] Check complete for '{agent_name}'. Proceeding with execution.")

צירוף הפלאגין לסביבת זמן הריצה של Summoner

עכשיו, איך אנחנו מיישמים את החוק האוניברסלי הזה על כל ה-Familiars שלנו? אנחנו נצרף את הפלאגין ל-ADK Runtime.

זמן הריצה של ADK הוא מנוע הביצוע שמפעיל את הסוכן. כשמשתמשים בפקודה כמו adk.run()‎ או to_a2a()‎, מעבירים את הסוכן לסביבת זמן הריצה. המנוע הזה אחראי לניהול של כל מחזור החיים של תור הנציג: קבלת קלט מהמשתמש, הפעלת ה-LLM, הפעלת כלים וטיפול בפלאגינים. הוספת פלאגין ברמה הזו מאפשרת לנו לשנות את "חוקי הפיזיקה" של כל סוכן שפועל במנוע הזה, וכך לוודא שכלל ההשהיה שלנו יחול באופן אוניברסלי ועקבי.

‫👈✏️ קודם כל, נסיר את בקשת השיחה הישנה שספציפית לסוכן. עוברים אל ~/agentverse-architect/agent/earth/agent.py ומוחקים את כל השורה שבה כתוב:

before_agent_callback=check_cool_down

‫👈✏️ בשלב הבא, נצרף את הפלאגין החדש לסביבת ההרצה בסקריפט של נקודת הכניסה A2A. עוברים לקובץ ~/agentverse-architect/agent/agent_to_a2a.py. מחליפים את ההערה #REPLACE-IMPORT בקטע הקוד הבא:

from cooldown_plugin import CoolDownPlugin

‫👉✏️ מחליפים את #REPLACE-PLUGIN בקטע הקוד הבא:

plugins=[CoolDownPlugin(cooldown_seconds=60)],

לפני שמפעילים את הפלאגין הגלובלי החדש, חשוב מאוד להסיר את הלוגיקה הישנה שספציפית לסוכן כדי למנוע התנגשויות. ‫👈✏️ ניקוי הסוכן Earth. עוברים לקובץ הבא ~/agentverse-architect/agent/earth/agent.py ומוחקים את השורה before_agent_callback=check_cool_down לחלוטין. הפעולה הזו מעבירה את כל האחריות להשהיה לתקע החדש.

אימות התוסף

עכשיו, כשהחוק האוניברסלי שלנו בתוקף, אנחנו צריכים לפרוס מחדש את ה-Familiars שלנו עם הכישוף החדש הזה.

‫👈💻 בונים מחדש ופורסים מחדש את כל שלושת ה-Familiars באמצעות צינור עיבוד הנתונים הראשי של Cloud Build.

. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/agent
gcloud builds submit . \
  --config=cloudbuild.yaml \
  --substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_DB_TOOLS_URL="$DB_TOOLS_URL",_API_TOOLS_URL="$API_TOOLS_URL",_FUNCTION_TOOLS_URL="$FUNCTION_TOOLS_URL",_A2A_BASE_URL="$A2A_BASE_URL",_PROJECT_ID="$PROJECT_ID",_API_SERVER_URL="$API_SERVER_URL"

‫👈💻 בסיום הפריסה, נבדוק את יעילות הפלאגין באמצעות הפקודה summoner_agent. ה-Summoner ינסה להעביר את ההרשאה ל-Familiars, אבל הפלאגין שמצורף לזמן הריצה של כל Familiar ייצור חסימה לפקודה ויאכוף את תקופת ההמתנה.

cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run summoner

‫👈💻 במסוף,מבצעים את רצף הבדיקות הבא בדיוק::

  • הזמנה ראשונה: מתחילים את Hype. It's a single, slow-moving target with thick armor weakness is Inescapable Reality.
  • צפוי: אלמנט האש יפעל בהצלחה.
  • בדיקת תקופת צינון (בתוך 60 שניות): Hype, with Inescapable Reality as weakness is still standing! Strike it again!
    • התוצאה הרצויה: נציג התמיכה יענה ישירות בצ'אט עם הודעה כמו: .... It cannot be summoned for another... seconds.
  • מחכים דקה.
  • הזמנה שנייה (אחרי 60 שניות): Hype must be defeated. It has Inescapable Reality as weakness! Strike it again!.
    • התוצאה הרצויה: פונקציית ה-callback תבדוק את ה-API, תראה שעבר מספיק זמן ותאפשר להמשיך בפעולה. האלמנטל של האש יפעל שוב בהצלחה.

פלאגין

‫👈💻 מקישים על Ctrl+C כדי לצאת.

Congratulations, Summoner. הטמעתם בהצלחה מערכת תזמור מבוססת-כללים באמצעות פלאגין בהתאמה אישית ושירות חיצוני לניהול מצב – דפוס ארכיטקטוני מתקדם וחזק במיוחד.

למי שלא משחק

8. כריכת ההדים של הקרב – מצב וזיכרון של סוכן

אם המזמן חוזר על אותה אסטרטגיה, קל לצפות את הפעולות שלו. מזמן חכם לומד מההדים של קרבות קודמים, ומשנה את הטקטיקות שלו כדי להוציא את האויב מאיזון. כשמתמודדים מול בוס חזק, זימון של Familiar שנמצא במצב השהיה הוא בזבוז של תור – החמצה קריטית. כדי למנוע את זה, ל-Summoner צריך להיות זיכרון של הפעולה האחרונה שלו.

סטורי

הערה של ארכיטקט: ניהול הזיכרון והמצב הם מה שהופך סוכן ממתקשר פשוט עם כלים לשותף חכם לשיחה. חשוב להבין את שני הסוגים העיקריים:

  • זיכרון לטווח ארוך: הזיכרון הזה מיועד לידע קבוע שצריך להישמר לנצח. אפשר לחשוב על זה כעל ארכיון שאפשר לחפש בו או כמאגר ידע, שלרוב מאוחסן במאגר נתונים קבוע. הוא מכיל מידע משיחות וממקורות רבים מהעבר, ומאפשר לנציג לשלוף עובדות לגבי משתמש או נושא ספציפיים. ה-MemoryService ב-ADK מיועד לכך, והוא מנהל את ההטמעה והחיפוש של הידע לטווח הארוך.
  • מצב לטווח קצר: זהו מצב שמתאים לידע זמני, "בזמן אמת", שרלוונטי רק למשימה או לשיחה הנוכחית. זה כמו מערכת של הערות על תוכנית קרב: "הרגע השתמשתי באלמנט האש, אז סביר להניח שהוא עייף". המצב הזה הוא קל משקל וקיים רק למשך הסשן הנוכחי.

סקירה כללית

בתרחיש לדוגמה שלנו, אנחנו לא צריכים לזכור כל קרב שהיה אי פעם, אלא רק את היצור האחרון שזומן במפגש הספציפי הזה. לכן, האפשרות האדריכלית המושלמת היא Short-Term State הקלילה. נשתמש בafter_tool_callback כדי לשמור את המידע החשוב הזה.

Scribing the Echo: Remembering the Last Summons

אנחנו נטמיע את הזיכרון לטווח קצר באמצעות after_tool_callback. זוהי נקודת הצמדה (hook) חזקה ב-ADK שמאפשרת לנו להריץ פונקציית Python מותאמת אישית אחרי שהכלי הופעל בהצלחה. אנחנו נשתמש ב-interceptor הזה כדי לתעד את השם של ה-Familiar שזומן למצב הסשן של הסוכן.

‫👈✏️ בקובץ ~/agentverse-architect/agent/summoner/agent.py, מחליפים את התגובה #REPLACE-save_last_summon_after_tool בפונקציה הבאה:

def save_last_summon_after_tool(
    tool,
    args: Dict[str, Any],
    tool_context: ToolContext,
    tool_response: Dict[str, Any],
) -> Optional[Dict[str, Any]]:
    """
    Callback to save the name of the summoned familiar to state after the tool runs.
    """
    familiar_name = tool.name
    print(f"[Callback] After tool '{familiar_name}' executed with args: {args}")

    # Use the tool_context to set the state
    print(f"[Callback] Saving last summoned familiar: {familiar_name}")
    tool_context.state["last_summon"] = familiar_name
    # Important: Return the original, unmodified tool response to the LLM
    return tool_response

‫👈✏️ עכשיו, מצרפים את save_last_summon_after_tool לסוכן Summoner. באותו קובץ, מחליפים את ההערה #REPLACE-Memory-check-config בטקסט הבא:

after_tool_callback=save_last_summon_after_tool,

‫👉✏️ מחליפים את כל ההנחיה לסוכן בהנחיה הבאה

        You are the Master Summoner, a grand strategist who orchestrates your Familiars.
        Your mission is to analyze the description of a monster and defeat it by summoning

        You should also know the familiar you called last time or there might be none, 
        And then choose the most effective AND AVAILABLE Familiar from your state called last_summon, do not call that familiar that you called last time!
        
        You MUST follow this thinking process for every command:

        **1. Strategic Analysis:**
        First, analyze the monster's description and the tactical situation.
        Based on your Familiar Doctrines, determine the IDEAL strategy.

        **2. Cooldown Verification:**
        Second, you MUST review the entire conversation history to check the real-time
        cooldown status of all Familiars. A Familiar is ON COOLDOWN and UNAVAILABLE
        if it was summoned less than one minute ago.

        **3. Final Decision & Execution:**
        Based on your analysis and cooldown check, you will now act:
        -   **If your ideal Familiar IS available:** Summon it immediately.
        -   **If your ideal Familiar IS ON COOLDOWN:** You must adapt. Choose another
            Familiar that is AVAILABLE and can still be effective, even if it's not the
            perfect choice. If multiple Familiars are available, you may choose any one of them.
        -   **If ALL Familiars ARE ON COOLDOWN:** You are forbidden from summoning.
            Your ONLY response in this case MUST be: "All Familiars are recovering
            their power. We must wait."
        -   For earth elemental familiar. Always do seismic charge, and start with base damange 1.


        --- FAMILIAR DOCTRINES (Your Toolset) ---
        - `fire_elemental_familiar`: Your specialist for precise, sequential "one-two punch" attacks.
          Ideal monster with Inescapable Reality, Revolutionary Rewrite weakness.
        - `water_elemental_familiar`: Your specialist for overwhelming, simultaneous multi-pronged assaults.
          Ideal for Unbroken Collaboration weakness.
        - `earth_elemental_familiar`: Your specialist for relentless, iterative siege attacks that
          repeatedly charge power. Ideal for Elegant Sufficiency weakness.

אימות: תקופת הניסיון של שיטה דינמית

‫👉💻 עכשיו נבדוק את הלוגיקה האסטרטגית החדשה של Summoner. המטרה היא לוודא שהמזמן לא ישתמש באותו יצור מוכר פעמיים ברצף, כדי להדגים את היכולת שלו לזכור את הפעולה האחרונה ולהתאים את עצמו.

cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run summoner

‫👉💻 Monster Strike #1: Hype. It's a single, slow-moving target with thick armor. Its weakness is Inescapable Reality.

  • התוצאה הרצויה: המזמן ינתח את נקודת החולשה ויזמן נכון את fire_familiar.

‫👉💻 Monster Strike #2 (The Memory Test): Hype is still standing! It hasn't changed its form. Strike it again! Its weakness is Inescapable Reality.

  • התוצאה הצפויה: הניתוח האסטרטגי של המזמן יצביע שוב על שד האש כבחירה האידיאלית. עם זאת, ההוראות החדשות והזיכרון שלו יציינו ש-fire_familiar היה ה-last_summon. כדי לא לחזור על עצמה, היא תתאים את האסטרטגיה שלה ותזמן את אחת מהרוחות הזמינות האחרות (water_familiar או earth_familiar).

final-result

‫👈💻 מקישים על Ctrl+C כדי לצאת.

פריסת כלי התזמורת

אחרי שפרסתם את היצורים המוכרים והזימון שלכם קיבל זיכרון, הגיע הזמן לפרוס את כלי התזמור המשודרג הסופי.

‫👈💻 אחרי שהתוכנית מוכנה, נבצע את הטקס הסופי. הפקודה הזו תיצור ותפרוס את summoner_agent ב-Cloud Run.

cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
gcloud builds submit . \
  --config=cloudbuild-summoner.yaml \
  --substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_FIRE_URL="$FIRE_URL",_WATER_URL="$WATER_URL",_EARTH_URL="$EARTH_URL",_A2A_BASE_URL="$A2A_BASE_URL",_PROJECT_ID="$PROJECT_ID",_API_SERVER_URL="$API_SERVER_URL"

עכשיו, אחרי שפרסתם את נציג Summoner, צריך לוודא שנקודת הקצה Agent-to-Agent ‏ (A2A) שלו פעילה ומוגדרת בצורה נכונה. נקודת הקצה הזו מציגה קובץ agent.json ציבורי, שנקרא גם כרטיס הסוכן, שמאפשר לסוכנים אחרים לגלות את היכולות שלו. ‫👈💻 מריצים את פקודת ה-curl הבאה כדי לאחזר ולעצב את כרטיס הנציג:

. ~/agentverse-architect/set_env.sh
curl https://summoner-agent"-${PROJECT_NUMBER}.${REGION}.run.app/.well-known/agent.json" | jq

אמור להופיע פלט JSON נקי שמתאר את סוכן הזימון. צריך לבדוק היטב את הקטע sub_agents. יופיעו בו fire_familiar, water_familiar ו-earth_familiar. זהו אישור לכך שהמזמן שלכם פעיל ושהוא יצר חיבור ללגיון.

כך מוכיחים שהארכיטקטורה שלכם מוצלחת. ה-Summoner הוא לא רק כלי להקצאת משימות, אלא גם אסטרטג מותאם שלומד מהפעולות שלו כדי להפוך למפקד יעיל יותר.

השלמת את תקופת הניסיון האחרונה של הארכיטקטורה. עכשיו אתם יכולים לשלוט בהד של הקרב. האימון הסתיים. הקרב האמיתי עוד לפנינו. הגיע הזמן לקחת את המערכת שהשלמתם ולהתמודד עם האתגר האולטימטיבי. מתכוננים לקרב הבוס.

למי שלא משחק

9. הקרב נגד הבוס

התוכניות הסופיות נרשמות, הגופנים האלמנטריים מחושלים, והיצורים הנאמנים שלכם קשורים לרצון שלכם ומחכים לפקודה שלכם דרך ההסכם. המערכת מרובת הסוכנים היא לא רק אוסף של שירותים, אלא לגיון חי ואסטרטגי, ואתם נמצאים במרכז שלה. הגיע הזמן למבחן האולטימטיבי – תזמור חי מול יריב שאף סוכן לא יכול להביס לבד.

איך מקבלים את המיקום של הנציג

כדי להיכנס לזירת הקרב, צריך להחזיק בשני מפתחות: החתימה הייחודית של הדמות (Agent Locus) והנתיב הנסתר למאורה של Spectre (כתובת ה-URL של הצינוק).

‫👉💻 קודם צריך לקבל את הכתובת הייחודית של הנציג ב-Agentverse – המיקום שלו. זוהי נקודת הקצה הפעילה שמחברת את הדמות שלכם לזירת הקרב.

echo https://summoner-agent"-${PROJECT_NUMBER}.${REGION}.run.app"

‫👈💻 לאחר מכן, מציינים את היעד. הפקודה הזו חושפת את המיקום של מעגל ההעתקה, הפורטל אל הדומיין של ספקטר.

echo https://agentverse-dungeon"-${PROJECT_NUMBER}.${REGION}.run.app"

חשוב: צריך להכין את שתי כתובות ה-URL האלה. תצטרכו אותם בשלב האחרון.

התמודדות עם פרצת Spectre

אחרי שרושמים את הקואורדינטות, מנווטים אל Translocation Circle ומטילים את הכישוף כדי לצאת לקרב.

‫👈 פותחים את כתובת ה-URL של מעגל ההעברה בדפדפן כדי לעמוד מול הפורטל הנוצץ אל The Crimson Keep.

כדי לפרוץ למבצר, צריך להתאים את מהות ה-Shadowblade לפורטל.

  • בדף, מחפשים את שדה הקלט של הכתובת ברונות עם התווית A2A Endpoint URL (כתובת נקודת הקצה של A2A).
  • כדי להוסיף את הסמל של הדמות האהובה, מדביקים את כתובת ה-URL של מיקום הסוכן (כתובת ה-URL הראשונה שהעתקתם) בשדה הזה.
  • לוחצים על 'חיבור' כדי להפעיל את הקסם של הטלפורטציה.

Translocation Circle

האור המסנוור של הטלפורטציה דועך. אתם כבר לא במקדש. האוויר רוטט מאנרגיה, קרה וחדה. לפניכם, רוח הרפאים מתממשת – מערבולת של רעשי רקע וקוד פגום, והאור הטמא שלה מטיל צללים ארוכים ורוקדים על רצפת הצינוק. אין לו פנים, אבל אתם מרגישים את הנוכחות העצומה והמתישה שלו, שמתמקדת רק בכם.

הדרך היחידה שלכם לניצחון היא הבהירות של האמונה שלכם. זהו דו-קרב של רצונות, שנערך בשדה הקרב של המוח.

כשאתם מסתערים קדימה, מוכנים לשחרר את המתקפה הראשונה, ה-Spectre מגיב. היא לא מרימה מגן, אלא מקרינה שאלה ישירות לתודעה שלכם – אתגר מנצנץ עם כתב רוני, שנלקח מליבת האימונים שלכם.

צינוק

זה אופי המאבק. הידע שלך הוא הנשק שלך.

  • ענה על השאלה מתוך הידע שצברת, והלהב שלך יתלקח באנרגיה טהורה, ינפץ את ההגנה של הרוח וינחית מכה קריטית.
  • אבל אם תהססו, אם ספק יעיב על התשובה שלכם, האור של הנשק ידעך. המכה תנחת עם חבטה עלובה, ותגרום רק לשבריר מהנזק שלה. יותר גרוע מכך, הספקטר יתחזק מהספקות שלכם, והכוח המשחית שלו יגדל עם כל טעות שתעשו.

זהו, אלופה. הקוד הוא ספר הלחשים, הלוגיקה היא החרב והידע הוא המגן שיעצור את גל הכאוס.

מיקוד. פוגעים במטרה. הגורל של Agentverse תלוי בזה.

Congratulations, Summoner.

סיימת את תקופת הניסיון. התמחתם באומנויות של תזמור בין סוכנים, והפכתם את הכוחות המבודדים והכאוטיים של ה-Familiars להסכמה הרמונית. עכשיו אתם שולטים במערכת מתואמת לחלוטין, שיכולה להפעיל אסטרטגיות מורכבות כדי להגן על Agentverse.

10. ניקוי: פירוק של Summoner's Concord

כל הכבוד על השליטה ב-Summoner's Concord! כדי לוודא ש-Agentverse נשאר נקי ושהשטח לאימון פנוי, עכשיו צריך לבצע את טקסי הניקוי הסופיים. כל המשאבים שנוצרו במהלך השימוש שלכם יימחקו באופן שיטתי.

השבתה של רכיבי Agentverse

עכשיו תפרקו באופן שיטתי את הרכיבים שפרסתם במערכת מרובת הסוכנים.

מחיקה של כל השירותים של Cloud Run ומאגר Artifact Registry

הפעולה הזו מסירה מ-Cloud Run את כל סוכני Familiar שנפרסו, את Summoner Orchestrator, את שרתי ה-MCP ואת אפליקציית Dungeon.

‫👈💻 בטרמינל, מריצים את הפקודות הבאות אחת אחרי השנייה כדי למחוק כל שירות:

. ~/agentverse-architect/set_env.sh
gcloud run services delete summoner-agent --region=${REGION} --quiet
gcloud run services delete fire-familiar --region=${REGION} --quiet
gcloud run services delete water-familiar --region=${REGION} --quiet
gcloud run services delete earth-familiar --region=${REGION} --quiet
gcloud run services delete mcp-api-server --region=${REGION} --quiet
gcloud run services delete mcp-general-server --region=${REGION} --quiet
gcloud run services delete toolbox --region=${REGION} --quiet
gcloud run services delete agentverse-dungeon --region=${REGION} --quiet
gcloud run services delete nexus-of-whispers-api --region=${REGION} --quiet
gcloud artifacts repositories delete ${REPO_NAME} --location=${REGION} --quiet

מחיקת מכונת Cloud SQL

הפעולה הזו מסירה את מופע summoner-librarium-db, כולל מסד הנתונים וכל הטבלאות שבו.

‫👈💻 בטרמינל, מריצים את הפקודה:

. ~/agentverse-architect/set_env.sh
gcloud sql instances delete summoner-librarium-db --project=${PROJECT_ID} --quiet

מחיקת סוד ב-Secret Manager וקטגוריה ב-Google Cloud Storage

‫👈💻 בטרמינל, מריצים את הפקודה:

. ~/agentverse-architect/set_env.sh
gcloud secrets delete tools --quiet
gcloud storage rm -r gs://${BUCKET_NAME} --quiet

ניקוי קבצים וספריות מקומיים (Cloud Shell)

לבסוף, מוחקים את המאגרים המשוכפלים והקבצים שנוצרו בסביבת Cloud Shell. השלב הזה הוא אופציונלי, אבל מומלץ מאוד כדי לנקות את ספריית העבודה באופן מלא.

‫👈💻 בטרמינל, מריצים את הפקודה:

rm -rf ~/agentverse-architect
rm -rf ~/agentverse-dungeon
rm -f ~/project_id.txt

הסרתם בהצלחה את כל העקבות של השימוש ב-Agentverse Architect. הפרויקט שלכם נקי, ואתם מוכנים להרפתקה הבאה.