เวิร์กโฟลว์ที่เน้น Agent เป็นอันดับแรก - ตั้งแต่พรอมต์จนถึงการผลิต

1. ภาพรวม

ยินดีต้อนรับสู่ "วันที่ 2" แม้ว่าการสร้างแอปและกด "เผยแพร่" จะเป็นเรื่องง่าย แต่การเข้าชมในโลกแห่งความเป็นจริงก็อาจทำให้เกิดข้อผิดพลาดในโลกแห่งความเป็นจริงได้ คุณสามารถสร้างฝูงเอเจนต์เฉพาะทางเพื่อจัดการการเชื่อมต่อการดำเนินงานให้คุณได้ แทนที่จะต้องเสียเวลาทั้งวันไปกับการจัดการ YAML หรือการค้นหาในบันทึก Codelab นี้แสดงให้เห็นว่าสแต็กแบบรวมของ Google Cloud (Eventarc, Cloud Run, Firestore, Cloud Build, BigQuery) ช่วยให้เอเจนต์ดึงข้อมูลลับ สตรีมบันทึก และแก้ไขปัญหาได้อย่างปลอดภัยได้ง่ายๆ โดยไม่ต้องดำเนินการใดๆ เพิ่มเติม

ภาพรวม

ใน Codelab นี้ คุณจะได้สร้าง DinoQuest ซึ่งเป็นเกมผจญภัยไดโนเสาร์ที่ขับเคลื่อนโดย Gemini ตั้งแต่ต้นจนจบ และเชื่อมต่อกับไปป์ไลน์ CI/CD ที่เป็น Agent อย่างเต็มรูปแบบ เมื่อจบหลักสูตร คุณจะได้รับสิ่งต่อไปนี้

  • เว็บแอป DinoQuest ที่ใช้งานได้ซึ่งทำงานบน Cloud Run (ชื่อบริการ: dinoquest)
  • ไปป์ไลน์การวิเคราะห์บันทึกที่สตรีมบันทึกของ Cloud Run ไปยัง BigQuery และสร้างแดชบอร์ดข้อมูลเชิงลึกเกี่ยวกับเกมแบบอินเทอร์แอกทีฟ
  • Remediation Agent (remediation-agent) - ADK Remediation Agent ที่ตรวจสอบข้อผิดพลาดของ Cloud Run และแก้ไขโดยอัตโนมัติ ซึ่งติดตั้งใช้งานเป็นบริการ Cloud Run ของตัวเองที่ทริกเกอร์โดย Eventarc
  • เอเจนต์ CI (ci-agent) ที่อ่าน Diff ของ PR, กำหนดขอบเขตการทดสอบอย่างชาญฉลาด, สร้างอิมเมจ Docker ผ่าน Cloud Build และโพสต์สถานะคอมมิตกลับไปยัง GitHub
  • เอเจนต์ CD ที่ให้คะแนนความเสี่ยงในการติดตั้งใช้งาน แยกการเข้าชม ตรวจสอบเมตริก และโปรโมตหรือย้อนกลับโดยอัตโนมัติ

สิ่งที่คุณจะได้เรียนรู้

  • วิธีทำให้แอป Vite + FastAPI แบบฟูลสแต็กใช้งานได้ใน Cloud Run เป็นคอนเทนเนอร์เดียว
  • วิธีกำหนดค่า Firebase Auth และ Firestore สำหรับแอป React
  • วิธีสร้างและทำให้ใช้งานได้ Agent ประเภท ADK ที่ตอบสนองต่อเหตุการณ์ Pub/Sub ผ่าน Eventarc
  • วิธีกำหนดเส้นทางบันทึกของ Cloud Run ไปยัง BigQuery และค้นหาข้อมูลวิเคราะห์เกม
  • วิธีเขียนทักษะที่เป็น Agent สำหรับ CI และการทำให้ Canary ใช้งานได้

