Skip to content
Learn Agentic AI12 min read0 views

AI Agent for Emergency Management: Disaster Information, Shelter Locations, and Updates

Learn how to build an AI agent for emergency management agencies that distributes disaster alerts, maps shelter locations, coordinates resource information, and provides real-time updates to affected citizens.

When Every Second of Communication Matters

During natural disasters — hurricanes, wildfires, floods, earthquakes — emergency management agencies face a communications crisis of their own. Hundreds of thousands of people need answers simultaneously: "Is my area under evacuation?" "Where is the nearest shelter?" "Is the shelter pet-friendly?" "When will power be restored?" "Where can I get drinking water?"

911 and emergency hotlines are overwhelmed. Social media fills with rumors. Official websites crash under traffic spikes. An AI agent can serve as a scalable, always-available information channel that provides accurate, location-specific answers to these questions. It does not coordinate the actual emergency response — it handles the citizen-facing communication layer so that emergency managers can focus on operations.

Designing for Disaster Conditions

Emergency management agents must work under constraints that normal government agents do not face. Internet connectivity may be intermittent. Power may be out. People are stressed, frightened, and may not speak English. The agent must be designed for degraded conditions from day one.

from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum


class DisasterType(Enum):
    HURRICANE = "hurricane"
    WILDFIRE = "wildfire"
    FLOOD = "flood"
    EARTHQUAKE = "earthquake"
    TORNADO = "tornado"
    WINTER_STORM = "winter_storm"
    HAZMAT = "hazardous_materials"
    TSUNAMI = "tsunami"


class AlertLevel(Enum):
    ADVISORY = "advisory"       # be aware
    WATCH = "watch"             # be prepared
    WARNING = "warning"         # take action
    EMERGENCY = "emergency"     # take action immediately


@dataclass
class DisasterEvent:
    event_id: str
    disaster_type: DisasterType
    name: str  # e.g., "Hurricane Maria"
    alert_level: AlertLevel
    affected_zones: list[str]  # zip codes, zone IDs
    start_time: datetime
    summary: str
    instructions: list[str]
    evacuation_zones: list[str] = field(default_factory=list)
    curfew_hours: str | None = None
    updated_at: datetime = field(default_factory=datetime.utcnow)


@dataclass
class EmergencyUpdate:
    update_id: str
    event_id: str
    timestamp: datetime
    message: str
    category: str  # shelter, power, water, roads, rescue
    affected_zones: list[str]
    source: str  # "County EOC", "National Weather Service"

Shelter Management System

During evacuations, shelter information is the most critical data the agent provides. People need to know where to go, whether the shelter has capacity, and whether it accommodates their specific needs (pets, medical equipment, accessibility).

@dataclass
class Shelter:
    shelter_id: str
    name: str
    address: str
    latitude: float
    longitude: float
    capacity: int
    current_occupancy: int
    status: str  # open, full, closed, opening_soon
    amenities: list[str] = field(default_factory=list)
    pet_friendly: bool = False
    ada_accessible: bool = True
    medical_staff: bool = False
    accepts_medical_equipment: bool = False
    generator_powered: bool = False
    last_updated: datetime = field(default_factory=datetime.utcnow)


SHELTER_REGISTRY: list[Shelter] = []


