Agent First Workflows - From prompt to production

1. סקירה כללית

ברוכים הבאים ל'יום השני'. יצירת אפליקציה ולחיצה על 'פרסום' היא קסם, אבל תנועה בעולם האמיתי מביאה איתה כשלים בעולם האמיתי. במקום לבזבז את הזמן על התמודדות עם YAML או על חיפוש ביומנים, אתם יכולים ליצור נחיל של סוכנים מיוחדים שינהלו בשבילכם את התשתית התפעולית. ב-Codelab הזה נסביר איך מחסנית מאוחדת של Google Cloud (Eventarc,‏ Cloud Run,‏ Firestore,‏ Cloud Build,‏ BigQuery) מאפשרת לסוכנים לאחזר סודות באופן מאובטח, להזרים יומנים ולפתור בעיות בקלות.

סקירה כללית

ב-Codelab הזה נסביר איך ליצור את DinoQuest – משחק הרפתקאות עם דינוזאורים שמבוסס על Gemini – מאפס, ולחבר אותו לפייפליין CI/CD אג'נטי מלא. בסיום התהליך יהיו לכם:

  • אפליקציית אינטרנט פעילה של DinoQuest שפועלת ב-Cloud Run (שם השירות: dinoquest)
  • צינור לניתוח יומנים שמעביר יומנים של Cloud Run ל-BigQuery ויוצר מרכז שליטה אינטראקטיבי עם תובנות לגבי המשחק
  • Remediation Agent (remediation-agent) – סוכן ADK לתיקון בעיות, שעוקב אחרי שגיאות ב-Cloud Run ומתקן אותן אוטומטית. הוא נפרס כשירות Cloud Run משלו, שמופעל על ידי Eventarc.
  • סוכן CI (ci-agent) שקורא את ההבדלים בבקשת משיכת השינויים, מגדיר את היקף הבדיקות בצורה חכמה, יוצר קובץ אימג' של Docker באמצעות Cloud Build ומפרסם סטטוס של קומיט בחזרה ב-GitHub
  • סוכן CD שמדרג את הסיכון של פריסה, מפצל את התנועה, עוקב אחרי מדדים ומקדם או מבטל את הפריסה באופן אוטומטי

מה תלמדו

  • איך פורסים אפליקציית Vite + FastAPI מלאה ב-Cloud Run כקונטיינר יחיד
  • איך מגדירים את Firebase Auth ו-Firestore באפליקציית React
  • איך יוצרים ופורסים סוכן ADK שמגיב לאירועים ב-Pub/Sub באמצעות Eventarc
  • איך לנתב יומנים של Cloud Run ל-BigQuery ולשאול שאילתות לגבי ניתוח נתונים של משחקים
  • איך כותבים יכולות סוכני ל-CI ולפריסה של גרסה ראשונית (canary)

הדרישות

  • פרויקט ב-Google Cloud שהחיוב בו מופעל
  • פרויקט Firebase (יכול להיות אותו פרויקט GCP)
  • חשבון ב-GitHub ומזלג של מאגר DinoQuest
  • גישה ל-Antigravity עם Gemini (הפעלת סוכנים של Google)
  • gcloud ה-CLI מותקן ומאומת – הוראות ההתקנה מפורטות בהמשך
  • node ≥ 18 וגם npm
  • python3 ≥ 3.11
  • git ו-gh (GitHub CLI)

התקנת ה-CLI של gcloud

macOS

brew install --cask google-cloud-sdk

אפשר גם להוריד את קובץ ההתקנה מהכתובת cloud.google.com/sdk/docs/install.

Windows

winget install Google.CloudSDK

אפשר גם להוריד את קובץ ההתקנה של Windows ‏ (.exe) מהכתובת cloud.google.com/sdk/docs/install ולהריץ אותו.

אחרי ההתקנה, מאתחלים ומאמתים:

gcloud init
gcloud auth login
gcloud auth application-default login

‫2. הגדרת Firebase

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

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

א. יצירת פרויקט Firebase

  1. נכנסים לכתובת console.firebase.google.com.
  2. לוחצים על הוספת פרויקט (האפשרות הזו מוסתרת באפשרות ליצירת פרויקט חדש) → בוחרים את פרויקט GCP הקיים (או יוצרים פרויקט חדש)
  3. משביתים את Google Analytics אם מוצגת בקשה לכך → יצירת פרויקט (או אפשר להשתמש בהגדרת ברירת המחדל)

ב. הפעלת אימות של Google

  1. במסוף Firebase, עוברים אל אבטחה → אימות (תחילת העבודה) → שיטת כניסה.
  2. לוחצים על Google → מעבירים את המתג הפעלה למצב מופעל → שומרים את כתובת האימייל לתמיכה → שמירה

ג. הוספת localhost כדומיין מורשה

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

ד. יצירה של מסד נתונים ב-Firestore

  1. עוברים אל Database & Storage → Firestore Database → Create database (מסד נתונים ואחסון → מסד נתונים ב-Firestore → יצירת מסד נתונים)
  2. בוחרים באפשרות מהדורה רגילההבא
  3. בוחרים אזור us-central1 (או בוחרים את האזור של Cloud Run)
  4. בוחרים באפשרות הפעלה במצב ייצוריצירה.

אחרי שיוצרים את מסד הנתונים, כדאי לרשום את מזהה מסד הנתונים. הוא ייראה כמו (default) אלא אם נתתם לו שם.

ה. הגדרת כללי אבטחה ב-Firebase

בקטע Firestore Database → Rules (מסד נתונים של Firestore → כללים), מחליפים את כללי ברירת המחדל בכללים הבאים:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // ===============================================================
    // Helper Functions
    // ===============================================================
    function isAuthenticated() {
      return request.auth != null;
    }
    
    function isOwner(userId) {
      return isAuthenticated() && request.auth.uid == userId;
    }

    function isValidUser(data) {
      return data.keys().hasAll(['uid', 'email']) &&
             data.uid is string && data.uid.size() > 0 &&
             (data.email == null || (data.email is string && data.email.matches("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$")));
    }

    function isValidDinosaur(data) {
      return data.keys().hasAll(['userId', 'name', 'type']) &&
             data.userId == request.auth.uid &&
             data.name is string && data.name.size() > 0 && data.name.size() < 50 &&
             data.type in ['Speedy', 'Tank', 'Balanced', 'Agile'];
    }

    function isValidGame(data) {
      return data.keys().hasAll(['userId', 'score']) &&
             data.userId == request.auth.uid &&
             data.score is number && data.score >= 0;
    }


    match /users/{userId} {
      allow read: if isOwner(userId);
      allow create: if isOwner(userId) && isValidUser(request.resource.data);
      allow update: if isOwner(userId) && isValidUser(request.resource.data);

      match /dinosaurs/{dinoId} {
        allow read: if isOwner(userId);
        allow create: if isOwner(userId) && isValidDinosaur(request.resource.data);
        allow update: if isOwner(userId) && isValidDinosaur(request.resource.data);
      }

      match /games/{gameId} {
        allow read: if isOwner(userId);
        allow create: if isOwner(userId) && isValidGame(request.resource.data);
      }

      match /seenAnnouncements/{announcementId} {
        allow read, create: if isOwner(userId);
      }
    }

    match /announcements/{announcementId} {
      allow read: if isAuthenticated();
    }

    // Default deny
    match /{document=**} {
      allow read, write: if false;
    }

    match /scores/{scoreId} {
      allow read: if true;
      allow create: if isAuthenticated();
      allow update: if false;
    }
  }
}

