สร้างเครื่องมือวางแผนเส้นทาง Formula E แบบ Multi-Agent ด้วย ADK และ A2A

1. 1. ภาพรวม

ใน Codelab นี้ คุณจะได้สร้างระบบ Multi-Agent ที่ออกแบบสนามแข่งรถ Formula E และได้รับการอนุมัติตามกฎ FIA แบบง่าย

คุณจะใช้ agents-cli เพื่อสร้างโปรเจ็กต์ Agent Development Kit (ADK) มาตรฐาน 2 โปรเจ็กต์ จากนั้นเขียนส่วนที่สำคัญ ได้แก่ ทักษะของ Agent, Agent 3 รายการ และการประเมิน ส่วนอื่นๆ ทั้งหมด (เลย์เอาต์โปรเจ็กต์, เซิร์ฟเวอร์, ทรัพยากร Dependency, การกำหนดค่าการติดตั้งใช้งาน) จะมาจาก CLI

หากเพิ่งเริ่มดู Formula E

คุณไม่จำเป็นต้องรู้จักกีฬามอเตอร์สปอร์ต คำ 5 คำต่อไปนี้ก็เพียงพอแล้ว

  • Formula E: การแข่งขันรถยนต์ไฟฟ้าทั้งหมดของ FIA การแข่งขันส่วนใหญ่จะจัดขึ้นในสนามแข่งชั่วคราวบนท้องถนนในใจกลางเมือง
  • การรับรอง: การอนุมัติอย่างเป็นทางการของ FIA ว่าสนามแข่งปลอดภัยสำหรับการแข่งขัน ถ้าไม่ผ่านการรับรอง ก็ลงแข่งไม่ได้
  • การเบรกแบบจ่ายพลังงานคืน: เมื่อรถเบรก มอเตอร์จะชาร์จแบตเตอรี่ การเบรกที่แรงขึ้นจะช่วยกู้คืนพลังงานได้มากขึ้น ดังนั้นกฎของ Codelab นี้จึงกำหนดให้มีโซนเบรกหนักอย่างน้อย 1 โซน
  • เลเยอร์ CAD: เลเยอร์ที่มีชื่อในภาพวาดการออกแบบสนามแข่ง เช่น เส้นทางวิ่ง เลนพิต และสิ่งกีดขวาง FIA จะตรวจสอบว่ามีข้อมูลที่จำเป็นหรือไม่
  • Attack Mode: นักแข่งจะได้รับพลังงานเพิ่มขึ้นชั่วคราวเมื่อขับผ่านโซนเปิดใช้งานที่อยู่นอกเส้นทางการแข่งขัน

Agent ของคุณจะทำหน้าที่ทั้ง 2 ฝ่าย โดยฝ่ายหนึ่งออกแบบสนามแข่ง และอีกฝ่ายตรวจสอบสนามแข่งตามกฎของ FIA

สิ่งที่คุณจะสร้าง

สถาปัตยกรรม: ในโปรเจ็กต์ track-planner ที่ทำงานใน Cloud Shell ตัวแทน track_planner จะใช้ get_track_topology, fia_assessor และ remote_gatekeeper โดย remote_gatekeeper จะเรียกใช้ตัวแทน gatekeeper ผ่าน A2A ในโปรเจ็กต์ Gatekeeper ซึ่งทำงานบนรันไทม์ของ Agent นั้น Agent ของ Gatekeeper จะใช้ verify_infrastructure_checklist

กล่องสีเขียวคือ Agent และกล่องเส้นประคือเครื่องมือของ Agent เช่นเดียวกับที่ ADK Playground วาดไว้ เครื่องมือ 2 รายการจะรวม Agent อื่นๆ ไว้ด้วยกัน ได้แก่ fia_assessor คือ Agent ผู้ประเมิน FIA ที่มีทักษะการปฏิบัติตามข้อกำหนดของ FIA และ remote_gatekeeper จะเรียก Agent ผู้เฝ้าประตูในโปรเจ็กต์อื่นผ่าน A2A

Agent

โปรเจ็กต์

งาน

thinking_level

สถาปนิกหลัก

track-planner

อ่านข้อมูลสถานที่ ถามผู้ประเมิน แก้ไขปัญหา ขออนุมัติจากผู้ตรวจสอบ

HIGH

ผู้ประเมิน FIA

track-planner

ตรวจสอบเลย์เอาต์โดยใช้ทักษะ FIA และเครื่องมือให้คะแนน

MEDIUM

ผู้รับสายแทนแบบโมเดลเสมือนของวัตถุ (Digital Twin)

gatekeeper

เรียกใช้รายการตรวจสอบการรับรองขั้นสุดท้าย

LOW

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

  • วิธีที่ agents-cli scaffold create จัดวางโปรเจ็กต์ ADK และไฟล์ที่คุณแก้ไข
  • วิธีจัดแพ็กเกจความรู้เกี่ยวกับโดเมนเป็นทักษะของ Agent (SKILL.md, references/, scripts/) และโหลดด้วย SkillToolset ของ ADK
  • วิธีจับคู่ thinking_level กับงานของ Agent แต่ละรายการ
  • วิธีประเมิน Agent ด้วย agents-cli eval run
  • วิธีทำให้ Agent ใช้งานได้ใน Agent Runtime, ข้อมูลประจำตัวของ Agent แตกต่างจากบัญชีบริการอย่างไร และวิธีเรียก Agent ที่ทำให้ใช้งานได้ผ่านโปรโตคอล A2A

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

ก่อนเริ่มต้น

คุณต้องมีโปรเจ็กต์ Google Cloud ที่เปิดใช้การเรียกเก็บเงิน หากคุณทำตาม Codelab นี้ในกิจกรรม ให้ใช้บัญชีและโปรเจ็กต์ที่ได้รับ

เปิด Cloud Shell และตั้งค่าโปรเจ็กต์

เปิด Cloud Shell แล้วเรียกใช้คำสั่งต่อไปนี้

# Cloud Shell sometimes opens without a project set. If so, this sets it to
# the first project on your account.
if [ -z "$(gcloud config get-value project 2>/dev/null)" ]; then
  gcloud config set project "$(gcloud projects list --format='value(projectId)' --limit=1)"
fi

export GOOGLE_CLOUD_PROJECT="$(gcloud config get-value project)"
export REGION="us-central1"
export ASSETS="$HOME/devrel-demos/codelabs/formula-e-track-planner"
echo "Project: $GOOGLE_CLOUD_PROJECT  Region: $REGION"

สร้างข้อมูลเข้าสู่ระบบสำหรับ Agent

gcloud ลงชื่อเข้าใช้แล้ว แต่โค้ด Python ที่ Agent เรียกใช้จะใช้ข้อมูลรับรองเริ่มต้นของแอปพลิเคชัน (ADC) ซึ่งต้องลงชื่อเข้าใช้แยกต่างหาก โดยทำดังนี้

gcloud auth application-default login

เปิดลิงก์ที่แสดงขึ้นมา ลงชื่อเข้าใช้ด้วยบัญชีเดียวกัน คัดลอกรหัส แล้ววางกลับลงใน Cloud Shell จากนั้นตั้งค่าโปรเจ็กต์ที่จะเรียกเก็บเงินตามโควต้า ดังนี้

gcloud auth application-default set-quota-project "$GOOGLE_CLOUD_PROJECT"

