ADK ve A2A ile çoklu aracı Formula E pist planlayıcısı oluşturma

1. 1. Genel Bakış

Bu codelab'de, Formula E sokak pisti tasarlayan ve basitleştirilmiş FIA kurallarına göre onay alan çoklu temsilci sistemi oluşturacaksınız.

İki standart Temsilci Geliştirme Kiti (ADK) projesi oluşturmak için agents-cli'ı kullanacak, ardından önemli kısımları (bir temsilci becerisi, üç temsilci ve bir değerlendirme) yazacaksınız. Diğer her şey (proje düzeni, sunucu, bağımlılıklar, dağıtım yapılandırması) KSA'dan gelir.

Formula E'yi yeni mi kullanmaya başladınız?

Motor sporları hakkında bilgi sahibi olmanız gerekmez. Bu beş terim yeterlidir:

  • Formula E: FIA'nın tamamen elektrikli araçlarla yapılan yarış şampiyonası. Yarışların çoğu şehir merkezlerindeki geçici sokak pistlerinde yapılır.
  • Homologasyon: FIA'nın bir pistin yarış için güvenli olduğuna dair resmi onayı. Homologasyon yoksa yarış da yok.
  • Rejeneratif frenleme: Araç fren yaptığında motorları pili şarj eder. Daha sert frenleme daha fazla enerji geri kazanımı sağlar. Bu nedenle, bu codelab'in kuralları en az bir sert frenleme bölgesi gerektirir.
  • CAD katmanları: Pistin tasarım çizimlerindeki adlandırılmış katmanlar (ör. yarış çizgisi, pit yolu ve bariyerler). FIA, zorunlu olanların mevcut olup olmadığını kontrol eder.
  • Saldırı Modu: Sürücüler, yarış çizgisinin dışındaki bir etkinleştirme bölgesinden geçerek geçici bir güç artışı elde eder.

Temsilcileriniz her iki tarafı da oynar: Biri pisti tasarlar, ikisi de FIA için kontrol eder.

Ne oluşturacaksınız?

Mimari: Cloud Shell'de çalışan track-planner projesinde track_planner temsilcisi get_track_topology, fia_assessor ve remote_gatekeeper'ı kullanır. remote_gatekeeper, A2A üzerinden gatekeeper temsilcisini çağırır. Agent Runtime'da çalışan bekçi projesinde bekçi temsilcisi, verify_infrastructure_checklist'i kullanır.

Yeşil kutular temsilcileri, kesikli kutular ise araçlarını gösterir. Bu, ADK alanındaki çizimle aynıdır. Araçlardan ikisi diğer temsilcileri sarmalar: fia_assessor, FIA uygunluk becerisine sahip FIA Assessor temsilcisidir ve remote_gatekeeper, diğer projedeki Gatekeeper temsilcisini A2A üzerinden çağırır.

Ajan

Proje

İş

thinking_level

Baş Mimar

track-planner

Mekanı okur, Değerlendirici'ye sorar, sorunları düzeltir, Onaylayıcı'dan onay ister.

HIGH

FIA Değerlendiricisi

track-planner

FIA becerisini ve puanlama aracını kullanarak düzeni kontrol eder.

MEDIUM

Dijital İkiz Bekçisi

gatekeeper

Son homologasyon kontrol listesini çalıştırır.

LOW

Öğrenecekleriniz

  • agents-cli scaffold create'in ADK projesini nasıl düzenlediği ve hangi dosyaları düzenlediğiniz.
  • Alan bilgisini Temsilci Becerisi (SKILL.md, references/, scripts/) olarak paketleme ve ADK'nin SkillToolset ile yükleme
  • thinking_level ile her bir temsilcinin işini eşleştirme.
  • agents-cli eval run ile temsilcileri değerlendirme
  • Agent Runtime'a temsilci dağıtma, temsilci kimliğinin hizmet hesabından farkı ve dağıtılan temsilciyi A2A protokolü üzerinden çağırma

2. 2. Ortamınızı ayarlama

Başlamadan önce

Faturalandırmanın etkin olduğu bir Google Cloud projeniz olmalıdır. Bu codelab'i bir etkinlikte takip ediyorsanız size verilen hesabı ve projeyi kullanın.