def find_nearest_shelters(
    user_lat: float,
    user_lon: float,
    needs_pet_friendly: bool = False,
    needs_medical: bool = False,
    needs_accessible: bool = False,
    max_results: int = 5,
) -> list[dict]:
    """Find nearest open shelters matching the user's needs."""
    from math import radians, sin, cos, sqrt, atan2

    def haversine(lat1, lon1, lat2, lon2):
        R = 3959
        dlat = radians(lat2 - lat1)
        dlon = radians(lon2 - lon1)
        a = sin(dlat/2)**2 + cos(radians(lat1)) * cos(radians(lat2)) * sin(dlon/2)**2
        return R * 2 * atan2(sqrt(a), sqrt(1-a))

    candidates = []
    for shelter in SHELTER_REGISTRY:
        if shelter.status not in ("open", "opening_soon"):
            continue
        if needs_pet_friendly and not shelter.pet_friendly:
            continue
        if needs_medical and not shelter.medical_staff:
            continue
        if needs_accessible and not shelter.ada_accessible:
            continue

        distance = haversine(user_lat, user_lon, shelter.latitude, shelter.longitude)
        spots_remaining = shelter.capacity - shelter.current_occupancy

        candidates.append({
            "name": shelter.name,
            "address": shelter.address,
            "distance_miles": round(distance, 1),
            "status": shelter.status,
            "spots_remaining": max(0, spots_remaining),
            "capacity_pct": round(shelter.current_occupancy / shelter.capacity * 100),
            "pet_friendly": shelter.pet_friendly,
            "ada_accessible": shelter.ada_accessible,
            "has_medical_staff": shelter.medical_staff,
            "generator_powered": shelter.generator_powered,
            "amenities": shelter.amenities,
            "last_updated": shelter.last_updated.isoformat(),
        })

    candidates.sort(key=lambda x: x["distance_miles"])
    return candidates[:max_results]

Alert Distribution Engine

The alert engine determines which information to push to which citizens based on their location and the disaster's affected zones.

See AI Voice Agents Handle Real Calls

Book a free demo or calculate how much you can save with AI voice automation.

from datetime import timedelta


class AlertDistributor:
    """Distribute disaster alerts to affected citizens."""

    def __init__(self):
        self.active_events: dict[str, DisasterEvent] = {}
        self.updates: list[EmergencyUpdate] = []

    def get_alerts_for_location(self, zipcode: str) -> list[dict]:
        """Get all active alerts affecting a specific location."""
        relevant = []

        for event in self.active_events.values():
            if zipcode in event.affected_zones or "all" in event.affected_zones:
                is_evacuation = zipcode in event.evacuation_zones

                relevant.append({
                    "event_name": event.name,
                    "type": event.disaster_type.value,
                    "alert_level": event.alert_level.value,
                    "summary": event.summary,
                    "instructions": event.instructions,
                    "evacuation_required": is_evacuation,
                    "curfew": event.curfew_hours,
                    "last_updated": event.updated_at.isoformat(),
                })

        # Sort by severity (emergency first)
        level_order = {
            "emergency": 0, "warning": 1, "watch": 2, "advisory": 3,
        }
        relevant.sort(key=lambda x: level_order.get(x["alert_level"], 4))
        return relevant

    def get_recent_updates(
        self, event_id: str, since_hours: int = 6
    ) -> list[dict]:
        """Get recent updates for a specific disaster event."""
        cutoff = datetime.utcnow() - timedelta(hours=since_hours)

        recent = [
            u for u in self.updates
            if u.event_id == event_id and u.timestamp >= cutoff
        ]
        recent.sort(key=lambda u: u.timestamp, reverse=True)

        return [
            {
                "time": u.timestamp.strftime("%I:%M %p"),
                "category": u.category,
                "message": u.message,
                "source": u.source,
            }
            for u in recent
        ]

Resource Coordination Information

Beyond shelters, citizens need to know about water distribution points, food banks, fuel availability, and medical facilities that are operational.

@dataclass
class ResourcePoint:
    resource_id: str
    resource_type: str  # water, food, fuel, medical, charging_station
    name: str
    address: str
    latitude: float
    longitude: float
    hours: str
    status: str  # open, closed, limited
    notes: str = ""
    last_verified: datetime = field(default_factory=datetime.utcnow)


def find_resources(
    user_lat: float,
    user_lon: float,
    resource_type: str,
    resources: list[ResourcePoint] = None,
    max_distance: float = 15.0,
) -> list[dict]:
    """Find nearby resource distribution points."""
    from math import radians, sin, cos, sqrt, atan2

    def haversine(lat1, lon1, lat2, lon2):
        R = 3959
        dlat = radians(lat2 - lat1)
        dlon = radians(lon2 - lon1)
        a = sin(dlat/2)**2 + cos(radians(lat1)) * cos(radians(lat2)) * sin(dlon/2)**2
        return R * 2 * atan2(sqrt(a), sqrt(1-a))

    results = []
    for r in resources or []:
        if r.resource_type != resource_type:
            continue
        if r.status == "closed":
            continue

        distance = haversine(user_lat, user_lon, r.latitude, r.longitude)
        if distance > max_distance:
            continue

        results.append({
            "name": r.name,
            "address": r.address,
            "distance_miles": round(distance, 1),
            "hours": r.hours,
            "status": r.status,
            "notes": r.notes,
            "last_verified": r.last_verified.strftime("%b %d, %I:%M %p"),
        })

    results.sort(key=lambda x: x["distance_miles"])
    return results[:10]