เปิดใช้ API

gcloud services enable \
    aiplatform.googleapis.com \
    cloudbuild.googleapis.com \
    artifactregistry.googleapis.com \
    storage.googleapis.com \
    cloudresourcemanager.googleapis.com \
    serviceusage.googleapis.com \
    compute.googleapis.com \
    iam.googleapis.com \
    logging.googleapis.com \
    cloudtrace.googleapis.com

จุดประสงค์ของ API แต่ละรายการมีดังนี้

API

ใช้สำหรับ

aiplatform

โมเดล Gemini และ Agent Runtime

cloudresourcemanager, serviceusage, iam

การตรวจสอบโปรเจ็กต์และสิทธิ์ที่ gcloud และ agents-cli deploy เรียกใช้

compute

สร้างบัญชีบริการเริ่มต้นของ Compute Engine ที่การติดตั้งใช้งานในขั้นตอนที่ 7 ใช้

storage, logging, cloudtrace

พื้นที่เก็บข้อมูล บันทึก และการติดตาม ตามที่คู่มือการตั้งค่า Agent Runtime แนะนำ

cloudbuild, artifactregistry

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

หลายโปรเจ็กต์เปิดใช้บางรายการเหล่านี้อยู่แล้ว การเปิดใช้ API ที่เปิดอยู่แล้วจะไม่เปลี่ยนแปลงอะไร

ติดตั้ง uv และ agents-cli

curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
uv tool install google-agents-cli==1.10.0
agents-cli --version

Codelab นี้ได้รับการทดสอบด้วย agents-cli 1.10.0 ดังนั้นให้ติดตั้งเวอร์ชันดังกล่าวเพื่อรับไฟล์ที่สร้างขึ้นเหมือนกัน

3. 3. วางโครงสร้างโปรเจ็กต์และเพิ่มชิ้นงาน

สร้างทั้ง 2 โปรเจ็กต์

agents-cli scaffold create จะสร้างโปรเจ็กต์ ADK ที่สมบูรณ์และทำให้ใช้งานได้ เรียกใช้ 2 ครั้ง โดยเรียกใช้ 1 ครั้งสำหรับระบบ Agent แต่ละระบบ

ก่อนอื่นคือเครื่องมือวางแผนแทร็ก

cd ~
agents-cli scaffold create track-planner \
  --agent adk \
  --deployment-target agent_runtime \
  --region "$REGION" \
  --prototype \
  --yes

จากนั้นผู้รับสายแทนจะดำเนินการดังนี้

cd ~
agents-cli scaffold create gatekeeper \
  --agent adk \
  --deployment-target agent_runtime \
  --region "$REGION" \
  --prototype \
  --yes

ธง

ความหมาย

--agent adk

เริ่มต้นจากเทมเพลต Python ADK

--deployment-target agent_runtime

สร้างเซิร์ฟเวอร์และการกำหนดค่าสำหรับ Agent Runtime

--prototype

ข้าม CI/CD และทำให้โปรเจ็กต์เรียบง่ายที่สุด

--yes

ยอมรับค่าเริ่มต้นโดยไม่ต้องแจ้งข้อความเตือน

สำรวจเลย์เอาต์

โปรเจ็กต์ที่สร้างขึ้นจะมีลักษณะดังนี้ คุณจะแก้ไขเฉพาะไฟล์ที่มีเครื่องหมาย ✍️ เท่านั้น

track-planner/
├── agents-cli-manifest.yaml   # Records the template, deployment target and root agent name
├── pyproject.toml             # Dependencies (google-adk, a2a-sdk, ...)
├── .env                       # Your project and model location, filled in for you
├── Dockerfile                 # Used by `agents-cli deploy`; copies app/ into the image
├── app/
│   ├── agent.py               # ✍️ Your agents
│   ├── fast_api_app.py        # Generated server: ADK API, A2A routes, Agent Runtime routes
│   └── app_utils/             # Generated helpers (A2A, sessions)
└── tests/
    ├── unit/                  # Fast tests with no model calls
    ├── integration/           # Generated server tests
    └── eval/                  # ✍️ eval_config.yaml and datasets for `agents-cli eval`

ดูคำอธิบายของไฟล์ที่สร้างขึ้นทั้งหมดได้ที่โครงสร้างโปรเจ็กต์ในคู่มือ Agents CLI

ลองใช้ Agent ที่สร้างขึ้น

ก่อนที่จะเปลี่ยนแปลงสิ่งใดๆ ให้เรียกใช้เอเจนต์เทมเพลตเพื่อดูว่าโครงสร้างพื้นฐานมีอะไรให้คุณบ้าง ติดตั้งทรัพยากร Dependency และเริ่ม Playground ในเครื่องบนพอร์ต 8080 โดยทำดังนี้

cd ~/track-planner
agents-cli install
agents-cli playground --port 8080

หากต้องการเปิด ให้คลิกปุ่มตัวอย่างเว็บในแถบเครื่องมือ Cloud Shell (ไอคอนรูปดวงตาที่ด้านขวาบน) แล้วเลือกแสดงตัวอย่างในพอร์ต 8080

ใน Playground ให้ถามคำถามที่เครื่องมือของ Agent เทมเพลตสามารถตอบได้ เช่น

What's the weather in San Francisco?

แผงด้านข้างจะแสดงแต่ละเหตุการณ์ รวมถึงการเรียกใช้เครื่องมือ get_weather และผลลัพธ์ คุณจะใช้มุมมองเดียวกันนี้ในภายหลังเพื่อติดตามตัวแทนของคุณเอง

เมื่อเสร็จแล้ว ให้กลับไปที่เทอร์มินัลแล้วกด Ctrl+C เพื่อหยุด Playground

เพิ่มชิ้นงาน Formula E

ข้อมูลสถานที่ กฎของ FIA สคริปต์ฟิสิกส์ เครื่องมือ และชุดข้อมูลการประเมินไม่ใช่บทเรียน ดังนั้นคุณจึงคัดลอกข้อมูลเหล่านี้จาก GitHub แทนการพิมพ์ได้โดยทำดังนี้

cd ~
git clone --depth 1 --filter=blob:none --sparse \
  --branch formula-e-lab-v1 \
  https://github.com/tdsymonds/devrel-demos.git
git -C devrel-demos sparse-checkout set codelabs/formula-e-track-planner

cp -r "$ASSETS/track-planner/." ~/track-planner/
cp -r "$ASSETS/gatekeeper/." ~/gatekeeper/

formula-e-lab-v1 เป็นแท็กการเผยแพร่แบบคงที่ ทุกคนจึงได้รับไฟล์เดียวกัน $ASSETS ได้รับการตั้งค่าในขั้นตอนที่ 2 และชี้ไปยังโฟลเดอร์ที่คุณเพิ่งโคลน

การดำเนินการนี้จะเพิ่มไฟล์ต่อไปนี้

track-planner/
├── app/
│   ├── tools.py                                  # get_track_topology, evaluate_track_layout
│   ├── auth.py                                   # A2A client with per-request token refresh
│   ├── data/circuits.json                        # Five candidate venues
│   └── skills/fia-compliance-skill/
│       ├── references/track_regulations.md       # The FIA rules
│       └── scripts/calculate_regen_zones.py      # Braking-energy calculator
└── tests/
    ├── unit/test_tools.py
    └── eval/datasets/track_eval.json, track_eval_quick.json
