Multi-Agenten-App für die Planung von Formel-E-Rennstrecken mit ADK und A2A erstellen

1. 1. Übersicht

In diesem Codelab erstellen Sie ein Multi-Agenten-System, das einen Formel-E-Straßenkurs entwirft und ihn anhand eines vereinfachten FIA-Regelwerks genehmigen lässt.

Sie verwenden agents-cli, um zwei Standardprojekte mit dem Agent Development Kit (ADK) zu generieren, und schreiben dann die wichtigen Teile: einen Agent Skill, drei Agenten und eine Bewertung. Alles andere (Projektlayout, Server, Abhängigkeiten, Bereitstellungskonfiguration) stammt aus der Befehlszeile.

Neu bei der Formel E?

Sie müssen sich nicht mit Motorsport auskennen. Diese fünf Begriffe reichen aus:

  • Formel E: die rein elektrische Rennserie der FIA. Die meisten Rennen finden auf temporären Straßenkursen in Stadtzentren statt.
  • Homologation: die offizielle Genehmigung der FIA, dass eine Rennstrecke sicher ist. Ohne Homologation kein Rennen.
  • Regeneratives Bremsen: Wenn das Auto bremst, wird der Akku durch die Motoren aufgeladen. Durch stärkeres Bremsen wird mehr Energie zurückgewonnen. Daher ist in diesem Codelab mindestens eine Zone mit starkem Bremsen erforderlich.
  • CAD-Ebenen: Benannte Ebenen in den Konstruktionszeichnungen der Rennstrecke, z. B. die Ideallinie, die Boxengasse und die Barrieren. Die FIA prüft, ob die obligatorischen vorhanden sind.
  • Attack Mode: Fahrer erhalten einen vorübergehenden Leistungsschub, wenn sie durch eine Aktivierungszone fahren, die sich abseits der Rennlinie befindet.

Ihre Agenten spielen auf beiden Seiten: Einer entwirft die Rennstrecke und zwei prüfen sie für die FIA.

Umfang

Architektur: Im Projekt „track-planner“, das in Cloud Shell ausgeführt wird, verwendet der Agent „track_planner“ die Tools „get_track_topology“, „fia_assessor“ und „remote_gatekeeper“. „remote_gatekeeper“ ruft den Agenten „gatekeeper“ über A2A auf. Im Gatekeeper-Projekt, das in der Agent Runtime ausgeführt wird, verwendet der Gatekeeper-Agent „verify_infrastructure_checklist“.

Grüne Felder sind Agenten und gestrichelte Felder sind ihre Tools, genau wie im ADK-Playground. Zwei der Tools umschließen andere KI-Agenten: fia_assessor ist der FIA Assessor-Agent mit der FIA-Compliance-Fähigkeit und remote_gatekeeper ruft den Gatekeeper-Agenten im anderen Projekt über A2A auf.

Agent

Projekt

Auftrag

thinking_level

Lead Architect

track-planner

Liest die Veranstaltungsorte, fragt den Assessor, behebt Probleme, bittet den Gatekeeper um Genehmigung

HIGH

FIA-Prüfer

track-planner

Prüft das Layout mithilfe des FIA-Skills und eines Bewertungstools

MEDIUM

Digital Twin Gatekeeper

gatekeeper

Führt die endgültige Homologations-Checkliste aus

LOW

Lerninhalte

  • Wie agents-cli scaffold create ein ADK-Projekt strukturiert und welche Dateien Sie bearbeiten.
  • Wie Sie Fachwissen als Agent Skill (SKILL.md, references/, scripts/) verpacken und mit SkillToolset des ADK laden.
  • So ordnen Sie thinking_level den Aufgaben der einzelnen KI-Agenten zu.
  • KI-Agenten mit agents-cli eval run bewerten.
  • Wie Sie einen KI-Agenten in der Agent Runtime bereitstellen, wie sich die Agentenidentität von einem Dienstkonto unterscheidet und wie Sie den bereitgestellten KI-Agenten über das A2A-Protokoll aufrufen.

2. 2. Umgebung einrichten

Hinweis

