使用 ADK 和 A2A 建構多代理方程式 E 賽道規劃工具

1. 1. 總覽

在本程式碼實驗室中,您將建構多代理系統,設計 Formula E 街道賽道,並根據簡化的 FIA 規則取得核准。

您將使用 agents-cli 生成兩個標準 Agent Development Kit (ADK) 專案,然後編寫重要部分:一個代理技能、三個代理和一項評估。其他所有項目 (專案版面配置、伺服器、依附元件、部署設定) 則來自 CLI。

第一次接觸電動方程式嗎?

你不需要瞭解賽車運動。只要這五個詞就夠了:

  • Formula E:FIA 的全電動賽車錦標賽。大多數賽事都在市中心的臨時街道賽道上舉行。
  • 認證:FIA 官方核准賽道可安全進行比賽。沒有認證,就不能參賽。
  • 再生煞車:車輛煞車時,馬達會為電池充電。煞車越用力,回收的能量越多,因此本程式碼實驗室的規則要求至少有一個重煞車區。
  • CAD 圖層:賽道設計圖中的命名圖層,例如賽車線、維修道和障礙物。FIA 會檢查這些必要項目是否存在。
  • 攻擊模式:車手只要駛過賽道外的啟動區,就能暫時提升動力。

代理會同時扮演兩種角色:一個負責設計賽道,另外兩個則負責檢查賽道是否符合 FIA 規定。

建構目標

架構:在 Cloud Shell 執行的 track-planner 專案中,track_planner 代理會使用 get_track_topology、fia_assessor 和 remote_gatekeeper。remote_gatekeeper 會透過 A2A 呼叫 gatekeeper 代理。在 Agent Runtime 執行的 gatekeeper 專案中,gatekeeper 代理會使用 verify_infrastructure_checklist。

綠色方塊代表代理,虛線方塊代表工具,與 ADK Playground 的繪製方式相同。其中兩項工具會包裝其他代理:fia_assessor 是具備 FIA 法規遵循技能的 FIA 評估人員代理,remote_gatekeeper 則會透過 A2A 呼叫其他專案中的 Gatekeeper 代理。

代理

專案

工作

thinking_level

首席架構師

track-planner

讀取場地、詢問評估者、修正問題、要求守門人核准

HIGH

FIA 評估人員

track-planner

使用 FIA 技能和評分工具檢查版面配置

MEDIUM

數位孿生守門人

gatekeeper

執行最終認證檢查清單

LOW

學習目標

  • agents-cli scaffold create 如何配置 ADK 專案,以及您編輯的檔案。
  • 如何將領域知識封裝為代理技能 (SKILL.md、references/、scripts/),並使用 ADK 的 SkillToolset 載入。
  • 如何根據各個代理的工作,提供thinking_level。
  • 如何使用 agents-cli eval run 評估代理。
  • 如何將代理部署至 Agent Runtime、代理身分與服務帳戶有何不同,以及如何透過 A2A 通訊協定呼叫已部署的代理。

2. 2. 設定環境

事前準備

您需要已啟用計費功能的 Google Cloud 專案,如果您是在活動中進行本程式碼實驗室,請使用主辦單位提供的帳戶和專案。

開啟 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"

為代理建立憑證