สิ่งที่คุณต้องมี

  • โปรเจ็กต์ Google Cloud ที่เปิดใช้การเรียกเก็บเงิน
  • โปรเจ็กต์ Firebase (อาจเป็นโปรเจ็กต์ GCP เดียวกัน)
  • บัญชี GitHub และ Fork ของที่เก็บ DinoQuest
  • สิทธิ์เข้าถึง Antigravity ด้วย Gemini (ตัวเรียกใช้เอเจนต์ของ Google)
  • gcloud ติดตั้งและตรวจสอบสิทธิ์ CLI แล้ว - ดูวิธีการติดตั้งด้านล่าง
  • node ≥ 18 และ npm
  • python3 ≥ 3.11
  • git และ gh (GitHub CLI)

ติดตั้ง gcloud CLI

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. ไปที่ฐานข้อมูลและพื้นที่เก็บข้อมูล → ฐานข้อมูล Firestore → สร้างฐานข้อมูล
  2. เลือก Standard Editionถัดไป
  3. เลือกภูมิภาค us-central1 (หรือเลือกภูมิภาค Cloud Run ที่ตรงกัน)
  4. เลือกเริ่มในโหมดที่ใช้งานจริงสร้าง

เมื่อสร้างแล้ว ให้จดรหัสฐานข้อมูล ซึ่งจะมีลักษณะเป็น (default) เว้นแต่คุณจะตั้งชื่อไว้

จ. ตั้งค่ากฎการรักษาความปลอดภัยของ Firebase

ใน Firestore Database → Rules ให้แทนที่กฎเริ่มต้นด้วยกฎต่อไปนี้

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. ตั้งชื่อว่า dinoquestRegister app
  4. คัดลอกfirebaseConfigออบเจ็กต์ที่แสดง คุณจะต้องใช้ในอีกสักครู่

3. การเรียกใช้เกม

บทบาทของเอเจนต์: สภาพแวดล้อม ก่อนที่จะให้เอเจนต์ทำงานได้ เราต้องมีโลกให้เอเจนต์จัดการ ในขั้นตอนนี้ เราจะติดตั้งใช้งาน DinoQuest เวอร์ชัน "Day One" ซึ่งจะสร้างบริการสด บันทึก และสถานะที่ฝูงของเราจะค้นพบและจัดการในภายหลัง

ภาพรวม

เลือกตัวเลือกใดตัวเลือกหนึ่งจาก 2 ตัวเลือกด้านล่าง หรือสร้าง GEMINI_API_KEY ที่คุณใช้เหมือนกันในทุกขั้นตอนต่อๆ ไป โดยไม่ต้องทำการเปลี่ยนแปลงอื่นๆ

ก. ตั้งค่าคีย์ Gemini API

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 Console
  4. คลิกสร้างข้อมูลเข้าสู่ระบบ → เลือกคีย์ API
  5. ในกล่องโต้ตอบการสร้าง ให้ทำดังนี้
    • ตั้งชื่อคีย์เป็น Dino_Key
    • เลือกช่องตรวจสอบสิทธิ์การเรียก API ผ่านบัญชีบริการ
    • ในส่วนบัญชีบริการ ให้เลือกบัญชีบริการ Compute เริ่มต้น (PROJECT_NUMBER-compute@developer.gserviceaccount.com)
    • กลับไปที่เลือกการจำกัด API แล้วเลือก GEMINI API
    • คลิกสร้าง
  6. คัดลอกคีย์ที่สร้างขึ้น

ตัวเลือก ข - AI Studio (เร็วที่สุดสำหรับการพัฒนาในเครื่อง)

  1. เปิด aistudio.google.com
  2. คลิกรับคีย์ API ในแถบด้านข้างทางซ้าย
  3. คลิกสร้างคีย์ API → เลือกโปรเจ็กต์ GCP → คัดลอกคีย์

คุณตั้งค่าคีย์ใดก็ได้เป็น GEMINI_API_KEY ในขั้นตอนถัดไป โดยแบ็กเอนด์จะถือว่าคีย์ทั้ง 2 เหมือนกัน

โคลนที่เก็บ