Sie benötigen ein Google Cloud-Projekt mit aktivierter Abrechnung. Wenn Sie dieses Codelab im Rahmen einer Veranstaltung durcharbeiten, verwenden Sie das Konto und das Projekt, die Ihnen zugewiesen wurden.

Cloud Shell öffnen und Projekt festlegen

Öffnen Sie Cloud Shell und führen Sie dann Folgendes aus:

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

Anmeldedaten für Ihre KI-Agenten erstellen

gcloud ist bereits angemeldet, aber der Python-Code, den Ihre KI-Agenten ausführen, verwendet Standardanmeldedaten für Anwendungen (Application Default Credentials, ADC), für die eine separate Anmeldung erforderlich ist:

gcloud auth application-default login

Öffnen Sie den angezeigten Link, melden Sie sich mit demselben Konto an, kopieren Sie den Code und fügen Sie ihn wieder in Cloud Shell ein. Legen Sie dann das Projekt fest, für das das Kontingent abgerechnet wird:

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

APIs aktivieren

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

Wofür die einzelnen APIs gedacht sind:

APIs

Verwendet für

aiplatform

Gemini-Modelle und Agent Runtime

cloudresourcemanager, serviceusage, iam

Die Projekt- und Berechtigungsprüfungen, die von gcloud und agents-cli deploy ausgeführt werden

compute

Erstellt das Compute Engine-Standarddienstkonto, das für die Bereitstellung in Schritt 7 verwendet wird.

storage, logging, cloudtrace

Speicher, Logs und Traces, wie im Einrichtungsleitfaden für die Agent Runtime empfohlen

cloudbuild, artifactregistry

Container-Builds und -Images, die vorsorglich für die Bereitstellung in Schritt 7 enthalten sind

In vielen Projekten sind einige davon bereits aktiviert. Wenn Sie eine bereits aktivierte API aktivieren, ändert sich nichts.

uv und agents-cli installieren

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

Dieses Codelab wurde mit agents-cli 1.10.0 getestet. Installieren Sie diese Version, um dieselben generierten Dateien zu erhalten.

3. 3. Projekte strukturieren und Assets hinzufügen

Beide Projekte generieren

agents-cli scaffold create generiert ein vollständiges, bereitstellbares ADK-Projekt. Führen Sie ihn zweimal aus, einmal für jedes Agentensystem.

Zuerst der Track-Planer:

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

Dann der Gatekeeper:

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

Flag

Bedeutung

--agent adk

Mit der Python-ADK-Vorlage beginnen

--deployment-target agent_runtime

Server und Konfiguration für Agent Runtime generieren

--prototype

CI/CD überspringen; Projekt minimal halten

--yes

Standardeinstellungen ohne Aufforderung akzeptieren

Layout ansehen