The Emergency Agent with Crisis Communication Principles

The agent's language during emergencies must follow established crisis communication principles: be first, be right, be credible.

EMERGENCY_AGENT_PROMPT = """You are an emergency information agent for the
county emergency management agency.

CRISIS COMMUNICATION RULES:
1. Be SPECIFIC and ACTIONABLE. Not "seek shelter" but "go to Lincoln High
   School shelter at 1234 Oak Street, capacity available, pet-friendly."
2. Lead with the most critical information. Evacuation orders first,
   then shelter locations, then resource points.
3. Include timestamps on all information. "As of 3:00 PM" matters during
   rapidly evolving situations.
4. Acknowledge uncertainty. If you do not have current shelter occupancy
   data, say so rather than guessing.
5. Never minimize danger. If an evacuation order is active, communicate
   urgency clearly.
6. Provide information in the user's language if possible.
7. For life-threatening emergencies, always direct to 911 first.
8. Include accessibility information for shelters proactively.

You have access to these tools:
- get_alerts(zipcode): Get active disaster alerts for a location
- find_shelters(lat, lon, needs): Find nearby open shelters
- find_resources(lat, lon, type): Find water, food, fuel, medical points
- get_updates(event_id): Get latest situational updates

Always end emergency responses with the local emergency hotline number.
"""

The language design is critical. During Hurricane Harvey, official communications that said "GET OUT OR DIE" were more effective than polite suggestions because they conveyed urgency without ambiguity. The agent should calibrate its tone to the alert level — advisory messages are informational, but emergency-level messages should convey urgency clearly.

FAQ

How does the agent function when internet connectivity is degraded during a disaster?

The agent is designed with a fallback architecture. The primary mode is full LLM-powered conversation over the internet. If connectivity is limited, the agent falls back to a keyword-matching mode that runs on cached data locally — it can still answer "nearest shelter" and "am I in an evacuation zone" using pre-downloaded shelter data and zone maps. For complete outage scenarios, the emergency management agency deploys SMS-based querying where citizens text a keyword (SHELTER, WATER, POWER) to a short code and receive automated responses from a lightweight backend that does not require internet access for the citizen.

How do you keep shelter occupancy data current during a rapidly evolving disaster?

Shelter occupancy is updated through multiple channels. Staff at each shelter report check-ins through a mobile app or phone call to the Emergency Operations Center (EOC). The EOC dashboard updates the central database, which the agent queries in real-time. Updates flow every 15-30 minutes during active operations. The agent always displays the "last updated" timestamp so citizens can assess how current the information is. If a shelter has not been updated in over 2 hours, the agent flags this: "Occupancy data for Lincoln High School was last updated at 2:00 PM — call the shelter directly at (555) 123-4567 for current availability."

Can the agent help citizens report damage or request assistance during recovery?

Yes. After the immediate emergency phase, the agent shifts to recovery mode. It helps citizens report property damage to the local emergency management agency, guides them through FEMA Individual Assistance applications, provides information about SBA disaster loans, and connects them with volunteer organizations (Red Cross, local relief agencies). It also tracks the status of utility restoration by neighborhood, road closures and reopenings, and boil-water advisories. The agent's role evolves with the disaster lifecycle: from preparedness (before), to response (during), to recovery (after).


#GovernmentAI #EmergencyManagement #DisasterResponse #ShelterMapping #CrisisCommunication #AgenticAI #LearnAI #AIEngineering

Share this article
C

CallSphere Team

Expert insights on AI voice agents and customer communication automation.

Try CallSphere AI Voice Agents

See how AI voice agents work for your industry. Live demo available -- no signup required.