gatekeeper/
├── app/tools.py                                  # verify_infrastructure_checklist
└── tests/unit/test_tools.py

ติดตั้งและทดสอบ

(cd ~/track-planner && agents-cli install && uv run pytest tests/unit)
(cd ~/gatekeeper && agents-cli install && uv run pytest tests/unit)

agents-cli install จะเรียกใช้ uv sync เพื่อสร้างสภาพแวดล้อมเสมือนจริงสำหรับแต่ละโปรเจ็กต์ การทำ Unit Test ทั้งหมดควรผ่าน

4. 4. เขียนทักษะการปฏิบัติตามข้อกำหนดของ FIA

ทักษะของ Agent จะรวมคำสั่ง เอกสารอ้างอิง และสคริปต์ไว้ในโฟลเดอร์เดียว SkillToolset ของ ADK จะโหลดข้อมูลใน 3 ระดับ เพื่อให้ Agent อ่านเฉพาะสิ่งที่จำเป็นเท่านั้น ดังนี้

ระดับ

ไฟล์

เมื่อตัวแทนเห็น

1

SKILL.md ส่วนหน้า (name, description)

เสมอ (โทเค็น 2-3 โหล)

2

เนื้อความ SKILL.md

เมื่อโทรหา load_skill

3

references/, scripts/

เมื่อโทรหา load_skill_resource หรือ run_skill_script

ทักษะจะอยู่ใน app/skills/ เนื่องจาก Dockerfile ที่สร้างขึ้นจะคัดลอกเฉพาะ app/ ลงในอิมเมจที่ติดตั้งใช้งาน

ดูไฟล์ระดับที่ 3

คุณคัดลอกไฟล์ระดับ 3 ของทักษะในขั้นตอนที่ 3 ดังนี้

  • references/track_regulations.md มีกฎที่ผู้ประเมินต้องตรวจสอบ ได้แก่ ขีดจำกัดความยาวและความกว้าง สิ่งกีดขวางที่จำเป็นสำหรับแต่ละโซนเบรก เลเยอร์ CAD ที่จำเป็น (รวมถึงเลเยอร์ทางการแพทย์สำหรับเส้นทางไปยังโรงพยาบาล) เป้าหมายการสร้างพลังงานใหม่ และกฎโหมดโจมตี
  • scripts/calculate_regen_zones.py เป็นเครื่องคิดเลข เมื่อพิจารณาจากความเร็วในการเข้าโค้ง ความเร็วในการออกจากโค้ง และระยะเบรกของโซนเบรก ระบบจะคำนวณพลังงานที่กู้คืนได้และสิ่งกีดขวางที่โค้งต้องการ เพื่อให้ Agent ไม่ต้องคาดเดาหลักฟิสิกส์

เรียกใช้สคริปต์สำหรับโค้งที่ 10 ของลอนดอน ซึ่งรถจะเบรกจาก 215 เป็น 55 กม./ชม. ในระยะทาง 82 เมตร

cd ~/track-planner
uv run python app/skills/fia-compliance-skill/scripts/calculate_regen_zones.py \
  --entry-kph 215 --exit-kph 55 --brake-dist-m 82

รถคันนี้กู้คืนพลังงานได้ประมาณ 508 kW ซึ่งสูงกว่าเป้าหมาย 250 kW รถจะชะลอความเร็วที่มากกว่า 2G ดังนั้นมุมโค้งจึงต้องมีแผงกั้น Tecpro (F1_TEC3)

{"entry_kph": 215.0, "exit_kph": 55.0, "brake_dist_m": 82.0, "deceleration_g": 2.07, "estimated_regen_kw": 507.7, "meets_250kw_target": true, "required_barrier_layer": "F1_TEC3"}

เขียน SKILL.md

สร้างไฟล์ที่เชื่อมโยงทักษะเข้าด้วยกัน โดยทำดังนี้

cloudshell edit app/skills/fia-compliance-skill/SKILL.md

เพิ่มเนื้อหานี้

---
name: fia-compliance-skill
description: >
  FIA Formula E street circuit rules: length and width limits, mandatory CAD
  layers, barrier selection, and Gen3 regenerative braking estimates. Use when
  designing, checking or fixing a Formula E circuit layout.
---

# FIA Formula E Compliance

Follow these steps for every circuit you check.

1. **Read the rules.** Call `load_skill_resource` with
   `file_path="references/track_regulations.md"`.
2. **Estimate regeneration for every heavy braking zone.** Call
   `run_skill_script` with `file_path="scripts/calculate_regen_zones.py"` and
   `args={"entry-kph": <entry>, "exit-kph": <exit>, "brake-dist-m": <distance>}`.
   Never guess kW values. Use the highest `estimated_regen_kw` as the
   circuit's peak regeneration.
3. **Check barriers.** Any zone whose `required_barrier_layer` is `F1_TEC3`
   needs the `F1_TEC3` CAD layer.
4. **Report.** List every rule the layout fails and a concrete fix for each
   one.

description คือสิ่งที่โมเดลอ่านเพื่อตัดสินใจว่าจะใช้ทักษะเมื่อใด ดังนั้นจึงระบุทั้งสิ่งที่ทักษะครอบคลุมและเวลาที่ควรใช้

ดูวิธีเชื่อมต่อทักษะ

เปิด app/tools.py ในเครื่องมือแก้ไข Cloud Shell โดยทำดังนี้

cloudshell edit app/tools.py

ค้นหาฟังก์ชัน build_fia_skill_toolset:

def build_fia_skill_toolset() -> SkillToolset:
    return SkillToolset(
        skills=[load_skill_from_dir(SKILL_DIR)],
        code_executor=UnsafeLocalCodeExecutor(),
    )
  • load_skill_from_dir อ่านโฟลเดอร์ทักษะ: SKILL.md, references/ และ scripts/
  • SkillToolset จะเปลี่ยนข้อมูลนี้เป็นเครื่องมือที่ Agent สามารถเรียกใช้ได้ ซึ่งได้แก่ list_skills, load_skill, load_skill_resource และ run_skill_script
  • UnsafeLocalCodeExecutor อนุญาตให้ run_skill_script เรียกใช้สคริปต์ Python ในเครื่องนี้ ซึ่งเหมาะสำหรับห้องปฏิบัติการ แต่ให้ใช้โปรแกรมดำเนินการที่ทำแซนด์บ็อกซ์ในเวอร์ชันที่ใช้งานจริง

คุณจะแนบชุดเครื่องมือนี้กับผู้ประเมินในขั้นตอนถัดไป

5. 5. เขียน Agent

โมเดล Gemini 3 จะควบคุมการให้เหตุผลด้วย thinking_level (LOW, MEDIUM หรือ HIGH) แทนงบประมาณโทเค็น ใน ADK คุณจะตั้งค่าด้วย types.ThinkingConfig(thinking_level=types.ThinkingLevel.HIGH) จับคู่กับงานของ Agent แต่ละรายการ การคิดมากขึ้นหมายถึงการวางแผนที่ดีขึ้น แต่ก็มีเวลาในการตอบสนองและค่าใช้จ่ายมากขึ้นด้วย

The Gatekeeper (LOW)

Gatekeeper จะเรียกใช้รายการตรวจสอบเชิงกำหนดเท่านั้น จึงไม่จำเป็นต้องใช้การให้เหตุผลมากนัก แทนที่ Agent เทมเพลต:

cloudshell edit ~/gatekeeper/app/agent.py
"""FIA Digital Twin Gatekeeper agent.

This agent runs in its own project and is deployed to Agent Runtime. The track
planner calls it over the A2A protocol.
"""

from google.adk.agents import Agent
from google.adk.apps import App
from google.adk.models import Gemini
from google.genai import types

from app.tools import verify_infrastructure_checklist

# Tested with Gemini 3.8 Flash. To try Gemini 4 Argon, change this to
# "gemini-4-argon", delete the `temperature` settings below (Argon ignores
# them) and run `uv add "google-genai>=2.30.1"` in this project first.
MODEL = "gemini-3.8-flash"

root_agent = Agent(
    # Must match `root_agent_name` in agents-cli-manifest.yaml.
    name="gatekeeper",
    model=Gemini(
        model=MODEL,
        retry_options=types.HttpRetryOptions(attempts=3),
    ),
    description=(
        "FIA Digital Twin Gatekeeper. Runs the final homologation checklist "
        "for a Formula E circuit blueprint."
    ),
    instruction=(
        "You are the FIA Digital Twin Gatekeeper. For every circuit blueprint "
        "you receive, call `verify_infrastructure_checklist` with its circuit "
        "ID, CAD layers, minimum width and peak regeneration. Reply with the "
        "status and any missing CAD layers. Never approve a blueprint the "
        "checklist rejects."
    ),
    # A deterministic checklist needs little reasoning: keep it fast and cheap.
    generate_content_config=types.GenerateContentConfig(
        temperature=0.0,
        thinking_config=types.ThinkingConfig(
            thinking_level=types.ThinkingLevel.LOW,
        ),
    ),
    tools=[verify_infrastructure_checklist],
)

app = App(
    root_agent=root_agent,
    name="app",
)

เรียกใช้ Gatekeeper ในเครื่อง

เปิดแท็บ Cloud Shell ที่ 2 และเริ่มเซิร์ฟเวอร์ที่สร้างขึ้นของ Gatekeeper ในพอร์ต 8001 โดยทำดังนี้

cd ~/gatekeeper
APP_URL=http://localhost:8001 uv run uvicorn app.fast_api_app:app --port 8001

กลับไปที่แท็บแรก แล้วดูการ์ด Agent A2A ของ Gatekeeper นี่คือวิธีที่ Agent อื่นๆ จะค้นพบว่า Gatekeeper คืออะไรและทำอะไรได้บ้าง

curl -s http://localhost:8001/a2a/app/.well-known/agent-card.json | jq .

คุณควรเห็น JSON ในลักษณะนี้ (แบบย่อ)

{
  "name": "gatekeeper",
  "description": "FIA Digital Twin Gatekeeper. Runs the final homologation checklist for a Formula E circuit blueprint.",
  "supportedInterfaces": [
    {"url": "http://localhost:8001/a2a/app", "protocolBinding": "JSONRPC", "protocolVersion": "1.0"}
  ],
  "skills": [
    {"id": "gatekeeper", "name": "model", "description": "FIA Digital Twin Gatekeeper. ..."},
    {"id": "gatekeeper-verify_infrastructure_checklist", "name": "verify_infrastructure_checklist", "description": "Runs the final homologation checklist ..."}
  ]
}
  • name และ description มาจากคำจำกัดความของ Agent(...) โดยตรง
  • skills แสดงรายการสิ่งที่ Agent ทำได้ ADK เพิ่ม verify_infrastructure_checklist โดยอัตโนมัติโดยใช้ Docstring ของเครื่องมือ
  • supportedInterfaces จะบอกผู้โทรว่าจะส่งคำขอ A2A ไปที่ใด นั่นคือเหตุผลที่คุณเริ่มเซิร์ฟเวอร์ด้วย APP_URL=http://localhost:8001: ผู้เรียกจะอ่านการ์ดก่อน จากนั้นจึงส่งคำขอไปยัง url ที่การ์ดโฆษณา

ไม่มีโค้ดใดที่เขียนด้วยมือเลย เซิร์ฟเวอร์ที่สร้างขึ้นจะสร้างการ์ดจาก Agent ของคุณ ผู้วางแผนเส้นทางจะอ่านการ์ดนี้เพื่อค้นหาและเรียก Gatekeeper

ผู้ประเมิน (MEDIUM) และสถาปนิกหลัก (HIGH)

เครื่องมือวางแผนเส้นทางมีตัวแทน 2 ราย ได้แก่

  • Assessor จะพิจารณากฎหลายข้อ จึงได้รับ MEDIUM โดยจะรวมอยู่ใน AgentTool ดังนั้น Lead Architect จึงเรียกใช้เหมือนฟังก์ชันและรับคำตัดสินกลับมา
  • สถาปนิกหลักจะวางแผน แก้ไข และประสานงานเพื่อให้HIGH โดยจะเข้าถึง Gatekeeper ผ่าน RemoteA2aAgent ซึ่งสร้างโดย create_remote_gatekeeper_agent() ใน app/auth.py และรวมไว้ใน AgentTool ด้วย

ทำไมต้องรวมผู้ช่วยทั้ง 2 รายการเป็นเครื่องมือ AgentTool จะส่งคำตอบกลับไปยังผู้เรียกใช้ เพื่อให้สถาปนิกหลักยังคงเป็นผู้รับผิดชอบและเขียนพิมพ์เขียวขั้นสุดท้าย หาก Gatekeeper เป็น sub_agent แทน Lead Architect จะส่งต่อการสนทนาให้ และสถานะสั้นๆ ของ Gatekeeper จะกลายเป็นคำตอบสุดท้าย

เปิดไฟล์ app/agent.py ของเครื่องมือวางแผนการติดตาม:

cloudshell edit ~/track-planner/app/agent.py

คัดลอกโค้ดต่อไปนี้และแทนที่เนื้อหาทั้งหมดของ ~/track-planner/app/agent.py ด้วยโค้ดดังกล่าว

"""Formula E track planner: Lead Architect, FIA Assessor and remote Gatekeeper.

- The Lead Architect (root agent) designs the circuit and stays in charge.
- The FIA Assessor checks the layout and is called as a tool (`AgentTool`).
- The Gatekeeper runs in a separate project. It is also called as a tool, over
  A2A, so its verdict comes back to the Lead Architect.
"""

from google.adk.agents import Agent
from google.adk.apps import App
from google.adk.models import Gemini
from google.adk.tools.agent_tool import AgentTool
from google.genai import types

from app.auth import create_remote_gatekeeper_agent
from app.tools import build_fia_skill_toolset
from app.tools import evaluate_track_layout
from app.tools import get_track_topology

# Tested with Gemini 3.8 Flash. To try Gemini 4 Argon, change this to
# "gemini-4-argon", delete the `temperature` settings below (Argon ignores
# them) and run `uv add "google-genai>=2.30.1"` in this project first.
MODEL = "gemini-3.8-flash"

fia_skill_toolset = build_fia_skill_toolset()

