
Building WeSave: satellite alerts for landfill fires in India, on AWS
How we used Strands Agents, Amazon Bedrock and serverless AWS to turn NASA satellite hotspots into human-approved smoke alerts for the schools and hospitals next to Indian landfills.
Environmental Hacks (WeMakeDevs × AWS, Bharat Builds Tour) · Air and Waste and Energy tracks
In January 2016 a fire at Mumbai's Deonar dump burned for about four days and more than 70 schools closed. In March 2023 a fire at Brahmapuram in Kochi sent smoke up to about ten kilometres, and classes for younger students were suspended. Satellites saw both fires. Nobody turned what they saw into a warning for the people next door.
India's satellite fire alert system is built for forests. The Forest Survey of India's FAST system "filters out all fires other than forest fires". So a hotspot on a landfill does not reach the city duty officer, or the school a kilometre downwind. That gap is what we built WeSave for.
Live dashboard: https://main.d14grr46u0o91n.amplifyapp.com · Code: https://github.com/Darsh-14/landfill-fire-watch
What WeSave does
Every three hours WeSave checks NASA FIRMS satellite hotspots against the real outlines of 30 Indian landfills. When a hotspot lands on a landfill it:
- decides, with fixed and tested rules, whether it is a possible or a probable fire;
- works out where the smoke may go from hourly wind, and lists the schools and hospitals inside that area;
- asks an AI agent to write two short alerts, one for residents and one for officials;
- checks every draft with 11 safety checks;
- waits. Nothing is sent until a person presses Send.
WeSave does not clean the air. It cuts exposure, by telling people early. It is for the duty officer at the fire service or pollution board, and it protects the families, schools and hospitals downwind.
The one rule that shaped everything: code decides, the model explains
A satellite hotspot is not a confirmed fire. A VIIRS pixel is about 375 m across (MODIS about 1 km), so heat can come from a factory next door, and cloud can hide a real fire. An alert system that panics hundreds of schools over a false reading stops being trusted. So we split the work:
- Deterministic Python decides whether a detection is on a landfill (outline buffered by half the pixel size), the incident status, the smoke screening sector and the list of affected places. All of it is unit tested.
- The model only writes text from facts that code computed, through read-only tools.
- A validator rejects any draft that names a place not in the computed list, changes a number, calls a fire "confirmed", makes health or AQI claims, cites an unverified rule, or drops the
[REPLAY]label on historical data. The agent gets one retry with the error list; after that a fixed template is used.
- A person approves every message. Historical replays can only go to a demo email list.
Architecture on AWS
- Amazon EventBridge Scheduler runs the scan Lambda every 3 hours.
- AWS Lambda (Python 3.13): three functions, scan, API and draft.
- Amazon S3 keeps every raw FIRMS CSV with its SHA-256 as object metadata, so any alert can be traced back to the exact file it came from.
- Amazon DynamoDB (on-demand) stores scans, detections, incidents, drafts and approvals in one table.
- Amazon Bedrock with Amazon Nova Pro, called through the Strands Agents SDK, writes the alerts.
- Amazon SNS has two email topics, live and demo. Only the approve endpoint, which needs the duty officer's token, publishes to them. A Cedar policy decides which topic a message may go to.
- Amazon API Gateway (HTTP API) serves the dashboard, throttled and restricted to the dashboard's origin.
- AWS Amplify Hosting serves the static dashboard (plain HTML, CSS and JS with Leaflet).
- AWS Systems Manager Parameter Store holds the NASA key and the admin token as SecureStrings.
- Amazon CloudWatch Logs gets JSON log lines, including every agent tool call and every validator result.
Everything is one AWS SAM template, with least-privilege IAM per function.
Why Strands Agents worked well here
The agent has five read-only tools (incident, smoke zone, receptors, limits, verified rules). Strands' structured output put the reply straight into a Pydantic model, so a malformed draft fails parsing instead of reaching a person. An after-tool-call hook logs every tool call to CloudWatch, which gave us an audit trail for free. Turn limits and a cancel signal keep the agent inside the Lambda timeout, so the fallback template and the database write always happen.
Does it work? A backtest with frozen rules
Before running anything, we froze every threshold and recorded the config hash. Then we replayed three documented fires from the NASA FIRMS archive:
Fire | Reported start | First detection by WeSave | Result |
|---|---|---|---|
Brahmapuram, Kochi, 2023 | 2 Mar | 2 Mar, 22:05 IST | Found the same day; 404 schools and hospitals in the 10 km sector |
Deonar, Mumbai, 2016 | 27 Jan | 28 Jan, 02:45 IST | Found one day after the reported start |
Ghazipur, Delhi, 2022 | 28 Mar | one satellite pass only | Missed: two small pixels on a single overpass stayed a "possible" fire |
We did not change a rule after seeing the Ghazipur miss. We also checked six 30-day monsoon windows with no reported fire and got zero alerts. Monsoon cloud hides fires too, so that is weak evidence, and we say so.
What fought back
- Bedrock regions and access. In ap-south-1 every model call returned "Operation not allowed", while the same calls worked in us-east-1. The stack stayed in Mumbai and only the model calls moved. Then Anthropic models needed a use-case form and a Marketplace subscription, which failed on the payment method. Because Bedrock's Converse API is the same for every model, switching to Amazon Nova Pro was one parameter, with no agent code changes.
- Our first real AWS scan found a bug. It returned 0 rows from all three VIIRS feeds. FIRMS
DAY_RANGE=1means "today's UTC date only", so scans early in the UTC day missed the previous night's passes. We changed the live window to two days and recorded it openly as a post-freeze amendment. The backtest accepts it only if putting the old value back reproduces the frozen hash exactly.
- Packaging Lambdas on Windows without Docker.
sam builddropped the Linux.sofiles from our prebuilt packages. We locked dependencies for Linux with uv, installed Linux wheels withpip --platform, zipped them ourselves and pointedCodeUriat the zips.
- OpenStreetMap calls fly-ash ponds "landfills" too. When we searched for every named landfill in India, 23 of the large ones were ash ponds, slag heaps or mine dumps next to power plants, a recipe for false alarms. We filter them by name, and a test catches the bug where "Nashik" matched "ash".
- The model's first drafts. Nova Pro's first draft often missed required wording, such as the
[REPLAY]label. The validator rejected it and the retry passed all 11 checks. That loop is exactly why the validator exists.
What we learned
- Put a deterministic layer between the model and the world. The validator plus one retry blocks wrong numbers and invented schools before a person ever sees the draft.
- Test it the way a judge will. The bug that mattered most only showed up on the first real scan in AWS.
- Freeze your rules before you look at results, and publish your misses. Ghazipur is in our README for a reason.
- Check the data's definitions. "Landfill" in a map dataset and "day range" in an API both meant something other than what we assumed.
Limits
WeSave sees surface fires only; underground fires can be missed. Satellites pass a few times a day, and cloud and smoke can block detection. A detection is not a confirmation, and the smoke area is a screening sector from wind direction, not a pollution forecast. 11 of the 30 landfill outlines were checked on imagery; 19 are not checked yet.
Credits
Fire data: NASA FIRMS (LANCE, ESDIS). Landfill outlines, schools and hospitals: © OpenStreetMap contributors (ODbL). Wind: Open-Meteo.com (CC BY 4.0). Code written with Claude Code (an AI coding assistant) under our direction; demo narration by Amazon Polly.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article