ที่เก็บหลักสูตรจะอยู่ใน https://github.com/gca-americas/dinoquest โปรดฟอร์กไปยังบัญชี GitHub ของคุณก่อน เราจะให้ตัวแทนดำเนินการกับที่เก็บของคุณแทน

หลังจาก Fork แล้ว ให้โคลนmain Branch ของที่เก็บ DinoQuest ที่ Fork ไว้ แล้วเข้าสู่ไดเรกทอรีโปรเจ็กต์

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

ข. ตั้งค่าตัวแปรสภาพแวดล้อม

ในทุกเทอร์มินัล Bash ใหม่ที่คุณเปิดระหว่าง Codelab นี้ โปรดตรวจสอบว่าได้ตั้งค่าตัวแปรสภาพแวดล้อมที่จำเป็นเหล่านี้แล้ว แทนที่ค่าตัวยึดตำแหน่งด้วยรายละเอียดโปรเจ็กต์จริง

ก่อนอื่น ให้ส่งออก 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 ส่วนแบ็กเอนด์จะใช้ข้อมูลรับรองเริ่มต้นของแอปพลิเคชันเพื่อสื่อสารกับ 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 นี้ คุณจะต้องใช้ 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. ติดตั้งทรัพยากร Dependency ของ Firestore ที่จำเป็น
    pip install google-cloud-firestore
    
  4. เรียกใช้สคริปต์การเริ่มต้น
    python3 prep/seed_scores.py
    
  5. ปิดใช้งานสภาพแวดล้อมเสมือน
    deactivate
    

ตอนนี้คุณสามารถเปิด URL ของบริการในเบราว์เซอร์ได้แล้ว DinoQuest พร้อมให้บริการอย่างเต็มรูปแบบแล้ว

4. ตั้งค่า Dino Theater

บทบาทของตัวแทน: Visualizer คุณจะตรวจสอบทีมเอเจนต์อัตโนมัติได้อย่างไร 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. DevOps ที่ใช้ Agent ใน IDE

บทบาทของเอเจนต์: Native Antigravity เราเชื่อมต่อ Antigravity กับเซิร์ฟเวอร์ MCP ที่มีการจัดการของ Google Cloud เพื่อลดช่องว่างระหว่าง IDE กับระบบคลาวด์ ซึ่งจะช่วยให้เอเจนต์เนทีฟมี "ดวงตา" ในโปรเจ็กต์ของคุณ ทำให้สามารถแยกวิเคราะห์บันทึก ตรวจสอบเมตริก และให้เหตุผลเกี่ยวกับโครงสร้างพื้นฐานได้โดยไม่ต้องสลับคีย์ API หรือสลับบริบทไปยังคอนโซล

ก่อนที่จะเรียกใช้ทักษะใดๆ คุณต้องกำหนดค่าการเข้าถึง Google Cloud ของ Antigravity และโหลด Playbook ของทักษะ DinoQuest

ก. ติดตั้งบริการ MCP ที่มีการจัดการของ Google

บริการ MCP ที่มีการจัดการของ Google ให้สิทธิ์เข้าถึง Google Cloud API ทั้งหมดผ่านปลายทางเดียวที่โฮสต์

ตรวจสอบสิทธิ์โดยใช้ข้อมูลรับรองเริ่มต้นของแอปพลิเคชัน:

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 ซึ่งช่วยให้ Agent สร้างแดชบอร์ดข้อมูลวิเคราะห์ระดับพรีเมียมได้ภายในเวลาไม่ถึง 2 นาที

log-router-bq-reportทักษะจะตั้งค่าซิงก์ Cloud Logging ที่สตรีมบันทึก Cloud Run ของ DinoQuest ไปยัง BigQuery อย่างต่อเนื่อง จากนั้นจะค้นหาข้อมูลเพื่อสร้างรายงานการรับส่งข้อมูลและข้อมูลเชิงลึกด้านการวิเคราะห์เกม

ภาพรวม

ก. กำหนดค่าตัวแปรของทักษะ

เปิด skills/log-router-bq-report/SKILL.md ในที่เก็บ DinoQuest และอัปเดตส่วนการกำหนดค่าที่ด้านบน