# 1. FIA Assessor: MEDIUM thinking to weigh several rules without much latency.
assessor_agent = Agent(
    name="fia_assessor",
    model=Gemini(
        model=MODEL,
        retry_options=types.HttpRetryOptions(attempts=3),
    ),
    description=(
        "FIA safety and energy assessor. Audits a proposed circuit against "
        "the geometry, regeneration and CAD layer rules."
    ),
    instruction=(
        "You are the FIA Assessor. Load the `fia-compliance-skill` and follow "
        "it. Estimate regeneration for each braking zone with "
        "`calculate_regen_zones.py`, then call `evaluate_track_layout` with "
        "the highest value. Reply with the verdict, the score and every "
        "remediation note."
    ),
    generate_content_config=types.GenerateContentConfig(
        temperature=0.1,
        thinking_config=types.ThinkingConfig(
            thinking_level=types.ThinkingLevel.MEDIUM,
        ),
    ),
    tools=[fia_skill_toolset, evaluate_track_layout],
)

# 2. Remote Gatekeeper, reached over A2A (see app/auth.py).
remote_gatekeeper = create_remote_gatekeeper_agent()

# 3. Lead Architect: HIGH thinking for multi-step planning and trade-offs.
root_agent = Agent(
    # Must match `root_agent_name` in agents-cli-manifest.yaml.
    name="track_planner",
    model=Gemini(
        model=MODEL,
        retry_options=types.HttpRetryOptions(attempts=3),
    ),
    description=(
        "Lead Formula E circuit architect. Designs FIA-compliant street "
        "circuits and gets them homologated."
    ),
    instruction=(
        "You are the Lead Formula E Circuit Architect. For every request:\n"
        "1. Call `get_track_topology` for the venue.\n"
        "2. Call the `fia_assessor` tool with the full topology.\n"
        "3. If the Assessor rejects the layout, propose concrete fixes (for "
        "example widen a sector to 10.0m or add missing CAD layers) and "
        "re-assess the fixed layout.\n"
        "4. Once the Assessor passes it, call the `remote_gatekeeper` tool "
        "with the circuit ID, CAD layers, minimum width and peak "
        "regeneration for final approval.\n"
        "5. Finish with a short blueprint: circuit ID, length, minimum width, "
        "peak regeneration, every CAD layer by name, and the Gatekeeper's "
        "status."
    ),
    generate_content_config=types.GenerateContentConfig(
        temperature=0.2,
        thinking_config=types.ThinkingConfig(
            thinking_level=types.ThinkingLevel.HIGH,
        ),
    ),
    # Both helpers are tools, so their answers come back to the Lead Architect
    # and it writes the final blueprint.
    tools=[
        get_track_topology,
        AgentTool(agent=assessor_agent),
        AgentTool(agent=remote_gatekeeper),
    ],
)

app = App(
    root_agent=root_agent,
    name="app",
)

เรียกใช้ทั้งระบบใน Playground

ตรวจสอบว่า Gatekeeper ยังคงทำงานอยู่ในแท็บที่ 2 ในแท็บแรก ให้เริ่มสนามทดลองของเครื่องมือวางแผนแทร็กโดยทำดังนี้

cd ~/track-planner
agents-cli playground --port 8080

คลิกตัวอย่างเว็บ > แสดงตัวอย่างในพอร์ต 8080 เช่นเดียวกับที่ทำในขั้นตอนที่ 3

ขอวงจรที่สถานที่จัดงานซึ่งเป็นไปตามกฎต่อไปนี้

Design and homologate a Formula E circuit at Tokyo Bay.

ดูแผงเหตุการณ์ขณะที่ Agent ทำงาน คุณควรเห็นข้อมูลต่อไปนี้ตามลำดับ

  1. get_track_topology: สถาปนิกหลักโหลดข้อมูลอ่าวโตเกียว
  2. fia_assessor: สถาปนิกหลักจะส่งเลย์เอาต์ให้ผู้ประเมิน ซึ่งจะเรียกใช้ load_skill, load_skill_resource และ run_skill_script (1 ครั้งต่อเขตการเบรก) จากนั้นจึงเรียกใช้ evaluate_track_layout
  3. remote_gatekeeper: Lead Architect โทรหาผู้รับสายแทนผ่าน A2A คุณจะเห็นคำขอที่บันทึกไว้ในแท็บที่ 2
  4. พิมพ์เขียวขั้นสุดท้ายจากสถาปนิกหลัก ซึ่งแสดงรายการเลเยอร์ CAD ทุกเลเยอร์และสถานะอนุมัติของผู้ตรวจสอบ

คลิกเหตุการณ์ใดก็ได้เพื่อดูอินพุตและเอาต์พุตที่แน่นอน

ตอนนี้ให้เริ่มเซสชันใหม่และลองใช้สถานที่ที่ละเมิดกฎต่อไปนี้

Can the Monaco Harbour layout be homologated? If not, fix it and try again.

ครั้งนี้ผู้ประเมินปฏิเสธทางโค้งรูปตัวเอสขนาด 6.8 เมตร สถาปนิกหัวหน้าโครงการจึงเสนอทางโค้งที่กว้างขึ้น และเลย์เอาต์ที่แก้ไขแล้วจะกลับไปที่ผู้ประเมินก่อนที่จะถึงผู้พิจารณาอนุมัติ

เมื่อเสร็จแล้ว ให้กด Ctrl+C ในแท็บแรกเพื่อหยุด Playground เปิด Gatekeeper ไว้ในแท็บที่ 2 เนื่องจากคุณจะต้องใช้ในขั้นตอนถัดไป

6. 6. ประเมิน Agent

agents-cli eval run จะเรียกใช้ Agent ของคุณกับชุดข้อมูล บันทึกทุกเทิร์นและการเรียกใช้เครื่องมือ และให้คะแนนผลลัพธ์ คุณเป็นผู้ตัดสินใจว่าจะวัดอะไรใน tests/eval/eval_config.yaml

ดูชุดข้อมูล

เปิดชุดข้อมูลใน Cloud Shell Editor โดยทำดังนี้

cd ~/track-planner
cloudshell edit tests/eval/datasets/track_eval.json

ไฟล์นี้มีรายการ eval_cases แต่ละเคสจะมี eval_case_id, prompt (สิ่งที่ผู้ใช้ถาม) และ reference (ลักษณะของคำตอบที่ดี) ผู้ประเมิน LLM จะเปรียบเทียบคำตอบของ Agent กับข้อมูลอ้างอิง

eval_case_id

สิ่งที่ได้รับการทดสอบ

fe_001_tokyo_compliant

สถานที่ที่ผ่านกฎทุกข้อและได้รับอนุมัติ

fe_002_monaco_narrow

ทางโค้งรูปตัวเอสขนาด 6.8 ม. ไม่เป็นไปตามกฎความกว้าง

fe_003_berlin_too_long

วงจร 4,350 ม. ไม่เป็นไปตามกฎความยาว

fe_004_missing_layers

เลย์เอาต์ไม่มีเลเยอร์ CAD ที่จำเป็น

fe_005_low_regen

โซนเบรกต่ำกว่าเป้าหมาย 250 kW

fe_006_sao_paulo_medical

การเข้าถึงโรงพยาบาลที่ต้องใช้เลเยอร์ CAD ทางการแพทย์

fe_007_attack_mode

โซนโหมดโจมตีบนเส้นทางการแข่งรถ

fe_008_multiturn_remediation

การสนทนาแบบหลายเทิร์น: โมนาโกถูกปฏิเสธ ผู้ใช้ขอให้แก้ไข และเลย์เอาต์ที่แก้ไขแล้วควรได้รับการอนุมัติ