Cloud Shell'i açma ve projenizi ayarlama

Cloud Shell'i açıp şu komutu çalıştırın:

# 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"

Temsilcileriniz için kimlik bilgileri oluşturma

gcloud oturumu zaten açık ancak temsilcilerinizin çalıştırdığı Python kodu, ayrı bir oturum açma işlemi gerektiren Uygulama Varsayılan Kimlik Bilgileri'ni (ADC) kullanıyor:

gcloud auth application-default login

Yazdırılan bağlantıyı açın, aynı hesapla oturum açın, kodu kopyalayın ve Cloud Shell'e geri yapıştırın. Ardından, kotanın faturalandırılacağı projeyi ayarlayın:

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

API'leri etkinleştirme

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'lerin kullanım amaçları:

API'ler

Kullanım alanı

aiplatform

Gemini modelleri ve Agent Runtime

cloudresourcemanager, serviceusage ve iam

gcloud ve agents-cli deploy tarafından çalıştırılan proje ve izin kontrolleri

compute

7. adımda dağıtımın kullandığı Compute Engine varsayılan hizmet hesabını oluşturur.

storage, logging ve cloudtrace

Agent Runtime kurulum kılavuzunda önerildiği şekilde depolama alanı, günlükler ve izler

cloudbuild, artifactregistry

7. adımdaki dağıtım için önlem olarak eklenen container derlemeleri ve görüntüleri

Birçok projede bu özelliklerin bazıları zaten etkindir. Zaten etkin olan bir API'yi etkinleştirmek hiçbir şeyi değiştirmez.

uv ve agents-cli uygulamasını yükleyin

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

Bu codelab, agents-cli 1.10.0 ile test edilmiştir. Bu nedenle, aynı oluşturulan dosyaları almak için bu sürümü yükleyin.

3. 3. Projelerin iskeletini oluşturma ve öğeleri ekleme

İki projeyi de oluştur

agents-cli scaffold create, eksiksiz ve dağıtılabilir bir ADK projesi oluşturur. Her temsilci sistemi için bir kez olmak üzere iki kez çalıştırın.

İlk olarak, pist planlayıcı:

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

Ardından onaylayıcı:

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

İşaret

Anlamı

--agent adk

Python ADK şablonuyla başlama

--deployment-target agent_runtime

Agent Runtime için sunucuyu ve yapılandırmayı oluşturma

--prototype

CI/CD'yi atla; projeyi minimum düzeyde tut

--yes

Varsayılanları sormadan kabul etme

Düzeni keşfetme