לוחצים על פרסום.

ו. הוספת אפליקציית אינטרנט וקבלת ההגדרה

  1. עוברים אל הגדרות הפרויקט (סמל גלגל השיניים) → הכרטיסייה כללי.
  2. גוללים אל האפליקציות שלך ← לוחצים על הוספת אפליקציה ← בוחרים בסמל האינטרנט ().
  3. נותנים לו את השם dinoquestרישום האפליקציה
  4. מעתיקים את האובייקט firebaseConfig שמוצג – תצטרכו אותו עוד מעט

3. הפעלת המשחק

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

סקירה כללית

בוחרים אחת משתי האפשרויות הבאות. או שיוצרתם GEMINI_API_KEY שבו אתם משתמשים באופן זהה בכל שלב מאוחר יותר – לא צריך לבצע שינויים נוספים.

א. הגדרת מפתח API של Gemini

‫Vertex AI מאפשר לכם ליצור מפתח Gemini API שקשור ישירות לפרויקט GCP שלכם ומחויב דרכו, באמצעות חשבון השירות שמוגדר כברירת מחדל בפרויקט – אין צורך בחשבון נפרד ב-AI Studio.

  1. מייצאים את מזהה הפרויקט ב-GCP:
    export PROJECT_ID=<YOUR_PROJECT_ID>
    
  2. מפעילים את ממשקי ה-API הנדרשים ומעניקים את ההרשאות הנדרשות לחשבון השירות שמשמש כברירת המחדל של Compute Engine:
    gcloud auth application-default set-quota-project $PROJECT_ID
    gcloud config set project $PROJECT_ID
    
    # Enable Vertex AI, Compute Engine, and Generative Language APIs
    gcloud services enable aiplatform.googleapis.com \
                           compute.googleapis.com \
                           generativelanguage.googleapis.com
    
    # Grant Vertex AI User role to the default compute service account
    PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
      --role="roles/aiplatform.user" \
      --condition=None
    
  3. פותחים את הדף של מפתחות Vertex AI API במסוף Cloud.
  4. לוחצים על Create Credentials (יצירת פרטי כניסה) → בוחרים באפשרות API Key (מפתח API).
  5. בתיבת הדו-שיח ליצירה:
    • נותנים למפתח את השם Dino_Key
    • מסמנים את התיבה Authenticate API calls through a service account (אימות קריאות ל-API באמצעות חשבון שירות).
    • בקטע Service account (חשבון שירות), בוחרים את חשבון השירות שמוגדר כברירת מחדל ל-Compute (PROJECT_NUMBER-compute@developer.gserviceaccount.com).
    • בקטע Select API restrictions (בחירת הגבלות על API), מסמנים את התיבה GEMINI API.
    • לחץ על צור.
  6. מעתיקים את המפתח שנוצר.

אפשרות ב' – AI Studio (הכי מהירה לפיתוח מקומי)

  1. פותחים את aistudio.google.com.
  2. לוחצים על Get API key (קבלת מפתח API) בסרגל הצד השמאלי.
  3. לוחצים על Create API key (יצירת מפתח API) → בוחרים את פרויקט GCP → מעתיקים את המפתח.

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

שכפול המאגר

מאגר הקורס נמצא ב-https://github.com/gca-americas/dinoquest. קודם צריך לשכפל אותו לחשבון GitHub שלכם. הסוכן יעבוד על המאגר שלכם במקום זאת.

אחרי הפיצול, משכפלים את הענף main של מאגר DinoQuest המפוצל ומזינים את ספריית הפרויקט:

git clone https://github.com/YOUR_GITHUB_USERNAME/dinoquest.git
cd dinoquest

ב. הגדרה של משתני סביבה

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

קודם מייצאים את כתובת ה-URL של המאגר ב-GitHub:

export GITHUB_REPO_URL=https://github.com/YOUR_GITHUB_USERNAME/dinoquest

לאחר מכן מייצאים את משתני הסביבה שנותרו:

export PROJECT_ID=your-project-id
export GOOGLE_CLOUD_PROJECT=$PROJECT_ID
export CLOUD_RUN_REGION=us-central1
export GOOGLE_GENAI_USE_VERTEXAI=True
export HARNESS_EVENTS_TOPIC=projects/$PROJECT_ID/topics/harness-events
export CLOUD_BUILD_REPO=<YOUR_GITHUB_USERNAME>-dinoquest

מוודאים שהמבנה נראה נכון:

dinoquest/
├── backend/          # FastAPI backend (serves frontend + Gemini API calls)
├── frontend/         # React/Vite frontend
├── skills/           # Agentic CI/CD skill files
├── Dockerfile        # Multi-stage build (React → Python)
├── start.sh          # Local dev launcher
└── README.md

ב. יצירת קובץ סביבת הקצה העורפי

קודם מייצאים את מפתח Gemini API:

export GEMINI_API_KEY=YOUR_GEMINI_API_KEY_FROM_STEP_2

לאחר מכן יוצרים את קובץ .env:

cat > backend/.env <<EOF
GEMINI_API_KEY=$GEMINI_API_KEY
GOOGLE_GENAI_USE_VERTEXAI=False
GOOGLE_CLOUD_PROJECT=$PROJECT_ID
EOF

ג. הפעלת Firebase App Check / חשבון שירות (ל-Cloud Run)

כשמריצים את הקצה העורפי ב-Cloud Run, הוא משתמש ב-Application Default Credentials כדי לתקשר עם Firebase – אין צורך בקובץ מפתח של חשבון שירות. השיחה ב-firebase_admin.initialize_app() תתעדכן אוטומטית ב-backend/main.py.

בפיתוח מקומי, צריך לבצע אימות פעם אחת:

gcloud auth application-default login

ד. יצירת קובץ התצורה של אפליקציית Firebase

בספרייה frontend/, יוצרים את הקובץ firebase-applet-config.json עם ההגדרות מהשלב הקודם:

{
  "apiKey": "YOUR_API_KEY",
  "authDomain": "YOUR_PROJECT_ID.firebaseapp.com",
  "projectId": "YOUR_PROJECT_ID",
  "storageBucket": "YOUR_PROJECT_ID.appspot.com",
  "messagingSenderId": "YOUR_SENDER_ID",
  "appId": "YOUR_APP_ID",
  "firestoreDatabaseId": "(default)"
}

הערה: הערך של firestoreDatabaseId צריך להיות זהה למזהה מסד הנתונים שיצרתם בשלב הקודם. אם השתמשתם בברירת המחדל, השאירו את הערך "(default)".