กรณีสุดท้ายใช้ agent_data แทน prompt โดยจะเล่นซ้ำเทิร์นก่อนหน้าของการสนทนา เพื่อให้คุณทดสอบวิธีที่ Agent จัดการกับคำขอติดตามผล ไม่ใช่แค่คำถามเดียว

track_eval_quick.json ในโฟลเดอร์เดียวกันมีเพียง 2 เคส ได้แก่ เคส 1 (คำถามเดียว) และเคส 8 (การสนทนา) คุณจะเรียกใช้สคริปต์นั้นเนื่องจากทำงานได้เร็วกว่าและใช้โควต้าน้อยกว่า

เขียนเมตริก

ชุดข้อมูลจะบอกสิ่งที่จะถาม Agent eval_config.yaml กล่าวถึงวิธีให้คะแนนคำตอบ agents-cli eval run จะอ่านคำตอบหลังจากที่ตัวแทนตอบทุกเคสแล้ว และเรียกใช้เมตริกแต่ละรายการกับคำตอบแต่ละรายการ

เปิดไฟล์ที่สร้างขึ้นโดย Scaffold ดังนี้

cloudshell edit tests/eval/eval_config.yaml

โดยมีผู้ประเมิน LLM ทั่วไป (custom_response_quality) และเมตริก agent_turn_count ที่นับเฉพาะเทิร์นอยู่แล้ว นั่นเป็นการเริ่มต้นที่ดีสำหรับตัวแทน แต่ไม่ได้พูดถึง Formula E เลย คุณจะเก็บผู้ประเมินไว้และเพิ่มเมตริกที่ตรวจสอบกฎเฉพาะสำหรับโดเมนนี้

การประเมินที่ดีมักจะผสมผสานเมตริก 2 ประเภทเข้าด้วยกัน ได้แก่

ชนิด

วิธีให้คะแนน

ดีสำหรับ

ข้อดีข้อเสีย

LLM-as-a-judge

โมเดลจะอ่านคำตอบและreferenceของเคส จากนั้นให้คะแนน 1 ถึง 5 พร้อมคำอธิบาย

คุณภาพที่คลุมเครือ: คำตอบถูกต้อง ครบถ้วน และชัดเจนหรือไม่

ใช้การเรียกโมเดล 1 ครั้งต่อเคส คะแนนอาจแตกต่างกันเล็กน้อยในแต่ละครั้งที่เรียกใช้

เมตริกโค้ด

ฟังก์ชัน Python ขนาดเล็กจะตรวจสอบคำตอบ

ข้อเท็จจริงที่ถูกต้องและตรวจสอบได้: คำตอบมีสิ่งที่ต้องมีอยู่หรือไม่

ตรวจสอบเฉพาะสิ่งที่คุณแสดงเป็นโค้ดได้

แทนที่เนื้อหาของไฟล์ด้วยข้อมูลต่อไปนี้

metrics_to_run:
  - custom_response_quality
  - fia_cad_layer_compliance

custom_metrics:
  # LLM-as-a-judge. response_quality.py is generated by `agents-cli scaffold
  # create`; it grades the final answer against the case's `reference`.
  - name: custom_response_quality
    custom_function_file: response_quality.py

  # Deterministic code metric: an approved blueprint must name every
  # mandatory FIA CAD layer.
  - name: fia_cad_layer_compliance
    custom_function: |
      def evaluate(instance):
          response = str(instance.get("response") or "")
          reference = str(instance.get("reference") or "")
          # Only approvals must list every layer. Rejections and other
          # questions (such as Attack Mode) don't, so skip them.
          if "APPROVED" not in reference:
              return {"score": 1.0, "explanation": "Not an approval case."}
          required = [
              "F1_TRACK_CENTRELINE",
              "F1_PIT_ENTRY_SPEED_LIMIT_LANE",
              "F1_WALL_TEMP",
              "F1_TEC3",
          ]
          missing = [layer for layer in required if layer not in response]
          return {
              "score": round(1 - len(missing) / len(required), 2),
              "explanation": "Missing: " + (", ".join(missing) or "none"),
          }

หน้าที่ของแต่ละส่วนมีดังนี้

  • metrics_to_run แสดงรายการเมตริกที่จะเรียกใช้ตามชื่อ การนำชื่อออกที่นี่จะเป็นการปิดเมตริกนั้นโดยไม่ลบออก
  • custom_response_quality คือ LLM Judge custom_function_file ชี้ไปที่ tests/eval/response_quality.py ซึ่งสร้างขึ้นโดย Scaffold เปิดข้อความแจ้งหากต้องการดูข้อความแจ้งการตัดสิน
  • fia_cad_layer_compliance คือเมตริกโค้ดที่เขียนในบรรทัดใต้ custom_function สำหรับแต่ละกรณี ระบบจะได้รับ instance (พรอมต์, response สุดท้ายของ Agent และ reference) สำหรับกรณีที่คำตอบที่คาดหวังคือการอนุมัติ ระบบจะตรวจสอบว่าคำตอบระบุชื่อเลเยอร์ CAD ที่จำเป็นทั้ง 4 เลเยอร์และแสดงรายการที่ขาดหายไป พิมพ์เขียวที่ไม่มี F1_TEC3 จะได้คะแนน 0.75 เป็นต้น กรณีอื่นๆ จะได้คะแนน 1.0 เนื่องจากคำตอบที่เป็นการปฏิเสธหรือโหมดการโจมตีไม่จำเป็นต้องระบุทุกชั้น

ทำไมต้องตรวจสอบเลเยอร์ CAD พิมพ์เขียวที่ได้รับอนุมัติซึ่งละเว้นเลเยอร์ที่จำเป็นนั้นไม่ถูกต้องแม้ว่าจะอ่านเข้าใจได้ดี และผู้ประเมิน LLM อาจมองข้ามเรื่องนี้ไป การตรวจสอบโค้ดจะใช้กฎเดียวกันในลักษณะเดียวกันทุกครั้งที่เรียกใช้

ทำการประเมิน

เปิด Gatekeeper ในเครื่องไว้ในแท็บที่ 2 แล้วเรียกใช้คำสั่งต่อไปนี้

agents-cli eval run \
  --dataset tests/eval/datasets/track_eval_quick.json \
  --config tests/eval/eval_config.yaml \
  --concurrency 1
ls artifacts/grade_results/

การประเมินจะใช้เวลาสักครู่ แต่ละเคสจะเรียกใช้โฟลว์ Multi-Agent ทั้งหมด ซึ่งเป็นการเรียกใช้โมเดลประมาณ 10 ครั้งโดยมี Lead Architect ทำหน้าที่คิด HIGH ดังนั้น Step 1/2: eval generate จึงเป็นส่วนที่ช้า ไม่ได้ติดขัดอะไร

เมื่อเสร็จแล้ว ให้เปิดรายงาน HTML ใน artifacts/grade_results/ ด้วย Cloud Shell Editor คะแนน fia_cad_layer_compliance ที่ต่ำบ่งบอกว่าคำตอบสุดท้ายของ Lead Architect ไม่ได้รวมเลเยอร์ไว้ ลองปรับคำสั่งให้รัดกุมขึ้นและเรียกใช้การประเมินอีกครั้ง

7. 7. ทำให้ Gatekeeper ใช้งานได้กับ Agent Runtime