Oluşturulan proje şu şekilde görünür. Yalnızca ✍️ ile işaretlenmiş dosyaları düzenlersiniz:

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`

Oluşturulan her dosyanın açıklaması için Agents CLI kılavuzundaki Proje yapısı bölümüne bakın.

Oluşturulan temsilciyi deneyin

Herhangi bir değişiklik yapmadan önce şablon temsilciyi çalıştırarak iskelenin size ne sunduğunu görün. Bağımlılıkları yükleyin ve yerel deneme alanını 8080 numaralı bağlantı noktasında başlatın:

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

Açmak için Cloud Shell araç çubuğundaki Web önizlemesi düğmesini (sağ üstteki göz simgesi) tıklayın, ardından 8080 bağlantı noktasında önizle'yi seçin.

Playground'da, şablon temsilciye araçlarının yanıtlayabileceği bir soru sorun. Örneğin:

What's the weather in San Francisco?

Yan panelde, get_weather araç çağrısı ve sonucu dahil olmak üzere her etkinlik gösterilir. Daha sonra kendi temsilcilerinizi takip etmek için aynı görünümü kullanacaksınız.

İşiniz bittiğinde terminale dönün ve Ctrl+C tuşlarına basarak oyun alanını durdurun.

Formula E öğelerini ekleme

Mekan verileri, FIA kuralları, fizik komut dosyası, araçlar ve değerlendirme veri kümeleri dersin konusu değildir. Bu nedenle, bunları yazmak yerine GitHub'dan kopyalayın:

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, sabit bir sürüm etiketi olduğundan herkes aynı dosyaları alır. $ASSETS, 2. adımda ayarlanmıştır ve az önce klonladığınız klasörü gösterir.

Bu işlem şu dosyaları ekler:

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

Yükleme ve test etme

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

agents-cli install, her proje için sanal ortam oluşturmak üzere uv sync komutunu çalıştırır. Tüm birim testleri başarılı olmalıdır.

4. 4. FIA uyumluluk becerisini yazma

Temsilci becerisi; talimatları, referans belgeleri ve komut dosyalarını tek bir klasörde toplar. ADK'nin SkillToolset özelliği, bunu üç düzeyde yükler. Böylece temsilci yalnızca ihtiyacı olanı okur:

Seviye

Dosya

Temsilci bunu gördüğünde

1

SKILL.md ön bilgi (name, description)

Her zaman (birkaç düzine jeton)

2

SKILL.md gövde

load_skill numaralı telefonu aradığında

3

references/, scripts/

load_skill_resource veya run_skill_script numaralı telefonu aradığında

Oluşturulan Dockerfile, yalnızca app/ öğesini dağıtılan görüntüye kopyaladığı için beceri app/skills/ içinde yer alır.

3. seviye dosyalara bakma

3. adımda becerinin 3. seviye dosyalarını kopyaladınız:

  • references/track_regulations.md, Değerlendirici'nin kontrol ettiği kuralları içerir: uzunluk ve genişlik sınırları, her fren bölgesinin ihtiyaç duyduğu bariyer, zorunlu CAD katmanları (hastane rotaları için tıbbi katmanlar), rejenerasyon hedefi ve Atak Modu kuralları.
  • scripts/calculate_regen_zones.py bir hesap makinesidir. Fren bölgesinin giriş hızı, çıkış hızı ve fren mesafesi verildiğinde, geri kazanılan enerjiyi ve virajın ihtiyaç duyduğu bariyeri hesaplar. Böylece temsilcinin fiziği tahmin etmesi gerekmez.

Londra'daki 10. viraj için senaryoyu çalıştırın. Burada arabalar 82 metre boyunca 215 km/saat'ten 55 km/saat'e kadar fren yapar:

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

Araç burada 250 kW hedefinin üzerinde, yaklaşık 508 kW enerji geri kazanıyor. 2G'den daha fazla yavaşladığı için virajda Tecpro bariyerleri (F1_TEC3) gerekiyor:

{"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 yazın

Beceriyi bir araya getiren dosyayı oluşturun:

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

Bu içeriği ekleyin:

---
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, modelin beceriyi ne zaman kullanacağına karar vermek için okuduğu kısımdır. Bu nedenle, becerinin ne kapsadığını ve ne zaman kullanılacağını belirtir.

Becerinin nasıl yapılandırıldığını inceleyin

Cloud Shell Düzenleyici'de app/tools.py dosyasını açın:

cloudshell edit app/tools.py

build_fia_skill_toolset işlevini bulma:

def build_fia_skill_toolset() -> SkillToolset:
    return SkillToolset(
        skills=[load_skill_from_dir(SKILL_DIR)],
        code_executor=UnsafeLocalCodeExecutor(),
    )
  • load_skill_from_dir, beceri klasörünü okur: SKILL.md, references/ ve scripts/.
  • SkillToolset, bunu temsilcinin çağırabileceği araçlara dönüştürür: list_skills, load_skill, load_skill_resource ve run_skill_script.
  • UnsafeLocalCodeExecutor, run_skill_script uygulamasının bu makinede Python komut dosyasını çalıştırmasına izin verir. Laboratuvar için bu sorun teşkil etmez ancak üretimde korumalı alana alınmış bir yürütücü kullanın.

Bu araç setini bir sonraki adımda Assessor'a ekleyeceksiniz.

5. 5. Temsilcileri yazma

Gemini 3 modelleri, akıl yürütmeyi jeton bütçesi yerine thinking_level (LOW, MEDIUM veya HIGH) ile kontrol eder. ADK'da bunu types.ThinkingConfig(thinking_level=types.ThinkingLevel.HIGH) ile ayarlarsınız. Her temsilcinin görevine göre ayarlayın: Daha fazla düşünme, daha iyi planlama anlamına gelir ancak daha fazla gecikme ve maliyet getirir.

The Gatekeeper (LOW)

Gatekeeper yalnızca deterministik bir kontrol listesi çalıştırdığından çok az akıl yürütme gerektirir. Şablon temsilciyi değiştirme:

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'ı yerel olarak çalıştırma

İkinci bir Cloud Shell sekmesi açın ve Gatekeeper'ın oluşturduğu sunucuyu 8001 numaralı bağlantı noktasında başlatın:

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

İlk sekmeye dönüp Gatekeeper'ın A2A aracı kartına bakın. Diğer temsilciler, Gatekeeper'ın ne olduğunu ve neler yapabileceğini bu şekilde öğrenir:

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

Şuna benzer bir JSON görürsünüz (kısaltılmış):

{
  "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 ve description, doğrudan Agent(...) tanımınızdan alınır.
  • skills, temsilcinin yapabileceklerini listeler. ADK, aracın docstring'ini kullanarak verify_infrastructure_checklist ifadesini otomatik olarak ekledi.
  • supportedInterfaces, arayanlara A2A isteklerini nereye göndereceklerini bildirir. Sunucuyu APP_URL=http://localhost:8001 ile başlatmanızın nedeni budur: Arayan önce kartı okur, ardından isteklerini kartın reklamını yaptığı url adresine gönderir.

Burada elle yazılmış hiçbir şey yoktur: İskelet sunucu, kartı temsilcinizden oluşturur. Yol planlayıcı, bu kartı okuyarak Bekçi'yi bulup çağırır.

Değerlendirici (MEDIUM) ve Baş Mimar (HIGH)

Pist planlayıcının iki temsilcisi vardır:

  • Değerlendirici birden fazla kuralı değerlendirir ve MEDIUM alır. AgentTool ile sarmalanmıştır. Bu sayede Baş Mimar, bunu bir işlev gibi çağırır ve kararı alır.
  • Baş Mimar planlama, düzeltme ve koordinasyon işlerini yapar. Bu nedenle HIGH alır. app/auth.py tarihinde create_remote_gatekeeper_agent() tarafından oluşturulan RemoteA2aAgent üzerinden Gatekeeper'a ulaşır ve bunu bir AgentTool ile sarmalar.

Neden her iki yardımcıyı da araç olarak sarmalıyoruz? AgentTool, yanıtını arayana döndürür. Böylece baş mimar, kontrolü elinde tutar ve nihai planı yazar. Gatekeeper bir sub_agent olsaydı Baş Mimar, görüşmeyi ona devrederdi ve Gatekeeper'ın kısa durumu nihai yanıt olurdu.

Pist planlayıcının app/agent.py dosyasını açın:

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

Aşağıdaki kodu kopyalayın ve ~/track-planner/app/agent.py dosyasının tüm içeriğini bu kodla değiştirin:

"""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",
)

Tüm sistemi oyun alanında çalıştırma

Gatekeeper'ın ikinci sekmenizde çalışmaya devam ettiğinden emin olun. İlk sekmede, Track Planner'ın deneme alanını başlatın:

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

3. adımda yaptığınız gibi Web Preview (Web Önizlemesi) > Preview on port 8080'i (8080 bağlantı noktasında önizle) tıklayın.

Kurallara uygun bir mekanda pist isteyin:

Design and homologate a Formula E circuit at Tokyo Bay.

Temsilciler çalışırken etkinlikler panelini izleyin. Sırasıyla şunları görmeniz gerekir:

  1. get_track_topology: Baş mimar, Tokyo Körfezi verilerini yükler.
  2. fia_assessor: Baş Mimar, düzeni Değerlendirici'ye teslim eder. Değerlendirici, load_skill, load_skill_resource ve run_skill_script (frenleme bölgesi başına bir kez) ve ardından evaluate_track_layout işlevlerini çağırır.
  3. remote_gatekeeper: Baş mimar, A2A üzerinden Gatekeeper'ı çağırır. İsteğin ikinci sekmenizde günlüğe kaydedildiğini görürsünüz.
  4. Baş mimarın her CAD katmanını ve Gatekeeper'ın ONAYLANDI durumunu listeleyen nihai planı.

Tam giriş ve çıkışlarını görmek için herhangi bir etkinliği tıklayın.

Şimdi yeni bir oturum başlatın ve kuralları ihlal eden bir mekan deneyin:

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

Bu sefer değerlendirici 6,8 metrelik şikanı reddeder, baş mimar daha geniş bir şikan önerir ve düzeltilen yerleşim, bekçiye ulaşmadan önce değerlendiriciye geri döner.

İşlemi tamamladığınızda, deneme alanını durdurmak için ilk sekmede Ctrl+C tuşlarına basın. Gatekeeper'ı ikinci sekmede çalışır durumda bırakın. Bir sonraki adımda buna ihtiyacınız olacak.

6. 6. Temsilcileri değerlendirme

agents-cli eval run, temsilcinizi bir veri kümesi üzerinde çalıştırır, her sırayı ve araç çağrısını kaydeder ve sonuçları notlandırır. tests/eval/eval_config.yaml'te neyi ölçeceğinize siz karar verirsiniz.

Veri kümesine bakma

Veri kümesini Cloud Shell Düzenleyici'de açın:

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

Dosyada eval_cases listesi bulunur. Her örnekte bir eval_case_id, bir prompt (kullanıcının sorduğu soru) ve bir reference (iyi bir yanıtın nasıl göründüğü) bulunur. LLM değerlendiricisi, temsilcinin yanıtını referansla karşılaştırır.

eval_case_id

Neleri test eder?

fe_001_tokyo_compliant

Tüm kurallara uyan ve onaylanan bir mekan

fe_002_monaco_narrow

6,8 m'lik şikan, genişlik kuralına uymuyor

fe_003_berlin_too_long

4.350 metrelik pist, uzunluk kuralına uymuyor.

fe_004_missing_layers

Zorunlu CAD katmanlarının eksik olduğu bir düzen

fe_005_low_regen

250 kW hedefinin altında bir frenleme bölgesi

fe_006_sao_paulo_medical

Tıbbi CAD katmanları gerektiren hastane erişimi

fe_007_attack_mode

Yarış çizgisinde bir Atak Modu bölgesi

fe_008_multiturn_remediation

Çok turlu bir görüşme: Monaco reddedilir, kullanıcı düzeltme ister ve düzeltilen düzen onaylanır.

Son örnekte prompt yerine agent_data kullanılmıştır. Sohbetin önceki sıralarını yeniden oynatır. Böylece temsilcinin yalnızca tek bir soruyu değil, ek istekleri nasıl işlediğini test edebilirsiniz.

Aynı klasördeki track_eval_quick.json yalnızca iki örnek içerir: örnek 1 (tek bir soru) ve örnek 8 (bir görüşme). Daha hızlı olduğu ve daha az kota kullandığı için bu sorguyu çalıştıracaksınız.

Metrikleri yazma

Veri kümesi, temsilciye ne sorulacağını belirtir. eval_config.yaml, yanıtların nasıl puanlanacağını belirtir. agents-cli eval run, müşteri temsilcisi her bir destek kaydını yanıtladıktan sonra bu yanıtları okur ve her bir yanıt için her metriği çalıştırır.

İskeletin oluşturduğu dosyayı açın:

cloudshell edit tests/eval/eval_config.yaml

Bu değerlendirme grubu, genel bir LLM değerlendirici (custom_response_quality) ve yalnızca sıra sayısını sayan bir agent_turn_count metriği içerir. Bu, bir temsilci için iyi bir başlangıç olsa da Formula E hakkında hiçbir şey söylemiyor. Değerlendiriciyi koruyacak ve bu alana özgü bir kuralı kontrol eden bir metrik ekleyeceksiniz.

İyi değerlendirmelerde genellikle iki tür metrik bir arada kullanılır:

Tür

Puanlama şekli

Şunlar için uygundur:

Ödün verme

LLM-as-a-judge

Model, yanıtı ve destek kaydının reference bilgisini okur, ardından açıklamayla birlikte 1 ile 5 arasında bir puan verir.

Belirsiz nitelikler: Yanıt doğru, eksiksiz ve net mi?

Her vaka için bir model çağrısı maliyeti vardır; puanlar çalıştırmalar arasında biraz farklılık gösterebilir.

Kod metriği

Küçük bir Python işlevi yanıtı kontrol eder.

Tam, kontrol edilebilir bilgiler: Yanıtta bulunması gereken bir bilgi var mı?

Yalnızca kodla ifade edebileceğiniz şeyleri kontrol eder.

Dosyanın içeriğini şununla değiştirin:

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"),
          }

Her bir parçanın işlevi:

  • metrics_to_run, çalıştırılacak metrikleri ada göre listeler. Burada bir adı kaldırdığınızda ilgili metrik silinmeden devre dışı bırakılır.
  • custom_response_quality, LLM değerlendiricisidir. custom_function_file, iskelenin oluşturduğu tests/eval/response_quality.py değerini gösteriyor. Değerlendirme istemini görmek istiyorsanız açın.
  • fia_cad_layer_compliance, custom_function altında satır içi olarak yazılan kod metriğinizdir. Her bir vaka için bir instance (istem, temsilcinin son response ve reference) alır. Beklenen yanıtın onay olduğu durumlarda, yanıtın dört zorunlu CAD katmanının tümünü adlandırdığını kontrol eder ve eksik olanları listeler. Örneğin, F1_TEC3 öğesini içermeyen bir planın puanı 0, 75 olur. Diğer durumlarda 1, 0 puan verilir.Çünkü ret veya Saldırı Modu yanıtında her katmanın listelenmesi gerekmez.

CAD katmanlarını neden kontrol etmelisiniz? Zorunlu bir katmanı içermeyen onaylanmış bir plan, iyi yazılmış olsa bile yanlıştır ve LLM değerlendiricisi bunu gözden kaçırabilir. Kod kontrolü, her çalıştırmada aynı kuralı aynı şekilde uygular.

Değerlendirmeyi çalıştırma

Yerel Gatekeeper'ı ikinci sekmenizde çalışır durumda tutun ve ardından şu komutu çalıştırın:

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

Değerlendirme birkaç dakika sürer. Her bir senaryo, tüm çoklu temsilci akışını çalıştırır. Bu akışta, Baş Mimar'ın HIGH üzerinde düşünmesi için yaklaşık on model çağrısı yapılır. Bu nedenle, Step 1/2: eval generate yavaş olan kısımdır. Sıkışmamış.

İşlem tamamlandığında Cloud Shell Düzenleyici'yi kullanarak artifacts/grade_results/ dizinindeki HTML raporunu açın. Düşük fia_cad_layer_compliance puanları, Baş Mimar'ın son yanıtında katmanların eksik olduğunu gösterir. Talimatını daha net hale getirip değerlendirmeyi tekrar çalıştırmayı deneyin.

7. 7. Gatekeeper'ı Agent Runtime'a dağıtma

Yalnızca Gatekeeper'ı dağıtırsınız. Rota planlayıcı, Cloud Shell'de çalışmaya devam eder ve bu API'yi çağırır.

Yeni bir Cloud Shell sekmesi açma

Dağıtım işlemi 5 ila 8 dakika sürer. Bu nedenle, 6. adımdaki değerlendirme tamamlanırken bu işlemi yeni bir sekmede yapın:

  1. Cloud Shell araç çubuğunda Yeni sekme aç'ı (+) tıklayın.
  2. Yeni sekmede 2. adımdaki değişkenler korunmaz. Bu nedenle, değişkenleri tekrar ayarlayın:
    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"
    

İkinci sekmenizde çalışan yerel Gatekeeper'ı açık bırakın. Değerlendirme için Gatekeeper'ın çalışması gerekir ve dağıtım için durdurulması gerekmez.

Dağıt

Yeni sekmede Gatekeeper'ı dağıtın. Projenin Compute Engine varsayılan hizmet hesabı olarak çalışır:

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

Dağıtım yaklaşık 5 ila 8 dakika sürer. Çalışırken Cloud Shell sekmesini kapatmayın. Günlük akışının bağlantısı kesilirse ilerleme durumunu agents-cli deploy --status ile kontrol edin. Beklerken 6. adıma dönün ve değerlendirme raporunuzu okuyun.

Temsilcinin kimliğini inceleme

agents-cli, dağıtılan kaynağı deployment_metadata.json içinde kaydeder:

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

Çıkışın ikinci satırı, Gatekeeper'ın çalıştığı kimliktir:

Birlikte dağıtıldığı araç

Örnek çıkış

Hizmet hesabı (varsayılan)

123456789012-compute@developer.gserviceaccount.com

Temsilci Kimliği

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

Hizmet hesabı, projede onu kullanan her şey tarafından paylaşılır. Temsilci kimliği bu temsilciye aittir. Bu sayede, temsilciye tam olarak ihtiyaç duyduğu rolleri verebilir ve işlemlerini denetleme günlüklerinde ayrı ayrı görebilirsiniz.

8. 8. A2A üzerinden dağıtılan Gatekeeper'a bağlanma

Agent Runtime, Gatekeeper'ın oluşturduğu A2A rotalarını kimliği doğrulanmış bir /api yolunun arkasında sunar.

6. adımdaki değerlendirmenin tamamlandığından emin olun, ardından ikinci sekmenizdeki yerel Gatekeeper'ı durdurun (Ctrl+C). Rota planlayıcı artık dağıtılan modeli çağırır. İlk sekmenizde, Track Planner'ı bu adrese yönlendirin:

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

İstemcinin jetonunu yenileme nedeni

app/auth.py adlı kişiyi aç. Google Cloud erişim jetonlarının süresi bir saat sonra dolar. Bu nedenle, başlangıçta sabit bir Authorization üstbilgisi ayarlayan istemci, bir saat sonra 401 Unauthorized ile başarısız olmaya başlar. GoogleAuthRefresh, httpx.Auth sınıfının alt sınıfıdır ve her istekte kimlik bilgilerini kontrol ederek gerektiğinde yeniler. create_remote_gatekeeper_agent(), bunu yalnızca https:// URL'leri için ekler.

Uçtan uca çalıştırma

Yeni GATEKEEPER_A2A_URL değerini alması için playground'u yeniden başlatın:

agents-cli playground --port 8080

Web Preview (Web Önizlemesi) > Preview on port 8080'i (8080 bağlantı noktasında önizle) tıklayın, yeni bir oturum başlatın ve şunu sorun:

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

Etkinlikler 5. adımdakiyle aynı görünür ancak remote_gatekeeper çağrısı artık ikinci sekmeniz yerine Agent Runtime'daki Gatekeeper'a gider.

Aramanın Agent Runtime'a ulaştığını görme

İsteğin, A2A üzerinden dağıtılan Gatekeeper'a gerçekten ulaştığını kanıtlayın:

  1. Cloud konsolunda Agent Platform'u arayın, ardından sol menüden Deployments'ı (Dağıtımlar) açın.
  2. Gatekeeper'ı seçin.
  3. Oturumlar sekmesini açın.

Kullanıcı kimliği A2A_USER_ ile başlayan yeni bir oturum görürsünüz. Gatekeeper'ın A2A sunucusu, rota planlayıcınız tarafından çağrıldığında bu kimliği oluşturur. Gatekeeper'ın model çağrısını ve bu istek için verify_infrastructure_checklist araç çağrısını görmek üzere aynı sayfadaki İzler sekmesini açın.

İsteğe bağlı: Parkur planlayıcıyı da dağıtın

Şu ana kadar rota planlayıcı Cloud Shell'de çalıştırıldı. Bu nedenle, Gatekeeper'a yapılan A2A çağrılarında sizin kimlik bilgileriniz kullanıldı. Planlayıcıyı da dağıtın. Her iki temsilci de Agent Runtime'da çalışır ve kendi dağıtılan kimlikleriyle birbirlerini çağırır.

Playground'u durdurmak için Ctrl+C tuşlarına basın, ardından planlayıcıyı Gatekeeper ile aynı şekilde dağıtın:

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

Her iki aracı da aynı Compute Engine hizmet hesabı olarak çalışır. --service-account'yi saklayın: Bu olmadan planlayıcı, Agent Runtime'ın varsayılan hizmet aracısı olarak çalışır ve Gatekeeper'ı çağıramaz (7. adımdaki Neden bu hizmet hesabı? bölümüne bakın).

Dağıtılan planlayıcı, Gatekeeper'a nasıl ulaşır?

  • agents-cli deploy, .env içindeki değerleri dağıtıma kopyalar. Böylece planlayıcı, yukarıda eklediğiniz GATEKEEPER_A2A_URL değerini alır.
  • Agent Runtime'da, app/auth.py içindeki GoogleAuthRefresh, sizin kimliğiniz yerine planlayıcının dağıtılan kimliğini alır.

Dağıtım yaklaşık 5 ila 8 dakika sürer. İşlem tamamlandığında planlayıcının hangi kimlikle çalıştığını kontrol edin:

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

Dağıtılan sistemi denemek için:

  1. Cloud Console'da Agent Platform > Deployments'a (Dağıtımlar) geri dönün.
  2. track-planner'ı seçin ve Playground sekmesini açın.
  3. Şunları girin:
    Design and homologate a Formula E circuit at Tokyo Bay.
    
  4. Gatekeeper'ın APPROVED (ONAYLANDI) durumuna sahip şablonu bekleyin.
  5. Deployments'a (Dağıtımlar) geri dönün, gatekeeper'ı seçin ve Sessions (Oturumlar) sekmesini açın. En yeni A2A_USER_ oturumu Cloud Shell'den değil, dağıtılan planlayıcıdan geldi.

Bir sonraki adımda temizlik yaparken planlayıcıyı da silin:

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

9. 9. Sorun giderme ve temizleme

Sorun giderme

Belirti

Düzelt

UREQ_TOS_NOT_ACCEPTED

Cloud Console'da Hizmet Şartları'nı kabul edin ve tekrar deneyin.

Proje: (unset)

2. adımdaki proje komutlarını yeniden çalıştırın.

service account info is missing 'email' field

gcloud auth application-default login komutunu çalıştırın (2. adım), ardından çalışan tüm sunucuları yeniden başlatın.

SKILL.md için FileNotFoundError

4. adımı tamamlayın veya $ASSETS/solution/track-planner/. değerini ~/track-planner/ alanına kopyalayın.

Connection refused - localhost:8001

Yerel Gatekeeper'ı başlatın (5. adım) veya GATEKEEPER_A2A_URL değerini dağıtılan Gatekeeper'a ayarlayın (8. adım).

Dağıtımda Permission 'resourcemanager.projects.setIamPolicy' denied

Hesabınızda Temsilci Kimliği kullanılamıyor. 7. adımdaki temizleme kutusunu takip edin, ardından hizmet hesabı dağıtımını kullanın.

Dağıtılan yol planlayıcı, Gatekeeper'dan 403 Forbidden bildiriyor

Planlayıcının kimliği, Gatekeeper'ı çağırmaya yetkili değil. 7. adımda olduğu gibi --service-account ile veya projenin sahibiyseniz --agent-identity ile yeniden dağıtın.

429 RESOURCE_EXHAUSTED

Gemini kotasına ulaştınız. Bir dakika bekleyin veya --concurrency 1 --qps 2 adresini agents-cli eval run listesine ekleyin.

Address already in use

Diğer sunucuyu durdurun veya başka bir --port seçin.

Temizleme

Çalışmaya devam etmemesi için dağıtılan Gatekeeper'ı silin:

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"

Yalnızca bu codelab için bir proje oluşturduysanız bunun yerine projenin tamamını silebilirsiniz. Bir etkinlikteyseniz organizatörler aksini söyleyene kadar size verilen projeyi kullanmaya devam edin.

Öğrendikleriniz

  • agents-cli scaffold create, size standart ve dağıtılabilir bir ADK projesi sunar. Sadece temsilcileri, becerileri ve değerlendirmeleri yazmanız yeterlidir.
  • Temsilci Becerileri, temsilci ihtiyaç duyana kadar alan bilgisini istemlerin dışında tutar.
  • thinking_level, her temsilci için akıl yürütme derinliğini hızla değiştirmenize olanak tanır.
  • agents-cli eval run, "İşe yarıyor mu?" sorusunu takip edebileceğiniz puanlara dönüştürür.
  • Temsilci Kimliği ve A2A, bağımsız olarak dağıtılan temsilcilerin birlikte güvenli bir şekilde çalışmasına olanak tanır.

Daha fazla bilgi