Das generierte Projekt sieht so aus. Sie bearbeiten nur die mit ✍️ gekennzeichneten Dateien:

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`

Eine Beschreibung aller generierten Dateien finden Sie im Leitfaden zur Agents CLI unter Projektstruktur.

Generierten KI-Agenten ausprobieren

Bevor Sie etwas ändern, führen Sie den Vorlagen-Agenten aus, um zu sehen, was das Gerüst bietet. Installieren Sie die Abhängigkeiten und starten Sie den lokalen Playground auf Port 8080:

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

Klicken Sie dazu in der Cloud Shell-Symbolleiste auf den Button Webvorschau (das Augensymbol oben rechts) und wählen Sie Vorschau auf Port 8080 aus.

Stellen Sie dem Vorlagen-Agenten im Playground eine Frage, die seine Tools beantworten können, z. B.:

What's the weather in San Francisco?

In der Seitenleiste werden alle Ereignisse angezeigt, einschließlich des get_weather-Toolaufrufs und des Ergebnisses. Sie verwenden dieselbe Ansicht später, um Ihre eigenen Agenten zu verfolgen.

Wenn Sie fertig sind, kehren Sie zum Terminal zurück und drücken Sie Strg + C, um den Playground zu beenden.

Formula E-Assets hinzufügen

Die Veranstaltungsortdaten, FIA-Regeln, das Physikskript, die Tools und die Bewertungs-Datasets sind nicht Teil der Lektion. Sie kopieren sie daher aus GitHub, anstatt sie einzugeben:

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 ist ein festes Release-Tag, sodass alle dieselben Dateien erhalten. $ASSETS wurde in Schritt 2 festgelegt und verweist auf den Ordner, den Sie gerade geklont haben.

Dadurch werden die folgenden Dateien hinzugefügt:

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

Installieren und testen

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

agents-cli install führt uv sync aus, um für jedes Projekt eine virtuelle Umgebung zu erstellen. Alle Unittests sollten erfolgreich sein.

4. 4. Skill zur FIA-Compliance schreiben

Ein Agenten-Skill bündelt Anweisungen, Referenzdokumente und Scripts in einem Ordner. Das SkillToolset des ADK lädt sie in drei Ebenen, sodass der KI-Agent nur das liest, was er benötigt:

Level

Datei

Wenn der Kundenservicemitarbeiter die Nachricht sieht

1

SKILL.md Vorspann (name, description)

Immer (einige Dutzend Tokens)

2

SKILL.md Körper

Wenn load_skill aufgerufen wird

3

references/, scripts/

Wenn load_skill_resource oder run_skill_script aufgerufen wird

Der Skill befindet sich in app/skills/, da die generierte Dockerfile nur app/ in das bereitgestellte Image kopiert.

Dateien der Stufe 3 ansehen

Sie haben die Dateien für Level 3 des Skills in Schritt 3 kopiert:

  • references/track_regulations.md enthält die Regeln, die der Assessor prüft: Längen- und Breitenbeschränkungen, welche Barriere jede Bremszone benötigt, die obligatorischen CAD-Ebenen (plus medizinische Ebenen für Krankenhausrouten), das Regenerationsziel und die Regeln für den Attack Mode.
  • scripts/calculate_regen_zones.py ist ein Rechner. Anhand der Einfahrtsgeschwindigkeit, der Ausfahrtsgeschwindigkeit und des Bremswegs einer Bremszone werden die zurückgewonnene Energie und die erforderliche Barriere für die Kurve berechnet. Der Agent muss also nie die Physik erraten.

Führen Sie das Skript für Kurve 10 in London aus, wo Autos auf einer Strecke von 82 Metern von 215 auf 55 km/h abbremsen:

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

Das Auto gewinnt hier etwa 508 kW zurück, was über dem Ziel von 250 kW liegt. Bei mehr als 2G wird es langsamer, daher sind Tecpro-Barrieren (F1_TEC3) erforderlich:

{"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 schreiben

Erstellen Sie die Datei, die den Skill zusammenführt:

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

Fügen Sie Folgendes hinzu:

---
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.

Die description wird vom Modell gelesen, um zu entscheiden, wann der Skill verwendet werden soll. Sie gibt also an, was der Skill abdeckt und wann er verwendet werden soll.

Ansehen, wie der Skill verknüpft ist

Öffnen Sie app/tools.py im Cloud Shell-Editor:

cloudshell edit app/tools.py

Suchen Sie die Funktion 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 liest den Skill-Ordner: SKILL.md, references/ und scripts/.
  • SkillToolset wandelt sie in Tools um, die der Agent aufrufen kann: list_skills, load_skill, load_skill_resource und run_skill_script.
  • UnsafeLocalCodeExecutor ermöglicht run_skill_script, das Python-Skript auf diesem Computer auszuführen. Für ein Lab ist das in Ordnung. Verwenden Sie in der Produktion einen Executor in einer Sandbox.

Im nächsten Schritt hängen Sie dieses Toolset an den Assessor an.

5. 5. Agenten schreiben

Gemini 3-Modelle steuern das logische Denken mit thinking_level (LOW, MEDIUM oder HIGH) anstelle eines Token-Budgets. Im ADK legen Sie sie mit types.ThinkingConfig(thinking_level=types.ThinkingLevel.HIGH) fest. Passen Sie ihn an die Aufgabe des jeweiligen Agenten an: Mehr Denkarbeit bedeutet bessere Planung, aber auch mehr Latenz und höhere Kosten.

Der Gatekeeper (LOW)

Der Gatekeeper führt nur eine deterministische Checkliste aus und benötigt daher nur wenig logisches Denken. Ersetzen Sie den Vorlagen-Agenten:

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 lokal ausführen

Öffnen Sie einen zweiten Cloud Shell-Tab und starten Sie den generierten Gatekeeper-Server an Port 8001:

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

Sehen Sie sich im ersten Tab die A2A-Agentenkarte des Gatekeepers an. So erfahren andere Agenten, was der Gatekeeper ist und was er kann:

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

Sie sollten JSON-Code wie diesen sehen (gekürzt):

{
  "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 und description stammen direkt aus Ihrer Agent(...)-Definition.
  • skills listet auf, was der Agent tun kann. Das ADK hat verify_infrastructure_checklist automatisch mithilfe des Docstrings des Tools hinzugefügt.
  • supportedInterfaces teilt Aufrufern mit, wohin A2A-Anfragen gesendet werden sollen. Deshalb haben Sie den Server mit APP_URL=http://localhost:8001 gestartet: Ein Aufrufer liest zuerst die Karte und sendet dann seine Anfragen an die url, die auf der Karte angegeben ist.

Nichts davon wurde manuell geschrieben: Der Scaffold-Server erstellt die Karte aus Ihrem KI-Agenten. Der Track Planner liest diese Karte, um den Gatekeeper zu finden und aufzurufen.

Der Assessor (MEDIUM) und der leitende Architekt (HIGH)

Der Track Planner hat zwei Agenten:

  • Der Assessor wägt mehrere Regeln ab und erhält daher MEDIUM. Er ist in einen AgentTool eingebunden, sodass der Lead Architect ihn wie eine Funktion aufruft und das Ergebnis zurückerhält.
  • Der Lead Architect plant, behebt und koordiniert, damit es HIGH wird. Sie erreicht den Gatekeeper über einen RemoteA2aAgent, der von create_remote_gatekeeper_agent() in app/auth.py erstellt wurde, und wird außerdem in einen AgentTool verpackt.

Warum sollten beide Hilfsprogramme als Tools verpackt werden? Ein AgentTool gibt seine Antwort an den Aufrufer zurück, sodass der Lead Architect die Kontrolle behält und den endgültigen Plan erstellt. Wenn der Gatekeeper stattdessen ein sub_agent wäre, würde der Lead Architect die Unterhaltung an ihn übergeben und der kurze Status des Gatekeepers würde zur endgültigen Antwort werden.

Öffnen Sie die app/agent.py-Datei des Track-Planers:

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

Kopieren Sie den folgenden Code und ersetzen Sie den gesamten Inhalt von ~/track-planner/app/agent.py damit:

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

Das gesamte System im Playground ausführen

Prüfen Sie, ob der Gatekeeper im zweiten Tab noch ausgeführt wird. Starten Sie im ersten Tab den Playground des Track-Planers:

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

Klicken Sie wie in Schritt 3 auf Webvorschau > Vorschau auf Port 8080.

Fragen Sie nach einer Rennstrecke an einem Veranstaltungsort, die die folgenden Regeln erfüllt:

Design and homologate a Formula E circuit at Tokyo Bay.

Beobachten Sie das Ereignissteuerfeld, während die KI-Agenten arbeiten. Sie sollten Folgendes sehen:

  1. get_track_topology: Der leitende Architekt lädt die Daten für die Bucht von Tokio.
  2. fia_assessor: Der Lead Architect übergibt das Layout an den Assessor, der load_skill, load_skill_resource und run_skill_script (einmal pro Bremszone) und dann evaluate_track_layout aufruft.
  3. remote_gatekeeper: Der Lead Architect ruft den Gatekeeper über A2A auf. Die Anfrage wird auf dem zweiten Tab protokolliert.
  4. Einen endgültigen Plan des leitenden Architekten, in dem alle CAD-Ebenen und der Status GENEHMIGT des Gatekeepers aufgeführt sind.

Klicken Sie auf ein Ereignis, um die genauen Ein- und Ausgaben aufzurufen.

Starten Sie jetzt eine neue Sitzung und probieren Sie einen Veranstaltungsort aus, der gegen die Regeln verstößt:

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

Dieses Mal lehnt der Assessor die 6,8 m breite Schikane ab, der Lead Architect schlägt eine breitere vor und das feste Layout geht zurück an den Assessor, bevor es den Gatekeeper erreicht.

Wenn Sie fertig sind, drücken Sie im ersten Tab Strg + C, um den Playground zu beenden. Lassen Sie Gatekeeper im zweiten Tab laufen. Sie benötigen ihn im nächsten Schritt.

6. 6. KI-Agenten bewerten

agents-cli eval run führt Ihren Agenten für ein Dataset aus, zeichnet jede Runde und jeden Toolaufruf auf und bewertet die Ergebnisse. Sie entscheiden, was in tests/eval/eval_config.yaml gemessen werden soll.

Dataset ansehen

Öffnen Sie das Dataset im Cloud Shell-Editor:

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

Die Datei enthält eine Liste von eval_cases. Jeder Fall hat eine eval_case_id, eine prompt (was der Nutzer fragt) und eine reference (wie eine gute Antwort aussieht). Der LLM-Judge vergleicht die Antwort des Agenten mit der Referenz.

eval_case_id

Was wird getestet?

fe_001_tokyo_compliant

Ein Veranstaltungsort, der alle Regeln erfüllt und genehmigt wird

fe_002_monaco_narrow

Die 6,8 m breite Schikane verstößt gegen die Breitenregel.

fe_003_berlin_too_long

Die 4.350 m lange Strecke verstößt gegen die Längenregel.

fe_004_missing_layers

Ein Layout, in dem obligatorische CAD-Ebenen fehlen

fe_005_low_regen

Eine Bremszone unter dem Zielwert von 250 kW

fe_006_sao_paulo_medical

Krankenhauszugang, für den medizinische CAD-Ebenen erforderlich sind

fe_007_attack_mode

Eine Attack-Mode-Zone auf der Rennlinie

fe_008_multiturn_remediation

Eine Multi-Turn-Unterhaltung: Monaco wird abgelehnt, der Nutzer bittet um eine Korrektur und das korrigierte Layout sollte genehmigt werden.

Im letzten Fall wird agent_data anstelle von prompt verwendet. Dabei werden die vorherigen Runden einer Unterhaltung wiederholt, sodass Sie testen können, wie der Agent mit einer Folgeanfrage umgeht, nicht nur mit einer einzelnen Frage.

track_eval_quick.json im selben Ordner enthält nur zwei Fälle: Fall 1 (eine einzelne Frage) und Fall 8 (eine Unterhaltung). Sie führen diese Abfrage aus, weil sie schneller ist und weniger Kontingent verbraucht.

Messwerte schreiben

Der Datensatz gibt an, was der KI-Agent gefragt werden soll. eval_config.yaml erklärt, wie die Antworten bewertet werden. agents-cli eval run liest sie, nachdem der KI-Agent alle Fälle beantwortet hat, und führt jeden Messwert für jede Antwort aus.

Öffnen Sie die vom Scaffold generierte Datei:

cloudshell edit tests/eval/eval_config.yaml

Sie enthält bereits einen generischen LLM-Judge (custom_response_quality) und einen agent_turn_count-Messwert, der nur die Turns zählt. Das ist ein guter Anfang für jeden Agenten, sagt aber nichts über die Formel E aus. Sie behalten den Judge bei und fügen einen Messwert hinzu, der eine für diese Domain spezifische Regel prüft.

Gute Bewertungen kombinieren in der Regel zwei Arten von Messwerten:

Art

Bewertung

Geeignet für

Kompromiss

LLM-as-a-judge

Ein Modell liest die Antwort und die reference des Falls und gibt dann eine Bewertung von 1 bis 5 mit einer Erklärung ab

Fuzzy-Qualitäten: Ist die Antwort korrekt, vollständig und klar?

Kostet einen Modellaufruf pro Fall; die Punktzahlen können zwischen den Ausführungen leicht variieren

Code-Messwert

Eine kleine Python-Funktion prüft die Antwort.

Genaue, überprüfbare Fakten: Enthielt die Antwort etwas, das vorhanden sein muss?

Prüft nur, was Sie im Code ausdrücken können

Ersetzen Sie den Inhalt der Datei durch:

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

Funktion der einzelnen Teile:

  • metrics_to_run listet die auszuführenden Messwerte nach Name auf. Wenn Sie hier einen Namen entfernen, wird der entsprechende Messwert deaktiviert, aber nicht gelöscht.
  • custom_response_quality ist der LLM-Judge. custom_function_file verweist auf tests/eval/response_quality.py, das vom Scaffold generiert wurde. Öffnen Sie ihn, wenn Sie den Prompt für die Bewertung sehen möchten.
  • fia_cad_layer_compliance ist Ihr Codemesswert, der inline unter custom_function geschrieben wird. Für jeden Fall erhält es ein instance (den Prompt, die endgültige response des Agenten und die reference). Wenn die erwartete Antwort eine Genehmigung ist, wird geprüft, ob in der Antwort alle vier obligatorischen CAD-Ebenen genannt werden und ob fehlende Ebenen aufgeführt sind. Ein Blueprint, in dem beispielsweise F1_TEC3 fehlt, erhält die Punktzahl 0,75. Andere Fälle erhalten die Punktzahl 1,0, da bei einer Ablehnung oder einer Antwort im Angriffsmodus nicht jede Ebene aufgeführt werden muss.

Warum CAD-Ebenen prüfen? Ein genehmigter Blueprint, in dem eine obligatorische Ebene fehlt, ist falsch, auch wenn er gut lesbar ist. Ein LLM-Judge kann das übersehen. Bei einer Codeüberprüfung wird dieselbe Regel bei jeder Ausführung auf dieselbe Weise angewendet.

Bewertung ausführen

Lassen Sie den lokalen Gatekeeper im zweiten Tab laufen und führen Sie dann Folgendes aus:

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

Die Bewertung dauert einige Minuten. In jedem Fall wird der gesamte Multi-Agenten-Ablauf ausgeführt, etwa zehn Modellaufrufe mit dem Lead Architect auf HIGH, sodass Step 1/2: eval generate der langsame Teil ist. Es ist nicht hängengeblieben.

Öffnen Sie nach Abschluss den HTML-Bericht in artifacts/grade_results/ mit dem Cloud Shell-Editor. Niedrige fia_cad_layer_compliance-Werte weisen darauf hin, dass in der endgültigen Antwort des Lead Architect Ebenen fehlen. Versuchen Sie, die Anweisung zu präzisieren, und führen Sie die Bewertung noch einmal aus.

7. 7. Gatekeeper in Agent Runtime bereitstellen

Sie stellen nur den Gatekeeper bereit. Der Track Planner wird weiterhin in Cloud Shell ausgeführt und ruft die Funktion auf.

Neuen Tab in Cloud Shell öffnen

Die Bereitstellung dauert 5 bis 8 Minuten. Führen Sie sie daher in einem neuen Tab aus, während die Bewertung aus Schritt 6 abgeschlossen wird:

  1. Klicken Sie in der Cloud Shell-Symbolleiste auf Neuen Tab öffnen (+).
  2. In einem neuen Tab werden die Variablen aus Schritt 2 nicht beibehalten. Legen Sie sie daher noch einmal fest:
    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"
    

Lassen Sie den lokalen Gatekeeper im zweiten Tab laufen: Er wird für die Bewertung weiterhin verwendet und muss für die Bereitstellung nicht gestoppt werden.

Bereitstellen

Stellen Sie Gatekeeper im neuen Tab bereit. Sie wird als Compute Engine-Standarddienstkonto des Projekts ausgeführt:

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

Die Bereitstellung dauert etwa 5 bis 8 Minuten. Schließen Sie den Cloud Shell-Tab nicht, während der Befehl ausgeführt wird. Wenn die Verbindung zum Logstream getrennt wird, können Sie den Fortschritt mit agents-cli deploy --status prüfen. In der Zwischenzeit können Sie zu Schritt 6 zurückkehren und den Bewertungsbericht lesen.

Identität des KI-Agenten prüfen

agents-cli zeichnet die bereitgestellte Ressource in deployment_metadata.json auf:

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

Die zweite Zeile der Ausgabe ist die Identität, unter der Gatekeeper ausgeführt wird:

Bereitgestellt mit

Beispielausgabe

Das Dienstkonto (Standard)

123456789012-compute@developer.gserviceaccount.com

Agentenidentität

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

Das Dienstkonto wird von allen Elementen im Projekt gemeinsam genutzt, die es verwenden. Eine Agentenidentität gehört zu diesem einen KI-Agenten. Sie können ihm also genau die Rollen zuweisen, die er benötigt, und seine Aktionen separat in Audit-Logs einsehen.

8. 8. Über A2A eine Verbindung zum bereitgestellten Gatekeeper herstellen

Die Agent Runtime stellt die vom Gatekeeper generierten A2A-Routen hinter einem authentifizierten /api-Pfad bereit.

Prüfen Sie, ob die Auswertung aus Schritt 6 abgeschlossen ist, und beenden Sie dann den lokalen Gatekeeper im zweiten Tab (Strg + C). Ab jetzt ruft der Track Planner die bereitgestellte Version auf. Richten Sie den Track Planner im ersten Tab darauf aus:

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

Warum der Client sein Token aktualisiert

Öffnen Sie app/auth.py. Google Cloud-Zugriffstokens laufen nach einer Stunde ab. Ein Client, der beim Start einen festen Authorization-Header festlegt, schlägt daher nach einer Stunde mit 401 Unauthorized fehl. GoogleAuthRefresh ist eine Unterklasse von httpx.Auth und prüft die Anmeldedaten bei jeder Anfrage. Bei Bedarf werden sie aktualisiert. create_remote_gatekeeper_agent() hängt ihn nur an https://-URLs an.

End-to-End-Ausführung

Starten Sie den Playground neu, damit die neue GATEKEEPER_A2A_URL übernommen wird:

agents-cli playground --port 8080

Klicken Sie auf Webvorschau > Vorschau auf Port 8080, starten Sie eine neue Sitzung und fragen Sie:

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

Die Ereignisse sehen genauso aus wie in Schritt 5, aber der remote_gatekeeper-Aufruf geht jetzt an den Gatekeeper in der Agent Runtime und nicht an Ihren zweiten Tab.

Anruf in der Agent Runtime ansehen

Weisen Sie nach, dass die Anfrage den bereitgestellten Gatekeeper über A2A tatsächlich erreicht hat:

  1. Suchen Sie in der Cloud Console nach Agent Platform und öffnen Sie dann im Menü auf der linken Seite Bereitstellungen.
  2. Wählen Sie Gatekeeper aus.
  3. Öffnen Sie den Tab Sitzungen.

Sie sehen eine neue Sitzung, deren User-ID mit A2A_USER_ beginnt. Der A2A-Server des Gatekeepers hat sie erstellt, als dein Track-Planer sie aufgerufen hat. Öffnen Sie auf derselben Seite den Tab Traces, um den Modellaufruf des Gatekeepers und den verify_infrastructure_checklist-Toolaufruf für diese Anfrage zu sehen.

Optional: Track Planner ebenfalls bereitstellen

Bisher wird der Track Planner in Cloud Shell ausgeführt, sodass für die A2A-Aufrufe an den Gatekeeper Ihre Anmeldedaten verwendet werden. Stellen Sie auch den Planer bereit. Beide Agenten werden in der Agent Runtime ausgeführt und rufen sich gegenseitig mit ihren eigenen bereitgestellten Identitäten auf.

Drücken Sie Strg + C, um den Playground zu beenden, und stellen Sie dann den Planer auf dieselbe Weise wie den Gatekeeper bereit:

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

Beide Agents werden als dasselbe Compute Engine-Dienstkonto ausgeführt. Behalten Sie --service-account bei. Ohne diese Angabe wird der Planer als Standard-Dienst-Agent von Agent Runtime ausgeführt und kann den Gatekeeper nicht aufrufen (siehe Warum dieses Dienstkonto? in Schritt 7).

So erreicht der bereitgestellte Planer den Gatekeeper:

  • agents-cli deploy kopiert die Werte in .env in das Deployment, sodass der Planer die oben hinzugefügte GATEKEEPER_A2A_URL erhält.
  • In der Agent Runtime übernimmt GoogleAuthRefresh in app/auth.py die bereitgestellte Identität des Planers anstelle Ihrer.

Die Bereitstellung dauert etwa 5 bis 8 Minuten. Prüfen Sie nach Abschluss, mit welcher Identität der Planer ausgeführt wird:

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

So testen Sie das bereitgestellte System:

  1. Kehren Sie in der Cloud Console zu Agent Platform > Bereitstellungen zurück.
  2. Wählen Sie track-planner aus und öffnen Sie den Tab Playground.
  3. Geben Sie Folgendes ein:
    Design and homologate a Formula E circuit at Tokyo Bay.
    
  4. Warten Sie auf den Blueprint mit dem Gatekeeper-Status APPROVED.
  5. Kehren Sie zu Bereitstellungen zurück, wählen Sie gatekeeper aus und öffnen Sie den Tab Sitzungen. Die neueste A2A_USER_-Sitzung stammt vom bereitgestellten Planer, nicht von Cloud Shell.

Löschen Sie beim Bereinigen im nächsten Schritt auch den Planer:

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

9. 9. Fehlerbehebung und Bereinigung

Fehlerbehebung

Symptom

Korrigieren

UREQ_TOS_NOT_ACCEPTED

Akzeptieren Sie die Nutzungsbedingungen in der Cloud Console und versuchen Sie es dann noch einmal.

Projekt ist (unset)

Führen Sie die Projektbefehle in Schritt 2 noch einmal aus.

service account info is missing 'email' field

Führen Sie gcloud auth application-default login (Schritt 2) aus und starten Sie alle laufenden Server neu.

FileNotFoundError für SKILL.md

Führen Sie Schritt 4 aus oder kopieren Sie $ASSETS/solution/track-planner/. in ~/track-planner/.

Connection refused nach localhost:8001

Starten Sie den lokalen Gatekeeper (Schritt 5) oder legen Sie GATEKEEPER_A2A_URL auf den bereitgestellten Gatekeeper fest (Schritt 8).

Permission 'resourcemanager.projects.setIamPolicy' denied bei Bereitstellung

Ihr Konto kann die Agentenidentität nicht verwenden. Folgen Sie der Anleitung im Feld „Bereinigen“ in Schritt 7 und verwenden Sie dann das Dienstkonto für die Bereitstellung.

Der bereitgestellte Track Planner meldet 403 Forbidden vom Gatekeeper

Die Identität des Planers ist nicht berechtigt, den Gatekeeper aufzurufen. Stellen Sie sie wie in Schritt 7 mit --service-account oder mit --agent-identity bereit, wenn Sie der Inhaber des Projekts sind.

429 RESOURCE_EXHAUSTED

Sie haben das Gemini-Kontingent erreicht. Warte eine Minute oder füge --concurrency 1 --qps 2 zu agents-cli eval run hinzu.

Address already in use

Beenden Sie den anderen Server oder wählen Sie einen anderen --port aus.

Bereinigen

Löschen Sie den bereitgestellten Gatekeeper, damit er nicht weiter ausgeführt wird:

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"

Wenn Sie ein Projekt nur für dieses Codelab erstellt haben, können Sie stattdessen das gesamte Projekt löschen. Wenn Sie an einer Veranstaltung teilnehmen, behalten Sie das Projekt, das Sie erhalten haben, bis die Organisatoren etwas anderes sagen.

Das haben Sie gelernt

  • agents-cli scaffold create bietet Ihnen ein standardmäßiges, bereitstellbares ADK-Projekt. Sie müssen nur KI-Agenten, Skills und Bewertungen schreiben.
  • Mit Agent Skills bleibt Fachwissen so lange aus Prompts heraus, bis der Agent es benötigt.
  • Mit thinking_level können Sie die Tiefe der Argumentation gegen die Geschwindigkeit pro Agent abwägen.
  • agents-cli eval run wandelt die Frage „Funktioniert es?“ in messbare Werte um.
  • Agent Identity und A2A ermöglichen es unabhängig voneinander bereitgestellten KI-Agenten, sicher zusammenzuarbeiten.

Weitere Informationen