คุณติดตั้งใช้งานเฉพาะ Gatekeeper เท่านั้น เครื่องมือวางแผนเส้นทางจะทำงานใน Cloud Shell ต่อไปและเรียกใช้เครื่องมือดังกล่าว

เปิดแท็บ Cloud Shell ใหม่

การทำให้ใช้งานได้จะใช้เวลา 5-8 นาที ดังนั้นให้ดำเนินการในแท็บใหม่ขณะที่การประเมินจากขั้นตอนที่ 6 เสร็จสิ้น

  1. คลิกเปิดแท็บใหม่ (+) ในแถบเครื่องมือ Cloud Shell
  2. แท็บใหม่จะไม่เก็บตัวแปรจากขั้นตอนที่ 2 ดังนั้นให้ตั้งค่าอีกครั้งโดยทำดังนี้
    export GOOGLE_CLOUD_PROJECT="$(gcloud config get-value project)"
    export REGION="us-central1"
    export ASSETS="$HOME/devrel-demos/codelabs/formula-e-track-planner"
    export PATH="$HOME/.local/bin:$PATH"
    echo "Project: $GOOGLE_CLOUD_PROJECT  Region: $REGION"
    

ปล่อยให้ Gatekeeper ในเครื่องทำงานในแท็บที่ 2 เนื่องจากการประเมินยังคงใช้ Gatekeeper อยู่ และการทำให้ใช้งานได้ไม่จำเป็นต้องหยุดการทำงานของ Gatekeeper

ทำให้ใช้งานได้

ติดตั้งใช้งาน Gatekeeper ในแท็บใหม่ โดยจะทำงานเป็นบัญชีบริการเริ่มต้นของ Compute Engine ของโปรเจ็กต์ ดังนี้

cd ~/gatekeeper
PROJECT_NUMBER=$(gcloud projects describe "$GOOGLE_CLOUD_PROJECT" --format="value(projectNumber)")
agents-cli deploy \
  --no-agent-identity \
  --service-account "${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
  --project "$GOOGLE_CLOUD_PROJECT" \
  --region "$REGION" \
  --no-confirm-project

การทำให้ใช้งานได้จะใช้เวลาประมาณ 5-8 นาที อย่าปิดแท็บ Cloud Shell ขณะที่ทำงานอยู่ หากสตรีมบันทึกยกเลิกการเชื่อมต่อ ให้ตรวจสอบความคืบหน้าด้วย agents-cli deploy --status ระหว่างที่รอ ให้กลับไปที่ขั้นตอนที่ 6 และอ่านรายงานการประเมิน

ตรวจสอบข้อมูลระบุตัวตนของ Agent

agents-cli บันทึกทรัพยากรที่ติดตั้งใช้งานใน deployment_metadata.json ดังนี้

export RUNTIME_ID=$(jq -r .remote_agent_runtime_id ~/gatekeeper/deployment_metadata.json)
echo "$RUNTIME_ID"

curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  "https://${REGION}-aiplatform.googleapis.com/v1beta1/${RUNTIME_ID}" \
  | jq -r .spec.effectiveIdentity

บรรทัดที่ 2 ของเอาต์พุตคือข้อมูลประจำตัวที่ Gatekeeper ทำงานเป็น:

ทำให้ใช้งานได้แล้วด้วย

ตัวอย่างเอาต์พุต

บัญชีบริการ (ค่าเริ่มต้น)

123456789012-compute@developer.gserviceaccount.com

ข้อมูลระบุตัวตนของ Agent

agents.global.org-.system.id.goog/resources/aiplatform/projects//locations/us-central1/reasoningEngines/

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

8. 8. เชื่อมต่อกับ Gatekeeper ที่ติดตั้งใช้งานผ่าน A2A

รันไทม์ของ Agent จะแสดงเส้นทาง A2A ที่ Gatekeeper สร้างขึ้นหลังเส้นทาง /api ที่ตรวจสอบสิทธิ์แล้ว

ตรวจสอบว่าการประเมินจากขั้นตอนที่ 6 เสร็จสิ้นแล้ว จากนั้นหยุด Gatekeeper ในเครื่องในแท็บที่ 2 (Ctrl+C) จากนี้ไป เครื่องมือวางแผนเส้นทางจะเรียกใช้เครื่องมือที่ติดตั้งใช้งานแล้ว ในแท็บแรก ให้ชี้เครื่องมือวางแผนแทร็กไปที่แท็บนั้น โดยทำดังนี้

export RUNTIME_ID=$(jq -r .remote_agent_runtime_id ~/gatekeeper/deployment_metadata.json)
: "${RUNTIME_ID:?No deployed Gatekeeper found. Complete Step 7 first.}"
cd ~/track-planner
echo "GATEKEEPER_A2A_URL=https://${REGION}-aiplatform.googleapis.com/reasoningEngines/v1/${RUNTIME_ID}/api/a2a/app" >> .env

เหตุผลที่ไคลเอ็นต์รีเฟรชโทเค็น

เปิด app/auth.py โทเค็นเพื่อการเข้าถึงของ Google Cloud จะหมดอายุหลังจากผ่านไป 1 ชั่วโมง ดังนั้นไคลเอ็นต์ที่ตั้งค่าส่วนหัว Authorization แบบคงที่เมื่อเริ่มต้นระบบจะเริ่มดำเนินการไม่สำเร็จพร้อมข้อผิดพลาด 401 Unauthorized หลังจากผ่านไป 1 ชั่วโมง GoogleAuthRefresh จะสร้างคลาสย่อย httpx.Auth และตรวจสอบข้อมูลเข้าสู่ระบบในทุกคำขอ โดยจะรีเฟรชข้อมูลเมื่อจำเป็น create_remote_gatekeeper_agent() จะแนบพารามิเตอร์ดังกล่าวกับ URL ของ https:// เท่านั้น

ดำเนินการตั้งแต่ต้นจนจบ

เริ่ม Playground อีกครั้งเพื่อให้รับ GATEKEEPER_A2A_URL ใหม่ โดยทำดังนี้

agents-cli playground --port 8080

คลิกตัวอย่างเว็บ > แสดงตัวอย่างในพอร์ต 8080 เริ่มเซสชันใหม่ แล้วถามว่า

Assess the Monaco Harbour layout, widen the chicane to 11m, and get Gatekeeper approval.

เหตุการณ์จะเหมือนกับในขั้นตอนที่ 5 แต่ตอนนี้การเรียก remote_gatekeeper จะไปที่ Gatekeeper ในรันไทม์ของ Agent แทนแท็บที่ 2

ดูสายที่เข้ามาใน Agent Runtime

พิสูจน์ว่าคำขอไปถึง Gatekeeper ที่ติดตั้งใช้งานผ่าน A2A จริงๆ โดยทำดังนี้

  1. ในคอนโซล Cloud ให้ค้นหา Agent Platform แล้วเปิดการติดตั้งใช้งานในเมนูด้านซ้าย
  2. เลือก gatekeeper
  3. เปิดแท็บเซสชัน

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

ไม่บังคับ: ติดตั้งใช้งานเครื่องมือวางแผนแทร็กด้วย