| 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. ตรวจสอบว่ามี Sink ของ BigQuery อยู่แล้วหรือไม่ หากไม่มี ระบบจะสร้างชุดข้อมูลและ Sink
  3. ให้สิทธิ์ IAM: การดำเนินการนี้จะให้บทบาทผู้แก้ไขข้อมูล BigQuery แก่writerIdentityของ Sink ในชุดข้อมูล

หมายเหตุ: เช่นเดียวกับ Sink ของ Eventarc คุณอาจเห็นคำเตือนจาก gcloud ในระหว่างกระบวนการนี้ว่า "โปรดอย่าลืมให้บทบาทผู้แก้ไขข้อมูล BigQuery แก่ serviceAccount:service-... ในชุดข้อมูล" ทักษะจะจัดการเรื่องนี้โดยอัตโนมัติ

ค. การใช้ Antigravity เพื่อสร้างรายงาน

เพียงขอให้ Antigravity "ตั้งค่าซิงก์บันทึกของ BigQuery และสร้างรายงานข้อมูลวิเคราะห์" ตัวแทนจะทำสิ่งต่อไปนี้

  1. กำหนดค่าโครงสร้างพื้นฐาน: สร้างชุดข้อมูล BigQuery และซิงก์ Cloud Logging
  2. จัดการสิทธิ์: มอบบทบาท IAM ที่จำเป็นให้กับข้อมูลประจำตัวของผู้เขียนของ Sink โดยอัตโนมัติ
  3. สร้างข้อมูลเชิงลึก: วิเคราะห์บันทึกและสร้างแดชบอร์ด HTML แบบอินเทอร์แอกทีฟระดับพรีเมียมพร้อมการวัดและวิเคราะห์อัตราการชนะของเกม

7. Self-Healing Remediation Agent

บทบาทของตัวแทน: ตัวแทน SRE เมื่อบริการที่ใช้งานจริงล้มเหลวตอน 02:00 น. คุณไม่ควรต้องตื่นขึ้นมา เอเจนต์นี้จะทำหน้าที่เป็นผู้ตอบคำถามแรก ระบบจะเรียกใช้โดยบันทึกข้อผิดพลาดของ Cloud Run ผ่าน Eventarc ซึ่งจะวิเคราะห์ข้อขัดข้อง เสนอการแก้ไข และเริ่มไปป์ไลน์การแก้ไขโดยอัตโนมัติ ทั้งหมดนี้เกิดขึ้นก่อนที่คุณจะเข้าสู่ระบบคอนโซลด้วยซ้ำ

DinoAgent เป็นตัวแทน ADK ที่รอรับฟังบันทึกข้อผิดพลาดของ Cloud Run ผ่าน Eventarc วินิจฉัยสาเหตุหลัก และแก้ไขโดยอัตโนมัติ ไม่ว่าจะด้วยการเพิ่มหน่วยความจำ การย้อนกลับการรับส่งข้อมูล หรือการยื่นคำขอ PR เพื่อแก้ไขโค้ดใน 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 อ่านไฟล์ต้นฉบับ ใช้แพตช์ และเปิด PR โดยต้องใช้โทเค็นเพื่อการเข้าถึงส่วนบุคคลของ GitHub ที่มีขอบเขต repo

  1. ไปที่ github.com/settings/tokensสร้างโทเค็นใหม่ (คลาสสิก)
  2. ตั้งชื่อ เลือกrepoขอบเขต → สร้างโทเค็น → คัดลอก

จัดเก็บไว้ใน Secret Manager โดยทำดังนี้

ก่อนอื่น ให้ส่งออกโทเค็น GitHub โดยทำดังนี้

export GH_TOKEN=ghp_YOUR_TOKEN_HERE

จากนั้นสร้างข้อมูลลับโดยทำดังนี้

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

ค. ตั้งค่าการแจ้งเตือนของ Slack (ไม่บังคับ)

