Project Info
Inspiration
During a disaster, the safest route can change in seconds. A road may become blocked, a fire perimeter may expand, visibility may deteriorate, or a new emergency call may suddenly become the highest priority. Traditional navigation systems optimize for ordinary travel. Emergency responders need something different: a system that can understand rapidly changing field reports, account for vehicle capacity and survivor urgency, and continuously recalculate routes as conditions evolve. We built Aegis Rescue to explore one question: What if emergency routing could react to new disaster intelligence as quickly as responders receive it? In January of 2025 all of us were stuck within the LA area during the Pacific Palisades Fire. Not only was our group put in distress, many of our friends and family within the area were displaced and had to quickly evacuate. After seeing in real time the destruction and chaos caused by the fires, we were all inspired to create some safety measure to create a more optimized approach for first responders and the general public to ensure the best approach to minimizing the destruction of these wildfires which have been abundant over the last few decades within California. Our Palisades Fire scenario demonstrates this idea through a fire engine conducting search-and-rescue missions while an ambulance independently handles medical calls and returns to the hospital when it reaches capacity. What It Does Aegis Rescue is a real-time disaster logistics and route-optimization platform. It combines live hazard intelligence, a continuously updated road graph, priority-aware vehicle routing, and an interactive tactical dashboard. The system can: Convert unstructured reports—such as 911 calls, fire department updates, weather alerts, and social posts—into structured changes to the road network. Increase the cost of dangerous roads or mark impassable roads as closed. Prioritize rescue sites based on urgency, demand, fire exposure, and travel cost. Coordinate multiple vehicles with different capacities, starting locations, and missions. Recalculate routes when fire conditions change during a trip. Compare continuing toward a rescue with retreating to safety. Display active routes, alternatives, hazards, rescue sites, and vehicle movement on a live map. Fall back to local routing if the backend is unavailable, keeping the demonstration resilient. At a high level, Aegis minimizes travel and hazard exposure while maximizing the priority of the people reached: $$\text{Route Score} = \text{Travel Cost} \mathbin{+} \lambda \cdot \text{Hazard Exposure} \mathbin{-} \mu \cdot \text{Priority Served}$$ As fire conditions evolve, the cost of traveling across a road becomes: $$\mathrm{LiveEdgeCost}(i,j)=\mathrm{BaseCost}(i,j)\times\mathrm{HazardMultiplier}(i,j)$$ A multiplier near (1) represents a clear road, while a very large multiplier represents an impassable route. How We Built It We designed Aegis around two specialized “brains” connected through a shared live-state layer: An extractor agent interprets unstructured field intelligence and converts it into structured node and edge updates. A deterministic OR-Tools optimization engine solves the mathematical routing problem using vehicle capacities, priorities, time windows, and current road conditions. We intentionally use AI for understanding language, not for calculating routes. Once the incoming intelligence has been structured, the optimization engine makes reproducible and explainable routing decisions. Redis acts as the system’s nervous system. It stores the road graph, hazard multipliers, rescue priorities, vehicle states, optimization contracts, and completed routes. Redis Pub/Sub allows new intelligence and route updates to move through the system in real time. The backend is built with Python and FastAPI. It supports: Capacitated Vehicle Routing Problems Traveling Salesperson Problems Priority-aware rescue selection Vehicle capacities and time windows Nearest-neighbor and 2-opt fallback algorithms Optional machine-learning warm starts Real-time route updates through WebSockets The frontend is a tactical dashboard built with React, TypeScript, Vite, and MapLibre GL. It visualizes: Historical fire progression Rescue locations and medical calls Emergency vehicle positions Active and alternative routes Road closures and hazard exposure Dynamic rerouting decisions For a realistic demonstration, we processed historical data from: LAFD Palisades Fire progression data OpenStreetMap road data USGS 3DEP elevation data EPA AirNow historical air-quality observations Historical fire progression is replayed while vehicles are moving, forcing the optimizer to respond to conditions that change during an active mission. Turning Emergency Audio Into Map Updates With Deepgram We used Deepgram Nova-3 to convert live police and emergency-dispatch audio into structured information that Aegis can act on. Deepgram transcribes noisy radio traffic and 911 calls in real time. We improve transcription accuracy with key terms for local roads, landmarks, emergency vocabulary, and place names such as “Palisades Drive,” “road closed,” “trapped,” and “mandatory evacuation.” The audio pipeline: Deepgram converts emergency audio into text. Speaker diarization separates callers, dispatchers, and field units. The system filters transcripts for relevant locations, hazards, casualties, and road closures. Our extraction agent converts those details into structured map updates. New emergency locations are added to the map as response points. Road hazards update the live graph and trigger route optimization. Responders immediately see the new incident and updated route on the tactical dashboard. Deepgram also applies smart formatting to addresses and unit numbers while redacting sensitive information such as phone, payment-card, and Social Security numbers. This allows Aegis to transform spoken reports into actionable map intelligence within seconds—without requiring dispatchers to manually re-enter information. Challenges We Faced Routing Through a Changing Environment A route that was optimal when a responder departed could become unsafe moments later. We needed to update road costs without rebuilding the entire graph every time a new hazard appeared. We addressed this by separating static road costs from live hazard multipliers. A hazard report becomes a small, constant-time Redis update, while the solver reads the latest combined cost whenever it recalculates a route. Combining AI With Deterministic Optimization Language models are useful for interpreting reports such as: “The fire crossed Route 4, and the road is now impassable.” However, they should not be trusted to perform safety-critical route optimization directly. We created a strict JSON contract between the extraction layer and the solver. This gave us the flexibility of natural-language understanding while keeping routing deterministic, testable, and explainable. Coordinating Independent Vehicles The fire engine and ambulance have different bases, capacities, objectives, and return conditions. Each vehicle needed its own operational state and route while still reacting to the same evolving disaster. We modeled the vehicles independently while allowing them to share the same live hazard graph. This lets both missions run concurrently without coupling their operational logic. Rendering Solver Output on Real Roads Optimization solvers return ordered graph nodes, while an interactive map needs complete road geometry. We built path-reconstruction logic that expands optimized routes into drawable road segments, allowing the dashboard to accurately display the paths selected by the backend. Keeping the Demo Reliable Live systems have many possible failure points. We added: Deterministic fallbacks for intelligence extraction Multiple fallback routing algorithms Semantic caching for repeated or similar reports Client-side route previews when the backend is unavailable Automated tests for routing, capacity, caching, traversal, and real-time updates These safeguards allow the demonstration to continue functioning even when an individual service is unavailable. What We Learned We learned that disaster routing is not simply a shortest-path problem. It is a dynamic vehicle-routing problem involving: Uncertainty Vehicle capacity Survivor urgency Time windows Hazard exposure Multiple vehicle types Rapidly changing constraints We also learned the value of giving each technology a focused responsibility: AI translates human language into structured operational updates. Redis maintains fast-changing shared state. Optimization algorithms make constrained routing decisions. The tactical dashboard gives humans visibility into why routes change. Most importantly, we learned that resilient systems need graceful degradation. During an emergency, partial functionality is far more useful than a system that fails completely when one service becomes unavailable. What’s Next We would like to expand Aegis Rescue with: Live feeds from Caltrans, NOAA, NASA FIRMS, and emergency dispatch systems Speech-to-text ingestion for radio and 911 traffic Confidence scores and human approval for uncertain intelligence Additional resources such as shelters, helicopters, supply trucks, and evacuation buses Traffic, fuel, crew-hour, and terrain constraints Predictive fire-spread modeling Offline-first operation for damaged communications infrastructure Field testing with emergency-management professionals Our long-term vision is a decision-support platform that helps responders transform fragmented disaster intelligence into coordinated action—without removing humans from the loop.
🛰️ Project Aegis Route
Real-time agentic optimization for wildfire search & rescue — voice-first, grounded in the January 2025 Palisades Fire.
Turn the chaos of disaster comms into an O(1) live state — then reroute the instant someone speaks.
Wildfire search-and-rescue runs on voice: 911 calls, dispatch radio, field units on the net. Aegis listens to that traffic, extracts what changed (a bridge is out, six trapped at the high school), writes it to a live graph in O(1), and re-optimizes multi-vehicle rescue routes — continuously. Then it speaks the new plan back to the crews.
🎤 Voice is the front door — powered by Deepgram
Voice isn't bolted on; it's the primary I/O of the whole system. Without speech-to-text there is no data to optimize on. Aegis uses Deepgram across four load-bearing surfaces:
| Deepgram product | Where it lives in Aegis | Why it's essential |
|---|---|---|
| STT — Nova-3 | The front door: 911 calls + dispatch radio → ingest.Signal → negative edge weights | No transcript = no live state = nothing to solve |
| STT streaming | Live radio-scanner feed → graph updates as the call is still happening | Reroutes mid-incident |
| TTS — Aura-2 | The solver's route → spoken advisory to field units | Hands-free instructions in a moving truck; closes the loop |
| Voice Agent API | Talk to Aegis: "new emergency at grid E5" → it acts + replies | Voice as the control surface — the marquee demo |
SAR-tuned, not a vanilla call: keyterm prompting (street names + survival vocab survive radio noise), speaker diarization (caller vs dispatcher), smart_format/numerals for addresses & unit numbers, and PII redaction for real 911 audio.
⭐ The marquee moment — reroute by voice, on a coordinate grid
Mid-mission, the dispatcher just talks. The Deepgram Voice Agent (one socket: Nova-3 → an LLM with function-calling → Aura-2) decides to call an Aegis tool:
Dispatcher (out loud): "Aegis, new emergency — two people trapped at grid echo five, critical."
→ agent callsadd_sar_location(grid="E5", demand=2, priority="critical")
→ a new node drops onto the coordinate grid in Redis, wired to its nearest roads
→ the real OR-Tools solver re-optimizes over live edge costs
Aegis (spoken back): "Copy. New rescue site at grid E5, node 10, priority critical, two victims. Rerouting 2 units, total cost 43."
🎙️ speech ──Nova-3──▶ intent + args ──▶ add_sar_location / block_road / reroute
│
O(1) edit ▼ (new node + edges on the grid)
Redis live state
│ build_contract → run_solver (OR-Tools)
▼
new routes ──Aura-2──▶ 🔊 spoken advisory + 🗺️ dashboard
Grid squares use NATO phonetics too — "echo five", "E-5", and E5 all resolve to the same lat/lng inside the Palisades operating box.
🏗️ Architecture
AUDIO BRAIN STATE (O(1)) SOLVE VOICE OUT
911 call ─┐
radio ────┼─▶ Deepgram ─▶ Extractor Agent ─▶ Redis live layer ─▶ build_contract ─▶ Aura-2 TTS 🔊
field ────┘ STT (+ semantic base × multiplier run_solver + pub/sub 🗺️
cache) node priorities (OR-Tools CVRP)
▲
GraphRAG static knowledge graph
(roads, terrain — indexed once)
Two layers, decoupled on purpose:
- GraphRAG = static knowledge graph (roads, terrain) — pre-indexed once.
- Redis = live state — real-time edge weights & node priorities, O(1) updates, independent of when you solve.
⚡ Quickstart
python -m venv .venv && .venv\Scripts\activate # (Windows) | source .venv/bin/activate
pip install -r requirements.txt
pytest -q # 46 tests, fully offline (fakeredis, no API keys needed)
python voice_demo.py # the Deepgram story: 911 calls → reroutes → spoken advisories
Everything runs offline by default — fakeredis, sidecar transcripts, and a graceful solver fallback — so the demo always works on stage. Add a Deepgram key to go live (below).
🗂️ The voice layer
| Module | Role |
|---|---|
voice/deepgram_stt.py | Ears. Audio → transcript → ingest.Signal (batch + live streaming, SAR keyterms, diarize, redact) |
voice/deepgram_tts.py | Mouth. Advisory text → spoken Aura-2 audio for field units |
voice/voice_agent.py | Brain + voice. Deepgram Voice Agent with function-calling tools: add_sar_location, block_road, reroute, status |
voice/grid.py | Coordinate grid ↔ lat/lng (A–H × 1–8), NATO phonetics, nearest-node wiring |
voice/dispatch_pipeline.py | The full loop: process_call(audio) → STT → extractor → Redis → solver → TTS |
voice/samples/ | Realistic 911/dispatch transcripts (hit real graph roads & nodes) |
The same tool dispatch backs both the live Voice Agent (run_live()) and the offline path (handle_text()) — so what you test offline is exactly what runs live.
🧪 Tests & metrics
- 46 tests passing (38 system + 8 new voice) —
pytest -q, no keys required. - Stress: 12,000 ticks → 480 solves, 96% semantic-cache hit, 4.84M tokens saved, all invariants held.
- Voice-triggered reroute calls the real OR-Tools CVRP solver with a Dijkstra live-cost matrix — a blocked road or a new node reroutes via true shortest path.
🔑 Going live with Deepgram
export DEEPGRAM_API_KEY=dg_xxx # unlocks Nova-3 STT, Aura-2 TTS, Voice Agent
python voice/make_sample_audio.py # synth the sample calls to real .wav (Aura-2)
python voice_demo.py # now transcribes REAL audio with Nova-3
python voice_demo.py --live # talk to Aegis: live Voice Agent (needs a mic)
Optional env: DEEPGRAM_STT_MODEL (default nova-3), DEEPGRAM_TTS_MODEL (default aura-2-thalia-en), AEGIS_AGENT_LLM (Voice Agent think model).
📚 More docs
- COMPLETE.md — full system walkthrough & PDF→code mapping
- INTEGRATION.md — solver ↔ frontend wiring
- DEMO.md — live demo script
- SLIDES.md — presentation deck (also rendered:
Project-Aegis-Route.pptx)
Built for CalHacks. GraphRAG + Redis + LLM agent + OR-Tools + React — with Deepgram as the voice that drives it all.
Analysis
View
Metric
- 5
- 2
- 1
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- CSSIn code
- FastAPIIn code
- HTMLIn code
- PythonIn code
- PyTorchIn code
- ReactIn code
- RedisIn code
- TypeScriptIn code
- OpenAIClaimed
8 of 9 appear in the indexed code. 1 claimed on Devpost could not be matched to code, which may simply mean the tool leaves no trace in the repository.
AI coding agents
No AI coding agent signals were found in this repository.
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
330 KB
Source files
93
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
A-Sanil/CalHacks
122 files · 49.7 MB · @ f073208
Structure
Interface
10 files · 8%Screens, components and styles rendered to the user.
API & routing
3 files · 2%Request entry points: routes, handlers and controllers.
Application logic
65 files · 53%Domain rules, services and shared utilities.
+5 more
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- Python56%
- TypeScript26%
- Markdown8%
- HTML7%
- CSS3%
- Shell0%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
pyproject.toml
pypi · 15- elkai
- fastapi
- httpx
- numpy
- ortools
- pydantic
- redis
- shapely
- torch
- uvicorn[standard]
- websockets
- +4 more
requirements.txt
pypi · 15- deepgram-sdk
- elkai
- fakeredis
- fastapi
- httpx
- numpy
- ortools
- pydantic
- pytest
- pytest-asyncio
- redis
- shapely
- torch
- uvicorn[standard]
- websockets
frontend/package.json
npm · 9- @turf/simplify
- maplibre-gl
- react
- react-dom
- +5 more
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
This project’s features have not been analysed yet.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.