שומרים את השינויים במאגר:

git add frontend/firebase-applet-config.json
git commit -m "chore: add firebase config"
git push origin main

ג. הפעלת DinoQuest באופן מקומי

1. הפעלת ממשקי ה-API הנדרשים

gcloud services enable \
  run.googleapis.com \
  cloudbuild.googleapis.com \
  artifactregistry.googleapis.com \
  secretmanager.googleapis.com \
  firestore.googleapis.com \
  logging.googleapis.com \
  pubsub.googleapis.com \
  eventarc.googleapis.com \
  aiplatform.googleapis.com \
  bigquery.googleapis.com \
  aiplatform.googleapis.com

‫2. התחלת DinoQuest

הסקריפט start.sh בונה את הקצה הקדמי של React ומעביר את הטרמינל לקצה העורפי של FastAPI, שמציג את הקבצים הסטטיים שעברו קומפילציה:

cd backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt -q

cd ..
# Force-remove the Vertex AI flag from the current terminal session to avoid conflicts
unset GOOGLE_GENAI_USE_VERTEXAI
./start.sh

פותחים את http://localhost:8000 בדפדפן. אמור להופיע מסך הכותרת של DinoQuest. נכנסים באמצעות חשבון Google, יוצרים את הדינוזאור הראשון ומוודאים שהוא נשמר ב-Firestore.

פתרון בעיות: אם מופיע דף ריק או שגיאות אימות של Firebase, צריך לוודא של-frontend/firebase-applet-config.json יש את הערכים הנכונים ושה-localhost נמצא ברשימת הדומיינים המורשים.

ה. פריסת DinoQuest ב-Cloud Run

1. הגדרת הפרויקט

export PROJECT_ID=$(gcloud config get-value project)

3. יצירת מאגר Artifact Registry

gcloud artifacts repositories create dinoquest \
  --repository-format=docker \
  --location=$CLOUD_RUN_REGION \
  --description="DinoQuest container images"

4. אחסון מפתח Gemini API ב-Secret Manager

echo -n $GEMINI_API_KEY | \
  gcloud secrets create gemini-api-key --data-file=-

# Grant the default compute service account access to the secret
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
gcloud secrets add-iam-policy-binding gemini-api-key \
  --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
  --role="roles/secretmanager.secretAccessor"

5. יצירת קובץ אימג' של קונטיינר באמצעות Cloud Build

gcloud builds submit \
  --tag $CLOUD_RUN_REGION-docker.pkg.dev/$PROJECT_ID/dinoquest/app:latest .

הפעולה הזו מריצה את קובץ ה-Dockerfile הרב-שלבי: קודם היא יוצרת את אפליקציית React, ואז אורזת את הפלט בתמונה של FastAPI. התהליך נמשך כ-3 עד 5 דקות.

6. פריסה ב-Cloud Run

קודם מייצאים את כתובת האימייל של האדמין:

export ADMIN_EMAIL=<YOUR_TEST_ACCOUNT_EMAIL>

לאחר מכן פורסים את השירות:

gcloud run deploy dinoquest \
  --image=$CLOUD_RUN_REGION-docker.pkg.dev/$PROJECT_ID/dinoquest/app:latest \
  --region=$CLOUD_RUN_REGION \
  --platform=managed \
  --allow-unauthenticated \
  --memory=128Mi \
  --set-secrets="GEMINI_API_KEY=gemini-api-key:latest" \
  --set-env-vars="ADMIN_EMAILS=$ADMIN_EMAIL" \
  --set-env-vars="GOOGLE_GENAI_USE_VERTEXAI=False" \
  --set-env-vars="GOOGLE_CLOUD_PROJECT=$PROJECT_ID"

בסיום הפקודה, Cloud Run מדפיס כתובת URL של שירות. מעתיקים את כתובת ה-URL הזו – תצטרכו אותה כדי לאשר את הדומיין ב-Firebase.

7. אישור הדומיין של Cloud Run ב-Firebase

כדי לאפשר למשתמשים להיכנס לאפליקציה שפרסתם, אתם צריכים להוסיף את כתובת ה-URL של Cloud Run לדומיינים המורשים של Firebase:

  1. חוזרים אל מסוף Firebaseאימות → הגדרות → דומיינים מורשים
  2. לוחצים על הוספת דומיין.
  3. מדביקים את כתובת ה-URL של שירות Cloud Run (לדוגמה, dinoquest-xxxxx.us-central1.run.app) – מסירים את התחילית https://
  4. לוחצים על שמירה.

8. איכלוס נתוני טבלת המובילים

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

  1. מוודאים שאתם נמצאים בספריית השורש dinoquest:
    cd ~/dinoquest
    
  2. יוצרים ומפעילים סביבה וירטואלית:
    python3 -m venv venv
    source venv/bin/activate
    
  3. מתקינים את יחסי התלות הנדרשים של Firestore:
    pip install google-cloud-firestore
    
  4. מריצים את הסקריפט להוספת נתונים:
    python3 prep/seed_scores.py
    
  5. משביתים את הסביבה הווירטואלית:
    deactivate
    

עכשיו אפשר לפתוח את כתובת ה-URL של השירות בדפדפן – DinoQuest פעיל לגמרי!

4. הגדרת Dino Theater

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

סקירה כללית

א. פריסת Dino Theater ב-Cloud Run

קודם חוזרים לספריית הבית ומשכפלים את הקוד של Dino Theater:

cd ~
git clone https://github.com/gca-americas/dinoquest-theater.git
cd dinoquest-theater
  1. יוצרים את מאגר התגים ומעבירים אותו:
    gcloud builds submit --tag $CLOUD_RUN_REGION-docker.pkg.dev/$PROJECT_ID/dinoquest/dino-theater:latest .
    
  2. הגדרת חשבון שירות והרשאות:
    # Create the service account
    gcloud iam service-accounts create dino-theater
    
    # Create the Pub/Sub topic (if you haven't yet)
    gcloud pubsub topics create harness-events
    
    # Create the subscription
    gcloud pubsub subscriptions create harness-events-theater \
      --topic=harness-events
    
    # Grant subscriber role
    gcloud pubsub subscriptions add-iam-policy-binding harness-events-theater \
      --member="serviceAccount:dino-theater@${PROJECT_ID}.iam.gserviceaccount.com" \
      --role="roles/pubsub.subscriber"
    
  3. פריסת האפליקציה:
    gcloud run deploy dino-theater \
      --image $CLOUD_RUN_REGION-docker.pkg.dev/$PROJECT_ID/dinoquest/dino-theater:latest \
      --region=$CLOUD_RUN_REGION \
      --service-account=dino-theater@${PROJECT_ID}.iam.gserviceaccount.com \
      --set-env-vars="GOOGLE_CLOUD_PROJECT=$PROJECT_ID" \
      --allow-unauthenticated \
      --min-instances=1
    
    הערה: מומלץ להשתמש ב---min-instances=1 כדי לשמור על חיבור ה-SSE פעיל בין אירועים.
  4. מוודאים שהיא פועלת: פותחים את כתובת ה-URL של השירות שהופעל בדפדפן (לדוגמה, https://dino-theater-xxx-uc.a.run.app/demo).

5. Agentic DevOps in the IDE

תפקיד הסוכן: Native Antigravity. כדי לגשר על הפער בין סביבת הפיתוח המשולבת (IDE) לבין הענן, אנחנו מחברים את Antigravity לשרתי MCP מנוהלים של Google Cloud. כך הסוכן המקורי מקבל 'עיניים' בפרויקט שלכם, והוא יכול לנתח יומנים, לבדוק מדדים ולבצע ניתוח של התשתית בלי שתצטרכו לנהל מפתחות API או לעבור בין הקשרים במסוף.

לפני שמפעילים מיומנויות, צריך להגדיר את הגישה של Antigravity ל-Google Cloud ולטעון את חוברות ההדרכה של מיומנות DinoQuest.

א. התקנה של שירות Google MCP מנוהל

שירות ה-MCP המנוהל של Google מספק גישה לכל Google Cloud APIs דרך נקודת קצה יחידה באירוח.

אימות באמצעות Application Default Credentials:

gcloud auth application-default login

ב. הגדרת mcp_config.json

יוצרים או מעדכנים את mcp_config.json בספריית ההגדרות של Antigravity (בדרך כלל ~/.gemini/antigravity/mcp_config.json) או מהמסוף. כך Antigravity מקבל גישה לכלים של Google Cloud ו-GitHub שהמיומנויות צריכות:

{
  "mcpServers": {
    "google-developer-knowledge": {
      "serverUrl": "https://developerknowledge.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    },
    "google-bigquery": {
      "serverUrl": "https://bigquery.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    },
    "google-cloud-logging": {
      "serverUrl": "https://logging.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    },
    "google-cloud-monitoring": {
      "serverUrl": "https://monitoring.googleapis.com/mcp",
      "authProviderType": "google_credentials",
      "disabledTools": [
        "get_dashboard",
        "list_dashboards"
      ]
    },
    "google-cloud-run": {
      "serverUrl": "https://run.googleapis.com/mcp",
      "authProviderType": "google_credentials",
      "disabledTools": [
        "deploy_service_from_image",
        "deploy_service_from_archive",
        "deploy_service_from_file_contents"
      ]
    },
    "google-cloud-sql": {
      "serverUrl": "https://sqladmin.googleapis.com/mcp",
      "authProviderType": "google_credentials",
      "disabled": true
    },
    "google-cloud-trace": {
      "serverUrl": "https://cloudtrace.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    },
    "google-error-reporting": {
      "serverUrl": "https://clouderrorreporting.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    },
    "google-firestore": {
      "serverUrl": "https://firestore.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    },
    "google-resource-manager": {
      "serverUrl": "https://cloudresourcemanager.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    },
    "gemini-cloud-assist": {
      "serverUrl": "https://geminicloudassist.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    }
  }
}

ג. טעינת מיומנויות ב-Antigravity (אופציונלי)

‫Antigravity מאתר מיומנויות בספריות סטנדרטיות ספציפיות. מעתיקים את כישורי DinoQuest מהמאגר המשוכפל לתיקיית הכישורים הגלובלית של Antigravity:

# Create the standard skills directory if it doesn't exist
mkdir -p ~/.gemini/antigravity/skills

# Copy all DinoQuest skills into the global skills folder
cp -r skills/* ~/.gemini/antigravity/skills/

ד. הפעלה מחדש של Antigravity(אופציונלי)

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

אחרי ההפעלה מחדש:

  1. מוודאים ששרתי ה-MCP של google ו-github מציגים סטטוס ירוק של 'מחובר' בהגדרות.
  2. מוודאים שהמיומנויות של DinoQuest מופיעות ברשימת המיומנויות.

הערה: לכל מיומנות יש טבלת ## Configuration בחלק העליון של SKILL.md. אחרי ההעתקה, צריך לעדכן את הערכים ב-~/.gemini/antigravity/skills//SKILL.md כך שיתאימו לפרויקט.

ה. תיקון שירות ענן בסביבת פיתוח משולבת (IDE) מקומית

  1. הפעלת השגיאה: פותחים בדפדפן את כתובת ה-URL של DinoQuest שפרסתם (מהשלב האחרון).
  2. מעבר לטבלת המובילים: לוחצים על הלחצן טבלת המובילים. ההטמעה הנוכחית של טבלת המובילים לא יעילה בכוונה – היא תנסה לטעון כמות עצומה של נתונים לזיכרון, מה שיגרום לשגיאת חוסר זיכרון (OOM).
  3. ב-Antigravity Agent Manager (Agent HUB), מבקשים ממנו לעזור לשחזר את השגיאה ואולי לתקן את שורש הבעיה.
  • הנחיה 1: תבדוק מה לא בסדר ב-dinoquest.
  • הנחיה 2: תוכל לבדוק את הקוד של המשחק Dinoquest ולתקן את מה שגרם לשגיאה 'אין מספיק זיכרון'?

6. סטרימינג של יומנים ל-BigQuery ויצירת ניתוחים

תפקיד הסוכן: סוכן נתונים. הפיכת יומנים גולמיים לאסטרטגיית מוצר מעשית לא צריכה להימשך שעות של ניתוח נתונים ידני. באמצעות Data Agent Kit ו-BigQuery MCP, אנחנו יוצרים פייפליין של 'Zero ETL' שמעביר יומנים בסטרימינג ישירות אל BigQuery, וכך מאפשר לסוכן ליצור לוח בקרה של ניתוח נתונים מתקדם תוך פחות משתי דקות.

התכונה log-router-bq-report מגדירה יעד ב-Cloud Logging שמעביר באופן רציף את היומנים של DinoQuest ב-Cloud Run ל-BigQuery, ואז שולחת שאילתות לנתונים כדי ליצור דוחות תנועה ותובנות לגבי ניתוח נתונים של משחקים.

סקירה כללית

א. הגדרת משתני המיומנות

פותחים את skills/log-router-bq-report/SKILL.md במאגר DinoQuest ומעדכנים את הקטע Configuration (הגדרה) בחלק העליון:

| Variable      | Your Value         |
|---------------|--------------------|
| SERVICE_NAME  | dinoquest          |
| BQ_DATASET    | dinoquest_logs     |
| LOG_SINK_NAME | dinoquest-bq-sink  |

ב. הפעלת המיומנות ב-Antigravity

פותחים את Antigravity עם מאגר DinoQuest כהקשר ומבקשים מ-Gemini:

Run the log-router-bq-report skill

המיומנות תאפשר:

  1. פתרון הבעיה בפרויקט GCP באופן אוטומטי
  2. בודקים אם יעד BigQuery כבר קיים – אם לא, המערכת תיצור את מערך הנתונים ואת היעד.
  3. הענקת הרשאות IAM: תוענק ל-writerIdentity של יעד ההעברה ההרשאה BigQuery Data Editor (עריכת נתונים ב-BigQuery) במערך הנתונים.

הערה: כמו ב-Eventarc sink, יכול להיות שתופיע אזהרה מ-gcloud במהלך התהליך הזה: "חשוב לזכור להעניק לחשבון השירות:service-... את התפקיד BigQuery Data Editor במערך הנתונים". המיומנות מטפלת בזה באופן אוטומטי.

ג. שימוש ב-Antigravity ליצירת הדוח

פשוט מבקשים מ-Antigravity "להגדיר את sink ביומן של BigQuery וליצור את דוח ניתוח הנתונים". הנציג/ה:

  1. הגדרת התשתית: יוצרים את מערך הנתונים ב-BigQuery ואת יעד הנתונים ב-Cloud Logging.
  2. ניהול הרשאות: הקצאה אוטומטית של תפקידי ה-IAM הנדרשים לזהות הכתיבה של ה-sink.
  3. יצירת תובנות: ניתוח היומנים ויצירת לוח בקרה אינטראקטיבי בפורמט HTML עם טלמטריה של המשחק וניתוח של שיעור הניצחונות.

7. סוכן תיקון עצמי

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

‫DinoAgent הוא סוכן ADK שמקשיב ליומני שגיאות של Cloud Run דרך Eventarc, מאבחן את שורש הבעיה ומתקן אותה באופן אוטומטי – על ידי הגדלת הזיכרון, החזרת התנועה או שליחת בקשת משיכה לתיקון קוד ב-GitHub.

סקירה כללית

א. שכפול המאגר של Remediation Agent

cd ~
git clone https://github.com/gca-americas/dinoquest-reme-agent.git
cd dinoquest-reme-agent

מבנה הפרויקט:

dinoquest-reme-agent/
├── main.py              # Service entrypoint — receives Eventarc HTTP POST, runs agent
├── runner.py            # ADK Runner + session service
├── agent.py             # LlmAgent definition, loads skill from file
├── tools.py             # Cloud Run v2 API tools (list/get/rollback/update)
├── skills/
   └── remediation/
       ├── SKILL.md     # Agent playbook — edit this to change behavior
       └── scripts/     # Shell scripts for the code-fix track
           ├── clone_repo.sh
           ├── read_file.sh
           ├── apply_fix.sh
           ├── commit_branch.sh
           ├── open_pr.sh
           └── rollback_fix.sh
├── requirements.txt
└── Dockerfile

ב. הגדרת גישה ל-GitHub (מסלול תיקון קוד)

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

  1. עוברים אל github.com/settings/tokensGenerate new token (classic) (יצירת טוקן חדש (קלאסי))
  2. נותנים לו שם, בוחרים את ההיקף repoיצירת טוקן ← מעתיקים אותו

אחסון ב-Secret Manager:

קודם מייצאים את הטוקן של GitHub:

export GH_TOKEN=ghp_YOUR_TOKEN_HERE

לאחר מכן יוצרים את ה-Secret:

echo -n $GH_TOKEN | \
  gcloud secrets create github-token --data-file=-

ג. הגדרת התראות ב-Slack (אופציונלי)

כשפעולת התיקון מסתיימת, DinoAgent מפרסם סיכום בערוץ Slack.

  1. עוברים אל api.slack.com/appsCreate New App → From scratch (יצירת אפליקציה חדשה → מאפס)
  2. נותנים לו את השם DinoAgent, בוחרים את סביבת העבודה → יצירת אפליקציה
  3. בקטע תכונותIncoming Webhooks → מעבירים את המתג למצב מופעל.
  4. לוחצים על הוספת Webhook חדש לסביבת העבודה → בוחרים ערוץ → אישור.
  5. מעתיקים את כתובת ה-URL של ה-webhook‏ (https://hooks.slack.com/services/...).

אחסון ב-Secret Manager:

export SLACK_TOKEN=YOUR_SLACK_WEBHOOK
echo -n "https://hooks.slack.com/services/$SLACK_TOKEN" | \
  gcloud secrets create slack-webhook --data-file=-

ד. יצירת חשבון השירות DinoAgent

gcloud iam service-accounts create remediation-agent \
  --display-name="Cloud Run Remediation Agent"

export SA="remediation-agent@${PROJECT_ID}.iam.gserviceaccount.com"

for ROLE in \
  roles/run.admin \
  roles/iam.serviceAccountUser \
  roles/eventarc.eventReceiver \
  roles/aiplatform.user \
  roles/artifactregistry.reader \
  roles/secretmanager.secretAccessor \
  roles/pubsub.publisher \
  roles/logging.viewer; do
  gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member="serviceAccount:${SA}" --role="$ROLE" \
    --condition=None
done

מעניקים לו גישה לסודות:

for SECRET in github-token slack-webhook; do
  gcloud secrets add-iam-policy-binding $SECRET \
    --member="serviceAccount:${SA}" \
    --role="roles/secretmanager.secretAccessor"
done

ה. פיתוח ופריסה של DinoAgent ב-Cloud Run

# Get Project Number for the CIAgent URL
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
export CIAGENT_URL=https://ci-agent-${PROJECT_NUMBER}.${CLOUD_RUN_REGION}.run.app
export SA="remediation-agent@${PROJECT_ID}.iam.gserviceaccount.com"
export GITHUB_REPO_URL=https://github.com/YOUR_REPO
HARNESS_EVENTS_TOPIC=projects/$PROJECT_ID/topics/harness-events


AGENT_IMAGE="$CLOUD_RUN_REGION-docker.pkg.dev/${PROJECT_ID}/dinoquest/remediation-agent:latest"
gcloud builds submit --tag $AGENT_IMAGE .


gcloud run deploy remediation-agent \
  --image=$AGENT_IMAGE \
  --region=$CLOUD_RUN_REGION \
  --service-account=$SA \
  --memory=2Gi \
  --set-env-vars="GOOGLE_CLOUD_PROJECT=${PROJECT_ID},GOOGLE_GENAI_USE_VERTEXAI=True" \
  --set-env-vars="GITHUB_REPO_URL=${GITHUB_REPO_URL}" \
  --set-secrets="SLACK_WEBHOOK_URL=slack-webhook:latest" \
  --set-env-vars="HARNESS_EVENTS_TOPIC=${HARNESS_EVENTS_TOPIC}" \
  --set-env-vars="CIAGENT_URL=${CIAGENT_URL}" \
  --set-secrets="GITHUB_TOKEN=github-token:latest" \
  --no-allow-unauthenticated \
  --min-instances=1 \
  --no-cpu-throttling \
  --timeout=300

ו. חיבור טריגר Eventarc

יוצרים נושא Pub/Sub כדי לקבל יומני שגיאות של Cloud Run:

gcloud pubsub topics create cloud-run-errors

יוצרים מאגר ב-Cloud Logging שמסנן יומני שגיאות משירות dinoquest ומנתב אותם לנושא:

export SERVICE_NAME=dinoquest
FILTER="resource.type=\"cloud_run_revision\" resource.labels.service_name=\"$SERVICE_NAME\" severity=ERROR NOT logName=~\"cloudaudit\" NOT httpRequest.requestUrl=~\"/_ah/health\""

gcloud logging sinks create cloud-run-errors-sink \
  pubsub.googleapis.com/projects/${PROJECT_ID}/topics/cloud-run-errors \
  --log-filter="$FILTER"

הערה: כשמריצים את הפקודה שלמעלה, gcloud מדפיס הודעת מידע: "חשוב להקצות לחשבון השירות serviceAccount:service-... את התפקיד 'פרסום הודעות ב-Pub/Sub' בנושא". בשלב הבא נסביר איך עושים את זה.

מעניקים לזהות הכתיבה של ה-sink (חשבון השירות שמוזכר באזהרה) הרשאה לפרסום:

SINK_SA=$(gcloud logging sinks describe cloud-run-errors-sink \
  --format='value(writerIdentity)')

gcloud pubsub topics add-iam-policy-binding cloud-run-errors \
  --member="${SINK_SA}" --role="roles/pubsub.publisher"

בודקים שהיא פעילה:

gcloud eventarc triggers describe remediation-trigger --location=$CLOUD_RUN_REGION

נותנים ל-Eventarc הרשאה להפעיל את סוכן התיקון:

gcloud run services add-iam-policy-binding remediation-agent \
  --region=$CLOUD_RUN_REGION \
  --member="serviceAccount:${SA}" \
  --role="roles/run.invoker"

יוצרים את הטריגר של Eventarc:

gcloud eventarc triggers create remediation-trigger \
  --location=$CLOUD_RUN_REGION \
  --destination-run-service=remediation-agent \
  --destination-run-region=$CLOUD_RUN_REGION \
  --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
  --transport-topic=projects/${PROJECT_ID}/topics/cloud-run-errors \
  --service-account=${SA}

התיקון מתבצע עכשיו באופן אוטומטי לגמרי. בנוסף להרחבת התשתית, DinoAgent מבצע ניתוח מעמיק של שורש הבעיה בקוד האפליקציה, מחיל תיקון סמנטי ומשתמש בתקשורת סוכן לסוכן (A2A) כדי להעביר את התיקון לסוכן ה-CI לצורך אימות ופריסה. אפשר לעיין בפרטי ההטמעה בבסיס הקוד של reme-agent.

8. הגדרת סוכן ה-CI

תפקיד הסוכן: צינור עיבוד נתונים של CI. לא צריך יותר להתמודד עם קובצי YAML מורכבים ועם סקריפטים ידניים של build. הסוכן הזה מנהל את התשתית התפעולית של בקשות משיכה. הוא קורא את שינויי הקוד, מבין את ההקשר, מגדיר את הבדיקות הנדרשות ובונה את תמונות ה-Docker באמצעות Cloud Build, כדי לוודא שכל קומיט מאושר על ידי הסוכן לפני שהוא מגיע לענף הראשי.

ci-agent הוא סוכן אוטונומי של צינור CI שמופעל כשירות Cloud Run. הוא שולח את ה-build של Docker ל-Cloud Build, מבצע בדיקה חוזרת כדי לראות אם הוא הסתיים, מאמת את האימג' ב-Artifact Registry ומדווח ל-GitHub.

סקירה כללית

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

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

א. שכפול מאגר ה-CIAgent

cd ~
git clone https://github.com/gca-americas/dinoquest-ci-agent.git
cd dinoquest-ci-agent

ב. יצירת חשבון השירות CIAgent

gcloud iam service-accounts create ci-agent \
  --display-name="CIAgent CI Pipeline"

export SA="ci-agent@${PROJECT_ID}.iam.gserviceaccount.com"

# Grant necessary roles to the service account
for ROLE in \
  roles/cloudbuild.builds.editor \
  roles/cloudbuild.builds.builder \
  roles/artifactregistry.reader \
  roles/artifactregistry.writer \
  roles/aiplatform.user \
  roles/secretmanager.secretAccessor \
  roles/pubsub.publisher \
  roles/developerconnect.admin; do
  gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member="serviceAccount:${SA}" --role="$ROLE" \
    --condition=None
done



# ci-agent needs to act as itself when running build steps
gcloud iam service-accounts add-iam-policy-binding $SA \
  --member="serviceAccount:${SA}" \
  --role="roles/iam.serviceAccountUser"

ג. חיבור מאגר GitHub ל-Cloud Build

‫CIAgent שולח גרסאות build דרך repoSource, ולכן צריך לחבר את מאגר GitHub ל-Cloud Build Developer Connect.

  1. עוברים אל GCP Console → Cloud Build → Repositories
  2. לוחצים על קישור מאגר.
  3. בוחרים באפשרות GitHub (Cloud Build GitHub App) (‏GitHub (אפליקציית GitHub של Cloud Build))
  4. מאשרים ובוחרים את מאגר YOUR_GITHUB_USERNAME/dinoquest
  5. לוחצים על Connect (חיבור) ועל Skip (דילוג) כשמוצגת בקשה ליצור טריגר.
  6. רושמים את שם החיבור (ברירת המחדל היא בדרך כלל שם המשתמש שלכם ב-GitHub או שם דומה).

ד. הענקת גישה לסודות ל-CIAgent

נשתמש מחדש בסודות שנוצרו קודם בשביל DinoAgent:

gcloud secrets add-iam-policy-binding github-token \
  --member="serviceAccount:${SA}" \
  --role="roles/secretmanager.secretAccessor"

gcloud secrets add-iam-policy-binding slack-webhook-ci \
  --member="serviceAccount:${SA}" \
  --role="roles/secretmanager.secretAccessor"

ה. פיתוח ופריסה של CIAgent ב-Cloud Run

# Set up required variables for orchestration
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
export CDAGENT_URL=https://cd-agent-${PROJECT_NUMBER}.${CLOUD_RUN_REGION}.run.app
export CI_AGENT_URL=ci-agent-${PROJECT_NUMBER}.${CLOUD_RUN_REGION}.run.app
export GITHUB_OWNER="YOUR_GITHUB_USERNAME"
export CLOUD_BUILD_CONNECTION="YOUR_CONNECTION_NAME"  # Update this if your connection name is different
export CLOUD_BUILD_REPO="YOUR_GITHUB_USERNAME-dinoquest" # Update this if your connection name is different

export SLACK_TOKEN=YOUR_SLACK_WEBHOOK
echo -n "https://hooks.slack.com/services/$SLACK_TOKEN" | \
  gcloud secrets create slack-webhook-ci --data-file=-

export SA="ci-agent@${PROJECT_ID}.iam.gserviceaccount.com"
AGENT_IMAGE="$CLOUD_RUN_REGION-docker.pkg.dev/${PROJECT_ID}/dinoquest/ci-agent:latest"
gcloud builds submit --tag $AGENT_IMAGE .

gcloud run deploy ci-agent \
  --image=$AGENT_IMAGE \
  --region=$CLOUD_RUN_REGION \
  --service-account=$SA \
  --memory=1Gi \
  --timeout=600 \
  --allow-unauthenticated \
  --min-instances=1 \
  --set-env-vars="GOOGLE_CLOUD_PROJECT=${PROJECT_ID},GOOGLE_GENAI_USE_VERTEXAI=True" \
  --set-env-vars="HARNESS_EVENTS_TOPIC=${HARNESS_EVENTS_TOPIC}" \
  --set-env-vars="HOST=${CI_AGENT_URL},PROTOCOL=https" \
  --set-secrets="SLACK_WEBHOOK_URL=slack-webhook-ci:latest" \
  --set-env-vars="GITHUB_OWNER=${GITHUB_OWNER},GITHUB_REPO=dinoquest" \
  --set-env-vars="CLOUD_BUILD_CONNECTION=${CLOUD_BUILD_CONNECTION},CLOUD_BUILD_REPO=${CLOUD_BUILD_REPO},CLOUD_BUILD_REGION=${CLOUD_RUN_REGION}" \
  --set-env-vars="CDAGENT_URL=${CDAGENT_URL}" \
  --set-secrets="GITHUB_TOKEN=github-token:latest" \
  --min-instances=1

ו. הגדרה של פקודה דרך שורת הפקודות ב-Slack

  1. עוברים אל api.slack.com/appsCreate New App (יצירת אפליקציה חדשה) → From scratch (מאפס).
  2. מעניקים את השם CIAgent, בוחרים את סביבת העבודה → יצירת אפליקציה
  3. בקטע תכונותפקודות דרך שורת הפקודותיצירת פקודה חדשה
  4. פקודה: /runci
  5. כתובת ה-URL של הבקשה: כתובת ה-URL של CIAgent Cloud Run מהשלב הקודם עם התוספת /slack (לדוגמה, https://ci-agent-xxx-.us-central1.run.app/slack)
  6. תיאור קצר: Trigger CI
  7. שמירה
  8. בקטע הגדרותהתקנת אפליקציה, לוחצים על התקנה ב-Workspace ואז על 'אישור'.

סוכן ה-CI פועל כ "מוח" שיושב מעל שירותים חזקים של Google Cloud כמו Cloud Build ו-Artifact Registry. אחרי שהבנייה מאומתת, היא מפעילה את שלב הפריסה הסופי על ידי קריאה לסוכן ה-CD באמצעות A2A, וכך מבטיחה מעבר חלק בין מחזורי הבנייה וההפצה.

9. הגדרת פריסה

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

cd-agent הוא סוכן פריסה של גרסה ראשונית (canary) אוטונומי שנפרס כשירות Cloud Run. הוא מקבל בקשות לפריסת A2A מ-ci-agent, מחשב ציון סיכון, מגדיר אחוז קנרי מכויל סיכון, עוקב אחרי מדדים ומקדם או מבטל את הפריסה באופן אוטומטי. הוא גם לומד מפריסות קודמות באמצעות Firestore.

סקירה כללית

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

  1. שיתוף הקשר חכם: סוכנים מעבירים זיכרונות מלאים של סשנים, הבדלים בבקשות למשיכת קוד וציוני סיכון, כדי להבטיח שלסוכן הבא יהיה את כל ההקשר לפני שהוא מתחיל לעבוד.
  2. לחיצות ידיים קוגניטיביות: סוכנים יכולים לנהל משא ומתן על שערים. לדוגמה, סוכן ה-CD יכול לבקש מסוכן ה-CI בדיקות עשן ספציפיות במהלך השקת קנרי כדי לאמת תיקון בזמן אמת.
  3. תיקון שגיאות בשיתוף פעולה: אם פריסה נכשלת, סוכן ה-CD יכול להודיע באופן יזום לסוכן התיקון על מדדים שנכשלו, ולהתחיל ניתוח אוטונומי של שורש הבעיה עוד לפני שמודיעים על כך לאדם.
  4. משא ומתן על משאבים: סוכנים יכולים לנהל משא ומתן על צורכי התשתית. לדוגמה, סוכן ה-CI יכול לבקש מסוכן התיקון להקצות עוד קיבולת בנייה אם הוא מזהה שינוי מבנה בקנה מידה גדול, או שסוכן ה-CD יכול להציע לשנות את קנה המידה של אשכול הייצור לפני מהדורה גדולה.
  5. הסכמה של כמה סוכנים: לשינויים בסיכון גבוה, כמה סוכנים (למשל, סוכן אבטחה וסוכן CD) יכולים לבצע 'אישור משותף' באמצעות A2A, כדי לוודא שהקוד לא רק נבנה ונפרס, אלא גם עומד במדיניות האבטחה לפני שהוא מגיע לייצור.

א. שכפול המאגר CDAgent

cd ~
git clone https://github.com/gca-americas/dinoquest-cd-agent.git
cd dinoquest-cd-agent

ב. יצירת מסד הנתונים ב-Firestore

‫CDAgent שומר את דפוסי הזיכרון של הפריסה ב-Firestore:

gcloud firestore databases create \
  --region=$CLOUD_RUN_REGION \
  --project=$PROJECT_ID

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

ג. יצירת חשבון השירות CDAgent

gcloud iam service-accounts create cd-agent \
  --display-name="CDAgent Canary Deployer"

export SA="cd-agent@${PROJECT_ID}.iam.gserviceaccount.com"

# Grant necessary roles
for ROLE in \
  roles/run.developer \
  roles/iam.serviceAccountUser \
  roles/artifactregistry.reader \
  roles/artifactregistry.writer \
  roles/monitoring.viewer \
  roles/datastore.user \
  roles/aiplatform.user \
  roles/run.admin \
  roles/pubsub.publisher; do
  gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member="serviceAccount:${SA}" --role="$ROLE" \
    --condition=None
done

ד. הענקת גישה לסודות ל-CDAgent

נשתמש מחדש בטוקן GitHub וב-webhook של Slack מהשלבים הקודמים, וניתן לחשבון השירות של Cloud Run גישה למפתח Gemini API כדי שהאפליקציה שנפרסה תוכל להשתמש בו:

gcloud secrets add-iam-policy-binding github-token \
  --member="serviceAccount:${SA}" \
  --role="roles/secretmanager.secretAccessor"

gcloud secrets add-iam-policy-binding slack-webhook-cd \
  --member="serviceAccount:${SA}" \
  --role="roles/secretmanager.secretAccessor"

# Grant the compute service account access to Gemini API key
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
gcloud secrets add-iam-policy-binding gemini-api-key \
  --project=$PROJECT_ID \
  --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
  --role="roles/secretmanager.secretAccessor"

ה. פיתוח ופריסה של CDAgent ב-Cloud Run

export GITHUB_OWNER="YOUR_GITHUB_USERNAME"

export CD_AGENT_URL=cd-agent-${PROJECT_NUMBER}.${CLOUD_RUN_REGION}.run.app

export SLACK_TOKEN=YOUR_SLACK_WEBHOOK
echo -n "https://hooks.slack.com/services/$SLACK_TOKEN" | \
  gcloud secrets create slack-webhook-cd --data-file=-

AGENT_IMAGE="$CLOUD_RUN_REGION-docker.pkg.dev/${PROJECT_ID}/dinoquest/cd-agent:latest"
gcloud builds submit --tag $AGENT_IMAGE .


export SA="cd-agent@${PROJECT_ID}.iam.gserviceaccount.com"


gcloud run deploy cd-agent \
  --image=$AGENT_IMAGE \
  --region=$CLOUD_RUN_REGION \
  --service-account=$SA \
  --memory=1Gi \
  --set-env-vars="GOOGLE_CLOUD_PROJECT=${PROJECT_ID}" \
  --set-env-vars="GOOGLE_GENAI_USE_VERTEXAI=True" \
  --set-env-vars="HOST=${CD_AGENT_URL},PROTOCOL=https" \
  --set-env-vars="CD_TARGET_SERVICE=dinoquest" \
  --set-env-vars="HARNESS_EVENTS_TOPIC=${HARNESS_EVENTS_TOPIC}" \
  --set-env-vars="GITHUB_OWNER=${GITHUB_OWNER}" \
  --set-env-vars="GITHUB_REPO=dinoquest" \
  --set-env-vars="DEMO_MODE=true" \
  --set-env-vars="LEADERBOARD_ENABLED=true" \
  --set-secrets="SLACK_WEBHOOK_URL=slack-webhook-cd:latest" \
  --set-secrets="GITHUB_TOKEN=github-token:latest" \
  --allow-unauthenticated \
  --min-instances=1 \
  --no-cpu-throttling \
  --timeout=300

הערה: --min-instances=1 --no-cpu-throttling שומר על המופע פעיל כדי שיוכל להגיב במהירות לפקודות של Slack ו-A2A.

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

10. התקדמות: הגעה לרמה 2 באמצעות נחיל הסוכנים

א. בדיקת כלל המערכת

  1. הפעלת השגיאה: פותחים בדפדפן את כתובת ה-URL של DinoQuest שפרסתם (מהשלב האחרון).
  2. מעבר לטבלת המובילים: לוחצים על הלחצן טבלת המובילים. ההטמעה הנוכחית של טבלת המובילים לא יעילה בכוונה – היא תנסה לטעון כמות עצומה של נתונים לזיכרון, מה שיגרום לשגיאת חוסר זיכרון (OOM).
  3. המתנה לסוכן: תוך כ-60 שניות, הסוכן remediation-agent יקבל את אירוע השגיאה דרך Eventarc ויתחיל באבחון.
  4. בדיקה ב-Slack: אמורה להופיע התראה בערוץ Slack שלכם שנראית כך:סיכום פעולות התיקון של DinoAgent
    • שירות: dinoquest
    • גרסה שנכשלה: dinoquest-xxxx-xxxx
    • הוכחה: "חריגה ממגבלת הזיכרון של 128MiB, עם שימוש ב-13x MiB".
    • למה הגרסה הזו הייתה גרועה: נקודת הקצה /api/leaderboard הייתה xxxxx בצורה לא יעילה, ולכן נגרמה שגיאת OOM.
    • הפעולה שבוצעה: הגדלת הזיכרון מ-xMi ל-yGi בשירות dinoquest. נוצרה גרסה חדשה.
    • בקשת משיכה לתיקון שורש הבעיה: https://github.com/YOUR_USERNAME/DinoQuest/pull/x
  5. אימות התיקונים:
    • GitHub: בודקים אם יש הסתעפות חדשה ובקשת משיכה במאגר. הסוכן תיקן את קוד האפליקציה כדי לפתור את דליפת הזיכרון הבסיסית.
    • Cloud Run: במסוף GCP, תופיע גרסה חדשה של שירות dinoquest עם הקצאת הזיכרון המעודכנת.
    • טבלת הבאז: כדאי לנסות שוב את טבלת הבאז – עכשיו היא אמורה להיטען בהצלחה בזכות הזיכרון המוגדל והתיקון של הקוד.

ב. אבולוציה: הטמעה של לוגיקת משחק ברמה 2

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

  1. חוזרים אל מאגר dinoquest:
    cd ~/dinoquest
    
  2. יצירה של ענף חדש ומעבר אליו:
    git checkout -b level_2
    
  3. החלת תיקון (patch) של רמה 2: מריצים את הסקריפט שסופק כדי לתקן את בסיס הקוד המקומי באמצעות נכסים, רכיבים ולוגיקת משחק של רמה 2:
    bash level_2_backup/levelup.sh
    
  4. שומרים ודוחפים את השינויים:
    git add .
    git commit -m "feat: add Level 2"
    git push origin level_2
    

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

  1. פותחים את Slack ועוברים לערוץ שבו מותקנת אפליקציית CIAgent.
  2. מפעילים את ה-CI build על ידי הקלדת הפקודה הבאה:
    /runci run ci on branch level_2
    
  3. מעקב אחר ההתקדמות:
    • Slack: הסוכן יאשר את הפקודה ויפרסם עדכונים ככל שה-build יתקדם.
    • Dino Theater: צופים ב'בועות המחשבה' בזמן שהסוכן מסווג את השינוי, שולח את המשימה של Cloud Build ומתקשר עם סוכן ה-CD.
    • GitHub: בודקים את בקשת משיכת השינויים level_2. תראו שהסוכן מפרסם סטטוסים של ביצוע פעולות (commit) ותגובה עם דוח מלא של CI.
  4. צפייה בתהליך:
    • כדי לראות את תהליך החשיבה של סוכן ה-CI, את סיווג השינוי ואת הרצת צינור עיבוד הנתונים, אפשר לעבור אל Dino Theater.
    • בודקים את בקשת משיכת השינויים ב-GitHub כדי לראות את סטטוס הקומיט והדוח הסופי שפורסמו על ידי CI Agent.

11. סיכום

בניתם מחסנית DevOps מלאה מבוססת-סוכנים ב-Google Cloud:

רכיב

תיאור

DinoQuest (Cloud Run dinoquest)

משחק מבוסס-Gemini – קצה קדמי של React + קצה עורפי של FastAPI

Firebase Auth + Firestore

אימות משתמשים ואחסון פרופילים של דינוזאורים

סוכן לתיקון (Cloud Run + Eventarc)

סוכן SRE שמתקן באופן אוטומטי שגיאות OOM ובאגים בקוד

log-router-bq-report

סוכן נתונים שמעביר יומנים ל-BigQuery ויוצר תובנות

CIAgent (Cloud Run)

סוכן CI שמגדיר את היקף הבדיקות, יוצר תמונות ומפעיל CD באמצעות A2A

CDAgent (Cloud Run)

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

כל התנהגות של סוכן נמצאת בספרייה skills/ כספרי הדרכה בפורמט Markdown. כדי לשנות את ההתנהגות, צריך לערוך את המיומנות ולא את הקוד. המיומנויות פועלות ב-Antigravity עם Gemini, וההפעלה שלהן מתבצעת באמצעות אמירת שם המיומנות לסוכן.