เมื่อการแก้ไขเสร็จสมบูรณ์ DinoAgent จะโพสต์สรุปไปยังช่องทาง Slack

  1. ไปที่ api.slack.com/appsสร้างแอปใหม่ → ตั้งแต่ต้น
  2. ตั้งชื่อว่า DinoAgent เลือกพื้นที่ทำงาน → สร้างแอป
  3. ในส่วนฟีเจอร์เว็บฮุคขาเข้า → เปิด/ปิด
  4. คลิกเพิ่มเว็บบุ๊กใหม่ไปยังพื้นที่ทำงาน → เลือกช่อง → อนุญาต
  5. คัดลอก URL ของเว็บฮุก (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 จะพิมพ์ข้อความข้อมูลที่ระบุว่า "โปรดอย่าลืมให้บทบาทผู้เผยแพร่ Pub/Sub แก่ serviceAccount:service-... ในหัวข้อ" ขั้นตอนถัดไปจะจัดการเรื่องนี้โดยเฉพาะ

ให้สิทธิ์การเผยแพร่แก่ข้อมูลประจำตัวของผู้เขียนของซิงก์ (บัญชีบริการที่กล่าวถึงในคำเตือน) ดังนี้

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 ยังทำการวิเคราะห์สาเหตุหลักอย่างละเอียดในโค้ดของแอปพลิเคชัน ใช้แพตช์เชิงความหมาย และใช้การสื่อสารAgent-to-Agent (A2A) เพื่อส่งต่อการแก้ไขไปยัง CI Agent เพื่อการยืนยันและการติดตั้งใช้งาน คุณสามารถดูรายละเอียดการใช้งานได้ในฐานโค้ดของ reme-agent

8. ตั้งค่า Agent CI

บทบาทของเอเจนต์: ไปป์ไลน์ CI ไม่ต้องกังวลกับไฟล์ YAML ที่ซับซ้อนและสคริปต์บิลด์ที่ต้องทำเองอีกต่อไป เอเจนต์นี้จัดการการทำงานภายในของคำขอให้รวมโค้ด โดยจะอ่านการเปลี่ยนแปลงโค้ด ทำความเข้าใจบริบท กำหนดขอบเขตการทดสอบที่จำเป็น และสร้างอิมเมจ Docker ผ่าน Cloud Build เพื่อให้มั่นใจว่าทุกการคอมมิตจะ "ได้รับการอนุมัติจากเอเจนต์" ก่อนที่จะไปถึง Branch หลัก

ci-agent คือ Agent ไปป์ไลน์ CI แบบอัตโนมัติที่ติดตั้งใช้งานเป็นบริการ Cloud Run โดยจะส่งบิลด์ Docker ไปยัง Cloud Build, ทำการสำรวจเพื่อดูว่าบิลด์เสร็จสมบูรณ์แล้วหรือไม่, ยืนยันอิมเมจใน Artifact Registry และรายงานไปยัง GitHub

ภาพรวม

เหตุใดจึงควรใช้เอเจนต์สำหรับไปป์ไลน์ CI ไปป์ไลน์ CI ที่เป็น Agent มีข้อดีดังนี้ ซึ่งต่างจากสคริปต์แบบคงที่แบบเดิม

  1. การจัดประเภทขอบเขตการรับรู้: ระบบจะกำหนดความลึกของการทดสอบที่จำเป็นอย่างชาญฉลาด โดยสลับระหว่างการตรวจสอบประเภท การทดสอบหน่วย หรือชุดการทดสอบการผสานรวมแบบเต็มตามผลกระทบเชิงความหมายของการเปลี่ยนแปลงโค้ด
  2. การจัดการ PR แบบอัตโนมัติ: Agent สามารถสร้าง PR โดยอัตโนมัติ โพสต์สรุปการเปลี่ยนแปลงแบบละเอียด และแม้แต่จัดการการสแกนหาข้อมูลลับและการตรวจสอบความปลอดภัยโดยไม่ต้องมีคนเข้ามาเกี่ยวข้อง
  3. การวินิจฉัยความล้มเหลวแบบเรียลไทม์: เมื่อบิลด์ล้มเหลว เอเจนต์ไม่ได้แสดงเพียงแค่บันทึก แต่จะวิเคราะห์สแต็กเทรซ ระบุสาเหตุที่เป็นไปได้ และโพสต์การวินิจฉัยที่มนุษย์อ่านได้ไปยัง PR โดยตรง

ก. โคลนที่เก็บ 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 ส่งบิลด์ผ่าน repoSource ซึ่งต้องเชื่อมต่อที่เก็บ GitHub กับ Cloud Build Developer Connect

  1. ไปที่ GCP Console → Cloud Build → ที่เก็บ
  2. คลิกเชื่อมต่อที่เก็บ
  3. เลือก GitHub (แอป Cloud Build GitHub)
  4. ให้สิทธิ์และเลือกที่เก็บ YOUR_GITHUB_USERNAME/dinoquest
  5. คลิกเชื่อมต่อและข้ามเมื่อระบบแจ้งให้สร้างทริกเกอร์
  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/appsสร้างแอปใหม่ตั้งแต่ต้น
  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 แล้วคลิกอนุญาต

Agent CI ทำหน้าที่เป็น "สมอง" ที่อยู่เหนือบริการ Google Cloud ที่มีประสิทธิภาพ เช่น Cloud Build และ Artifact Registry เมื่อยืนยันบิลด์แล้ว ระบบจะทริกเกอร์ระยะการติดตั้งใช้งานสุดท้ายโดยเรียกใช้เอเจนต์ CD ผ่าน A2A เพื่อให้มั่นใจว่าการส่งต่อระหว่างวงจรบิลด์และวงจรการเผยแพร่จะเป็นไปอย่างราบรื่น

9. ตั้งค่าการทำให้ใช้งานได้

บทบาทของตัวแทน: ตัวแทน CD การติดตั้งใช้งานไม่ควรเป็นการเสี่ยง เอเจนต์นี้จะจัดการความเสี่ยงให้คุณ โดยจะให้คะแนนความปลอดภัยในการติดตั้งใช้งาน จัดการการแยกการรับส่งข้อมูลของ Canary และตรวจสอบเมตริกแบบเรียลไทม์เพื่อตัดสินใจว่าจะโปรโมตการเผยแพร่หรือย้อนกลับ ซึ่งเป็นผู้ดูแลขั้นสุดท้ายในฝูงเอเจนต์อิสระ

cd-agent คือเอเจนต์การทำให้ Canary ใช้งานได้แบบอัตโนมัติที่ทำให้ใช้งานได้เป็นบริการ Cloud Run โดยจะรับคำขอการติดตั้งใช้งาน A2A จาก ci-agent คำนวณคะแนนความเสี่ยง กำหนดเปอร์เซ็นต์ Canary ที่ปรับตามความเสี่ยง ตรวจสอบเมตริก และเลื่อนระดับหรือย้อนกลับโดยอัตโนมัติ นอกจากนี้ยังเรียนรู้จากการติดตั้งใช้งานที่ผ่านมาโดยใช้ Firestore ด้วย

ภาพรวม

การเชื่อมต่อเอเจนต์โดยตรงจะสร้าง "ไปป์ไลน์การรับรู้" ซึ่งการส่งต่อแต่ละครั้งเป็นการโอนความตั้งใจและบริบทที่สมบูรณ์ การสื่อสารแบบ A2A ต่างจากเว็บฮุคแบบดั้งเดิมตรงที่ช่วยให้ทำสิ่งต่อไปนี้ได้

  1. การแชร์บริบทอัจฉริยะ: เจ้าหน้าที่ส่งหน่วยความจำของเซสชันทั้งหมด, ความแตกต่างของคำขอแก้ไข และคะแนนความเสี่ยง เพื่อให้เจ้าหน้าที่คนถัดไปทราบ "เหตุผล" ทั้งหมดก่อนเริ่มงาน
  2. การสื่อสารเพื่อทำความเข้าใจ: ตัวแทนสามารถเจรจาต่อรองเกตได้ ตัวอย่างเช่น CD Agent สามารถขอการทดสอบ Smoke Test ที่เฉพาะเจาะจงจาก CI Agent ในระหว่างการเปิดตัว Canary เพื่อยืนยันการแก้ไขแบบเรียลไทม์
  3. การแก้ไขร่วมกัน: หากการติดตั้งใช้งานล้มเหลว CD Agent จะแจ้งเตือน Remediation Agent อย่างรวดเร็วด้วยเมตริกที่ล้มเหลว ซึ่งจะเริ่มการวิเคราะห์หาสาเหตุหลักโดยอัตโนมัติก่อนที่ระบบจะแจ้งเตือนเจ้าหน้าที่
  4. การเจรจาต่อรองทรัพยากร: ตัวแทนสามารถเจรจาต่อรองความต้องการด้านโครงสร้างพื้นฐานได้ เช่น CI Agent สามารถขอให้ Remediation Agent จัดสรรความสามารถในการสร้างเพิ่มเติมได้หากตรวจพบการรีแฟกเตอร์ขนาดใหญ่ หรือ CD Agent สามารถแนะนำให้ปรับขนาดคลัสเตอร์ Production ก่อนการเปิดตัวครั้งใหญ่ได้
  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 และเว็บฮุก 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 ด้วย Agent Swarm

ก. ทดสอบ Full Swarm

  1. ทริกเกอร์ข้อผิดพลาด: เปิด URL ของ DinoQuest ที่คุณติดตั้งใช้งาน (จากขั้นตอนสุดท้าย) ในเบราว์เซอร์
  2. ไปที่ลีดเดอร์บอร์ด: คลิกปุ่มลีดเดอร์บอร์ด การติดตั้งใช้งานลีดเดอร์บอร์ดในปัจจุบันตั้งใจให้ไม่มีประสิทธิภาพ ซึ่งจะพยายามโหลดข้อมูลจำนวนมากไปยังหน่วยความจำ ซึ่งจะทําให้เกิดข้อผิดพลาดหน่วยความจำไม่พอ (OOM)
  3. รอ Agent: ภายในประมาณ 60 วินาที remediation-agent จะได้รับเหตุการณ์ข้อผิดพลาดผ่าน Eventarc และเริ่มการวินิจฉัย
  4. ตรวจสอบ Slack: คุณควรเห็นการแจ้งเตือนในช่อง Slack ที่มีลักษณะดังนี้สรุปการแก้ไขของ DinoAgent
    • บริการ: dinoquest
    • การแก้ไขที่ไม่สำเร็จ: dinoquest-xxxx-xxxx
    • หลักฐาน: "ใช้หน่วยความจำเกินขีดจำกัด 128 MiB โดยใช้ไป 13x MiB"
    • เหตุใดการแก้ไขนี้จึงไม่ดี: ปลายทาง /api/leaderboard xxxxx อย่างไม่มีประสิทธิภาพ ทำให้เกิดข้อผิดพลาด OOM
    • การดำเนินการที่ทำ: เพิ่มหน่วยความจำจาก xMi เป็น yGi สำหรับบริการ dinoquest สร้างการแก้ไขใหม่แล้ว
    • PR สาเหตุของปัญหา: https://github.com/YOUR_USERNAME/DinoQuest/pull/x
  5. ยืนยันการแก้ไข
    • GitHub: ตรวจสอบที่เก็บเพื่อหา Branch ใหม่และคำขอ Pull เอเจนต์ได้แก้ไขโค้ดของแอปพลิเคชันเพื่อแก้ไขหน่วยความจำรั่วไหลพื้นฐาน
    • Cloud Run: ในคอนโซล GCP คุณจะเห็นรีวิชันใหม่ของบริการ dinoquest ที่มีการจัดสรรหน่วยความจำที่อัปเดตแล้ว
    • ลีดเดอร์บอร์ด: ลองใช้ลีดเดอร์บอร์ดอีกครั้ง ตอนนี้ควรโหลดได้สำเร็จแล้วเนื่องจากมีการเพิ่มหน่วยความจำและแก้ไขโค้ดในที่สุด

ข. Evolution: Implementing Level 2 Game Logic

คุณจะเพิ่มฟีเจอร์ใหม่ที่สำคัญ นั่นคือเลเวล 2 (ทำลายดาวเคราะห์น้อย) ซึ่งจะช่วยให้ไดโนเสาร์ที่มีคะแนนสูงได้เลื่อนไปสู่โหมดเกมใหม่

  1. กลับไปที่ที่เก็บ dinoquest
    cd ~/dinoquest
    
  2. สร้างและเปลี่ยนไปใช้ Branch ใหม่
    git checkout -b level_2
    
  3. ใช้แพตช์ระดับ 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 Slash ที่คุณกำหนดค่าไว้ก่อนหน้านี้ นี่คือวิธีที่คุณโต้ตอบกับไปป์ไลน์ CI แบบอัตโนมัติในสถานการณ์จริง

  1. เปิด Slack แล้วไปที่ช่องที่ติดตั้งแอป CIAgent
  2. ทริกเกอร์บิลด์ CI โดยพิมพ์คำสั่งต่อไปนี้
    /runci run ci on branch level_2
    
  3. ตรวจสอบความคืบหน้า
    • Slack: เอเจนต์จะรับทราบคำสั่งของคุณและโพสต์ข้อมูลอัปเดตเมื่อบิลด์คืบหน้า
    • Dino Theater: ดู "ฟองความคิด" ขณะที่เอเจนต์จัดประเภทการเปลี่ยนแปลง ส่งงาน Cloud Build และสื่อสารกับเอเจนต์ CD
    • GitHub: ตรวจสอบ level_2 PR คุณจะเห็นเอเจนต์โพสต์สถานะการคอมมิตและความคิดเห็นรายงาน CI แบบเต็ม
  4. ดูขั้นตอน
    • ดูว่า CI Agent คิดอย่างไร จัดประเภทการเปลี่ยนแปลง และเรียกใช้ไปป์ไลน์ได้ที่Dino Theater
    • ตรวจสอบ PR ของ GitHub เพื่อดูว่า CI Agent โพสต์สถานะการคอมมิตและรายงานสุดท้ายหรือไม่

11. บทสรุป

คุณได้สร้างสแต็ก DevOps ที่สมบูรณ์แบบบน Google Cloud แล้ว

ส่วนประกอบ

การทำงาน

DinoQuest (Cloud Run dinoquest)

เกมที่ทำงานด้วย Gemini - ส่วนหน้า React + ส่วนหลัง FastAPI

Firebase Auth + Firestore

การตรวจสอบสิทธิ์ผู้ใช้และการจัดเก็บโปรไฟล์ไดโนเสาร์

Agent การแก้ไข (Cloud Run + Eventarc)

ตัวแทน SRE ที่แก้ไขข้อผิดพลาด OOM และข้อบกพร่องของโค้ดโดยอัตโนมัติ

log-router-bq-report

ตัวแทนข้อมูลที่สตรีมบันทึกไปยัง BigQuery และสร้างข้อมูลเชิงลึก

CIAgent (Cloud Run)

CI Agent ที่กำหนดขอบเขตการทดสอบ สร้างอิมเมจ และเรียกใช้ CD ผ่าน A2A

CDAgent (Cloud Run)

เอเจนต์ CD ที่เรียกใช้การติดตั้งใช้งาน Canary ที่ให้คะแนนความเสี่ยงพร้อมการเปลี่ยนกลับอัตโนมัติ

ลักษณะการทำงานของ Agent ทั้งหมดจะอยู่ในไดเรกทอรี skills/ เป็นเพลย์บุ๊ก Markdown โดยเปลี่ยนลักษณะการทำงานด้วยการแก้ไขทักษะ ไม่ใช่โค้ด ทักษะจะทำงานบน Antigravity ด้วย Gemini และจะเรียกใช้ได้โดยการบอก Agent ว่าจะเรียกใช้ทักษะใด