solution:
metadata:
id: racecondition
title: "Race Condition: Explore a high-scale agentic AI-powered simulation sandbox with Gemini Enterprise Agent Platform"
description: Learn how to use Google Cloud with cutting-edge agentic technologies to create a simulation sandbox for a city looking to plan and host a marathon. You will learn how to combine Agent Development Kit with Gemini Enterprise Agent Platform, AlloyDB and Gemma to orchestrate multiple agents for planning, evaluating and simulating a city-scale event.
fallbackCta:
title: "Get the code"
icon: "github_white"
url: https://github.com/GoogleCloudPlatform/race-condition
accentColor:
foreground: "white"
background: "#141e2a"
tryGCPCta:
url: https://trygcp.dev/claim/race-condition-solution#vf=16g
verifyUrl: https://trygcp.dev/api/events/race-condition-solution/live
largeSidebar: true
compactUI: true
code:
assetsPath: external-assets/marathon/
remotePath: https://github.com/GoogleCloudPlatform/race-condition/blob/main
utmOverrides:
source: gfdsolutions
medium: referral
campaign: solution-racecondition
sections:
- type: watch
youtubeId: m6EyN2Z7HJk
# overrideImage: /external-assets/marathon/watch-placeholder.png
title: "Race Condition: Explore a high-scale agentic AI-powered simulation sandbox with Gemini Enterprise Agent Platform"
description: Learn how to use Google Cloud with cutting-edge agentic technologies to create a simulation sandbox for a city looking to plan and host a marathon. You will learn how to combine Agent Development Kit with Gemini Enterprise Agent Platform, AlloyDB and Gemma to orchestrate multiple agents for planning, evaluating and simulating a city-scale event.
technologies:
- icon: /external-assets/cloud-run.svg
label: Cloud Run
url: https://cloud.google.com/run
- icon: /external-assets/adk.png
label: Agent Development Kit
url: https://docs.cloud.google.com/agent-builder/agent-development-kit/overview
- icon: /external-assets/memorystore.svg
label: Memorystore
url: https://cloud.google.com/memorystore
- icon: /external-assets/alloy.svg
label: AlloyDB
url: https://cloud.google.com/products/alloydb
- icon: /external-assets/pubsub.svg
label: Pub/Sub
url: https://cloud.google.com/pubsub
- icon: /external-assets/angular.svg
label: Angular
url: https://angular.dev
- icon: /external-assets/geap.svg
label: Gemini Enterprise Agent Platform
url: https://docs.cloud.google.com/gemini-enterprise-agent-platform
- icon: /external-assets/gke.png
label: Kubernetes Engine
url: https://cloud.google.com/kubernetes-engine
- icon: /external-assets/gemma.png
label: Gemma
url: https://deepmind.google/models/gemma/
- icon: /external-assets/gemini.svg
label: Gemini
url: https://docs.cloud.google.com/gemini/docs/
- type: explore
mode: video
subsections:
- id: video-1
title: Planning a marathon with Cloud MCP and Google Maps
description: See how the autonomous Planner agent uses the Google Maps Model Context Protocol (MCP) server to analyze real-world terrain, elevation profiles, and road categories to plot an optimal and scenic marathon route.
videoPath: external-assets/marathon/demo1.mp4
orientation: landscape
frame: none
links:
- type: codelab
url: https://codelabs.developers.google.com/next26/dev-keynote/building-agents-with-skills
logOffset: 1300
logs:
- timestamp: 0
summary: Execution started for agent 'planner'.
autoSequencePath: true
sequence:
- angular
- basic-planner
- timestamp: 135
summary: Agent 'planner' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- basic-planner
- gemini
- timestamp: 1751
summary: The model returned response payload(s) 'load_skill' back to agent 'Planner'.
detail: |
[Planner] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'name': 'gis-spatial-engineering'
},
name='load_skill'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- agent-engine
- timestamp: 1771
summary: Agent 'planner' invoked remote function capability 'load_skill'.
autoSequencePath: true
sequence:
- basic-planner
- agent-engine
- timestamp: 1774
summary: Capability 'load_skill' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- basic-planner
- timestamp: 1803
summary: Agent 'planner' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- basic-planner
- gemini
- timestamp: 3013
summary: The model returned response payload(s) 'plan_marathon_route' back to agent 'Planner'.
detail: |
[Planner] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'algorithm': 'zone_sweep',
'runner_count': 10000
},
name='plan_marathon_route'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- agent-engine
- timestamp: 3014
summary: Agent 'planner' invoked remote function capability 'plan_marathon_route'.
autoSequencePath: true
sequence:
- basic-planner
- agent-engine
- timestamp: 3286
summary: Capability 'plan_marathon_route' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- basic-planner
- timestamp: 3303
summary: Agent 'planner' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- basic-planner
- gemini
- timestamp: 4648
summary: The model returned response payload(s) 'report_marathon_route', 'search_places', 'lookup_weather' back to agent 'Planner'.
detail: |
[Planner] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={},
name='report_marathon_route'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=Nonemedia_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'textQuery': 'landmarks in Las Vegas'
},
name='search_places'
) function_response=None inline_data=None text=None thought=None thought_signature=None video_metadata=None tool_call=None tool_response=None part_metadata=Nonemedia_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'date': {
'day': 15,
'month': 3,
'year': 2025
},
'location': {
'address': 'Las Vegas, NV'
},
'unitsSystem': 'IMPERIAL'
},
name='lookup_weather'
) function_response=None inline_data=None text=None thought=None thought_signature=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- basic-planner
- timestamp: 4650
summary: Agent 'planner' invoked remote function capability 'report_marathon_route'.
autoSequencePath: true
sequence:
- basic-planner
- agent-engine
- timestamp: 4651
summary: Agent 'planner' invoked remote function capability 'search_places'.
autoSequencePath: true
sequence:
- basic-planner
- agent-engine
- timestamp: 4651
summary: Agent 'planner' invoked remote function capability 'lookup_weather'.
autoSequencePath: true
sequence:
- basic-planner
- agent-engine
- timestamp: 4656
summary: Capability 'report_marathon_route' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- basic-planner
- angular
- timestamp: 4953
summary: Capability 'lookup_weather' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- basic-planner
- angular
- timestamp: 5417
summary: Capability 'search_places' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- basic-planner
- angular
- timestamp: 5443
summary: Agent 'planner' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- basic-planner
- gemini
- timestamp: 10585
summary: The model returned response payload back to agent 'Planner'.
detail: |
[Planner] Model End
This is the comprehensive marathon event plan for the **Las Vegas "Strip & Sweep" Marathon**, designed for 10,000 participants.
### **1. Route Design & Highlights**
The course is a mathematically certified **26.2188-mile** route that captures the iconic energy of the Las Vegas Strip before sweeping through the surrounding neighborhoods.
* **Start Line:** The world-famous **"Welcome to Fabulous Las Vegas" Sign**.
* **The Strip Segment:** Runners head northbound on Las Vegas Boulevard, passing landmarks like the **Mandalay Bay**, **MGM Grand**, and the **Fountains of Bellagio**.
* **Neighborhood Sweep:** The route transitions into the city via Spring Mountain Rd and Sahara Ave, offering a diverse look at the Las Vegas valley.
* **Finish Line:** A grand finale near the **Michelob Ultra Arena**, providing a high-capacity area for post-race celebrations.
### **2. Safety & Medical Plan**
* **Emergency Corridors:** Dedicated lanes on Las Vegas Blvd and Sahara Ave are reserved for emergency vehicle access to **University Medical Center (UMC)** and **Sunrise Hospital**.
* **Medical Tents:**
* **Major Tents:** Located at the Start, Halfway (Mile 13.1), Mile 20 ("The Wall"), and the Finish Line.
* **Course Tents:** Additional support at Mile 8 and Mile 17.
* **Weather Mitigation:** Given the desert climate (average March highs of 70°F), all water stations will include electrolyte replacement and cooling towels.
### **3. Logistics & Operations**
* **Wave Start:** To manage 10,000 runners, participants will be released in 4 waves of 2,500 every 15 minutes starting at 6:00 AM.
* **Hydration:** 8 water stations are positioned approximately every 3 miles (Miles 3.1, 6.2, 9.3, 12.4, 15.5, 18.6, 21.7, and 24.8).
* **Sanitation:** 80 portable toilet units are distributed across 8 locations along the course to ensure runner comfort.
* **Traffic Control:** Rolling road closures will begin at 4:00 AM. Major intersections will be managed by LVMPD to allow timed vehicle crossings during gaps in the runner field.
### **4. Community & Engagement**
* **Cheer Zones:** Six high-energy zones are established to keep spirits high:
* *Momentum Mile (Mile 13.1):* A major spectator hub with live DJs.
* *Wall Breakers (Mile 25):* Final push support near the finish.
* **Business Continuity:** "Open for Business" signage and designated access routes will be provided for Strip properties and local businesses along Sahara Ave to minimize economic impact.
### **5. Participant Experience**
* **Scenic Variety:** The route balances the neon spectacle of the Strip with the scenic mountain backdrops of the valley.
* **Entertainment:** Local Las Vegas performers and bands will be stationed at every major cheer zone.
* **Post-Race:** The finish area features a "Recovery Lounge" with local food vendors and a medal engraving station.
### **6. Financial Viability**
* **Revenue Strategy:** A mix of tiered registration fees (averaging $150) and "Title Sponsorships" from major resort partners.
* **Cost Management:** Budget is prioritized for high-visibility security (LVMPD) and premium runner swag (medals and tech shirts) to ensure high retention for future years.
**Route Coordinates Summary:**
* **Start:** 36.0861, -115.1729
* **Halfway:** 36.1444, -115.1818
* **Finish:** 36.0856, -115.1899
sequence:
- gemini
- geap
- agent-engine
- basic-planner
- pubsub
- cloudrun
- angular
- id: video-2
title: Multi-agent orchestration with evaluation
description: Watch the Planner orchestrate specialized sub-agents to handle safety, traffic, and logistics. Before finalizing the race parameters, an LLM-as-Judge framework automatically evaluates and scores the plan against strict event criteria.
videoPath: external-assets/marathon/demo2.mp4
orientation: landscape
frame: none
links:
- type: codelab
url: https://codelabs.developers.google.com/next26/dev-keynote/build-multi-agent-marathon-planner
logOffset: 1100
logs:
- timestamp: 0
summary: Execution started for agent 'planner_with_eval'.
autoSequencePath: true
sequence:
- angular
- advanced-planner
- timestamp: 70
summary: Agent 'planner_with_eval' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- advanced-planner
- gemini
- timestamp: 1284
summary: The model returned response payload(s) 'load_skill' back to agent 'Planner_With_Eval'.
detail: |
[Planner_With_Eval] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'name': 'gis-spatial-engineering'
},
name='load_skill'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- advanced-planner
- timestamp: 1294
summary: Agent 'planner_with_eval' invoked remote function capability 'load_skill'.
autoSequencePath: true
sequence:
- advanced-planner
- agent-engine
- timestamp: 1295
summary: Capability 'load_skill' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- angular
- timestamp: 1307
summary: Agent 'planner_with_eval' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- advanced-planner
- gemini
- timestamp: 1901
summary: The model returned response payload(s) 'plan_marathon_route' back to agent 'Planner_With_Eval'.
detail: |
[Planner_With_Eval] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'algorithm': 'zone_sweep',
'finish_landmark': 'Michelob Ultra Arena',
'runner_count': 10000
},
name='plan_marathon_route'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- advanced-planner
- timestamp: 1902
summary: Agent 'planner_with_eval' invoked remote function capability 'plan_marathon_route'.
autoSequencePath: true
sequence:
- advanced-planner
- agent-engine
- timestamp: 2043
summary: Capability 'plan_marathon_route' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- advanced-planner
- timestamp: 2072
summary: Agent 'planner_with_eval' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- advanced-planner
- gemini
- timestamp: 2502
summary: The model returned response payload(s) 'report_marathon_route', 'assess_traffic_impact' back to agent 'Planner_With_Eval'.
detail: |
[Planner_With_Eval] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={},
name='report_marathon_route'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=Nonemedia_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={},
name='assess_traffic_impact'
) function_response=None inline_data=None text=None thought=None thought_signature=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- advanced-planner
- timestamp: 2503
summary: Agent 'planner_with_eval' invoked remote function capability 'report_marathon_route'.
autoSequencePath: true
sequence:
- advanced-planner
- google-maps
- timestamp: 2504
summary: Agent 'planner_with_eval' invoked remote function capability 'assess_traffic_impact'.
autoSequencePath: true
sequence:
- advanced-planner
- google-maps
- timestamp: 2517
summary: Capability 'report_marathon_route' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- advanced-planner
- timestamp: 2517
summary: Capability 'assess_traffic_impact' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- advanced-planner
- timestamp: 2527
summary: Agent 'planner_with_eval' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- advanced-planner
- gemini
- timestamp: 4630
summary: The model returned response payload(s) 'evaluate_plan', 'submit_plan_to_simulator' back to agent 'Planner_With_Eval'.
detail: |
[Planner_With_Eval] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'evaluation_request': '{"user_intent": "Plan a marathon in Las Vegas for 10,000 runners", "proposed_plan": "The \'Neon & Neighborhoods Marathon\' is a 26.2-mile course starting at the iconic Las Vegas Sign and finishing at the Michelob Ultra Arena. \\n\\n**Safety**: Emergency vehicle corridors are established with access to Sunrise Hospital and UMC. Emergency vehicle crossing points are placed every 2 miles. Evacuation routes are maintained via parallel side streets. Crowd safety barricades will be deployed in high-traffic Strip areas.\\n\\n**Community**: The race starts at 6:00 AM to minimize resident disruption. Business continuity for Strip hotels is ensured via rear access. The route is equitable, traversing Spring Valley and Paradise. Six cheer zones are established for community engagement.\\n\\n**Intent Alignment**: This plan delivers a scenic Las Vegas marathon for 10,000 participants on a moderate budget.\\n\\n**Logistics**: Features a state-of-the-art RFID timing system, 500 course marshals, and a comprehensive traffic control plan with LVMPD. Signage includes mile markers every 0.5 miles. 8 water stations and 80 porta-potties are distributed along the course. Wave management will handle 4 waves of 2,500 runners.\\n\\n**Participant Experience**: Runners will enjoy scenic views of the Strip and local landmarks. Spectator zones at key miles (5, 8.7, 13.1, 17.5, 20, 25) will feature entertainment and live music.\\n\\n**Financial Viability**: Estimated budget of $1.2M covered by $1.5M in revenue from registration fees ($120/runner) and local sponsors."}'
},
name='evaluate_plan'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=Nonemedia_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'action': 'verify',
'message': "The 'Neon & Neighborhoods Marathon' in Las Vegas for 10,000 runners. Starts at Las Vegas Sign, finishes at Michelob Ultra Arena. Includes 8 water stations, 6 medical tents, and 6 cheer zones. Traffic control plan covers 15 closed segments."
},
name='submit_plan_to_simulator'
) function_response=None inline_data=None text=None thought=None thought_signature=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- advanced-planner
- timestamp: 4631
summary: Agent 'planner_with_eval' invoked remote function capability 'submit_plan_to_simulator'.
autoSequencePath: true
sequence:
- advanced-planner
- scaled-simulator
- timestamp: 4632
summary: Agent 'planner_with_eval' invoked remote function capability 'evaluate_plan'.
autoSequencePath: true
sequence:
- advanced-planner
- scaled-simulator
- timestamp: 4906
summary: Execution started for agent 'simulator'.
autoSequencePath: true
sequence:
- scaled-simulator
- agent-engine
- timestamp: 4908
summary: Agent 'simulator' initiated a content generation call with model 'gemini-flash-lite-latest'.
autoSequencePath: true
sequence:
- scaled-simulator
- gemini
- timestamp: 5259
summary: The model returned response payload(s) 'verify_plan' back to agent 'Simulator'.
detail: |
[Simulator] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'plan_json': '{"action": "verify", "narrative": "The \'Neon & Neighborhoods Marathon\' in Las Vegas for 10,000 runners. Starts at Las Vegas Sign, finishes at Michelob Ultra Arena. Includes 8 water stations, 6 medical tents, and 6 cheer zones. Traffic control plan covers 15 closed segments."}'
},
name='verify_plan'
) function_response=None inline_data=None text=None thought=None thought_signature=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- scaled-simulator
- timestamp: 5260
summary: Agent 'simulator' invoked remote function capability 'verify_plan'.
autoSequencePath: true
sequence:
- scaled-simulator
- agent-engine
- timestamp: 5261
summary: Capability 'verify_plan' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- scaled-simulator
- timestamp: 5263
summary: Agent 'simulator' initiated a content generation call with model 'gemini-flash-lite-latest'.
autoSequencePath: true
sequence:
- scaled-simulator
- gemini
- timestamp: 5449
summary: The model returned response payload back to agent 'Simulator'.
detail: |
[Simulator] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=None function_response=None inline_data=None text='' thought=None thought_signature=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- scaled-simulator
- timestamp: 5455
summary: Capability 'submit_plan_to_simulator' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- scaled-simulator
- timestamp: 10526
summary: Capability 'evaluate_plan' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- scaled-simulator
- timestamp: 10557
summary: Agent 'planner_with_eval' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- advanced-planner
- gemini
- timestamp: 13641
summary: The model returned response payload(s) 'validate_and_emit_a2ui', 'validate_and_emit_a2ui' back to agent 'Planner_With_Eval'.
detail: |
[Planner_With_Eval] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'payload': """{"surfaceUpdate": {"surfaceId": "dashboard", "components": [
{"id": "tag", "component": {"Text": {"text": {"literalString": "PLAN"}, "usageHint": "label"}}},
{"id": "plan-meta", "component": {"Text": {
"text": {"literalString": "#0042 2024/05/15 08:30:00 AM"},
"usageHint": "caption"}}},
{"id": "tag-row", "component": {"Row": {"children": {"explicitList": ["tag", "plan-meta"]}}}},
{"id": "score-num", "component": {"Text": {"text": {"literalString": "100"}, "usageHint": "h1"}}},
{"id": "score-lbl", "component": {"Text": {"text": {"literalString": "Score"}, "usageHint": "caption"}}},
{"id": "score-col", "component": {"Column": {"children": {"explicitList": ["score-num", "score-lbl"]}}}},
{"id": "title", "component": {"Text": {
"text": {"literalString": "Neon & Neighborhoods Marathon"},
"usageHint": "h2"}}},
{"id": "left-col", "component": {"Column": {"children": {"explicitList": ["tag-row", "title"]}}}},
{"id": "header", "component": {"Row": {"children": {"explicitList": ["left-col", "score-col"]}}}},
{"id": "sc-l", "component": {"Text": {"text": {"literalString": "Safety Compliance"}, "usageHint": "body"}}},
{"id": "sc-v", "component": {"Text": {"text": {"literalString": "100"}, "usageHint": "body"}}},
{"id": "sc-r", "component": {"Row": {"children": {"explicitList": ["sc-l", "sc-v"]}}}},
{"id": "lc-l", "component": {"Text": {"text": {"literalString": "Logistics Completeness"}, "usageHint": "body"}}},
{"id": "lc-v", "component": {"Text": {"text": {"literalString": "100"}, "usageHint": "body"}}},
{"id": "lc-r", "component": {"Row": {"children": {"explicitList": ["lc-l", "lc-v"]}}}},
{"id": "pe-l", "component": {"Text": {"text": {"literalString": "Participant Experience"}, "usageHint": "body"}}},
{"id": "pe-v", "component": {"Text": {"text": {"literalString": "100"}, "usageHint": "body"}}},
{"id": "pe-r", "component": {"Row": {"children": {"explicitList": ["pe-l", "pe-v"]}}}},
{"id": "dc-l", "component": {"Text": {"text": {"literalString": "Distance Compliance"}, "usageHint": "body"}}},
{"id": "dc-v", "component": {"Text": {"text": {"literalString": "100"}, "usageHint": "body"}}},
{"id": "dc-r", "component": {"Row": {"children": {"explicitList": ["dc-l", "dc-v"]}}}},
{"id": "grid-left", "component": {"Column": {"children": {"explicitList": ["sc-r", "lc-r", "pe-r", "dc-r"]}}}},
{"id": "ci-l", "component": {"Text": {"text": {"literalString": "Community Impact"}, "usageHint": "body"}}},
{"id": "ci-v", "component": {"Text": {"text": {"literalString": "100"}, "usageHint": "body"}}},
{"id": "ci-r", "component": {"Row": {"children": {"explicitList": ["ci-l", "ci-v"]}}}},
{"id": "fv-l", "component": {"Text": {"text": {"literalString": "Financial Viability"}, "usageHint": "body"}}},
{"id": "fv-v", "component": {"Text": {"text": {"literalString": "100"}, "usageHint": "body"}}},
{"id": "fv-r", "component": {"Row": {"children": {"explicitList": ["fv-l", "fv-v"]}}}},
{"id": "ia-l", "component": {"Text": {"text": {"literalString": "Intent Alignment"}, "usageHint": "body"}}},
{"id": "ia-v", "component": {"Text": {"text": {"literalString": "100"}, "usageHint": "body"}}},
{"id": "ia-r", "component": {"Row": {"children": {"explicitList": ["ia-l", "ia-v"]}}}},
{"id": "grid-right", "component": {"Column": {"children": {"explicitList": ["ci-r", "fv-r", "ia-r"]}}}},
{"id": "grid", "component": {"Row": {"children": {"explicitList": ["grid-left", "grid-right"]}}}},
{"id": "d1", "component": {"Divider": {}}},
{"id": "findings-hdr", "component": {"Text": {"text": {"literalString": "Findings"}, "usageHint": "caption"}}},
{"id": "f1-title", "component": {"Text": {
"text": {"literalString": "No major issues found"},
"usageHint": "body"}}},
{"id": "f1-sev", "component": {"Text": {"text": {"literalString": "NONE"}, "usageHint": "caption"}}},
{"id": "f1-row", "component": {"Row": {"children": {"explicitList": ["f1-title", "f1-sev"]}}}},
{"id": "f1-desc", "component": {"Text": {
"text": {"literalString": "The plan is comprehensive and meets all quality criteria."},
"usageHint": "body"}}},
{"id": "d2", "component": {"Divider": {}}},
{"id": "btn-text", "component": {"Text": {"text": {"literalString": "Run Simulation"}}}},
{"id": "btn1", "component": {"Button": {
"child": "btn-text", "action": {"name": "run_simulation"},
"primary": {"literalBoolean": true}}}},
{"id": "btn-row", "component": {"Row": {"children": {"explicitList": ["btn1"]}}}},
{"id": "content", "component": {"Column": {"children": {
"explicitList": ["header", "grid", "d1", "findings-hdr",
"f1-row", "f1-desc", "d2", "btn-row"]}}}},
{"id": "card1", "component": {"Card": {"child": "content"}}}
]}}"""
},
name='validate_and_emit_a2ui'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=Nonemedia_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'payload': '{"beginRendering": {"surfaceId": "dashboard", "root": "card1"}}'
},
name='validate_and_emit_a2ui'
) function_response=None inline_data=None text=None thought=None thought_signature=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- advanced-planner
- timestamp: 13643
summary: Agent 'planner_with_eval' invoked remote function capability 'validate_and_emit_a2ui'.
autoSequencePath: true
sequence:
- advanced-planner
- agent-engine
- timestamp: 13647
summary: Tool call 'validate_and_emit_a2ui' finished execution and piped results back to agent 'Planner_With_Eval'.
detail: |
[Planner_With_Eval] Tool End: validate_and_emit_a2ui
Status: success
autoSequencePath: true
sequence:
- advanced-planner
- angular
- timestamp: 13670
summary: Agent 'planner_with_eval' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- advanced-planner
- gemini
- timestamp: 15442
summary: The model returned response payload back to agent 'Planner_With_Eval'.
detail: |
[Planner_With_Eval] Model End
I have designed a comprehensive plan for the **Neon & Neighborhoods Marathon** in Las Vegas, tailored for 10,000 runners. The event is structured to provide a world-class participant experience while ensuring safety and minimizing community disruption.
### **Plan Overview: Neon & Neighborhoods Marathon**
* **City:** Las Vegas, NV
* **Scale:** 10,000 runners (managed in 4 waves of 2,500)
* **Theme:** Scenic & Iconic (Strip + Local Neighborhoods)
* **Route:** A 26.2-mile course starting at the **Las Vegas Sign** and finishing at the **Michelob Ultra Arena**. The route sweeps through Las Vegas Boulevard, Spring Mountain Road, Rainbow Boulevard, and Sunset Road.
### **The Six Quality Pillars**
1. **Safety:** We have established dedicated emergency corridors with direct access to **Sunrise Hospital** and **UMC**. Emergency vehicle crossing points are stationed every 2 miles, and evacuation routes remain accessible via parallel side streets.
2. **Community:** To minimize disruption, the race starts at **6:00 AM**, allowing major roads to reopen by noon. Business continuity for Strip hotels is maintained through rear access points. Six **cheer zones** are strategically placed to engage local residents.
3. **Intent Alignment:** This plan directly addresses the request for a 10,000-runner event in Las Vegas with a scenic focus, all within a moderate budget.
4. **Logistics:** The event features an **RFID timing system**, 500 course marshals, and a comprehensive traffic control plan coordinated with LVMPD. We have allocated **8 water stations**, **6 medical tents**, and **80 porta-potties** along the course.
5. **Participant Experience:** Runners will enjoy iconic views of the Strip and local landmarks. Spectator zones at key miles (5, 13.1, 20, etc.) will feature live music and entertainment to keep energy high.
6. **Financial Viability:** The estimated budget of **$1.2M** (permits, security, infrastructure) is fully covered by a projected **$1.5M in revenue** from registration fees ($120/runner) and local sponsorships.
### **Evaluation & Verification Results**
The plan has been rigorously evaluated and verified:
* **Overall Score:** **100/100** (All criteria met, including Safety, Logistics, and Community Impact).
* **Distance Compliance:** **100%** (Mathematically verified 26.2-mile route).
* **Simulator Verification:** **Success** (The plan is structurally sound and ready for execution).
* **Simulation ID:** `9d702a72-c6d3-4794-be32-09a462211688`
The interactive dashboard below provides a detailed breakdown of the scores and findings. You can also trigger a full simulation to see the plan in action.
sequence:
- gemini
- geap
- agent-engine
- advanced-planner
- pubsub
- cloudrun
- angular
- id: video-3
title: Learning from telemetry
description: Trace inter-agent communication pulses and debug complex multi-turn decision logic in real-time. The simulation framework captures detailed runtime telemetry from every Cloud Run microservice to ensure high observability.
videoPath: external-assets/marathon/demo3.mp4
orientation: landscape
frame: none
links:
- type: codelab
url: https://codelabs.developers.google.com/next26/dev-keynote/enhancing-agents-with-memory
logOffset: 1000
logs:
- timestamp: 0
summary: Execution started for agent 'planner_with_memory'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 28
summary: Agent 'planner_with_memory' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 721
summary: The model returned response payload(s) 'recall_past_simulations', 'get_local_laws_and_regulations' back to agent 'Planner_With_Memory'.
detail: |
[Planner_With_Memory] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'city': 'Las Vegas',
'query': 'marathon in Las Vegas for 10000 runners'
},
name='recall_past_simulations'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=Nonemedia_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'city': 'Las Vegas',
'query': 'restrictions for running a race on the Las Vegas strip'
},
name='get_local_laws_and_regulations'
) function_response=None inline_data=None text=None thought=None thought_signature=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- planner-memory
- timestamp: 732
summary: Agent 'planner_with_memory' invoked remote function capability 'recall_past_simulations'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 733
summary: Agent 'planner_with_memory' invoked remote function capability 'get_local_laws_and_regulations'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 733
summary: Capability 'recall_past_simulations' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- planner-memory
- timestamp: 733
summary: Capability 'get_local_laws_and_regulations' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- planner-memory
- timestamp: 743
summary: Agent 'planner_with_memory' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 1171
summary: The model returned response payload(s) 'load_skill', 'load_skill' back to agent 'Planner_With_Memory'.
detail: |
[Planner_With_Memory] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'name': 'gis-spatial-engineering'
},
name='load_skill'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=Nonemedia_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'name': 'directing-the-event'
},
name='load_skill'
) function_response=None inline_data=None text=None thought=None thought_signature=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- planner-memory
- timestamp: 1172
summary: Agent 'planner_with_memory' invoked remote function capability 'load_skill'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 1173
summary: Agent 'planner_with_memory' invoked remote function capability 'load_skill'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 1173
summary: Capability 'load_skill' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- planner-memory
- timestamp: 1173
summary: Capability 'load_skill' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- planner-memory
- timestamp: 1183
summary: Agent 'planner_with_memory' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 1595
summary: The model returned response payload(s) 'plan_marathon_route', 'plan_marathon_event' back to agent 'Planner_With_Memory'.
detail: |
[Planner_With_Memory] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'algorithm': 'zone_sweep',
'runner_count': 10000
},
name='plan_marathon_route'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=Nonemedia_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'city': 'Las Vegas',
'event_name': 'Las Vegas Grand Marathon 2026'
},
name='plan_marathon_event'
) function_response=None inline_data=None text=None thought=None thought_signature=None video_metadata=None tool_call=None tool_response=None part_metadata=None
sequence:
- gemini
- planner-memory
- timestamp: 1596
summary: Agent 'planner_with_memory' invoked remote function capability 'plan_marathon_route'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 1624
summary: Agent 'planner_with_memory' invoked remote function capability 'plan_marathon_event'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 1625
summary: Capability 'plan_marathon_event' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- planner-memory
- timestamp: 1625
summary: Capability 'plan_marathon_route' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- planner-memory
- timestamp: 1632
summary: Agent 'planner_with_memory' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 1973
summary: The model returned response payload(s) 'report_marathon_route', 'assess_traffic_impact' back to agent 'Planner_With_Memory'.
detail: |
[Planner_With_Memory] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={},
name='report_marathon_route'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=Nonemedia_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={},
name='assess_traffic_impact'
) function_response=None inline_data=None text=None thought=None thought_signature=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- planner-memory
- timestamp: 1974
summary: Agent 'planner_with_memory' invoked remote function capability 'report_marathon_route'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 1974
summary: Agent 'planner_with_memory' invoked remote function capability 'assess_traffic_impact'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 1982
summary: Capability 'report_marathon_route' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- planner-memory
- timestamp: 1982
summary: Capability 'assess_traffic_impact' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- planner-memory
- timestamp: 1989
summary: Agent 'planner_with_memory' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 2516
summary: The model returned response payload(s) 'evaluate_plan' back to agent 'Planner_With_Memory'.
detail: |
[Planner_With_Memory] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'evaluation_request': '{"user_intent": "Plan a marathon in Las Vegas for 10,000 runners", "proposed_plan": {"city": "Las Vegas", "event_name": "Las Vegas Grand Marathon 2026", "runner_count": 10000, "route_highlights": "Starts at the Las Vegas Sign, goes northbound on the Strip, sweeps through neighborhoods, and finishes near Spring Mountain Road.", "logistics": {"start_time": "08:00 AM", "wave_count": 5, "water_stations": "Every 5km", "medical_tents": "6 locations including Start, Finish, and Halfway", "portable_toilets": "8 locations with 10 units each", "cheer_zones": "6 locations"}, "traffic_impact": "16 closed segments, 14 affected intersections. Major impact on Las Vegas Boulevard and Sahara Avenue."}}'
},
name='evaluate_plan'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- planner-memory
- timestamp: 2516
summary: Agent 'planner_with_memory' invoked remote function capability 'evaluate_plan'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 8574
summary: Capability 'evaluate_plan' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- planner-memory
- timestamp: 8592
summary: Agent 'planner_with_memory' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 9621
summary: The model returned response payload(s) 'store_route', 'submit_plan_to_simulator' back to agent 'Planner_With_Memory'.
detail: |
[Planner_With_Memory] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'evaluation_result': '{"overall_score": 89, "scores": {"community_impact": 60, "distance_compliance": 100, "financial_viability": 100, "intent_alignment": 100, "logistics_completeness": 100, "participant_experience": 100, "safety_compliance": 60}, "findings": [{"criterion": "safety_compliance", "description": "Score 3/5", "severity": "low"}, {"criterion": "community_impact", "description": "Score 3/5", "severity": "low"}]}',
'route_data': '{"features": [{"geometry": {"coordinates": [-115.172851, 36.086141], "type": "Point"}, "properties": {"marker-type": "start", "name": "Start Line"}, "type": "Feature"}, {"geometry": {"coordinates": [-115.166237, 36.123254], "type": "Point"}, "properties": {"marker-type": "finish", "name": "Finish Line"}, "type": "Feature"}, {"geometry": {"coordinates": [[-115.172851, 36.086141], [-115.172908, 36.093604], [-115.172932, 36.097313], [-115.172955, 36.100858], [-115.172975, 36.108764], [-115.172869, 36.114682], [-115.17284, 36.11849], [-115.172601, 36.119587], [-115.171965, 36.12121], [-115.169311, 36.125471], [-115.165668, 36.131033]], "type": "LineString"}, "properties": {"certified": true, "distance_mi": 26.2905, "name": "Las Vegas Boulevard", "route_type": "marathon"}, "type": "Feature"}], "type": "FeatureCollection"}'
},
name='store_route'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=Nonemedia_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'action': 'verify',
'message': 'The Las Vegas Grand Marathon 2026 is a 26.2-mile route starting at the Las Vegas Sign and finishing near Spring Mountain Road. It features 10,000 runners across 5 waves, with 8 hydration stations, 6 medical tents, and 6 cheer zones. Traffic impact includes 16 closed segments and 14 affected intersections.'
},
name='submit_plan_to_simulator'
) function_response=None inline_data=None text=None thought=None thought_signature=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- planner-memory
- timestamp: 9622
summary: Agent 'planner_with_memory' invoked remote function capability 'submit_plan_to_simulator'.
autoSequencePath: true
sequence:
- planner-memory
- agent-engine
- scaled-simulator
- timestamp: 9622
summary: Agent 'planner_with_memory' invoked remote function capability 'store_route'.
autoSequencePath: true
sequence:
- planner-memory
- alloy
- timestamp: 9631
summary: Capability 'store_route' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- alloy
- planner-memory
- timestamp: 10004
summary: Capability 'submit_plan_to_simulator' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- scaled-simulator
- agent-engine
- planner-memory
- timestamp: 10025
summary: Agent 'planner_with_memory' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 12376
summary: The model returned response payload(s) 'validate_and_emit_a2ui', 'validate_and_emit_a2ui' back to agent 'Planner_With_Memory'.
detail: |
[Planner_With_Memory] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'payload': '{"surfaceUpdate": {"surfaceId": "dashboard", "components": [{"id": "tag", "component": {"Text": {"text": {"literalString": "PLAN"}, "usageHint": "label"}}}, {"id": "plan-meta", "component": {"Text": {"text": {"literalString": "#6e6a 26/04/10 02:23:49 PM"}, "usageHint": "caption"}}}, {"id": "tag-row", "component": {"Row": {"children": {"explicitList": ["tag", "plan-meta"]}}}}, {"id": "score-num", "component": {"Text": {"text": {"literalString": "89"}, "usageHint": "h1"}}}, {"id": "score-lbl", "component": {"Text": {"text": {"literalString": "Score"}, "usageHint": "caption"}}}, {"id": "score-col", "component": {"Column": {"children": {"explicitList": ["score-num", "score-lbl"]}}}}, {"id": "title", "component": {"Text": {"text": {"literalString": "Las Vegas Grand Marathon 2026"}, "usageHint": "h2"}}}, {"id": "left-col", "component": {"Column": {"children": {"explicitList": ["tag-row", "title"]}}}}, {"id": "header", "component": {"Row": {"children": {"explicitList": ["left-col", "score-col"]}}}}, {"id": "sc-l", "component": {"Text": {"text": {"literalString": "Safety Compliance"}, "usageHint": "body"}}}, {"id": "sc-v", "component": {"Text": {"text": {"literalString": "60"}, "usageHint": "body"}}}, {"id": "sc-r", "component": {"Row": {"children": {"explicitList": ["sc-l", "sc-v"]}}}}, {"id": "lc-l", "component": {"Text": {"text": {"literalString": "Logistics Completeness"}, "usageHint": "body"}}}, {"id": "lc-v", "component": {"Text": {"text": {"literalString": "100"}, "usageHint": "body"}}}, {"id": "lc-r", "component": {"Row": {"children": {"explicitList": ["lc-l", "lc-v"]}}}}, {"id": "pe-l", "component": {"Text": {"text": {"literalString": "Participant Experience"}, "usageHint": "body"}}}, {"id": "pe-v", "component": {"Text": {"text": {"literalString": "100"}, "usageHint": "body"}}}, {"id": "pe-r", "component": {"Row": {"children": {"explicitList": ["pe-l", "pe-v"]}}}}, {"id": "dc-l", "component": {"Text": {"text": {"literalString": "Distance Compliance"}, "usageHint": "body"}}}, {"id": "dc-v", "component": {"Text": {"text": {"literalString": "100"}, "usageHint": "body"}}}, {"id": "dc-r", "component": {"Row": {"children": {"explicitList": ["dc-l", "dc-v"]}}}}, {"id": "grid-left", "component": {"Column": {"children": {"explicitList": ["sc-r", "lc-r", "pe-r", "dc-r"]}}}}, {"id": "ci-l", "component": {"Text": {"text": {"literalString": "Community Impact"}, "usageHint": "body"}}}, {"id": "ci-v", "component": {"Text": {"text": {"literalString": "60"}, "usageHint": "body"}}}, {"id": "ci-r", "component": {"Row": {"children": {"explicitList": ["ci-l", "ci-v"]}}}}, {"id": "fv-l", "component": {"Text": {"text": {"literalString": "Financial Viability"}, "usageHint": "body"}}}, {"id": "fv-v", "component": {"Text": {"text": {"literalString": "100"}, "usageHint": "body"}}}, {"id": "fv-r", "component": {"Row": {"children": {"explicitList": ["fv-l", "fv-v"]}}}}, {"id": "ia-l", "component": {"Text": {"text": {"literalString": "Intent Alignment"}, "usageHint": "body"}}}, {"id": "ia-v", "component": {"Text": {"text": {"literalString": "100"}, "usageHint": "body"}}}, {"id": "ia-r", "component": {"Row": {"children": {"explicitList": ["ia-l", "ia-v"]}}}}, {"id": "grid-right", "component": {"Column": {"children": {"explicitList": ["ci-r", "fv-r", "ia-r"]}}}}, {"id": "grid", "component": {"Row": {"children": {"explicitList": ["grid-left", "grid-right"]}}}}, {"id": "d1", "component": {"Divider": {}}}, {"id": "findings-hdr", "component": {"Text": {"text": {"literalString": "Findings"}, "usageHint": "caption"}}}, {"id": "f1-title", "component": {"Text": {"text": {"literalString": "Safety Compliance Gap"}, "usageHint": "body"}}}, {"id": "f1-sev", "component": {"Text": {"text": {"literalString": "MODERATE"}, "usageHint": "caption"}}}, {"id": "f1-row", "component": {"Row": {"children": {"explicitList": ["f1-title", "f1-sev"]}}}}, {"id": "f1-desc", "component": {"Text": {"text": {"literalString": "Score 3/5: Review safety gaps including emergency vehicle access and evacuation routes."}, "usageHint": "body"}}}, {"id": "f2-title", "component": {"Text": {"text": {"literalString": "Community Impact Gap"}, "usageHint": "body"}}}, {"id": "f2-sev", "component": {"Text": {"text": {"literalString": "MODERATE"}, "usageHint": "caption"}}}, {"id": "f2-row", "component": {"Row": {"children": {"explicitList": ["f2-title", "f2-sev"]}}}}, {"id": "f2-desc", "component": {"Text": {"text": {"literalString": "Score 3/5: Address community considerations including resident notification and business access."}, "usageHint": "body"}}}, {"id": "d2", "component": {"Divider": {}}}, {"id": "btn-text", "component": {"Text": {"text": {"literalString": "Run Simulation"}}}}, {"id": "btn1", "component": {"Button": {"child": "btn-text", "action": {"name": "run_simulation"}, "primary": {"literalBoolean": true}}}}, {"id": "btn-row", "component": {"Row": {"children": {"explicitList": ["btn1"]}}}}, {"id": "content", "component": {"Column": {"children": {"explicitList": ["header", "grid", "d1", "findings-hdr", "f1-row", "f1-desc", "f2-row", "f2-desc", "d2", "btn-row"]}}}}, {"id": "card1", "component": {"Card": {"child": "content"}}}]}}'
},
name='validate_and_emit_a2ui'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=Nonemedia_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'payload': '{"beginRendering": {"surfaceId": "dashboard", "root": "card1"}}'
},
name='validate_and_emit_a2ui'
) function_response=None inline_data=None text=None thought=None thought_signature=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- planner-memory
- timestamp: 12377
summary: Agent 'planner_with_memory' invoked remote function capability 'validate_and_emit_a2ui'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 12377
summary: Agent 'planner_with_memory' invoked remote function capability 'validate_and_emit_a2ui'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 12378
summary: Tool call 'validate_and_emit_a2ui' finished execution and piped results back to agent 'Planner_With_Memory'.
detail: |
[Planner_With_Memory] Tool End: validate_and_emit_a2ui
Status: success
autoSequencePath: true
sequence:
- agent-engine
- planner-memory
- angular
- timestamp: 12378
summary: Tool call 'validate_and_emit_a2ui' finished execution and piped results back to agent 'Planner_With_Memory'.
detail: |
[Planner_With_Memory] Tool End: validate_and_emit_a2ui
Status: success
autoSequencePath: true
sequence:
- agent-engine
- planner-memory
- angular
- timestamp: 12392
summary: Agent 'planner_with_memory' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 14468
summary: The model returned response payload back to agent 'Planner_With_Memory'.
detail: |
[Planner_With_Memory] Model End
I have designed a comprehensive plan for the **Las Vegas Grand Marathon 2026**, tailored for 10,000 participants. The event is scheduled for a comfortable Spring morning, starting at 08:00 AM.
### **Route Overview**
The 26.2-mile course follows a scenic **Zone-Sweep** design:
* **Start:** The iconic "Welcome to Fabulous Las Vegas" Sign.
* **The Strip:** Runners head northbound on Las Vegas Boulevard, passing major landmarks like the MGM Grand and Bellagio.
* **Neighborhood Sweep:** The route then weaves through diverse Las Vegas neighborhoods, including segments on Sahara Avenue, Valley View Boulevard, and Sunset Road.
* **Finish:** A grand finish near Spring Mountain Road.
### **Logistics & Participant Experience**
* **Waves:** 5 waves to manage the 10,000-runner flow.
* **Hydration:** 8 water stations placed approximately every 5km.
* **Medical Support:** 6 medical tents, including major facilities at the Start, Halfway (Mile 13.1), "The Wall" (Mile 20), and the Finish Line.
* **Amenities:** 8 portable toilet banks (10 units each) and 6 high-energy Cheer Zones (e.g., "Momentum Mile" and "Wall Breakers") to keep spirits high.
### **Traffic & Community Impact**
* **Closures:** 16 road segments will be closed, including significant portions of Las Vegas Boulevard and Sahara Avenue.
* **Intersections:** 14 major intersections will be affected. We will implement rolling closures and clear detour signage to minimize disruption.
* **Regulations:** The plan complies with local codes regarding sidewalk vending and public right-of-way obstructions.
### **Plan Evaluation**
The plan received an overall score of **89/100** from our specialized evaluator:
* **Safety Compliance (60):** While medical coverage is strong, further review of emergency vehicle access corridors is recommended.
* **Logistics (100):** Comprehensive timing, wave, and station planning.
* **Participant Experience (100):** High scenic variety and excellent amenities.
* **Community Impact (60):** Additional focus on resident notification and business access corridors is suggested.
* **Distance Compliance (100):** Verified at exactly 26.2 miles.
**Route ID:** `6e6a2b59-b438-4f7f-a6d9-2ea76a6b5f5d`
The plan has been **verified** as simulation-ready. You can view the full details in the dashboard above.
**Would you like to run the simulation now to see how the 10,000 runners perform on this course?**
sequence:
- gemini
- geap
- planner-memory
- pubsub
- cloudrun
- angular
- id: video-4
title: Scaling agentic brains with Gemma
description: |
Experience high-throughput agentic simulation as the platform scales to support hundreds of autonomous runner NPCs. By leveraging vLLM on Google Kubernetes Engine (GKE), lightweight Gemma models drive dynamic runtime behaviors with ultra-low latency.
As the simulation progresses, the event log highlights different individual runners' progress, velocities and hydration levels.
videoPath: external-assets/marathon/demo4.mp4
orientation: landscape
frame: none
links:
- type: codelab
url: https://codelabs.developers.google.com/next26/dev-keynote/intent-to-infrastructure
logs:
- timestamp: 0
summary: Execution started for agent 'planner_with_memory'.
autoSequencePath: true
sequence:
- planner-memory
- timestamp: 32
summary: Agent 'planner_with_memory' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 1059
summary: The model returned response payload(s) 'get_route' back to agent 'Planner_With_Memory'.
detail: |
[Planner_With_Memory] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'activate_route': True,
'route_id': '66c0e0c6-11af-433e-8f3b-cb4524e1e019'
},
name='get_route'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- planner-memory
- timestamp: 1060
summary: Agent 'planner_with_memory' invoked remote function capability 'get_route'.
autoSequencePath: true
sequence:
- planner-memory
- agent-engine
- timestamp: 1071
summary: Capability 'get_route' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- planner-memory
- timestamp: 1076
summary: Agent 'planner_with_memory' initiated a content generation call with model 'gemini-3-flash-preview'.
autoSequencePath: true
sequence:
- planner-memory
- gemini
- timestamp: 1757
summary: The model returned response payload(s) 'start_simulation', 'submit_plan_to_simulator' back to agent 'Planner_With_Memory'.
detail: |
[Planner_With_Memory] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'action': 'execute',
'message': 'Executing simulation for the Neon & Neighborhoods Marathon in Las Vegas with 10,000 runners (simulating 1,000 runners).',
'simulation_config': {
'runner_count': 1000
}
},
name='start_simulation'
) function_response=None inline_data=None text=None thought=None video_metadata=None tool_call=None tool_response=None part_metadata=Nonemedia_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'action': 'execute',
'message': 'Executing simulation for the Neon & Neighborhoods Marathon in Las Vegas with 10,000 runners (simulating 1,000 runners).',
'simulation_config': {
'runner_count': 1000
}
},
name='submit_plan_to_simulator'
) function_response=None inline_data=None text=None thought=None thought_signature=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- agent-engine
- planner-memory
- timestamp: 1758
summary: Agent 'planner_with_memory' invoked remote function capability 'start_simulation'.
autoSequencePath: true
sequence:
- planner-memory
- agent-engine
- scaled-simulator
- timestamp: 1759
summary: Agent 'planner_with_memory' invoked remote function capability 'submit_plan_to_simulator'.
autoSequencePath: true
sequence:
- planner-memory
- agent-engine
- scaled-simulator
- timestamp: 1759
summary: Capability 'start_simulation' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- scaled-simulator
- timestamp: 1769
summary: Agent 'simulator' initiated a content generation call with model 'gemini-flash-lite-latest'.
autoSequencePath: true
sequence:
- scaled-simulator
- gemini
- timestamp: 2078
summary: The model returned response payload(s) 'simulation_pipeline' back to agent 'Simulator'.
detail: |
[Simulator] Model End
media_resolution=None code_execution_result=None executable_code=None file_data=None function_call=FunctionCall(
args={
'request': '{"action": "execute", "narrative": "Executing simulation for the Neon & Neighborhoods Marathon in Las Vegas with 10,000 runners (simulating 1,000 runners).", "simulation_config": {"runner_count": 1000}}'
},
name='simulation_pipeline'
) function_response=None inline_data=None text=None thought=None thought_signature=None video_metadata=None tool_call=None tool_response=None part_metadata=None
autoSequencePath: true
sequence:
- gemini
- timestamp: 2080
summary: Agent 'simulator' invoked remote function capability 'simulation_pipeline'.
autoSequencePath: true
sequence:
- agent-engine
- scaled-simulator
- timestamp: 2081
summary: Execution started for agent 'simulation_pipeline'.
autoSequencePath: true
sequence:
- agent-engine
- scaled-simulator
- timestamp: 2086
summary: Agent 'pre_race' initiated a content generation call with model 'gemini-flash-lite-latest'.
autoSequencePath: true
sequence:
- scaled-simulator
- gemini
- timestamp: 2086
summary: Agent 'pre_race' invoked remote function capability 'prepare_simulation'.
autoSequencePath: true
sequence:
- agent-engine
- scaled-simulator
- timestamp: 2087
summary: Capability 'prepare_simulation' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- scaled-simulator
- timestamp: 2088
summary: Agent 'pre_race' initiated a content generation call with model 'gemini-flash-lite-latest'.
autoSequencePath: true
sequence:
- gemini
- scaled-simulator
- timestamp: 2088
summary: Agent 'pre_race' invoked remote function capability 'spawn_runners'.
autoSequencePath: true
sequence:
- scaled-simulator
- agent-engine
- timestamp: 2090
summary: Capability 'spawn_runners' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- scaled-simulator
- agent-engine
- timestamp: 2091
summary: Agent 'pre_race' initiated a content generation call with model 'gemini-flash-lite-latest'.
autoSequencePath: true
sequence:
- scaled-simulator
- agent-engine
- timestamp: 2091
summary: Agent 'pre_race' invoked remote function capability 'start_race_collector'.
autoSequencePath: true
sequence:
- scaled-simulator
- agent-engine
- timestamp: 2091
summary: Capability 'start_race_collector' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- scaled-simulator
- agent-engine
- timestamp: 2092
summary: Agent 'pre_race' initiated a content generation call with model 'gemini-flash-lite-latest'.
autoSequencePath: true
sequence:
- scaled-simulator
- gemini
- timestamp: 2092
summary: Agent 'pre_race' invoked remote function capability 'fire_start_gun'.
autoSequencePath: true
sequence:
- scaled-simulator
- agent-engine
- timestamp: 2220
summary: Capability 'fire_start_gun' finished execution and piped results back to execution environment.
autoSequencePath: true
sequence:
- agent-engine
- scaled-simulator
- timestamp: 2221
summary: Agent 'pre_race' initiated a content generation call with model 'gemini-flash-lite-latest'.
autoSequencePath: true
sequence:
- scaled-simulator
- gemini
- timestamp: 2955
summary: "Event tick: Runner at velocity 1.4386, distance 0, water 100. Session ID: 81cb951c-1ba4-4edc-bce4-3da6daf6e677"
autoSequencePath: true
sequence:
- gemma
- scaled-simulator
- timestamp: 5118
summary: "Event tick: Runner at velocity 0.8439, distance 2.6166, water 89.9. Session ID: 35e88278-4772-4fc5-9f74-c9ca3e312bfd"
autoSequencePath: true
sequence:
- gemma
- scaled-simulator
- timestamp: 7580
summary: "Event tick: Runner at velocity 1.2117, distance 7.2691, water 99.3. Session ID: 296eb31a-3426-46dd-bc5a-cc655a582fcc"
autoSequencePath: true
sequence:
- gemma
- scaled-simulator
- timestamp: 10044
summary: "Event tick: Runner at velocity 0.8439, distance 7.7215, water 100. Session ID: 5fc43613-f50e-483d-b498-2f2213f1bda9"
autoSequencePath: true
sequence:
- gemma
- scaled-simulator
- timestamp: 11220
summary: "Event tick: Runner at velocity 0.8439, distance 7.4869, water 98. Session ID: 3d3bd44a-ddce-47e0-bd5c-194593f1a539"
autoSequencePath: true
sequence:
- gemma
- scaled-simulator
- timestamp: 13176
summary: "Event tick: Runner at velocity 0.8716, distance 10.6728, water 90.5. Session ID: 4721cea4-656c-43be-8aa2-c60216eeea87"
autoSequencePath: true
sequence:
- gemma
- scaled-simulator
- timestamp: 15618
summary: "Event tick: Runner at velocity 0.8439, distance 12.8695, water 75.3. Session ID: 4cfbd315-56f9-45e7-811f-be0aa293fde7"
autoSequencePath: true
sequence:
- gemma
- scaled-simulator
- timestamp: 17719
summary: "Event tick: Runner at velocity 0.9192, distance 16.8874, water 100. Session ID: 7c4700ea-f9ac-4653-85db-bacaad4931dc"
autoSequencePath: true
sequence:
- gemma
- scaled-simulator
- timestamp: 20100
summary: "Event tick: Runner at velocity 1.9133, distance 29.5434, water 97.20542606683905. Session ID: 0f0d7374-7301-4736-9c4e-1e340425a7b1"
autoSequencePath: true
sequence:
- gemma
- scaled-simulator
- timestamp: 20710
summary: "Event tick: Runner at velocity 1.3474, distance 28.0116, water 100. Session ID: 07d19553-8c61-41db-abfb-1093142575f5"
autoSequencePath: true
sequence:
- gemma
- scaled-simulator
- timestamp: 23165
summary: "Event tick: Runner at velocity 1.6973, distance 29.5652, water 43.66604124220852. Session ID: 49ed6fd5-0a0a-43dd-8cd4-59675a36daa3"
autoSequencePath: true
sequence:
- gemma
- scaled-simulator
- timestamp: 25630
summary: "Event tick: Runner at velocity 1.2555, distance 26.5227, water 65.24160094507704. Session ID: e7771ddb-0907-4e35-85b4-1790808087dd"
autoSequencePath: true
sequence:
- gemma
- scaled-simulator
- type: inspect
subsections:
- id: planner-inspect
title: Planner agent and Google Maps MCP server
architecture:
- angular
- cloudrun
- pubsub
- basic-planner
- agent-engine
- geap
examples:
- title: Planner
icons:
- /external-assets/basic-planner.svg
- /external-assets/adk.png
mode: markdown
info: |
The Planner is an ADK [`LlmAgent`](https://adk.dev/agents/llm-agents/) that wraps a Gemini model with tools, instructions, and lifecycle callbacks. ADK stands for [Agent Development Kit](https://adk.dev), a specialized suite of software tools, libraries, and APIs designed to simplify the creation, deployment, and management of autonomous AI agents.
| Parameter | What it does |
|-----------|-------------|
| `model` | Pins this agent to `gemini-3-flash-preview`. `LlmAgent` inherits from [parent agents](https://adk.dev/agents/multi-agents/) if left empty. |
| `static_instruction` | `PLANNER.build()` returns the system prompt. Marked as stable, enabling [context caching](https://adk.dev/context/caching/). |
| `generate_content_config` | `temperature=0.1` for structured output like GeoJSON routes. |
| `tools` | `get_tools()` returns a mix of [tool types](https://adk.dev/tools-custom/function-tools/) that ADK runs in parallel: [`SkillToolset`](https://adk.dev/skills/) (lazy-loaded), `PreloadMemoryTool` (injects [past conversations](https://adk.dev/sessions/memory/) before each LLM call), `FunctionTool` wrappers, and an [MCP toolset](https://adk.dev/tools-custom/mcp-tools/) for Google Maps. |
| `before_model_callback` | Runs `financial_guardrail_callback` before every LLM call. If it returns an `LlmResponse`, ADK [skips the model](https://adk.dev/callbacks/types-of-callbacks/) and uses that response instead. |
code:
language: python
linkify: true
repoPath: agents/planner/agent.py
regionTag: planner_agent
- title: Maps MCP Tools
icons:
- /external-assets/basic-planner.svg
- /external-assets/maps.svg
mode: markdown
info: |
This function discovers Google Maps [MCP tools](https://adk.dev/tools-custom/mcp-tools/) at runtime through the [Agent Registry](https://cloud.google.com/vertex-ai/generative-ai/docs/agent-registry/overview) service (`agentregistry.googleapis.com`). Once discovered, the planner's LLM can call Maps tools directly for landmarks, weather, and routing data.
The Maps server is identified in the registry by the string `"mapstools.googleapis.com"` (held in the `_MAPS_MCP_DISPLAY_NAME` constant at the top of the snippet — the resource names are opaque UUIDs, so display name is the stable handle). The discovery flow:
1. Create an `AgentRegistry` client with the project ID and a `header_provider` that injects the Maps API key
2. Call `registry.list_mcp_servers()` and match each entry's `displayName` against `"mapstools.googleapis.com"`
3. Call `registry.get_mcp_toolset()` to get a toolset the LLM can call directly
4. Strip default ADC auth headers, since Maps uses API key auth, not application default credentials
code:
language: python
linkify: true
repoPath: agents/planner/adk_tools.py
regionTag: maps_mcp_tools
- title: Planner Role & Persona
icons:
- /external-assets/basic-planner.svg
- /external-assets/gemini.svg
mode: markdown
info: |
The `ROLE` section opens the system prompt, defining the agent as a city marathon event architect.
The prompt uses short constraint phrases the model can reference when making tradeoffs:
- Five planning priorities: safety, community, logistics, finances, experience
- Route generation instructions for the `plan_marathon_route` tool, including the zone-sweep algorithm and Las Vegas Strip start/finish constraints
code:
language: python
linkify: true
repoPath: agents/planner/prompts.py
regionTag: planner_role
- title: Strict Execution Workflow
icons:
- /external-assets/basic-planner.svg
- /external-assets/gemini.svg
mode: markdown
info: |
The `WORKFLOW` section enforces a strict 7-step execution order.
**Lazy skill loading** (step 2): The agent calls [`load_skill`](https://adk.dev/skills/) to activate `gis-spatial-engineering` right before it needs the route tools. Skills are loaded on-demand, keeping the tool namespace small.
**Parallel tool calls** (step 4): The prompt tells the model to call `report_marathon_route`, weather lookup, and landmark lookup "in the SAME response." ADK [runs them concurrently](https://adk.dev/tools-custom/function-tools/), cutting latency vs. sequential calls.
The "EXACTLY ONCE" constraints prevent models from re-invoking tools on long or ambiguous results.
code:
language: python
linkify: true
repoPath: agents/planner/prompts.py
regionTag: planner_workflow
- id: evaluation-planner-inspect
title: Planner with evaluation
description: |
Extends the base planner with a secondary evaluation agent that scores the route against quality metrics, then refines the plan based on those scores.
architecture:
- cloudrun
- pubsub
- advanced-planner
- agent-engine
- geap
examples:
- title: Planner with Evaluation
icons:
- /external-assets/planner-with-evaluation.svg
- /external-assets/adk.png
mode: markdown
info: |
This agent extends the base Planner with automated plan [evaluation](https://adk.dev/evaluate/). Compare this `get_agent()` to the base planner's. The differences show how ADK agents compose:
| Difference | What changed |
|-----------|-------------|
| `model` | Read from `PLANNER_MODEL` env var (default `gemini-3-flash-preview`), so you can swap models at deploy time |
| `static_instruction` | Uses `PLANNER_WITH_EVAL.build()`, a `PromptBuilder.override()` of the base planner. Replaces the workflow and tools sections with evaluation-aware versions and adds A2UI dashboard instructions. |
| `generate_content_config` | `temperature=0.2`, `max_output_tokens=8192`, and conditional `ThinkingConfig(thinking_budget=1024)` for "pro" models. Visible above `get_agent()` in the snippet. |
| `tools` | Adds `evaluate_plan`, `start_simulation`, `submit_plan_to_simulator`, and `validate_and_emit_a2ui` alongside the base planner's tools |
code:
language: python
linkify: true
repoPath: agents/planner_with_eval/agent.py
regionTag: planner_eval_agent
- title: Strict Evaluation Workflow
icons:
- /external-assets/planner-with-evaluation.svg
- /external-assets/gemini.svg
mode: markdown
info: |
This workflow replaces the base planner's via `PromptBuilder.override()`, expanding it from 7 steps to 9 with evaluation, verification, and A2UI dashboard rendering.
What's new over the base workflow:
- Step 4 adds `assess_traffic_impact` as a parallel tool call alongside `report_marathon_route`
- Step 5 requires coverage of six quality pillars with specific keywords the evaluator checks for
- Step 6 runs `evaluate_plan` and `submit_plan_to_simulator(action="verify")` in the same response. Evaluation scores plan quality while the simulator validates structural readiness, independently and concurrently.
- Step 8 emits a structured UI dashboard via `validate_and_emit_a2ui`
- Step 9 stops the agent ("STOP and wait for user feedback") to prevent unwanted continuation
code:
language: python
linkify: true
repoPath: agents/planner_with_eval/prompts.py
regionTag: eval_workflow
- title: Simulator Handoff
icons:
- /external-assets/planner-with-evaluation.svg
- /external-assets/adk.png
- /external-assets/geap.svg
mode: markdown
info: |
This [`FunctionTool`](https://adk.dev/tools-custom/function-tools/) sends the marathon plan to the simulator agent via the [A2A protocol](https://adk.dev/a2a/intro/). It handles two actions: `verify` (structural check) and `execute` (run the simulation).
Three problems it solves:
**Two-channel data transfer.** The GeoJSON route is too large for an A2A message context window. So the tool writes the full route to Redis (`simdata:{session_id}`) and sends only a reference plus a narrative summary via A2A. The simulator reads the route back from Redis.
**Re-entrancy guard.** The LLM sometimes ignores "STOP" instructions and calls this tool again in the same turn. The guard checks `tool_context.state["simulation_executed_invocation"]` against the current `invocation_id`. Same invocation = duplicate; new user message = legitimate retry.
**Coordination with `start_simulation`.** Both tools get called in the same LLM response. This function polls `tool_context.state` for up to 2 seconds waiting for `start_simulation` to write a fresh `simulator_session_id`, using token matching to distinguish fresh values from stale ones.
code:
language: python
linkify: true
repoPath: agents/planner_with_eval/tools.py
regionTag: submit_to_simulator
- id: memory-planner-inspect
title: Planner with Memory
mode: html
architecture:
- cloudrun
- pubsub
- planner-memory
- geap
examples:
- title: Planner with Memory
icons:
- /external-assets/memory-planner.svg
- /external-assets/adk.png
mode: markdown
info: |
The third planner variant. It extends the eval planner with cross-session [memory](https://adk.dev/sessions/memory/).
The key line is [`after_agent_callback=[auto_save_memories]`](https://adk.dev/callbacks/types-of-callbacks/), an ADK lifecycle hook that fires after the agent completes its response. This pattern works any time you need post-response side effects (logging, persistence, cleanup) without changing what the agent says to the user.
Other differences from the eval planner:
- No `before_model_callback`. The code comments explain why: this variant uses A2UI cards for financial refusals instead of the programmatic guardrail. A `before_model_callback` would short-circuit the LLM before it could emit the refusal card.
- Prompt uses `PLANNER_WITH_MEMORY.build()`, which overrides the eval planner's workflow with memory-aware steps (recall past routes, save new ones).
- Tools add memory recall and AlloyDB rules lookup alongside the eval planner's set.
code:
language: python
linkify: true
repoPath: agents/planner_with_memory/agent.py
regionTag: planner_memory_agent
- title: Memory Integration
icons:
- /external-assets/memory-planner.svg
- /external-assets/adk.png
mode: markdown
info: |
Called by `after_agent_callback` after every agent turn. It saves the current session to [Vertex AI Memory Bank](https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/manage-memory) so future sessions can recall past marathon plans.
1. Checks if a `memory_service` already exists on the `invocation_context` (set during runner initialization)
2. If not, creates one via `create_memory_service()` using the `AGENT_ENGINE_ID` environment variable, which connects to the Memory Bank API for a specific [Agent Engine](https://adk.dev/deploy/agent-engine/) deployment
3. Calls `memory_service.add_session_to_memory(session)`, which sends the session's conversation events to Memory Bank for indexing
On the retrieval side, `PreloadMemoryTool` automatically searches this memory bank before each LLM call and injects relevant past conversations into the system prompt. The model doesn't need to call a tool explicitly.
code:
language: python
linkify: true
repoPath: agents/planner_with_memory/services/memory_manager.py
regionTag: auto_save_memories
links:
- label: "Preload Memory Tool API Reference"
url: https://adk.dev/api-reference/python/google-adk.html#google.adk.tools.preload_memory_tool.PreloadMemoryTool
- id: simulator-inspect
title: Scaling runners with Kubernetes Engine and Gemma
mode: html
architecture:
- cloudrun
- pubsub
- scaled-simulator
- runner-agent
- agent-engine
- kubernetes-engine
- gemma
- geap
examples:
- title: Orchestrating Simulator
icons:
- /external-assets/simulator.svg
mode: markdown
info: |
The simulation uses ADK's [workflow agents](https://adk.dev/agents/workflow-agents/) to run a multi-phase race. This [`SequentialAgent`](https://adk.dev/agents/workflow-agents/sequential-agents/) runs three sub-agents in order:
1. `pre_race_agent` spawns runner NPCs and fires the start gun. It uses a deterministic `before_model_callback` to sequence tool calls without any LLM involvement.
2. `race_engine` is a [`LoopAgent`](https://adk.dev/agents/workflow-agents/loop-agents/) that advances simulation ticks until all runners finish or the race times out. Each iteration calls `advance_tick` then `check_race_complete`, exiting via `actions.escalate` when done.
3. `post_race_agent` collects results and generates analytics.
The `SequentialAgent` itself has no LLM. It just runs `sub_agents` in list order, keeping expensive model calls inside each sub-agent where they're needed. The orchestration layer is pure control flow.
The root simulator agent is actually an `LlmAgent` that wraps this pipeline as an [`AgentTool`](https://adk.dev/agents/multi-agents/). It receives A2A messages, parses the JSON action field, and routes to the right tool.
code:
language: python
linkify: true
repoPath: agents/simulator/agent.py
regionTag: simulator_pipeline
- title: Scaled NPC Runner
icons:
- /external-assets/simulator.svg
- /external-assets/gke.png
- /external-assets/runner.svg
- /external-assets/gemma.png
mode: markdown
info: |
Each NPC runner is an [`LlmAgent`](https://adk.dev/agents/llm-agents/) that receives tick updates and decides how to race. The `static_instruction` defines the full strategy in a compact prompt. A tick update in simulation and games systems is an event that represents a discrete step in time, providing the delta time to apply state updates, AI decisions, or other logic.
The required action sequence: call `accelerate` (or `brake`) to set speed, then call `process_tick` to advance. The model must call tools in this order every turn.
Hydration rules are threshold-based: always rehydrate below 40, probabilistic above 40, always when exhausted. These give the LLM clear decision boundaries instead of open-ended reasoning.
The `inner_thought` parameter on every `process_tick` call is a required 5-word internal monologue. The prompt is specific about what "unique" means here: "random cravings, regrets, weird observations, bargaining with their legs."
code:
language: python
linkify: true
repoPath: agents/runner/agent.py
regionTag: runner_instruction
- id: npc-runner-logic
title: Autonomous NPC Runner Decision Making
description: |
To run hundreds of NPC runners more cost effectively, the platform uses Gemma models served via vLLM on [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine), keeping per-tick latency and cost low.
mode: html
architecture:
- cloudrun
- pubsub
- scaled-simulator
- runner-agent
- agent-engine
- kubernetes-engine
- gemma
- geap
examples:
- title: Competitive Strategy Logic
icons:
- /external-assets/runner.svg
- /external-assets/gemma.png
mode: markdown
info: |
How the runner agent configures its model for high throughput at low cost. The runner supports multiple backends: [Gemini](https://adk.dev/agents/models/google-gemini/), [Ollama](https://adk.dev/agents/models/ollama/), or [vLLM](https://adk.dev/agents/models/vllm/) serving [Gemma](https://adk.dev/agents/models/google-gemma/) on [GKE](https://adk.dev/deploy/gke/).
| Setting | Why |
|---------|-----|
| `include_contents="none"` | No conversation history. The runner gets only the current tick's input, keeping token count constant regardless of race length. Set via `LlmAgent`'s [`include_contents`](https://adk.dev/agents/llm-agents/) parameter. |
| `ThinkingConfig(thinking_budget=0)` | Disables extended thinking for Gemini models. Runners need fast mechanical decisions, not deep reasoning. |
| `temperature` | `0.3` for Gemini (consistent tool use), `0.8` for non-Gemini (more varied `inner_thought` generation). |
| `max_output_tokens=256` | Runner outputs are short: a couple tool calls and a one-sentence summary. Capping tokens saves cost at scale. |
`get_agent()` wires this config with `static_instruction` and the shared running/hydration tools. When running hundreds of NPCs on vLLM + Gemma on GKE, these settings keep per-tick latency and cost low.
code:
language: python
linkify: true
repoPath: agents/runner/agent.py
regionTag: runner_model_config
- id: communication-inspect
title: Inter-agent communication and discovery
mode: html
architecture:
- cloudrun
- pubsub
- agent-engine
examples:
- title: Dynamic Agent Discovery
icons:
- /external-assets/agent-engine.png
mode: markdown
info: |
Agents discover each other at runtime via [A2A](https://adk.dev/a2a/intro/). An `AgentCard` is the structured manifest each ADK agent publishes — its name, URL, supported transports, and capabilities — that callers use to connect to it.
This method fetches every agent card from the Gateway's `/api/v1/agent-types` endpoint, parses each one with `AgentCard.model_validate()` (which handles camelCase ↔ snake_case alias resolution), and caches the result for 30 seconds across all `SimulationA2AClient` instances in the same process.
The caller (`get_agent()`) uses the card's URL to create a `RemoteA2aAgent` instance, picking the right transport: `http_json` for [Agent Engine](https://adk.dev/deploy/agent-engine/) deployments (which reject JSON-RPC), `jsonrpc` for local/[Cloud Run](https://adk.dev/deploy/cloud-run/) agents.
code:
language: python
linkify: true
repoPath: agents/utils/communication.py
regionTag: a2a_discovery
- title: Real-time Telemetry Pulses
icons:
- /external-assets/agent-engine.png
mode: markdown
info: |
`emit_narrative_pulse` is the project's high-level helper for sending a narrative event to a session. The caller provides plain text and an author name; the function fills in the structural fields (origin shape, destination list, status, event type, JSON payload) and delegates to the lower-level `emit_gateway_message` (defined just above this snippet in the same file). That call serializes the event into a protobuf `Wrapper`, publishes it to Redis, and the frontend renders it via WebSocket.
`emit_inter_agent_pulse` builds on top of `emit_narrative_pulse`: it formats a human-readable banner (`📢 planner -> simulator: ...` for requests, `📨` for responses) and forwards it as a narrative pulse with `type="inter-agent"`. So one function call by an agent — `emit_inter_agent_pulse(...)` — flows through `emit_narrative_pulse` → `emit_gateway_message` → Redis → WebSocket → the animated communication graph.
Both wrappers are project utilities, not part of the ADK framework. [View `pulses.py` on GitHub →](https://github.com/GoogleCloudPlatform/race-condition/blob/main/agents/utils/pulses.py)
code:
language: python
linkify: true
repoPath: agents/utils/pulses.py
regionTag: emit_narrative_pulse
- id: prompt-builder-inspect
title: "Concept: Composable prompt management"
# devOnly: true
description: |
Three planner agents share most of their system prompt but differ in specific sections. `PromptBuilder` solves this with named sections in an `OrderedDict`, assembled by `build()`, extended by `override()`. Each variant specifies only what's different.
Below: the builder class, then all three planners and their workflow prompts side by side.
architecture:
- basic-planner
- advanced-planner
- planner-memory
examples:
- title: PromptBuilder
icons:
- /external-assets/basic-planner.svg
mode: markdown
info: |
The class is immutable. `override()` returns a new instance, so you can't accidentally mutate a parent builder that other agents depend on.
Two output modes optimize for [context caching](https://adk.dev/context/caching/):
- `build()` joins all sections into a single string for [`static_instruction`](https://adk.dev/agents/llm-agents/) (stable content, cacheable)
- `dynamic(exclude=(...))` returns an async `InstructionProvider` for `instruction` (per-request content that can read `ctx.state`)
code:
language: python
linkify: true
repoPath: agents/utils/prompt_builder.py
regionTag: prompt_builder
- title: Base planner assembly
icons:
- /external-assets/basic-planner.svg
mode: markdown
info: |
The base planner defines six named sections, each a string constant defined earlier in the file. Order matters: `build()` joins them top-to-bottom, so the model sees `ROLE` first and `FINANCIAL` last.
All three planner variants inherit these sections. When the eval planner calls `override(workflow=EVAL_WORKFLOW)`, only the `workflow` key gets replaced. The other five carry forward unchanged.
code:
language: python
linkify: true
repoPath: agents/planner/prompts.py
regionTag: planner_builder
- title: Base planner workflow
icons:
- /external-assets/basic-planner.svg
mode: markdown
info: |
The base planner's 7-step workflow. This is the `workflow` section that each variant replaces. Compare it with the eval and memory workflows below to see exactly what changes at each level of the override chain.
Steps 1-4 are shared across all variants (generate route, load skill, report results). Steps 5-7 are where variants diverge.
code:
language: python
linkify: true
repoPath: agents/planner/prompts.py
regionTag: planner_workflow
- title: Eval planner override
icons:
- /external-assets/planner-with-evaluation.svg
mode: markdown
info: |
The eval planner inherits from `PLANNER` and replaces two sections (`tools`, `workflow`) while adding three new ones (`simulator`, `a2ui`, `execution`). New keys append to the end of the ordered dict, so the model sees inherited sections first, then eval-specific ones.
code:
language: python
linkify: true
repoPath: agents/planner_with_eval/prompts.py
regionTag: planner_eval_builder
- title: Eval planner workflow
icons:
- /external-assets/planner-with-evaluation.svg
mode: markdown
info: |
The eval workflow expands from 7 to 9 steps. Compare with the base workflow above:
- Steps 1-3 are identical (requirements, skill, route)
- Step 4 adds `assess_traffic_impact` as a parallel call
- Step 5 adds six quality pillars with specific keyword requirements the evaluator checks for
- Step 6 is new: parallel `evaluate_plan` + `submit_plan_to_simulator(action="verify")`
- Steps 8-9 are new: A2UI dashboard emission and explicit STOP
The prompt states "this workflow REPLACES the base planner workflow" so the model doesn't try to merge them.
code:
language: python
linkify: true
repoPath: agents/planner_with_eval/prompts.py
regionTag: eval_workflow
- title: Memory planner override
icons:
- /external-assets/memory-planner.svg
mode: markdown
info: |
The memory planner extends the eval planner, not the base. It replaces `tools`, `workflow`, and `execution` again, and adds `memory` and `post_simulation`. The full chain:
`PLANNER` (6 sections) -> `PLANNER_WITH_EVAL` (replaces 2, adds 3) -> `PLANNER_WITH_MEMORY` (replaces 3, adds 2)
Each level only specifies what's different. `ROLE`, `RULES`, `SKILLS`, and `FINANCIAL` are defined once in the base and inherited through the entire chain.
code:
language: python
linkify: true
repoPath: agents/planner_with_memory/prompts.py
regionTag: planner_memory_builder
- title: Memory planner workflow
icons:
- /external-assets/memory-planner.svg
mode: markdown
info: |
The memory workflow is the most complex variant. Compare with the base and eval workflows:
- Adds `TERMINAL_RULES` preamble: after any simulation, the agent must call `record_simulation` + `store_simulation_summary` + emit an A2UI card, then stop. This prevents re-execution.
- Adds message classification before step 1: "recall a stored route" vs. "plan a new marathon" routes to different workflows entirely
- Step 2 is new: parallel `recall_past_simulations` + `get_local_and_traffic_rules` before skill loading
- Step 6 adds `store_route` as a parallel call alongside verification, persisting the route for future recall
11 total sections, but the core `ROLE`, `RULES`, `SKILLS`, and `FINANCIAL` are still just inherited from the base.
code:
language: python
linkify: true
repoPath: agents/planner_with_memory/prompts.py
regionTag: memory_workflow
- id: autopilot-inspect
title: "Concept: LLM-free agents with callback interception"
# devOnly: true
description: |
This project runs two versions of the same runner agent: one powered by Gemini/Gemma, one completely deterministic.
- **Cost.** At 1000 runners x ~50 ticks per race, that's 50,000 model calls per simulation. The autopilot runner makes zero.
- **Latency.** LLM calls take 200-2000ms. The autopilot callback returns in microseconds.
- **Determinism.** Same session ID, same runner profile, same race outcome. Good for testing, replay, and debugging.
- **Reliability.** No prompt injection, no hallucinated tool calls, no "I'm sorry, I can't accelerate" refusals.
The agent still gets ADK's [A2A protocol](https://adk.dev/a2a/intro/), tool calling, telemetry, and session state without the LLM. The simulator doesn't care which version is running.
architecture:
- cloudrun
- runner-agent
- kubernetes-engine
examples:
- title: Autopilot agent wiring
icons:
- /external-assets/runner.svg
mode: markdown
info: |
The autopilot reuses the base runner via `get_base_agent()` and overrides three things: the callback, the instruction, and the generation config. The model (`gemini-3.1-flash-lite-preview`) is inherited from the base runner and never actually called -- `before_model_callback=autopilot_callback` intercepts every invocation.
ADK's `LlmAgent` requires a valid model name; you can't pass `"none"` or an arbitrary string. The model here is a real Gemini model used as a fallback: if the callback ever fails to return an `LlmResponse`, ADK calls this model instead. `max_output_tokens=1` and `temperature=0.0` minimize cost and nondeterminism in that case.
code:
language: python
linkify: true
repoPath: agents/runner_autopilot/agent.py
regionTag: autopilot_agent
- title: Building LlmResponse objects
icons:
- /external-assets/runner.svg
mode: markdown
info: |
When your [`before_model_callback`](https://adk.dev/callbacks/types-of-callbacks/) returns an `LlmResponse`, ADK treats it as if the model produced it. You can return tool calls, and ADK will execute them through its normal tool pipeline.
There are two response patterns here:
`_function_call_response(name, args)` builds an `LlmResponse` containing a `FunctionCall` part. ADK sees this, runs the named tool with the given args, then calls the callback *again* with the tool's result appended to `llm_request.contents`. This is the DECIDE phase.
`_text_response(text)` builds an `LlmResponse` containing a text part. ADK treats this as the agent's final answer for the turn. This is the SUMMARIZE phase.
The two-phase loop (DECIDE, then SUMMARIZE) mirrors what an LLM would do on its own: pick an action, see the result, respond. The callback makes both decisions programmatically instead. Watch out for the re-invocation behavior: after a tool call, ADK calls your callback again with the tool result. If you don't detect that second call and return text, you'll loop forever.
code:
language: python
linkify: true
repoPath: agents/runner_autopilot/autopilot.py
regionTag: autopilot_responses
- title: Dispatch table and callback
icons:
- /external-assets/runner.svg
mode: markdown
info: |
`autopilot_callback` is the callback entry point, called by ADK before every model invocation. Because it always returns an `LlmResponse`, the model never runs.
Here's how a request flows through:
1. `detect_phase()` checks whether the last content entry has `function_response` parts. If so, a tool just executed and we're in SUMMARIZE phase. Return a one-line status summary.
2. Otherwise, we're in DECIDE phase. Parse the user message into a typed `RunnerEvent` (event type + data dict).
3. Look up the handler in the `HANDLERS` dispatch table. Each handler is a pure function: `(state, data) -> LlmResponse`.
4. Return the handler's response. ADK executes any tool calls in it, then calls back for the summary.
Adding a new event type is just two steps: write a handler function, add it to `HANDLERS`. The callback itself doesn't change.
code:
language: python
linkify: true
repoPath: agents/runner_autopilot/autopilot.py
regionTag: autopilot_dispatch
- id: a2ui-inspect
title: "Concept: A2UI — teaching agents to render UI"
# devOnly: true
description: |
[A2UI](https://a2ui.org) is an open protocol for agents to emit declarative UI as JSON. The agent composes a flat list of typed components (Card, Row, Text, Button, Slider, and 12 others from the [v0.8 Standard Catalog](https://a2ui.org/specification/v0.8-a2ui/)). The frontend renders them natively. No executable code crosses the trust boundary.
This project teaches the agent the protocol through an [ADK skill](https://adk.dev/skills/) containing the spec, a validation tool that catches structural errors before the payload reaches the frontend, and dashboard templates in the system prompt.
architecture:
- angular
- advanced-planner
- cloudrun
examples:
- title: Component spec as a skill
icons:
- /external-assets/planner-with-evaluation.svg
mode: markdown
info: |
The agent learns the A2UI protocol from this skill file. When loaded via [`load_skill`](https://adk.dev/skills/), the content below becomes part of the system prompt. The `validate_and_emit_a2ui` tool is registered separately as a top-level [`FunctionTool`](https://adk.dev/tools-custom/function-tools/) by the planner, so it stays available regardless of whether this skill is loaded.
The spec defines three things the LLM needs to produce valid payloads:
1. **Message structure.** Two message types work together: `surfaceUpdate` sends a flat array of component definitions, `beginRendering` tells the frontend which component is root. Both are required. Without `beginRendering`, the frontend buffers components but never renders them.
2. **Typed value wrappers.** All property values use wrappers like `{"literalString": "..."}` or `{"literalBoolean": true}` instead of raw JSON primitives. This is how the [A2UI v0.8 protocol](https://a2ui.org/specification/v0.8-a2ui/) distinguishes literal values from data-bound paths.
3. **The 18 Standard Catalog primitives.** Layout containers (Column, Row, Card), display components (Text, Image, Icon), and input controls (Button, Slider, TextField). Each has required and optional properties listed in the tables below.
Why a skill file instead of hardcoding the spec in the prompt? Skills are lazy-loaded. Agents that don't need A2UI rendering never pay the token cost.
code:
linkify: true
repoPath: agents/skills/a2ui-rendering/SKILL.md
regionTag:
- a2ui_skill_message_structure
- a2ui_skill_wrappers
- title: Validation tool
icons:
- /external-assets/planner-with-evaluation.svg
mode: markdown
info: |
This tool catches structural mistakes before the payload reaches the frontend, returning violations the LLM can act on to self-correct.
Validation runs in two passes:
**Pass 1 (per-component)** iterates the `components` array and checks four things for each entry: the component type exists in the 18-type catalog, all required properties are present, string and boolean properties use typed wrappers (`literalString`, `literalBoolean`) instead of raw values, and container children use `{"explicitList": [...]}` instead of raw arrays.
**Pass 2 (reference resolution)** collects every ID reference from `child`, `children.explicitList`, `tabItems[].child`, `entryPointChild`, and `contentChild` properties, then verifies each one resolves to a component ID in the same `surfaceUpdate`. This catches dangling references from typos or deleted components.
On failure, the tool returns `{"status": "error", "violations": [...]}` where each violation includes the component ID, field name, and a human-readable fix. The LLM reads these, patches the payload, and calls the tool again. On success, the validated payload passes through to the frontend via the ADK event stream.
code:
linkify: true
repoPath: agents/skills/a2ui-rendering/tools.py
regionTag:
- a2ui_validation_passes
- a2ui_validation_result
- title: Dashboard template in the prompt
icons:
- /external-assets/planner-with-evaluation.svg
mode: markdown
info: |
The skill spec tells the LLM *what* A2UI components exist. This prompt teaches it *how* to assemble them. The example is the smallest valid `surfaceUpdate` + `beginRendering` pair: a `Card` containing a `Column` with two `Text` children, four components total.
The full Plan Dashboard and Simulation Results templates further down in the `A2UI` constant follow the same pattern. They just compose more rows and columns.
Three rules trip up LLMs and the example shows all three: `Card` takes a singular `child` ID (not `body` or `children`), container children go inside `explicitList`, and every string value gets a `literalString` wrapper.
The eval planner picks this up via `PromptBuilder.override(a2ui=A2UI)`, which appends it after the inherited base prompt. Other planners don't get it.
code:
linkify: true
repoPath: agents/planner_with_eval/prompts.py
regionTag: a2ui_prompt_template
- title: Recursive frontend renderer
icons:
- /external-assets/angular.svg
mode: markdown
info: |
The Angular renderer uses a single recursive `ng-template` to walk the A2UI component tree. Four excerpts from the template show the pattern.
The **entry point** binds `rootNode` to the template, which dispatches on `getType(node)` via `ngSwitch`. Each component type gets its own case. The CSS class is derived from the type name (`a2ui-Column`, `a2ui-Text`, etc.), so styling maps directly to the A2UI catalog.
**Column** is a layout container. It iterates `getChildren(node)` and recurses through the same `#renderer` template for each child. Row, List, and Card follow the same pattern with minor variations.
**Display components** (Text, Icon, Image) are leaf nodes. They read properties through helpers like `getText()` and `getUsageHint()`, which unwrap the v0.8 typed value wrappers (`{literalString: "..."}`) into plain strings. No recursion needed.
**Button** is where the agent's actions reach the user. It recurses its `child` for the label, and `handleButtonClick` routes the `action.name` string to a registry of TypeScript callbacks. The `run_simulation` action, for example, sends a message back to the agent via the gateway service.
code:
language: html
linkify: true
repoPath: web/frontend/src/app/components/a2ui/a2-ui-controller.component.html
regionTag:
- a2ui_template_entry
- a2ui_template_column
- a2ui_template_display
- a2ui_template_button
- type: quiz
questions:
- title: Which Google Cloud framework is used to build the autonomous agents in the Race Condition simulation?
answers:
- answer: Angular Development Platform
- answer: Agent Development Kit (ADK)
correct: true
- answer: Cloud Run Functions SDK
- answer: Vertex AI Studio
- title: How does the Planner agent fetch real-world geographic and routing data?
answers:
- answer: By querying a static local JSON dataset
- answer: Through a Model Context Protocol (MCP) server connected to Google Maps
correct: true
- answer: Using hardcoded lat/long pairs in system prompts
- answer: By using the Google Maps JavaScript API
- title: To scale the simulation to hundreds of autonomous NPCs economically, where are the lightweight runner models hosted?
answers:
- answer: As Google Kubernetes Engine (GKE) workloads serving Gemma via vLLM
correct: true
- answer: Inside a single local Docker container using SQLite
- answer: On Cloud Storage buckets using static HTML rendering
- answer: Using standard HTTP callbacks to third-party webhooks
- title: What technique is used by the Advanced Planner to ensure the generated marathon route meets safety and logistical standards?
answers:
- answer: Manual human-in-the-loop approval via email
- answer: Automated LLM-as-Judge evaluation scoring
correct: true
- answer: Simple regex string matching on the narrative output
- answer: Unit tests using standard Python assertions
- title: How do agents within the simulation persist important data across independent user sessions?
answers:
- answer: Storing flat files inside container memory
- answer: Writing logs directly to stdout for persistent capture
- answer: Leveraging the Vertex AI Memory Bank service
correct: true
- answer: Stashing variables in browser localStorage
- type: video
youtubeId: WYPdz3OZfuQ
navigationTitle: "Bonus: Fireside Chat"
title: Fireside chat with the team
description: Join Casey West and Tom Greenaway as they chat through some of the development choices and learnings made during the creation of Race Condition.
# - type: video
# youtubeId: A01DQ8_xy7Q
# navigationTitle: "Bonus: Developer Keynote"
# title: Cloud Next 2026 Developer Keynote
# description: Watch the full developer keynote from Cloud Next 2026, featuring Race Condition as the simulation sandbox powering all the agent demos and other announcements.
- type: build
promoType: github
links:
- url: https://github.com/GoogleCloudPlatform/race-condition
label: Open on GitHub
- url: https://developer.google.com/solutions
label: Explore more Solutions
- url: https://docs.cloud.google.com/gemini-enterprise-agent-platform
label: Gemini Enterprise Agent Platform
architecture:
height: 420
# expandedByDefault: true
boxes:
- id: geapbox
label: "Gemini Enterprise Agent Platform"
entities:
- geap
- session-store
- memory-bank
- gemini
entities:
- id: angular
label: Angular
icon: /external-assets/angular.svg
x: 0
y: -4
connections:
- from: angular
to: cloudrun
- id: cloudrun
label: Cloud Run
icon: /external-assets/cloud-run.svg
x: 2
y: -4
connections:
- from: cloudrun
to: pubsub
- id: pubsub
label: Pub/Sub
icon: /external-assets/pubsub.svg
x: 4
y: -4
connections:
- from: pubsub
to: basic-planner
- from: pubsub
to: advanced-planner
- from: pubsub
to: planner-memory
- from: pubsub
to: scaled-simulator
# - from: pubsub
# to: agent-engine
- id: basic-planner
label: Planner
icon: /external-assets/basic-planner.svg
x: 6
y: -4
inspect: planner-inspect
connections:
- from: basic-planner
to: agent-engine
- from: basic-planner
to: google-maps
- id: google-maps
label: Google Maps
icon: /external-assets/maps.svg
x: 6
y: -6
- id: advanced-planner
label: Planner with evaluation
icon: /external-assets/planner-with-evaluation.svg
x: 6
y: -2
inspect: evaluation-planner-inspect
connections:
- from: advanced-planner
to: agent-engine
- id: planner-memory
label: Planner with memory
icon: /external-assets/memory-planner.svg
x: 6
y: -8
inspect: memory-planner-inspect
connections:
- from: planner-memory
to: agent-engine
- from: planner-memory
to: memorystore
- from: planner-memory
to: alloy
- from: planner-memory
to: geap
- id: scaled-simulator
label: Simulator
icon: /external-assets/simulator.svg
x: 6
y: 0
inspect: simulator-inspect
connections:
- from: scaled-simulator
to: agent-engine
- from: scaled-simulator
to: runner-agent
- id: runner-agent
label: Runner Agent
icon: /external-assets/runner.svg
x: 8
y: 1
inspect: npc-runner-logic
connections:
- from: runner-agent
to: agent-engine
- from: runner-agent
to: kubernetes-engine
- id: kubernetes-engine
label: Kubernetes Engine
icon: /external-assets/gke.png
x: 10
y: 1
connections:
- from: kubernetes-engine
to: gemma
- id: gemma
label: Gemma
icon: /external-assets/gemma.png
x: 12
y: 1
- id: agent-engine
label: Agent Engine
icon: /external-assets/agent-engine.png
x: 8
y: -4
inspect: communication-inspect
connections:
- from: agent-engine
to: geap
- id: memorystore
label: Memorystore
icon: /external-assets/memorystore.svg
x: 8
y: -9
- id: alloy
label: AlloyDB
icon: /external-assets/alloy.svg
x: 8
y: -7
- id: geap
label: Gemini Enterprise Agent Platform
icon: /external-assets/geap.svg
x: 10
y: -4
connections:
- from: geap
to: gemini
- from: geap
to: session-store
- from: geap
to: memory-bank
- id: gemini
label: Gemini
icon: /external-assets/gemini.svg
x: 12
y: -6
- id: session-store
label: Session Store
icon: /external-assets/session-store.svg
x: 12
y: -4
- id: memory-bank
label: Memory Bank
icon: /external-assets/memory-bank.svg
x: 12
y: -2
badges:
startBadge: https://developers.google.com/profile/badges/playlists/solutions/race-condition/view
exploreBadge: https://developers.google.com/profile/badges/playlists/solutions/race-condition/learn
quizBadge: https://developers.google.com/profile/badges/playlists/solutions/race-condition/quiz
buildBadge: https://developers.google.com/profile/badges/playlists/solutions/race-condition/action