gcloud 已登入,但代理執行的 Python 程式碼會使用應用程式預設憑證 (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

建立步驟 7 部署作業使用的 Compute Engine 預設服務帳戶

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

本程式碼實驗室搭配 agents-cli 1.10.0 進行測試,因此請安裝該版本,取得相同的生成檔案。

3. 3. 建構專案並新增素材資源

生成兩項專案

agents-cli scaffold create 會生成完整、可部署的 ADK 專案。執行兩次,每個代理系統各一次。

首先是賽道規劃工具:

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 指南中的「專案結構」一節。

試用生成的代理

在變更任何內容之前,請先執行範本代理,看看鷹架會提供什麼內容。安裝依附元件,並在通訊埠 8080 啟動本機 Playground:

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

如要開啟,請點選 Cloud Shell 工具列中的「網頁預覽」按鈕 (右上方的眼睛圖示),然後選取「透過以下通訊埠預覽:8080」。

在 Playground 中,向範本代理提出工具可回答的問題,例如:

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,為每個專案建立虛擬環境。所有單元測試都應通過。

4. 4. 編寫 FIA 法規遵循技能

代理技能會將指令、參考文件和指令碼封裝在一個資料夾中。ADK 的 SkillToolset 會分三個層級載入,因此代理只會讀取所需內容:

等級

檔案

代理看到時

1

SKILL.md front matter (name,description)

一律 (數十個權杖)

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是計算機。只要輸入煞車區的進入速度、離開速度和煞車距離,系統就會計算出回收的能量和彎道所需的護欄,因此代理不必猜測物理數據。

執行倫敦第 10 彎道的指令碼,車輛在 82 公尺內從時速 215 公里減速至 55 公里:

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,判斷何時使用這項技能,因此請說明技能涵蓋內容和使用時機。

查看技能的連結方式

在 Cloud Shell 編輯器中開啟 app/tools.py:

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 會將其轉換為代理可呼叫的工具:list_skills、load_skill、load_skill_resource 和 run_skill_script。
  • UnsafeLocalCodeExecutor 可讓 run_skill_script 在這部機器上執行 Python 指令碼。這在實驗室中沒問題,但在實際工作環境中,請使用沙箱執行工具。

在下一個步驟中,您會將這個工具組附加至 Assessor。

5. 5. 編寫代理

Gemini 3 模型會使用 thinking_level (LOW、MEDIUM 或 HIGH) 控制推論,而非使用權杖預算。在 ADK 中,您可以使用 types.ThinkingConfig(thinking_level=types.ThinkingLevel.HIGH) 設定。請根據各個代理的工作調整:思考程度越高,規劃越完善,但延遲時間和費用也會增加。

守門人 (LOW)

Gatekeeper 只會執行確定性檢查清單,因此不需要太多推論。取代範本代理:

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 分頁,並在通訊埠 8001 啟動 Gatekeeper 產生的伺服器:

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

返回第一個分頁,查看 Gatekeeper 的 A2A 代理資訊卡。其他代理會透過以下方式,瞭解 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 列出代理可執行的操作。ADK 會使用工具的 docstring 自動新增 verify_infrastructure_checklist。
  • supportedInterfaces 會告知呼叫端 A2A 要求的傳送位置。這就是為什麼您要使用 APP_URL=http://localhost:8001 啟動伺服器:呼叫端會先讀取資訊卡,然後將要求傳送至資訊卡宣傳的任何 url。

這裡沒有任何內容是手動編寫,鷹架伺服器會根據代理建構資訊卡。賽道規劃人員會讀取這張卡片,找出並呼叫 Gatekeeper。

評估人員 (MEDIUM) 和首席架構師 (HIGH)

賽道規劃工具包含兩個代理:

  • Assessor 會評估多項規則,因此會取得 MEDIUM。這項工具會包裝在 AgentTool 中,因此首席架構師可以像呼叫函式一樣呼叫這項工具,並取得判定結果。
  • 首席架構師負責規劃、修正和協調,因此會獲得 HIGH。它會透過 app/auth.py 中 create_remote_gatekeeper_agent() 建立的 RemoteA2aAgent 抵達 Gatekeeper,並將其包裝在 AgentTool 中。

為什麼要將這兩個輔助函式包裝成工具?AgentTool 會將答案傳回給呼叫端,因此首席架構師仍負責撰寫最終藍圖。如果 Gatekeeper 是 sub_agent,Lead Architect 會將對話交給 Gatekeeper,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 仍在第二個分頁中執行。在第一個分頁中,啟動 Track Planner 的 Playground:

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

依序點選「網頁預覽」 >「透過以下通訊埠預覽:8080」,如步驟 3 所示。

要求在符合規則的場地進行巡迴賽:

Design and homologate a Formula E circuit at Tokyo Bay.

在代理執行工作時,觀察事件面板。您應該會依序看到:

  1. get_track_topology:首席架構師載入東京灣資料。
  2. fia_assessor:首席架構師將版面配置交給評估工具,後者會呼叫 load_skill、load_skill_resource 和 run_skill_script (每個煞車區一次),然後呼叫 evaluate_track_layout。
  3. remote_gatekeeper:首席架構師透過 A2A 呼叫總機人員。您會在第二個分頁中看到記錄的要求。
  4. 首席建築師提供的最終藍圖,列出每個 CAD 圖層和守門人的「APPROVED」狀態。

按一下任何事件,即可查看確切的輸入和輸出內容。

現在,請開始新工作階段,並嘗試違反規則的場地:

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

這次評估人員拒絕了 6.8 公尺的減速彎,首席架構師提議加寬,修正後的版面配置在送交守門人前,會先回到評估人員手中。

完成後,在第一個分頁按下 Ctrl+C 鍵,停止 Playground。請讓 Gatekeeper 在第二個分頁中繼續執行,下一個步驟會用到。

6. 6. 評估代理

agents-cli eval run 會在資料集執行代理、記錄每個回合和工具呼叫,並為結果評分。您可以決定要在 tests/eval/eval_config.yaml 中評估哪些項目。

查看資料集

在 Cloud Shell 編輯器中開啟資料集:

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

檔案中包含 eval_cases 清單。每個案例都有 eval_case_id、prompt (使用者提問) 和 reference (理想答案)。LLM 評判會比較代理的回覆與參考答案。

eval_case_id

測試內容

fe_001_tokyo_compliant

通過所有規則並獲得核准的場地

fe_002_monaco_narrow

6.8 公尺的減速彎道不符合寬度規則

fe_003_berlin_too_long

4350 公尺的線路不符合長度規則

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。這項功能會重播對話的前幾輪,讓您測試代理如何處理後續要求,而不只是單一問題。

同一資料夾中的 track_eval_quick.json 只有兩個案例:案例 1 (單一問題) 和案例 8 (對話)。您將執行該查詢,因為速度更快且使用的配額較少。

寫入指標

資料集會指出要向代理提出的問題。eval_config.yaml說明如何為答案評分。agents-cli eval run 會在代理回答所有案件後讀取答案,並針對每個答案執行各項指標。

開啟鷹架產生的檔案:

cloudshell edit tests/eval/eval_config.yaml

其中已包含一般 LLM 評判 (custom_response_quality) 和僅計算回合數的 agent_turn_count 指標。這對任何代理來說都是很好的開始,但並未提及 Formula E。您會保留評判模型,並新增指標來檢查這個領域專屬的規則。

良好的評估通常會結合兩種指標:

種類

評分方式

適用情況

缺點

LLM-as-a-judge

模型會讀取答案和案件的reference,然後給予 1 到 5 分,並附上說明

模糊品質:答案是否正確、完整且清楚?

每次評估都會呼叫模型,因此會產生費用;每次執行的分數可能略有不同

程式碼指標

一個小型 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 評審。custom_function_file 指向 Scaffold 產生的 tests/eval/response_quality.py。如要查看評估提示,請開啟該檔案。
  • fia_cad_layer_compliance 是程式碼指標,內嵌在 custom_function 下方。每個案例都會收到 instance (提示、代理的最終 response 和 reference)。如果預期答案是核准,系統會檢查回覆是否列出所有四個必要的 CAD 圖層,並列出缺少的圖層。舉例來說,如果藍圖省略 F1_TEC3,分數會是 0.75。其他情況則會獲得 1.0 分,因為拒絕或攻擊模式答案不需要列出每個層級。

為什麼要檢查 CAD 圖層?如果核准的藍圖缺少必要層,即使讀起來很合理,也是錯誤的,而 LLM 評估模型可能會忽略這點。程式碼檢查每次執行時,都會以相同方式套用相同規則。

執行評估作業

讓本機 Gatekeeper 在第二個分頁中繼續執行,然後執行下列指令:

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

評估作業會在幾分鐘內完成。每個案件都會執行整個多代理流程,大約十次模型呼叫,其中首席架構師使用 HIGH 思考,因此 Step 1/2: eval generate 是速度較慢的部分。沒有卡住。

完成後,請使用 Cloud Shell 編輯器在 artifacts/grade_results/ 中開啟 HTML 報表。如果 fia_cad_layer_compliance 分數偏低,表示首席架構師的最終答案遺漏了某些層。請嘗試縮減指令,然後再次執行評估。

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 在第二個分頁中繼續執行:評估作業仍會使用該 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 閱讀評估報告。

檢查代理的身分

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

輸出內容的第二行是 Gatekeeper 執行的身分:

部署工具:

輸出範例

服務帳戶 (預設)

123456789012-compute@developer.gserviceaccount.com

Agent Identity

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

專案中所有使用該服務帳戶的項目都會共用該帳戶。Agent Identity 屬於這個代理,因此您可以授予其所需的角色,並在稽核記錄中單獨查看其動作。

8. 8. 透過 A2A 連線至已部署的 Gatekeeper

Agent Runtime 會在經過驗證的 /api 路徑後方,提供 Gatekeeper 生成的 A2A 路徑。

確認步驟 6 的評估作業已完成,然後在第二個分頁中停止本機 Gatekeeper (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 標頭,1 小時後就會開始失敗,並顯示 401 Unauthorized。GoogleAuthRefresh 是 httpx.Auth 的子類別,會檢查每項要求的憑證,並視需要重新整理。create_remote_gatekeeper_agent() 只會為 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 呼叫現在會傳送至 Agent Runtime 上的 Gatekeeper,而不是第二個分頁。

查看 Agent Runtime 收到的呼叫

證明要求確實透過 A2A 傳送至已部署的 Gatekeeper:

  1. 在 Cloud 控制台搜尋「Agent Platform」,然後開啟左選單中的「部署作業」。
  2. 選取「gatekeeper」。
  3. 開啟「Sessions」(工作階段) 分頁。

您會看到新的工作階段,其使用者 ID 開頭為 A2A_USER_。Gatekeeper 的 A2A 伺服器在路線規劃工具呼叫時建立。在同一頁面開啟「追蹤記錄」分頁,查看 Gatekeeper 的模型呼叫和該要求的 verify_infrastructure_checklist 工具呼叫。

選用:一併部署追蹤規劃工具

目前為止,軌道規劃工具是在 Cloud Shell 中執行,因此對 Gatekeeper 的 A2A 呼叫會使用「您的」憑證。接著部署規劃代理,兩個代理都會在 Agent Runtime 執行,並使用各自的部署身分互相呼叫。

按下 Ctrl+C 停止 Playground,然後按照部署 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

這兩個代理程式會以相同的 Compute Engine 服務帳戶身分執行。保留 --service-account:如果沒有這個參數,規劃器會以 Agent Runtime 的預設服務代理身分執行,無法呼叫 Gatekeeper (請參閱步驟 7 的「為什麼要使用這個服務帳戶?」)。

部署的規劃器如何連線至 Gatekeeper:

  • agents-cli deploy 會將 .env 中的值複製到部署作業,因此規劃工具會取得您在上方新增的 GATEKEEPER_A2A_URL。
  • 在 Agent Runtime 中,app/auth.py 中的 GoogleAuthRefresh 會採用規劃工具的部署身分,而非您的身分。

部署作業約需 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 Platform」 >「部署作業」。
  2. 選取「track-planner」,然後開啟「Playground」分頁。
  3. 輸入:
    Design and homologate a Formula E circuit at Tokyo Bay.
    
  4. 等待藍圖狀態變更為 Gatekeeper 的「APPROVED」。
  5. 返回「Deployments」,選取「gatekeeper」,然後開啟「Sessions」分頁。最新的 A2A_USER_ 工作階段來自已部署的規劃工具,而非 Cloud Shell。

在下一個步驟中執行清理作業時,請一併刪除規劃工具:

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 的清理方塊操作,然後使用服務帳戶部署。

部署的軌道規劃器回報 Gatekeeper 的 403 Forbidden

規劃工具的身分不得呼叫 Gatekeeper。請按照步驟 7,使用 --service-account 重新部署,如果您是專案擁有者,則可使用 --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"

如果您是為了這個程式碼實驗室建立專案,可以改為刪除整個專案。如果你正在參加活動,請保留主辦單位提供的專案,除非主辦單位另有指示。

您學到的內容

  • agents-cli scaffold create 提供可部署的標準 ADK 專案,您只需編寫代理、技能和評估。
  • 代理程式技能可讓代理程式在需要時,才將領域知識加入提示。
  • thinking_level 可讓您調整每個代理的推論深度和速度。
  • agents-cli eval run 可將「是否有效?」轉化為可追蹤的分數。
  • 代理身分和 A2A 可讓獨立部署的代理安全協作。

瞭解詳情