1. 1. Przegląd
W tym ćwiczeniu utworzysz system wieloagentowy, który projektuje tor uliczny Formuły E i zatwierdza go zgodnie z uproszczonym zestawem przepisów FIA.
Użyjesz agents-cli do wygenerowania 2 standardowych projektów pakietu Agent Development Kit (ADK), a następnie napiszesz najważniejsze części: umiejętność agenta, 3 agentów i ocenę. Wszystko inne (układ projektu, serwer, zależności, konfiguracja wdrożenia) pochodzi z interfejsu wiersza poleceń.
Nie znasz Formuły E?
Nie musisz znać się na sportach motorowych. Wystarczy tych 5 haseł:
- Formuła E: mistrzostwa FIA w wyścigach samochodów elektrycznych. Większość wyścigów odbywa się na tymczasowych torach ulicznych w centrach miast.
- Homologacja: oficjalne zatwierdzenie przez FIA, że tor jest bezpieczny do wyścigów. Bez homologacji nie ma wyścigu.
- Hamowanie regeneracyjne: gdy samochód hamuje, silniki ładują akumulator. Mocniejsze hamowanie pozwala odzyskać więcej energii, dlatego reguły tego ćwiczenia wymagają co najmniej 1 strefy mocnego hamowania.
- Warstwy CAD: nazwane warstwy w rysunkach projektowych toru, takie jak linia wyścigowa, aleja serwisowa i bariery. FIA sprawdza, czy są tam te obowiązkowe.
- Tryb ataku: kierowcy otrzymują tymczasowe zwiększenie mocy, gdy przejeżdżają przez strefę aktywacji umieszczoną poza linią wyścigu.
Agenty odgrywają obie role: jeden projektuje tor, a drugi sprawdza go pod kątem zgodności z wymaganiami FIA.
Co utworzysz
Zielone pola to agenty, a pola z przerywaną linią to ich narzędzia, tak samo jak w przypadku ADK Playground. Dwa narzędzia opakowują innych agentów: fia_assessor to agent FIA Assessor z umiejętnością zgodności z FIA, a remote_gatekeeper wywołuje agenta Gatekeeper w innym projekcie przez A2A.
Agent | Projekt | Zadanie |
|
Główny architekt |
| Odczytuje miejsce, pyta rzeczoznawcę, rozwiązuje problemy, prosi strażnika o zatwierdzenie |
|
Asesor FIA |
| Sprawdza układ za pomocą umiejętności FIA i narzędzia do oceny. |
|
Digital Twin Gatekeeper |
| Uruchamia końcową listę kontrolną homologacji |
|
Czego się nauczysz
- jak
agents-cli scaffold createukłada projekt ADK i które pliki edytujesz; - Jak spakować wiedzę o domenie jako umiejętność agenta (
SKILL.md,references/,scripts/) i wczytać ją za pomocąSkillToolsetADK. - Jak dopasować
thinking_leveldo zadania każdego agenta. - Jak oceniać agentów za pomocą
agents-cli eval run. - Jak wdrożyć agenta w Agent Runtime, czym Agent Identity różni się od konta usługi i jak wywołać wdrożonego agenta za pomocą protokołu A2A.
2. 2. Konfigurowanie środowiska
Zanim zaczniesz
Potrzebujesz projektu Google Cloud z włączonymi płatnościami. Jeśli wykonujesz ten ćwiczenie w ramach wydarzenia, użyj konta i projektu, które zostały Ci udostępnione.
Otwieranie Cloud Shell i ustawianie projektu
Otwórz Cloud Shell i uruchom:
# 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"
Tworzenie danych logowania dla agentów
gcloud jest już zalogowany, ale kod Pythona, który uruchamiają Twoi agenci, używa domyślnego uwierzytelniania aplikacji (ADC), które wymaga osobnego logowania:
gcloud auth application-default login
Otwórz wyświetlony link, zaloguj się na to samo konto, skopiuj kod i wklej go z powrotem w Cloud Shell. Następnie ustaw projekt, w którym rozliczany jest limit:
gcloud auth application-default set-quota-project "$GOOGLE_CLOUD_PROJECT"
Włączanie interfejsów 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
Do czego służą poszczególne interfejsy API:
Interfejsy API | Używane dla |
| Modele Gemini i Agent Runtime |
| kontrole projektu i uprawnień, które wykonują |
| tworzy domyślne konto usługi Compute Engine, którego używa wdrożenie w kroku 7; |
| miejsce na dane, logi i logi czasu zgodnie z zaleceniami w przewodniku po konfiguracji Agent Runtime. |
| kompilacje i obrazy kontenerów, które są uwzględniane jako środek ostrożności na potrzeby wdrożenia w kroku 7; |
Wiele projektów ma już włączone niektóre z tych funkcji. Włączenie interfejsu API, który jest już włączony, niczego nie zmienia.
Instalowanie aplikacji uv i rozszerzenia 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
To ćwiczenie zostało przetestowane z narzędziem agents-cli w wersji 1.10.0, więc zainstaluj tę wersję, aby uzyskać takie same wygenerowane pliki.
3. 3. Tworzenie projektów i dodawanie zasobów
Wygeneruj oba projekty
agents-cli scaffold create generuje kompletny projekt ADK, który można wdrożyć. Uruchom go 2 razy, po jednym dla każdego systemu agenta.
Najpierw planer ścieżki:
cd ~
agents-cli scaffold create track-planner \
--agent adk \
--deployment-target agent_runtime \
--region "$REGION" \
--prototype \
--yes
Następnie osoba pracująca w recepcji/sekretariacie:
cd ~
agents-cli scaffold create gatekeeper \
--agent adk \
--deployment-target agent_runtime \
--region "$REGION" \
--prototype \
--yes
Flaga | Znaczenie |
| Zacznij od szablonu ADK w Pythonie |
| Generowanie serwera i konfiguracji dla środowiska wykonawczego agenta |
| Pomiń CI/CD; zachowaj minimalny rozmiar projektu |
| Zaakceptuj wartości domyślne bez wyświetlania prośby |
Przeglądanie układu
Wygenerowany projekt wygląda tak. Edytuj tylko pliki oznaczone symbolem ✍️:
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`
Opis każdego wygenerowanego pliku znajdziesz w sekcji Struktura projektu w przewodniku po interfejsie wiersza poleceń agentów.
Testowanie wygenerowanego agenta
Zanim wprowadzisz jakiekolwiek zmiany, uruchom agenta szablonu, aby zobaczyć, co daje szkielet. Zainstaluj zależności i uruchom lokalne środowisko testowe na porcie 8080:
cd ~/track-planner
agents-cli install
agents-cli playground --port 8080
Aby go otworzyć, kliknij przycisk Podgląd w przeglądarce na pasku narzędzi Cloud Shell (ikona oka w prawym górnym rogu), a następnie wybierz Podejrzyj na porcie 8080.
W środowisku testowym zadaj agentowi szablonu pytanie, na które jego narzędzia mogą odpowiedzieć, na przykład:
What's the weather in San Francisco?
W panelu bocznym wyświetlane są wszystkie zdarzenia, w tym wywołanie narzędzia get_weather i jego wynik. Później użyjesz tego samego widoku, aby śledzić własnych agentów.
Gdy skończysz, wróć do terminala i naciśnij Ctrl+C, aby zatrzymać środowisko testowe.
Dodaj zasoby Formuły E
Dane o miejscu, zasady FIA, skrypt fizyki, narzędzia i zbiory danych do oceny nie są częścią lekcji, więc skopiuj je z GitHuba, zamiast je wpisywać:
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 to stały tag wersji, więc wszyscy otrzymują te same pliki. Zmienna $ASSETS została ustawiona w kroku 2 i wskazuje folder, który właśnie został sklonowany.
Spowoduje to dodanie tych plików:
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
Instalowanie i testowanie
(cd ~/track-planner && agents-cli install && uv run pytest tests/unit)
(cd ~/gatekeeper && agents-cli install && uv run pytest tests/unit)
agents-cli install uruchamia uv sync, aby utworzyć środowisko wirtualne dla każdego projektu. Wszystkie testy jednostkowe powinny zakończyć się powodzeniem.
4. 4. Napisz umiejętność zgodności z FIA
Umiejętność agenta zawiera instrukcje, dokumenty referencyjne i skrypty w jednym folderze. SkillToolset ADK wczytuje go na 3 poziomach, dzięki czemu agent odczytuje tylko to, czego potrzebuje:
Poziom | Plik | Kiedy pracownik obsługi klienta widzi tę informację |
1 |
| Zawsze (kilkadziesiąt tokenów) |
2 |
| Gdy dzwoni do |
3 |
| Gdy wywołuje funkcję |
Umiejętność znajduje się w app/skills/, ponieważ wygenerowany plik Dockerfile kopiuje tylko app/ do wdrożonego obrazu.
Przeglądanie plików na poziomie 3
W kroku 3 skopiowano pliki poziomu 3 umiejętności:
references/track_regulations.mdzawiera reguły, które sprawdza rzeczoznawca: limity długości i szerokości, bariery wymagane w każdej strefie hamowania, obowiązkowe warstwy CAD (oraz warstwy medyczne w przypadku tras do szpitala), cel regeneracji i reguły trybu ataku.scripts/calculate_regen_zones.pyto kalkulator. Na podstawie prędkości wejścia w strefę hamowania, prędkości wyjścia i drogi hamowania oblicza odzyskaną energię i barierę, której wymaga zakręt, dzięki czemu agent nie musi zgadywać fizyki.
Uruchom skrypt dla zakrętu 10 w Londynie, gdzie samochody hamują z 215 do 55 km/h na odcinku 82 metrów:
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
Samochód odzyskuje tu około 508 kW, czyli więcej niż docelowe 250 kW. Zwalnia przy przeciążeniu powyżej 2 G, więc na zakręcie potrzebne są bariery 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"}
Zapisz: SKILL.md
Utwórz plik, który połączy umiejętność:
cloudshell edit app/skills/fia-compliance-skill/SKILL.md
Dodaj te treści:
---
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 to tekst, który model odczytuje, aby zdecydować, kiedy użyć umiejętności. Zawiera on informacje o tym, co obejmuje umiejętność i kiedy jej używać.
Zobacz, jak działa umiejętność
Otwórz plik app/tools.py w edytorze Cloud Shell:
cloudshell edit app/tools.py
Znajdź funkcję 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_dirodczytuje folder umiejętności:SKILL.md,references/iscripts/.SkillToolsetprzekształca je w narzędzia, które agent może wywołać:list_skills,load_skill,load_skill_resourceirun_skill_script.UnsafeLocalCodeExecutorumożliwiarun_skill_scripturuchomienie skryptu w Pythonie na tym komputerze. W środowisku laboratoryjnym jest to dopuszczalne, ale w środowisku produkcyjnym należy używać wykonawcy w trybie piaskownicy.
W następnym kroku dołączysz ten zestaw narzędzi do narzędzia do oceny.
5. 5. Pisanie agentów
Modele Gemini 3 kontrolują rozumowanie za pomocą thinking_level (LOW, MEDIUM lub HIGH) zamiast budżetu tokenów. W pakiecie ADK ustawiasz go za pomocą types.ThinkingConfig(thinking_level=types.ThinkingLevel.HIGH). Dopasuj go do zadania każdego agenta: więcej myślenia oznacza lepsze planowanie, ale też większy czas oczekiwania i koszt.
Asystent (LOW)
Gatekeeper wykonuje tylko deterministyczną listę kontrolną, więc nie wymaga dużego rozumowania. Zastąp agenta szablonu:
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",
)
Lokalne uruchamianie Gatekeepera
Otwórz drugą kartę Cloud Shell i uruchom wygenerowany serwer Gatekeepera na porcie 8001:
cd ~/gatekeeper
APP_URL=http://localhost:8001 uv run uvicorn app.fast_api_app:app --port 8001
Wróć na pierwszą kartę i spójrz na kartę agenta Gatekeepera w A2A. W ten sposób inne agenty dowiadują się, czym jest Gatekeeper i co potrafi:
curl -s http://localhost:8001/a2a/app/.well-known/agent-card.json | jq .
Powinien wyświetlić się taki obiekt JSON (skrócony):
{
"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 ..."}
]
}
- Wartości
nameidescriptionpochodzą bezpośrednio z definicjiAgent(...). skillszawiera listę działań, które może wykonać agent. Pakiet ADK automatycznie dodałverify_infrastructure_checklist, używając docstringu narzędzia.supportedInterfacesinformuje rozmówców, gdzie wysyłać żądania A2A. Dlatego serwer został uruchomiony zAPP_URL=http://localhost:8001: element wywołujący najpierw odczytuje kartę, a następnie wysyła żądania do dowolnegourl, który jest reklamowany na karcie.
Nic nie zostało napisane ręcznie: serwer szkieletowy tworzy kartę na podstawie agenta. Planista torów odczyta tę kartę, aby znaleźć i wezwać strażnika.
Asesor (MEDIUM) i główny architekt (HIGH)
Planer ścieżek ma 2 agenty:
- Asesor bierze pod uwagę kilka reguł, więc otrzymuje
MEDIUM. Jest on opakowany wAgentTool, więc główny architekt wywołuje go jak funkcję i otrzymuje wynik. - Główny architekt planuje, naprawia i koordynuje, dzięki czemu
HIGH. Dociera do strażnika dostępu przezRemoteA2aAgent, utworzony przezcreate_remote_gatekeeper_agent()wapp/auth.py, i jest opakowany wAgentTool.
Dlaczego oba pomocniki są opakowane jako narzędzia? AgentTool zwraca odpowiedź elementowi wywołującemu, dzięki czemu główny architekt zachowuje kontrolę i tworzy ostateczny plan. Gdyby strażnik był sub_agent, główny architekt przekazałby mu rozmowę, a krótki stan strażnika stałby się ostateczną odpowiedzią.
Otwórz plik app/agent.py planera ścieżek:
cloudshell edit ~/track-planner/app/agent.py
Skopiuj poniższy kod i zastąp nim całą zawartość pliku ~/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",
)
Uruchamianie całego systemu w środowisku testowym
Upewnij się, że Gatekeeper nadal działa na drugiej karcie. Na pierwszej karcie uruchom środowisko testowe planisty ścieżek:
cd ~/track-planner
agents-cli playground --port 8080
Kliknij Podgląd w przeglądarce > Podejrzyj na porcie 8080, tak jak w kroku 3.
Poproś o tor w miejscu, które spełnia zasady:
Design and homologate a Formula E circuit at Tokyo Bay.
Obserwuj panel zdarzeń podczas pracy agentów. Powinny się wyświetlić kolejno:
get_track_topology: główny architekt wczytuje dane dotyczące Zatoki Tokijskiej.fia_assessor: główny architekt przekazuje układ rzeczoznawcy, który wywołujeload_skill,load_skill_resourceirun_skill_script(raz na strefę hamowania), a następnieevaluate_track_layout.remote_gatekeeper: główny architekt dzwoni do strażnika przez A2A. Żądanie pojawi się na drugiej karcie.- Ostateczny plan od głównego architekta, zawierający listę wszystkich warstw CAD i stan ZATWIERDZONY od strażnika.
Kliknij dowolne zdarzenie, aby zobaczyć jego dokładne dane wejściowe i wyjściowe.
Teraz rozpocznij nową sesję i wypróbuj miejsce, które narusza zasady:
Can the Monaco Harbour layout be homologated? If not, fix it and try again.
Tym razem rzeczoznawca odrzuca szykanę o szerokości 6,8 m, główny architekt proponuje szerszą, a poprawiony układ wraca do rzeczoznawcy, zanim trafi do strażnika.
Gdy skończysz, naciśnij Ctrl+C na pierwszej karcie, aby zatrzymać środowisko testowe. Pozostaw Gatekeepera uruchomionego na drugiej karcie – będzie Ci potrzebny w następnym kroku.
6. 6. Ocenianie agentów
agents-cli eval run uruchamia agenta na zbiorze danych, rejestruje każdą turę i wywołanie narzędzia oraz ocenia wyniki. To Ty decydujesz, co chcesz mierzyć w tests/eval/eval_config.yaml.
Przeglądanie zbioru danych
Otwórz zbiór danych w edytorze Cloud Shell:
cd ~/track-planner
cloudshell edit tests/eval/datasets/track_eval.json
Plik zawiera listę: eval_cases. Każdy przypadek ma eval_case_id, prompt (pytanie użytkownika) i reference (jak wygląda dobra odpowiedź). Sędzia LLM porównuje odpowiedź agenta z odpowiedzią wzorcową.
| Co sprawdza |
| Miejsce, które spełnia wszystkie reguły i zostaje zatwierdzone. |
| Szykana o szerokości 6,8 m nie spełnia reguły szerokości. |
| Obwód o długości 4350 m nie spełnia reguły dotyczącej długości. |
| Układ, w którym brakuje obowiązkowych warstw CAD |
| strefę hamowania poniżej docelowej wartości 250 kW, |
| Dostęp do szpitala wymagający warstw CAD dotyczących medycyny |
| Strefa trybu ataku na linii wyścigowej |
| Wieloetapowa rozmowa: Monaco zostaje odrzucone, użytkownik prosi o poprawkę, a poprawiony układ powinien zostać zatwierdzony. |
W ostatnim przypadku użyto agent_data zamiast prompt. Odtwarza wcześniejsze tury rozmowy, dzięki czemu możesz sprawdzić, jak agent radzi sobie z kolejnymi prośbami, a nie tylko z pojedynczym pytaniem.
track_eval_quick.json w tym samym folderze zawiera tylko 2 przypadki: przypadek 1 (pojedyncze pytanie) i przypadek 8 (rozmowa). Uruchomisz to zapytanie, ponieważ jest szybsze i zużywa mniej limitu.
Zapisywanie danych
Zbiór danych określa, o co należy zapytać agenta. eval_config.yaml podaje sposób oceniania odpowiedzi. agents-cli eval run odczytuje go po udzieleniu przez agenta odpowiedzi na wszystkie zgłoszenia i uruchamia każdy rodzaj danych dla każdej odpowiedzi.
Otwórz plik wygenerowany przez szablon:
cloudshell edit tests/eval/eval_config.yaml
Zawiera już ogólny sędziowski model LLM (custom_response_quality) i wskaźnik agent_turn_count, który zlicza tylko tury. To dobry początek dla każdego agenta, ale nie mówi nic o Formule E. Zachowasz sędziego i dodasz wskaźnik, który sprawdza regułę dotyczącą tej domeny.
Dobre oceny zwykle łączą 2 rodzaje danych:
Rodzaj | Sposób oceniania | Przeznaczenie | Słabsze strony |
LLM-as-a-judge | Model odczytuje odpowiedź i | Cechy rozmyte: czy odpowiedź jest poprawna, kompletna i jasna? | Kosztuje 1 wywołanie modelu na przypadek; wyniki mogą się nieznacznie różnić między uruchomieniami |
Dane dotyczące kodu | Niewielka funkcja Pythona sprawdza odpowiedź. | Dokładne, możliwe do sprawdzenia fakty: czy odpowiedź zawierała coś, co musi się w niej znaleźć? | Sprawdza tylko to, co można wyrazić w kodzie. |
Zastąp zawartość pliku tym kodem:
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"),
}
Co robi każda część:
metrics_to_runzawiera listę danych do uruchomienia według nazwy. Usunięcie nazwy w tym miejscu spowoduje wyłączenie tego wskaźnika bez jego usuwania.custom_response_qualityto sędzia LLM.custom_function_filepunktów wtests/eval/response_quality.py, które wygenerował szablon. Otwórz go, jeśli chcesz zobaczyć prompta do oceny.fia_cad_layer_complianceto wskaźnik kodu zapisany w tekście podcustom_function. W każdym przypadku otrzymujeinstance(prompt, ostateczną odpowiedź agentaresponseireference). W przypadkach, gdy oczekiwana odpowiedź jest zatwierdzeniem, sprawdza, czy odpowiedź zawiera nazwy wszystkich 4 wymaganych warstw CAD, i wymienia te, których brakuje. Na przykład plan, który pomijaF1_TEC3, otrzymuje wynik 0,75. Inne przypadki otrzymują wynik 1,0, ponieważ odrzucenie lub odpowiedź w trybie ataku nie muszą zawierać wszystkich warstw.
Dlaczego warto sprawdzać warstwy CAD? Zatwierdzony plan, który pomija obowiązkową warstwę, jest nieprawidłowy, nawet jeśli jest czytelny, a sędzia LLM może to przeoczyć. Sprawdzanie kodu stosuje tę samą regułę w ten sam sposób przy każdym uruchomieniu.
Przeprowadź ocenę
Pozostaw lokalną bramkę uruchomioną na drugiej karcie, a następnie uruchom:
agents-cli eval run \
--dataset tests/eval/datasets/track_eval_quick.json \
--config tests/eval/eval_config.yaml \
--concurrency 1
ls artifacts/grade_results/
Ocena zajmuje kilka minut. Każdy przypadek obejmuje cały proces z wieloma agentami, czyli około 10 wywołań modelu, przy czym główny architekt myśli w HIGH, więc Step 1/2: eval generate jest powolną częścią. Nie jest zablokowany.
Po zakończeniu otwórz raport HTML w artifacts/grade_results/ za pomocą edytora Cloud Shell. Niskie wyniki fia_cad_layer_compliance oznaczają, że ostateczna odpowiedź głównego architekta pomija warstwy. Spróbuj doprecyzować instrukcje i ponownie przeprowadzić ocenę.
7. 7. Wdrażanie Gatekeepera w Agent Runtime
Wdrażasz tylko Gatekeepera. Planer ścieżek nadal działa w Cloud Shell i wywołuje tę funkcję.
Otwieranie nowej karty Cloud Shell
Wdrażanie zajmuje od 5 do 8 minut, więc wykonaj je w nowej karcie, podczas gdy ocena z kroku 6 się kończy:
- Na pasku narzędzi Cloud Shell kliknij Otwórz nową kartę (+).
- Nowa karta nie zachowuje zmiennych z kroku 2, więc ustaw je ponownie:
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"
Pozostaw lokalną usługę Gatekeeper uruchomioną na drugiej karcie: ocena nadal z niej korzysta, a wdrożenie nie wymaga jej zatrzymania.
Wdróż
Na nowej karcie wdróż Gatekeepera. Działa jako domyślne konto usługi Compute Engine projektu:
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
Wdrażanie trwa około 5–8 minut. Nie zamykaj karty Cloud Shell podczas działania skryptu. Jeśli strumień logów zostanie rozłączony, sprawdź postęp za pomocą polecenia agents-cli deploy --status. W międzyczasie wróć do kroku 6 i zapoznaj się z raportem z oceny.
Sprawdzanie tożsamości agenta
agents-cli rejestruje wdrożony zasób w 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
Drugi wiersz danych wyjściowych to tożsamość, z którą działa Gatekeeper:
Wdrożono z użyciem: | Przykładowe dane wyjściowe |
Konto usługi (domyślne) |
|
Tożsamość agenta |
|
Konto usługi jest współdzielone przez wszystkie elementy w projekcie, które go używają. Tożsamość agenta należy do tego jednego agenta, więc możesz przyznać mu dokładnie te role, których potrzebuje, i osobno wyświetlać jego działania w dziennikach kontrolnych.
8. 8. Łączenie się z wdrożonym Gatekeeperem przez A2A
Agent Runtime obsługuje trasy A2A wygenerowane przez Gatekeepera za uwierzytelnioną ścieżką /api.
Upewnij się, że ocena z kroku 6 została zakończona, a następnie zatrzymaj lokalnego Gatekeepera na drugiej karcie (Ctrl+C). Od teraz narzędzie do planowania ścieżki będzie wywoływać wdrożoną wersję. Na pierwszej karcie skieruj na niego narzędzie do planowania ścieżki:
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
Dlaczego klient odświeża token
Otwórz pokój app/auth.py. Tokeny dostępu Google Cloud wygasają po godzinie, więc klient, który podczas uruchamiania ustawia stały nagłówek Authorization, po godzinie zaczyna zwracać błąd 401 Unauthorized. GoogleAuthRefresh jest podklasą httpx.Auth i sprawdza dane logowania przy każdym żądaniu, odświeżając je w razie potrzeby. create_remote_gatekeeper_agent() dołącza go tylko do adresów URL https://.
Uruchomienie od początku do końca
Ponownie uruchom środowisko testowe, aby uwzględnić nową wartość GATEKEEPER_A2A_URL:
agents-cli playground --port 8080
Kliknij Podgląd w przeglądarce > Podejrzyj na porcie 8080, rozpocznij nową sesję i zapytaj:
Assess the Monaco Harbour layout, widen the chicane to 11m, and get Gatekeeper approval.
Zdarzenia wyglądają tak samo jak w kroku 5, ale wywołanie remote_gatekeeper jest teraz kierowane do strażnika w środowisku wykonawczym agentów, a nie do drugiej karty.
Wyświetlanie połączenia przychodzącego w Agent Runtime
Udowodnij, że żądanie rzeczywiście dotarło do wdrożonego strażnika przez A2A:
- W konsoli Cloud wyszukaj Agent Platform, a następnie w menu po lewej stronie otwórz Wdrożenia.
- Wybierz gatekeeper.
- Otwórz kartę Sesje.
Zobaczysz nową sesję, której identyfikator użytkownika zaczyna się od A2A_USER_. Został on utworzony przez serwer A2A Gatekeepera, gdy wywołał go Twój planer ścieżki. Otwórz kartę Ślady na tej samej stronie, aby zobaczyć wywołanie modelu strażnika i wywołanie narzędzia verify_infrastructure_checklist dla tego żądania.
Opcjonalnie: wdróż też planowanie ścieżki
Do tej pory narzędzie do planowania ścieżek działało w Cloud Shell, więc jego wywołania A2A do Gatekeepera używały Twoich danych logowania. Wdróż też planistę. Obaj agenci będą działać w Agent Runtime i wywoływać się nawzajem za pomocą własnych wdrożonych tożsamości.
Naciśnij Ctrl+C, aby zatrzymać Playground, a następnie wdróż planner w taki sam sposób jak 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
Oba agenty działają jako to samo konto usługi Compute Engine. Zachowaj --service-account: bez tego moduł planujący działa jako domyślny agent usługi Agent Runtime i nie może wywołać Gatekeepera (patrz Dlaczego to konto usługi? w kroku 7).
Jak wdrożony planista dociera do osoby pracującej w recepcji/sekretariacie:
agents-cli deploykopiuje wartości z pliku.envdo wdrożenia, dzięki czemu planista otrzymuje dodany przez Ciebie parametrGATEKEEPER_A2A_URL.- W środowisku wykonawczym agentów
GoogleAuthRefreshwapp/auth.pyprzejmuje wdrożoną tożsamość planisty zamiast Twojej.
Wdrażanie trwa około 5–8 minut. Po zakończeniu sprawdź, z jaką tożsamością działa planista:
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
Aby wypróbować wdrożony system:
- W konsoli Cloud wróć do Agent Platform > Wdrożenia.
- Wybierz track-planner i otwórz kartę Playground.
- Wpisz:
Design and homologate a Formula E circuit at Tokyo Bay. - Poczekaj na schemat ze statusem APPROVED (Zatwierdzony) od strażnika.
- Wróć do sekcji Wdrożenia, wybierz gatekeeper i otwórz kartę Sesje. Najnowsza sesja
A2A_USER_pochodzi z wdrożonego planera, a nie z Cloud Shell.
Podczas czyszczenia w następnym kroku usuń też planistę:
curl -X DELETE -H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://${REGION}-aiplatform.googleapis.com/v1beta1/${PLANNER_ID}?force=true"
9. 9. Rozwiązywanie problemów i czyszczenie
Rozwiązywanie problemów
Krótki opis problemu | Napraw |
| Zaakceptuj Warunki korzystania z usługi w konsoli Cloud, a następnie spróbuj ponownie. |
Projekt: | Ponownie uruchom polecenia projektu z kroku 2. |
| Uruchom |
| Wykonaj krok 4 lub skopiuj |
Od | Uruchom lokalną bramę (krok 5) lub ustaw |
| Na Twoim koncie nie można używać tożsamości agenta. Wykonaj czynności opisane w polu czyszczenia w kroku 7, a następnie użyj wdrożenia konta usługi. |
Wdrożony moduł planowania ścieżki zgłasza | Tożsamość planisty nie może wywoływać strażnika. Wdróż ją ponownie za pomocą |
| Osiągnięto limit Gemini. Poczekaj chwilę lub dodaj |
| Zatrzymaj drugi serwer lub wybierz inny |
Czyszczenie danych
Usuń wdrożony kontroler Gatekeeper, aby nie działał dalej:
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"
Jeśli projekt został utworzony tylko na potrzeby tego codelab, możesz usunąć cały projekt. Jeśli jesteś na wydarzeniu, zachowaj otrzymany projekt, chyba że organizatorzy powiedzą inaczej.
Czego się nauczysz
agents-cli scaffold createudostępnia standardowy projekt ADK, który można wdrożyć. Musisz tylko napisać agentów, umiejętności i oceny.- Umiejętności agenta sprawiają, że wiedza o domenie nie jest uwzględniana w promptach, dopóki agent jej nie potrzebuje.
thinking_levelpozwala na kompromis między głębią rozumowania a szybkością działania poszczególnych agentów.agents-cli eval runprzekształca pytanie „Czy to działa?” w wyniki, które możesz śledzić.- Tożsamość agenta i A2A umożliwiają bezpieczną współpracę niezależnie wdrożonych agentów.