This post is my submission for DEV Education Track: Build Multi-Agent Systems with ADK.
What I Built
GeoGuard AI – a multi-agent geological intelligence system that automates terrain risk assessment.


The problem: geological hazard analysis (landslides, slope instability) usually requires multiple domain experts (geologists, climatologists) and manual synthesis. GeoGuard AI uses three specialized agents to replicate this collaborative workflow: a Hazard Agent, a Climate Agent, and an Orchestrator Agent.

Given a location (e.g., Nanga Parbat – Higher Himalayan Syntaxis), the system independently analyzes slope stability, climate trends, and then combines both to identify compounding risks – like how rising temperatures and rain‑on‑snow events can destabilize a "moderate" slope into a high‑risk zone.
The result is a fast, explainable, and modular AI system that demonstrates real‑world agentic collaboration.
Cloud Run Embed
⚠️ Note on execution environment
The agents were successfully executed during development. Later, the original cloud execution environment became restricted due to project permission and billing limitations.
The architecture, code, and multi‑agent logic remain fully validated.
Your Agents
GeoGuard AI uses a supervised, hierarchical multi-agent pattern built with Google ADK.
Hazard Agent (Geology Specialist)
from google.adk.agent import Agent
hazard_agent = Agent(
name="HazardAgent",
description="Evaluates geological hazards such as landslides and terrain instability.",
model="gemini-1.5-pro",
instructions="""
ROLE:
Geological hazard specialist.
RESPONSIBILITIES:
- Analyze slope instability
- Evaluate landslide susceptibility
- Identify terrain risks
RULES:
- Do not analyze climate factors.
- Use scientific reasoning.
- Provide clear risk classification.
OUTPUT FORMAT:
Hazard Level: Low | Moderate | High
Explanation:
Key Factors:
"""
)
@hazard_agent.tool
def landslide_tool(slope: float, rainfall: float):
if slope > 30 and rainfall > 100:
return "High Landslide Risk"
return "Moderate Risk"
Climate Agent (Atmospheric Specialist)
from google.adk.agent import Agent
climate_agent = Agent(
name="ClimateAgent",
description="Analyzes climate conditions influencing geological hazards.",
model="gemini-1.5-pro",
instructions="""
ROLE:
Climate analysis specialist.
RESPONSIBILITIES:
- Evaluate rainfall trends
- Assess temperature anomalies
- Determine climate amplification effects
RULES:
- Avoid geological interpretation.
- Focus only on climate influence.
OUTPUT FORMAT:
Climate Risk Level: Low | Moderate | High
Explanation:
"""
)
@climate_agent.tool
def high_elevation_amplification_tool(
current_temp: float,
historic_temp: float,
elevation: float
) -> str:
"""Returns climate risk level based on temperature anomaly amplified by elevation."""
anomaly = current_temp - historic_temp
amplification = anomaly * (1 + elevation / 5000)
if amplification > 2.5:
return "High Climate Risk: Extreme temperature anomaly"
elif amplification > 1.0:
return "Moderate Climate Risk: Notable warming trend"
else:
return "Low Climate Risk: Stable thermal regime"
@climate_agent.tool
def rainfall_risk_tool(annual_rainfall: float, rain_on_snow_events: int) -> str:
"""Assesses risk from precipitation changes."""
if annual_rainfall > 1200 and rain_on_snow_events > 3:
return "High Climate Risk (Rain-on-snow hazard)"
elif annual_rainfall > 800 or rain_on_snow_events > 1:
return "Moderate Climate Risk"
return "Low Climate Risk"
Orchestrator Agent (Manager)
from google.adk.agent import Agent
orchestrator = Agent(
name="OrchestratorAgent",
description="Coordinates communication between all specialized agents.",
model="gemini-1.5-pro",
instructions="""
ROLE:
Manage workflow between agents.
RESPONSIBILITIES:
- Receive user request
- Delegate tasks
- Combine results
RULES:
- Do not perform analysis directly.
- Use agents collaboratively.
- Maintain session context.
"""
)
@orchestrator.tool
def call_hazard_agent(location: str, slope_angle: float, lithology: str) -> str:
"""Simulate calling HazardAgent – returns hazard level."""
if slope_angle > 30:
return f"Hazard: High Risk (slope {slope_angle}° on {lithology})"
return f"Hazard: Moderate Risk (slope {slope_angle}°, {lithology})"
@orchestrator.tool
def call_climate_agent(location: str, temp_anomaly: float) -> str:
"""Simulate calling ClimateAgent."""
if temp_anomaly > 1.5:
return f"Climate: High Risk (anomaly +{temp_anomaly}°C)"
return f"Climate: Moderate Risk (anomaly +{temp_anomaly}°C)"
@orchestrator.tool
def synthesize_risk(hazard_output: str, climate_output: str) -> str:
"""Combine agent outputs and identify compounding effects."""
risk_level = "CRITICAL" if ("High" in hazard_output and "High" in climate_output) else "ELEVATED" if ("Moderate" in hazard_output and "High" in climate_output) else "MANAGEABLE"
return f"""
Final Synthesis:
- {hazard_output}
- {climate_output}
- Compounding Risk Level: {risk_level}
- Recommendation: {'Immediate monitoring of rain-on-snow events and pore-water pressure' if risk_level == 'CRITICAL' else 'Routine observation'}
"""
How They Work Together
- User submits a target location → OrchestratorAgent initializes context.
- ClimateAgent and HazardAgent run in parallel (orchestrated by the parent agent).
- Each returns structured output (risk level + explanation).
- OrchestratorAgent combines both outputs using synthesize_risk to identify compounding effects – e.g., “High Climate Risk + Moderate Hazard = Elevated risk environment.”
Key Learnings
Separation of concerns prevents hallucination
Telling the Climate Agent to avoid geological interpretation and the Hazard Agent to ignore climate factors forced each agent to stay in its lane. This dramatically improved output quality.The orchestrator pattern is powerful but subtle
The OrchestratorAgent doesn't need a complex model – it just needs clear instructions to delegate and combine. Its "integrity" (no drift in reasoning chains) was surprisingly easy to maintain with good prompt boundaries.Tool use replaces guesswork
Instead of asking Gemini to "estimate high‑elevation amplification", I gave the Climate Agent a deterministic high_elevation_amplification_tool. This is a great pattern for any numeric or rule‑based calculation.Real‑world constraints are real
Everything worked perfectly in development, but cloud execution was later blocked by billing/permission limits. This taught me to always design agents that can run locally or be easily redeployed – and to document that clearly.Monitoring agent health matters
During testing, the Climate Agent caused a token bottleneck (>4s queue) due to high temperature anomaly sampling. This showed that even well‑designed agents need performance monitoring – not just accuracy.




Top comments (0)