จนถึงตอนนี้ ตัววางแผนเส้นทางจะทำงานใน Cloud Shell ดังนั้นการเรียก A2A ไปยัง Gatekeeper จะใช้ข้อมูลเข้าสู่ระบบของคุณ ทำให้ Planner ใช้งานได้ด้วย และ Agent ทั้ง 2 ตัวจะทำงานบน Agent Runtime โดยเรียกใช้กันและกันด้วยข้อมูลระบุตัวตนที่ทำให้ใช้งานได้ของตนเอง

กด Ctrl+C เพื่อหยุด Playground จากนั้นติดตั้งใช้งาน Planner ในลักษณะเดียวกับ Gatekeeper ดังนี้

cd ~/track-planner
PROJECT_NUMBER=$(gcloud projects describe "$GOOGLE_CLOUD_PROJECT" --format="value(projectNumber)")
agents-cli deploy \
  --no-agent-identity \
  --service-account "${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
  --project "$GOOGLE_CLOUD_PROJECT" \
  --region "$REGION" \
  --no-confirm-project

ทั้ง 2 เอเจนต์จะทำงานเป็นบัญชีบริการ Compute Engine เดียวกัน เก็บ --service-account ไว้: หากไม่มี ตัววางแผนจะทำงานเป็นตัวแทนบริการเริ่มต้นของรันไทม์ของ Agent และไม่สามารถเรียก Gatekeeper ได้ (ดูเหตุใดจึงต้องใช้บัญชีบริการนี้ในขั้นตอนที่ 7)

วิธีที่เครื่องมือวางแผนที่ติดตั้งใช้งานเข้าถึง Gatekeeper

  • agents-cli deploy จะคัดลอกค่าใน .env ไปยังการติดตั้งใช้งาน เพื่อให้เครื่องมือวางแผนได้รับ GATEKEEPER_A2A_URL ที่คุณเพิ่มไว้ด้านบน
  • ภายในรันไทม์ของ Agent GoogleAuthRefresh ใน app/auth.py จะเลือกข้อมูลประจำตัวที่ใช้งานอยู่ของ Planner แทนข้อมูลประจำตัวของคุณ

การทำให้ใช้งานได้จะใช้เวลาประมาณ 5-8 นาที เมื่อเสร็จแล้ว ให้ตรวจสอบว่าเครื่องมือวางแผนทำงานในฐานะข้อมูลประจำตัวใด โดยทำดังนี้

export PLANNER_ID=$(jq -r .remote_agent_runtime_id deployment_metadata.json)
curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  "https://${REGION}-aiplatform.googleapis.com/v1beta1/${PLANNER_ID}" \
  | jq -r .spec.effectiveIdentity

วิธีลองใช้ระบบที่ติดตั้งใช้งาน

  1. ในคอนโซล Cloud ให้กลับไปที่แพลตฟอร์ม Agent > การติดตั้งใช้งาน
  2. เลือก track-planner แล้วเปิดแท็บ Playground
  3. ป้อนข้อมูลต่อไปนี้
    Design and homologate a Formula E circuit at Tokyo Bay.
    
  4. รอพิมพ์เขียวที่มีสถานะอนุมัติจาก Gatekeeper
  5. กลับไปที่การติดตั้งใช้งาน เลือก gatekeeper แล้วเปิดแท็บเซสชัน เซสชัน A2A_USER_ ล่าสุดมาจาก Planner ที่ติดตั้งใช้งาน ไม่ใช่จาก Cloud Shell

เมื่อคุณล้างข้อมูลในขั้นตอนถัดไป ให้ลบ Planner ด้วย โดยทำดังนี้

curl -X DELETE -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  "https://${REGION}-aiplatform.googleapis.com/v1beta1/${PLANNER_ID}?force=true"

9. 9. การแก้ปัญหาและการล้างข้อมูล

การแก้ปัญหา

ลักษณะปัญหา

แก้ไข

UREQ_TOS_NOT_ACCEPTED

ยอมรับข้อกำหนดในการให้บริการในคอนโซล Cloud แล้วลองอีกครั้ง

โปรเจ็กต์คือ (unset)

เรียกใช้คำสั่งโปรเจ็กต์ในขั้นตอนที่ 2 อีกครั้ง

service account info is missing 'email' field

เรียกใช้ gcloud auth application-default login (ขั้นตอนที่ 2) แล้วรีสตาร์ทเซิร์ฟเวอร์ที่ทำงานอยู่

FileNotFoundError เป็นเวลา SKILL.md

ทำขั้นตอนที่ 4 ให้เสร็จ หรือคัดลอก $ASSETS/solution/track-planner/. ไปยัง ~/track-planner/

Connection refused ถึง localhost:8001

เริ่ม Gatekeeper ในเครื่อง (ขั้นตอนที่ 5) หรือตั้งค่า GATEKEEPER_A2A_URL เป็น Gatekeeper ที่ติดตั้งใช้งาน (ขั้นตอนที่ 8)

Permission 'resourcemanager.projects.setIamPolicy' deniedเมื่อทำให้ใช้งานได้

บัญชีของคุณใช้ข้อมูลประจำตัวของตัวแทนไม่ได้ ทำตามช่องการล้างข้อมูลในขั้นตอนที่ 7 จากนั้นใช้การติดตั้งใช้งานบัญชีบริการ

เครื่องมือวางแผนเส้นทางที่ติดตั้งใช้งานรายงาน 403 Forbidden จาก Gatekeeper

ข้อมูลประจำตัวของผู้วางแผนไม่ได้รับอนุญาตให้เรียก Gatekeeper ทำให้ใช้งานได้อีกครั้งด้วย --service-account ตามขั้นตอนที่ 7 หรือด้วย --agent-identity หากคุณเป็นเจ้าของโปรเจ็กต์

429 RESOURCE_EXHAUSTED

คุณใช้โควต้า Gemini ครบแล้ว โปรดรอสักครู่ หรือเพิ่ม --concurrency 1 --qps 2 ไปยัง agents-cli eval run

Address already in use

หยุดเซิร์ฟเวอร์อื่น หรือเลือก --port อื่น

ล้างข้อมูล

ลบ Gatekeeper ที่ติดตั้งใช้งานเพื่อไม่ให้ทำงานต่อไป โดยทำดังนี้

export RUNTIME_ID=$(jq -r .remote_agent_runtime_id ~/gatekeeper/deployment_metadata.json)
: "${RUNTIME_ID:?No deployed Gatekeeper found.}"
curl -X DELETE -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  "https://${REGION}-aiplatform.googleapis.com/v1beta1/${RUNTIME_ID}?force=true"

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

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

  • agents-cli scaffold create มีโปรเจ็กต์ ADK มาตรฐานที่ทำให้ใช้งานได้ คุณเพียงแค่เขียน Agent, ทักษะ และการประเมินเท่านั้น
  • ทักษะของ Agent จะเก็บความรู้เกี่ยวกับโดเมนไว้นอกพรอมต์จนกว่า Agent จะต้องการใช้
  • thinking_level ช่วยให้คุณแลกเปลี่ยนความลึกของการให้เหตุผลกับความเร็วต่อ Agent ได้
  • agents-cli eval run เปลี่ยนคำถามที่ว่า "ได้ผลไหม" ให้เป็นคะแนนที่คุณติดตามได้
  • ข้อมูลประจำตัวของ Agent และ A2A ช่วยให้ Agent ที่ติดตั้งใช้งานอย่างอิสระทำงานร่วมกันได้อย่างปลอดภัย

ดูข้อมูลเพิ่มเติม