1. 1. Visão geral
Neste codelab, você vai criar um sistema multiagente que projeta um circuito de rua da Fórmula E e o aprova de acordo com um conjunto simplificado de regras da FIA.
Você vai usar o agents-cli para gerar dois projetos padrão do Kit de Desenvolvimento de Agente (ADK) e, em seguida, escrever as partes que importam: uma habilidade de agente, três agentes e uma avaliação. Todo o resto (layout do projeto, servidor, dependências, configuração de implantação) vem da CLI.
Não conhece a Fórmula E?
Você não precisa entender de automobilismo. Estes cinco termos são suficientes:
- Fórmula E: o campeonato de corrida totalmente elétrico da FIA. A maioria das corridas acontece em circuitos de rua temporários nos centros das cidades.
- Homologação: a aprovação oficial da FIA de que um circuito é seguro para corridas. Sem homologação, sem corrida.
- Frenagem regenerativa: quando o carro freia, os motores recarregam a bateria. Uma frenagem mais brusca recupera mais energia. Por isso, as regras deste codelab exigem pelo menos uma zona de frenagem brusca.
- Camadas de CAD: camadas nomeadas nos desenhos de design do circuito, como a linha de corrida, o pit lane e as barreiras. A FIA verifica se os obrigatórios estão presentes.
- Modo de ataque: os pilotos recebem um aumento temporário de potência ao passar por uma zona de ativação fora da linha de corrida.
Seus agentes jogam dos dois lados: um projeta o circuito e dois verificam se ele está de acordo com a FIA.
O que você criará
As caixas verdes são agentes, e as caixas tracejadas são as ferramentas deles, da mesma forma que o ADK Playground as desenha. Duas das ferramentas envolvem outros agentes: fia_assessor é o agente FIA Assessor com a habilidade de conformidade com a FIA, e remote_gatekeeper chama o agente Gatekeeper no outro projeto por A2A.
Agente | Projeto | Job |
|
Lead Architect |
| Lê o local, pergunta ao Assessor, corrige problemas, pede aprovação ao Gatekeeper |
|
Avaliador da FIA |
| Verifica o layout usando a habilidade de FIA e uma ferramenta de pontuação |
|
Gatekeeper do Gêmeo Digital |
| Executa a lista de verificação de homologação final |
|
O que você vai aprender
- Como o
agents-cli scaffold createorganiza um projeto do ADK e quais arquivos você edita. - Como empacotar o conhecimento de domínio como uma Habilidade do Agente (
SKILL.md,references/,scripts/) e carregá-lo com oSkillToolsetdo ADK. - Como associar
thinking_levelao job de cada agente. - Como avaliar agentes com o
agents-cli eval run. - Como implantar um agente no Agent Runtime, como a identidade do agente é diferente de uma conta de serviço e como chamar o agente implantado pelo protocolo A2A.
2. 2. Configurar o ambiente
Antes de começar
Você precisa de um projeto na nuvem do Google Cloud com o faturamento ativado. Se você estiver seguindo este codelab em um evento, use a conta e o projeto que recebeu.
Abrir o Cloud Shell e definir seu projeto
Abra o Cloud Shell e execute:
# 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"
Criar credenciais para seus agentes
A gcloud já está conectada, mas o código Python executado pelos agentes usa o Application Default Credentials (ADC), que precisa de um login separado:
gcloud auth application-default login
Abra o link que aparece, faça login com a mesma conta, copie o código e cole-o de volta no Cloud Shell. Em seguida, defina o projeto em que a cota é faturada:
gcloud auth application-default set-quota-project "$GOOGLE_CLOUD_PROJECT"
Ative as APIs
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
Para que serve cada API:
APIs | Usado para |
| Modelos do Gemini e Agent Runtime |
| As verificações de projeto e permissão que |
| Cria a conta de serviço padrão do Compute Engine que a implantação na Etapa 7 usa. |
| Armazenamento, registros e traces, conforme recomendado pelo guia de configuração do Agent Runtime |
| Compilações e imagens de contêiner, incluídas como precaução para a implantação na Etapa 7 |
Muitos projetos já têm algumas dessas opções ativadas. Ativar uma API que já está ativada não muda nada.
Instalar uv e 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
Este codelab foi testado com o agents-cli 1.10.0. Instale essa versão para receber os mesmos arquivos gerados.
3. 3. Criar o scaffold dos projetos e adicionar os recursos
Gerar os dois projetos
O agents-cli scaffold create gera um projeto do ADK completo e implantável. Execute-o duas vezes, uma para cada sistema de agente.
Primeiro, o planejador de trilhas:
cd ~
agents-cli scaffold create track-planner \
--agent adk \
--deployment-target agent_runtime \
--region "$REGION" \
--prototype \
--yes
Depois, o recepcionista:
cd ~
agents-cli scaffold create gatekeeper \
--agent adk \
--deployment-target agent_runtime \
--region "$REGION" \
--prototype \
--yes
Sinalização | Significado |
| Começar com o modelo do ADK para Python |
| Gerar o servidor e a configuração para o Agent Runtime |
| Pular CI/CD; manter o projeto mínimo |
| Aceitar os padrões sem solicitar |
Analisar o layout
O projeto gerado tem esta aparência. Você só edita os arquivos marcados com ✍️:
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`
Para uma descrição de cada arquivo gerado, consulte Estrutura do projeto no guia da CLI de agentes.
Testar o agente gerado
Antes de mudar qualquer coisa, execute o agente de modelo para ver o que o scaffold oferece. Instale as dependências e inicie o playground local na porta 8080:
cd ~/track-planner
agents-cli install
agents-cli playground --port 8080
Para abrir, clique no botão Visualização da Web na barra de ferramentas do Cloud Shell (o ícone de olho no canto superior direito) e selecione Visualizar na porta 8080.
No playground, faça ao agente de modelo uma pergunta que as ferramentas dele possam responder, por exemplo:
What's the weather in San Francisco?
O painel lateral mostra cada evento, incluindo a chamada de ferramenta get_weather e o resultado dela. Você vai usar a mesma visualização mais tarde para acompanhar seus próprios agentes.
Quando terminar, volte ao terminal e pressione Ctrl+C para interromper o playground.
Adicionar os recursos da Fórmula E
Os dados do local, as regras da FIA, o script de física, as ferramentas e os conjuntos de dados de avaliação não são a lição. Por isso, você vai copiá-los do GitHub em vez de digitá-los:
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 é uma tag de lançamento fixa, então todos recebem os mesmos arquivos. $ASSETS foi definido na Etapa 2 e aponta para a pasta que você acabou de clonar.
Isso adiciona os seguintes arquivos:
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
Instalar e testar
(cd ~/track-planner && agents-cli install && uv run pytest tests/unit)
(cd ~/gatekeeper && agents-cli install && uv run pytest tests/unit)
O agents-cli install executa o uv sync para criar um ambiente virtual para cada projeto. Todos os testes de unidade precisam ser aprovados.
4. 4. Escrever a habilidade de conformidade com a FIA
Uma habilidade de agente agrupa instruções, documentos de referência e scripts em uma pasta. O SkillToolset do ADK o carrega em três níveis, para que o agente leia apenas o que precisa:
Nível | Arquivo | Quando o agente vê |
1 |
| Sempre (algumas dezenas de tokens) |
2 | Corpo | Quando ele chama |
3 |
| Quando ele chama |
A habilidade está em app/skills/ porque o Dockerfile gerado só copia app/ para a imagem implantada.
Analisar os arquivos do nível 3
Você copiou os arquivos de nível 3 da habilidade na Etapa 3:
references/track_regulations.mdcontém as regras que o Assessor verifica: limites de comprimento e largura, qual barreira cada zona de frenagem precisa, as camadas CAD obrigatórias (além das camadas médicas para rotas hospitalares), a meta de regeneração e as regras do Modo de Ataque.scripts/calculate_regen_zones.pyé uma calculadora. Com base na velocidade de entrada, na velocidade de saída e na distância de frenagem de uma zona de frenagem, ele calcula a energia recuperada e a barreira que a curva precisa, para que o agente nunca precise adivinhar a física.
Execute o script para a curva 10 de Londres, em que os carros freiam de 215 para 55 km/h em 82 metros:
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
O carro recupera cerca de 508 kW aqui, acima da meta de 250 kW. Ele desacelera a mais de 2G, então a curva precisa de barreiras 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"}
Gravar SKILL.md
Crie o arquivo que une a habilidade:
cloudshell edit app/skills/fia-compliance-skill/SKILL.md
Adicione este conteúdo:
---
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.
O description é o que o modelo lê para decidir quando usar a habilidade. Por isso, ele informa o que a habilidade abrange e quando usá-la.
Veja como a habilidade está conectada
Abra app/tools.py no editor do Cloud Shell:
cloudshell edit app/tools.py
Encontre a função 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_dirlê a pasta de habilidades:SKILL.md,references/escripts/.- O
SkillToolsetas transforma em ferramentas que o agente pode chamar:list_skills,load_skill,load_skill_resourceerun_skill_script. UnsafeLocalCodeExecutorpermite querun_skill_scriptexecute o script Python nesta máquina. Isso é aceitável para um laboratório, mas use um executor em sandbox na produção.
Você vai anexar esse conjunto de ferramentas ao Assessor na próxima etapa.
5. 5. Escrever os agentes
Os modelos do Gemini 3 controlam o raciocínio com thinking_level (LOW, MEDIUM ou HIGH) em vez de um limite de tokens. No ADK, você define isso com types.ThinkingConfig(thinking_level=types.ThinkingLevel.HIGH). Combine isso com o trabalho de cada agente: mais reflexão significa um planejamento melhor, mas também mais latência e custo.
O Gatekeeper (LOW)
O Gatekeeper só executa uma lista de verificação determinística, então precisa de pouco raciocínio. Substitua o agente de modelo:
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",
)
Executar o Gatekeeper localmente
Abra uma segunda guia do Cloud Shell e inicie o servidor gerado pelo Gatekeeper na porta 8001:
cd ~/gatekeeper
APP_URL=http://localhost:8001 uv run uvicorn app.fast_api_app:app --port 8001
De volta à primeira guia, confira o card de agente A2A do Gatekeeper. É assim que outros agentes descobrem o que é o Gatekeeper e o que ele pode fazer:
curl -s http://localhost:8001/a2a/app/.well-known/agent-card.json | jq .
Você verá um JSON como este (abreviado):
{
"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 ..."}
]
}
nameedescriptionvêm diretamente da definição deAgent(...).skillslista o que o agente pode fazer. O ADK adicionouverify_infrastructure_checklistautomaticamente, usando a docstring da ferramenta.supportedInterfacesinforma aos autores das chamadas para onde enviar solicitações A2A. Por isso, você iniciou o servidor comAPP_URL=http://localhost:8001: um autor de chamada lê o cartão primeiro e, em seguida, envia as solicitações para qualquerurlque o cartão anunciar.
Nada aqui foi escrito à mão: o servidor estruturado cria o card com base no seu agente. O planejador de trajetos vai ler esse cartão para encontrar e chamar o Gatekeeper.
O avaliador (MEDIUM) e o arquiteto líder (HIGH)
O planejador de trajetos tem dois agentes:
- O Avaliador considera várias regras, então recebe
MEDIUM. Ele é encapsulado em umAgentTool, então o Lead Architect o chama como uma função e recebe o veredito de volta. - O arquiteto-chefe planeja, corrige e coordena, então ele recebe
HIGH. Ele chega ao Gatekeeper por umRemoteA2aAgent, criado porcreate_remote_gatekeeper_agent()emapp/auth.py, e também o envolve em umAgentTool.
Por que encapsular os dois auxiliares como ferramentas? Um AgentTool retorna a resposta ao autor da chamada, então o arquiteto principal continua no comando e escreve o projeto final. Se o Gatekeeper fosse um sub_agent, o Lead Architect entregaria a conversa para ele, e o status curto do Gatekeeper se tornaria a resposta final.
Abra o arquivo app/agent.py do planejador de trajetos:
cloudshell edit ~/track-planner/app/agent.py
Copie o código a seguir e substitua todo o conteúdo de ~/track-planner/app/agent.py por ele:
"""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",
)
Executar todo o sistema no playground
Verifique se o Gatekeeper ainda está em execução na segunda guia. Na primeira guia, inicie o playground do planejador de trajetos:
cd ~/track-planner
agents-cli playground --port 8080
Clique em Visualização na Web > Visualizar na porta 8080, como você fez na Etapa 3.
Peça um circuito em um local que atenda às regras:
Design and homologate a Formula E circuit at Tokyo Bay.
Observe o painel de eventos enquanto os agentes trabalham. Você vai ver, em ordem:
get_track_topology: o arquiteto-chefe carrega os dados da Baía de Tóquio.fia_assessor: o arquiteto-chefe entrega o layout ao avaliador, que chamaload_skill,load_skill_resourceerun_skill_script(uma vez por zona de frenagem) e, em seguida,evaluate_track_layout.remote_gatekeeper: o arquiteto líder chama o Gatekeeper pelo A2A. A solicitação vai aparecer registrada na segunda guia.- Um projeto final do arquiteto-chefe, listando todas as camadas de CAD e o status APROVADO do Gatekeeper.
Clique em qualquer evento para ver as entradas e saídas exatas.
Agora inicie uma nova sessão e tente um local que viole as regras:
Can the Monaco Harbour layout be homologated? If not, fix it and try again.
Desta vez, o avaliador rejeita a chicane de 6,8 m, o arquiteto líder propõe uma mais larga, e o layout corrigido volta para o avaliador antes de chegar ao gatekeeper.
Quando terminar, pressione Ctrl+C na primeira guia para interromper o playground. Deixe o Gatekeeper em execução na segunda guia: você vai precisar dele na próxima etapa.
6. 6. Avaliar os agentes
O agents-cli eval run executa o agente em um conjunto de dados, registra cada turno e chamada de ferramenta e avalia os resultados. Você decide o que medir no tests/eval/eval_config.yaml.
Analisar o conjunto de dados
Abra o conjunto de dados no editor do Cloud Shell:
cd ~/track-planner
cloudshell edit tests/eval/datasets/track_eval.json
O arquivo contém uma lista de eval_cases. Cada caso tem um eval_case_id, um prompt (o que o usuário pergunta) e um reference (como é uma boa resposta). O juiz LLM compara a resposta do agente com a referência.
| O que é testado |
| Um local que segue todas as regras e é aprovado |
| A chicane de 6,8 m não segue a regra de largura |
| O circuito de 4.350 m não obedece à regra de comprimento |
| Um layout sem as camadas CAD obrigatórias |
| Uma zona de frenagem abaixo da meta de 250 kW |
| Acesso ao hospital que precisa de camadas de CAD médico |
| Uma zona de Modo de Ataque na linha de corrida |
| Uma conversa com várias interações: o layout de Mônaco é rejeitado, o usuário pede uma correção e o layout corrigido é aprovado. |
O último caso usa agent_data em vez de prompt. Ele repete as interações anteriores de uma conversa para que você possa testar como o agente lida com uma solicitação de acompanhamento, não apenas com uma única pergunta.
track_eval_quick.json na mesma pasta contém apenas dois casos: o caso 1 (uma única pergunta) e o caso 8 (uma conversa). Você vai executar esse porque ele é mais rápido e usa menos cota.
Gravar as métricas
O conjunto de dados diz o que perguntar ao agente. eval_config.yaml diz como pontuar as respostas. O agents-cli eval run lê o arquivo depois que o agente responde a todos os casos e executa cada métrica em cada resposta.
Abra o arquivo gerado pelo scaffold:
cloudshell edit tests/eval/eval_config.yaml
Ele já contém um avaliador de LLM genérico (custom_response_quality) e uma métrica agent_turn_count que conta apenas as interações. Esse é um bom começo para qualquer agente, mas não diz nada sobre a Fórmula E. Você vai manter o avaliador e adicionar uma métrica que verifica uma regra específica para esse domínio.
As boas avaliações geralmente combinam dois tipos de métricas:
Tipo | Como é a pontuação | Ideal para | Compensação |
LLM-as-a-judge | Um modelo lê a resposta e o | Qualidades imprecisas: a resposta está correta, completa e clara? | Custa uma chamada de modelo por caso; as pontuações podem variar um pouco entre as execuções |
Métrica de código | Uma pequena função Python verifica a resposta | Fatos exatos e verificáveis: a resposta incluiu algo que precisa estar lá? | Verifica apenas o que você pode expressar em código |
Substitua o conteúdo do arquivo por:
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"),
}
O que cada parte faz:
metrics_to_runlista as métricas a serem executadas, por nome. Remover um nome aqui desativa a métrica sem excluí-la.custom_response_qualityé o LLM Judge.custom_function_fileaponta paratests/eval/response_quality.py, que foi gerado pelo scaffold. Abra-o se quiser ver o comando de avaliação.fia_cad_layer_complianceé a métrica do código, escrita inline emcustom_function. Para cada caso, ele recebe uminstance(o comando, oresponsefinal do agente e oreference). Para casos em que a resposta esperada é uma aprovação, ele verifica se a resposta nomeia todas as quatro camadas obrigatórias do CAD e lista as que estão faltando. Um blueprint que deixa de foraF1_TEC3, por exemplo, tem uma pontuação de 0,75. Outros casos recebem uma pontuação de 1,0, porque uma rejeição ou uma resposta do Modo de Ataque não precisa listar todas as camadas.
Por que verificar as camadas de CAD? Um blueprint aprovado que deixa de fora uma camada obrigatória está errado, mesmo que seja bem escrito, e um juiz de LLM pode ignorar isso. Uma verificação de código aplica a mesma regra da mesma maneira em cada execução.
Executar a avaliação
Mantenha o Gatekeeper local em execução na segunda guia e execute:
agents-cli eval run \
--dataset tests/eval/datasets/track_eval_quick.json \
--config tests/eval/eval_config.yaml \
--concurrency 1
ls artifacts/grade_results/
A avaliação leva alguns minutos. Cada caso executa todo o fluxo multiagente, cerca de dez chamadas de modelo com o arquiteto principal no pensamento HIGH, então Step 1/2: eval generate é a parte lenta. Não está travado.
Quando terminar, abra o relatório HTML em artifacts/grade_results/ com o editor do Cloud Shell. Pontuações baixas de fia_cad_layer_compliance indicam que a resposta final do arquiteto principal está deixando de fora camadas. Tente restringir as instruções e executar a avaliação novamente.
7. 7. Implantar o Gatekeeper no Agent Runtime
Você só implanta o Gatekeeper. O planejador de trajetos continua em execução no Cloud Shell e o chama.
Abrir uma nova guia do Cloud Shell.
A implantação leva de 5 a 8 minutos. Por isso, faça isso em uma nova guia enquanto a avaliação da Etapa 6 é concluída:
- Clique em Abrir uma nova guia (+) na barra de ferramentas do Cloud Shell.
- Uma nova guia não mantém as variáveis da Etapa 2, então defina-as novamente:
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"
Deixe o Gatekeeper local em execução na segunda guia: a avaliação ainda o usa, e a implantação não precisa que ele seja interrompido.
Implantar
Na nova guia, implante o Gatekeeper. Ele é executado como a conta de serviço padrão do Compute Engine do projeto:
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
A implantação leva de 5 a 8 minutos. Não feche a guia do Cloud Shell enquanto ele estiver em execução. Se o fluxo de registros for desconectado, verifique o progresso com agents-cli deploy --status. Enquanto espera, volte para a Etapa 6 e leia o relatório de avaliação.
Inspecionar a identidade do agente
agents-cli registra o recurso implantado em 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
A segunda linha de saída é a identidade em que o Gatekeeper é executado:
Implantado com | Exemplo de saída |
A conta de serviço (padrão) |
|
Identidade do agente |
|
A conta de serviço é compartilhada por tudo no projeto que a utiliza. Uma identidade de agente pertence a esse agente, então é possível conceder a ela exatamente os papéis necessários e ver as ações dela separadamente nos registros de auditoria.
8. 8. Conectar-se ao Gatekeeper implantado por A2A
O Agent Runtime disponibiliza as rotas A2A geradas pelo Gatekeeper por um caminho /api autenticado.
Verifique se a avaliação da Etapa 6 foi concluída e interrompa o Gatekeeper local na segunda guia (Ctrl+C). A partir de agora, o planejador de trajetos chama o que foi implantado. Na primeira guia, aponte o planejador de trajetos para ele:
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
Por que o cliente atualiza o token
Abra app/auth.py. Os tokens de acesso do Google Cloud expiram após uma hora. Portanto, um cliente que define um cabeçalho Authorization fixo na inicialização começa a falhar com 401 Unauthorized após uma hora. GoogleAuthRefresh é uma subclasse de httpx.Auth e verifica as credenciais em todas as solicitações, atualizando-as quando necessário. create_remote_gatekeeper_agent() só o anexa para URLs https://.
Executar de ponta a ponta
Inicie o playground novamente para que ele use o novo GATEKEEPER_A2A_URL:
agents-cli playground --port 8080
Clique em Visualização na Web > Visualizar na porta 8080, inicie uma nova sessão e pergunte:
Assess the Monaco Harbour layout, widen the chicane to 11m, and get Gatekeeper approval.
Os eventos são os mesmos da Etapa 5, mas a chamada remote_gatekeeper agora vai para o Gatekeeper no Agent Runtime, em vez da segunda guia.
Ver a chamada chegar no Agent Runtime
Prove que a solicitação realmente chegou ao Gatekeeper implantado por A2A:
- No console do Cloud, pesquise Plataforma de Agentes e abra Implantações no menu à esquerda.
- Selecione gatekeeper.
- Abra a guia Sessões.
Você vai encontrar uma nova sessão em que o ID do usuário começa com A2A_USER_. O servidor A2A do Gatekeeper o criou quando foi chamado pelo planejador de trajetos. Abra a guia Traces na mesma página para ver a chamada de modelo do Gatekeeper e a chamada de ferramenta verify_infrastructure_checklist para essa solicitação.
Opcional: implantar o planejador de trajetos também
Até agora, o planejador de trajetos é executado no Cloud Shell, então as chamadas A2A para o Gatekeeper usam as suas credenciais. Implante o planejador também, e os dois agentes serão executados no Agent Runtime, chamando um ao outro com as próprias identidades implantadas.
Pressione Ctrl+C para interromper o playground e implante o planejador da mesma forma que o 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
Os dois agentes são executados como a mesma conta de serviço do Compute Engine. Mantenha --service-account: sem ele, o planejador é executado como o agente de serviço padrão do Agent Runtime e não pode chamar o Gatekeeper (consulte Por que essa conta de serviço? na Etapa 7).
Como o planejador implantado alcança o Gatekeeper:
agents-cli deploycopia os valores em.envpara a implantação, de modo que o planejador receba oGATEKEEPER_A2A_URLque você adicionou acima.- No Agent Runtime,
GoogleAuthRefreshemapp/auth.pyusa a identidade implantada do planejador em vez da sua.
A implantação leva de 5 a 8 minutos. Quando terminar, verifique qual identidade o planejador executa:
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
Para testar o sistema implantado:
- No console do Cloud, volte para Plataforma de Agentes > Implantações.
- Selecione track-planner e abra a guia Playground.
- Insira o seguinte:
Design and homologate a Formula E circuit at Tokyo Bay. - Aguarde o blueprint com o status APROVADO do Gatekeeper.
- Volte para Implantações, selecione gatekeeper e abra a guia Sessões. A sessão mais recente do
A2A_USER_veio do planejador implantado, não do Cloud Shell.
Ao fazer a limpeza na próxima etapa, exclua também o planejador:
curl -X DELETE -H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://${REGION}-aiplatform.googleapis.com/v1beta1/${PLANNER_ID}?force=true"
9. 9. Solução de problemas e limpeza
Solução de problemas
Sintoma | Correção |
| Aceite os Termos de Serviço no console do Cloud e tente novamente. |
O projeto é | Execute novamente os comandos do projeto na Etapa 2. |
| Execute |
| Conclua a Etapa 4 ou copie |
| Inicie o Gatekeeper local (Etapa 5) ou defina |
| Sua conta não pode usar a identidade do agente. Siga as instruções de limpeza na Etapa 7 e use a implantação da conta de serviço. |
O planejador de faixa implantado informa | A identidade do planejador não tem permissão para chamar o Gatekeeper. Implante-o novamente com |
| Você atingiu a cota do Gemini. Aguarde um minuto ou adicione |
| Interrompa o outro servidor ou escolha outro |
Limpar
Exclua o Gatekeeper implantado para que ele não continue em execução:
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"
Se você criou um projeto apenas para este codelab, exclua o projeto inteiro. Se você estiver em um evento, mantenha o projeto que recebeu até que os organizadores digam o contrário.
O que você aprendeu
- O
agents-cli scaffold createoferece um projeto do ADK padrão e implantável. Você só precisa escrever agentes, habilidades e avaliações. - As habilidades do agente mantêm o conhecimento do domínio fora dos comandos até que o agente precise dele.
- O
thinking_levelpermite que você troque a profundidade do raciocínio pela velocidade por agente. - O
agents-cli eval runtransforma a pergunta "isso funciona?" em pontuações que você pode acompanhar. - A identidade do agente e o A2A permitem que agentes implantados de forma independente trabalhem juntos com segurança.