AWS Builder Center

What If India's Next Energy Breakthrough Is Already Installed?

India is installing solar panels on millions of rooftops, but who makes sure they keep working? We built SuryaSaathi, an AI-powered solar monitoring agent on AWS, to detect wasted energy, distinguish dust and equipment faults from pollution-related drops, and automate maintenance follow-ups. Built in four days for the AWS Bharat Builds Tour Environmental Hacks, SuryaSaathi explores how AI agents can help India recover clean energy from infrastructure it already has.

Senior Software Engineer
Every winter in Delhi, a rooftop solar system makes a little less, and every winter the vendor gives the same answer: "It's the pollution." I wanted to know how often that was actually true. It turns out nobody knows, because nobody is looking.
That question became SuryaSaathi, an AI agent that checks every rooftop solar system every day, tells smog, dust and faults apart, and makes the vendor fix what they owe. My teammates Yukti, Mayank and I built it in four days for the Bharat Builds Tour. It's live at main.danjquy1xcblp.amplifyapp.com , and the code is on GitHub  , you can check the demo on Youtube .
The short version: India is putting solar on lakhs of roofs, and almost nobody checks them after the installer leaves. SuryaSaathi compares what each roof made with what it should have made, works out whether the shortfall was the sky or the vendor, and chases the free cleaning or repair until it's done. The family gets one WhatsApp message. As of today, our deployed agent has watched 5 simulated Delhi roofs for 30 days, filed 7 cases, escalated 2 to the DISCOM and verified 5 fixes.

1. Introduction: why I couldn't let this go

1.1 Purpose: the problem I saw

The numbers stopped me first. More than 50 lakh homes  in India now have rooftop solar under PM Surya Ghar, about 14.8 GW of capacity. Then I read that 99% of users stop monitoring  once the installer leaves. Ninety-nine percent. We're building one of the largest rooftop solar fleets in the world, and almost none of it is being watched.
That matters more in North India than almost anywhere. Dust settling on the glass costs 0.3–0.6% of output a day in Delhi, and systems here can lose 17–25% of a year's output  to it, even with monthly cleaning. A failing inverter can halve production overnight.
When output drops, there are three usual suspects. I started thinking of them as three fingerprints:
CauseWhose problemWhat the data showsWhat should happen
SmogNobody'sExpected and actual fall together, and recover togetherNothing
DustThe vendor'sThe gap widens every dry day; rain resets itFree cleaning, owed for 5 years
FaultThe vendor'sOutput collapses overnight while the sunlight doesn'tFree repair, owed for 5 years
Here's the unfair part. On an electricity bill, all three look exactly the same: a smaller saving. So "it's the pollution" always wins, the five years of free maintenance the family is owed goes unclaimed, and the panels quietly lose a fifth of their value.

1.2 Why now: the duty exists, the tool doesn't

The timing turned out to matter as much as the idea. On 17 September 2026, Delhi notified the Delhi Solar Energy Policy 2023 (Second Amendment) . Most headlines were about money: households using up to 400 units a month can now get a 3 kW system at zero upfront cost , with the Centre's ₹78,000 matched by Delhi's ₹78,000.
The line that caught my eye was quieter. The amendment makes DISCOMs responsible for monitoring generation and identifying under-performing systems. It gives every system a Digital Solar Asset Identification Number (DSAIN), a permanent record of its specifications, warranty and generation. Vendors still owe five years of free maintenance at their own cost, as the Delhi Solar Portal  sets out. What's missing is the evidence.
And the scale is about to jump. Delhi had 10,073 rooftop systems  when the policy was approved, and the gazette targets 2.20 lakh new residential installations. That's about 2.2 lakh more roofs that will need watching, by people who've just been handed the job and have no tool to do it. That's the gap we set out to fill.

1.3 Scope

SuryaSaathi does four things for every roof, every day: collect yesterday's reading, compare it with what that roof should have made, diagnose smog, dust or a fault, and act on it until the fix is verified. It works with the hardware already on most roofs.
What it doesn't do: it doesn't install or sell panels, it doesn't clean or repair anything itself, and it never files a claim against a vendor because of smog.

1.4 Definitions

  • DISCOM: the electricity distribution company. In Delhi, it's now responsible for finding under-performing rooftop systems.
  • Expected output: what a specific roof should have made on a specific day, given the sunlight and haze.
  • Performance: actual output ÷ expected output.
  • O&M: operation and maintenance. Under PM Surya Ghar, the vendor owes it free for five years.
  • DSAIN: Digital Solar Asset Identification Number, a permanent ID for every rooftop system in Delhi.
  • Case: one maintenance claim against a vendor, from filing to verified fix.

2. Overall description: who it's for

2.1 Where SuryaSaathi sits

SuryaSaathi doesn't replace anything that already exists. It sits in the gap between the pieces: the PM Surya Ghar vendor who installed the roof, the DISCOM data logger or inverter that already records output, the DISCOM that now has to watch performance, and the Delhi Solar Portal where each system's DSAIN record lives. Today, nothing connects "this roof made less" to "this vendor owes a visit." That connection is the product.

2.2 The three people we built for

The most useful thing the SRS format did for us was make us write down who the users actually are. There are three, and they want completely different things.
The family wants to be left alone. They shouldn't need an app, a dashboard or a login. Their whole experience is:
  1. The vendor installs the system and puts a QR sticker on the inverter. The family gives consent once.
  2. Readings arrive every day. The family does nothing.
  3. A problem is found, a claim is filed and the fix is verified, all automatically.
  4. They get one WhatsApp message, in Hindi, when it's fixed, plus a monthly money report.
सफाई हो गई! Output वापस 96% पर है।
The vendor needs to know what they owe. Their view lists the cases the agent filed against roofs they installed, each with its evidence attached: the chart, the readings and the rupees lost.
The DISCOM needs cases that arrive already investigated. Their console works like this:
  1. Open the console to see roof health and money being lost, by zone.
  2. Check the vendor leaderboard: who's slow, who's overdue.
  3. Work the escalation queue, with readings, chart and notices already attached.
  4. Act on repeat offenders, under rules that already allow it.

2.3 Operating environment

Everything runs serverless on AWS and is defined in AWS CDK, so one command deploys the whole stack. The public site and the DISCOM console are Next.js apps on AWS Amplify Hosting.

2.4 Constraints

  • No new hardware on most roofs. It has to work with what's already installed.
  • Consent first. A household's readings are used only with their consent.
  • Every decision must be explainable, because each one can become a claim against a business.
  • Cheap enough for a DISCOM to run at city scale, with near-zero cost when idle.
  • Simulated data for now. Every system, reading and case in our demo is simulated, built on real Delhi weather patterns.

2.5 Assumptions and dependencies

We assume most new Delhi roofs have a DISCOM data logger or a WiFi inverter, and that the maker's cloud can be read with consent. We depend on NASA POWER  for satellite sunlight, Open-Meteo  for air quality and weather, and pvlib  for modelling each roof.

3. Functional requirements: one reading's journey

The clearest way I know to explain what SuryaSaathi must do is to follow one reading from one roof: a 3 kW system in Dwarka, on 12 October. Each step is a requirement.
FR-1: Collect the reading without the family lifting a finger. The DISCOM data logger reads the inverter every 15 minutes and sends yesterday's total, 9.1 kWh, to AWS IoT Core over MQTT with TLS.
FR-2: Know what the roof should have made. Overnight, the system has already worked out that roof's expected output from satellite sunlight and that day's haze: 11.6 kWh. The key detail is that expected already includes the smog.
FR-3: Measure performance. Performance is actual divided by expected:
1
\text{Performance} = \frac{\text{actual kWh}}{\text{expected kWh}}
A healthy roof sits in the high 90s on a clear day and on a smoggy one, because smog lowers both numbers together. That's what makes the three causes separable. The question stops being "did output drop?" and becomes "did output drop more than the sky explains?"
FR-4: Diagnose using simple rules the agent can explain. These are our v1 rules:
RuleConditionAction
SmogExpected is low but performance stays above 90%No action
Dust3-day average below 91% and falling over 5 dry daysClaim cleaning
FaultPerformance below 60% overnight, or an inverter fault codeClaim repair
Verified fixPerformance back above 93% after the visitClose case
For our Dwarka roof, the agent checks each suspect in turn. Smog in the air? Already counted in "expected", so it's ruled out. Inverter fault? No fault code and no sudden drop, so it's ruled out. Dust? The gap has widened every dry day and the last rain reset it, so that's the diagnosis.
FR-5: Never punish a vendor for the weather. If overnight rain washes the panels and the next reading is back to normal, an open dust case closes itself. No visit is needed, and no false claim is made.
FR-6: File the claim with evidence. Case SS-0142 goes to the vendor as a free-cleaning claim, with the chart, the readings and the rupees lost attached, citing the five-year maintenance duty.
FR-7: Chase the deadline and escalate. The vendor has 3 days. In our story they miss it, so the full case file goes to the DISCOM, automatically.
FR-8: Verify the fix, then tell the family once. The case only closes when new readings show performance back above 93%. Then the family gets the only message SuryaSaathi ever sends them:
आपके panels पर धूल थी। हमने vendor से मुफ्त सफाई करवा दी। (Vendor देर कर रहा था, इसलिए DISCOM से करवाया।) Output वापस 96% पर है।
You can watch a whole month of this on one roof, in about a minute, in the live demo : dust builds up, the agent catches it, the vendor misses the deadline, the DISCOM steps in, and the family gets one message. You can even break the inverter or bring in smog yourself and watch how the agent reacts.

4. External interfaces: how a roof talks, and how people hear back

4.1 Four ways a roof can report

One constraint shaped this section: no new hardware on most roofs. So we designed four ways in, from the most common to the last resort.
SourceWhich roofsHow it works
Data loggerNew Delhi roofsFitted by the DISCOM at installation; reads the inverter every 15 minutes
Inverter cloudWiFi invertersThe maker's cloud API, pulled once a day with the family's consent
Camera clipAny roof, any ageA small camera photographs the inverter screen; no wiring touched
WhatsApp photoFallbackThe family sends a picture of the screen, and the model reads the numbers
The camera clip is the one I'm proudest of on paper. It's an ESP32-CAM running FreeRTOS that the vendor clips in front of the inverter. Every hour it photographs the screen, something like E-TODAY 9.1, and the model reads the number. It works with any brand of inverter and never touches the wiring, so it can bring even a ten-year-old roof into the system.
Every reading, whichever way it comes in, arrives on one MQTT topic per device, like suryasaathi/dl/SS-DL-000123/telemetry, and is checked against one shared JSON schema.

4.2 How people hear back

  • The family: one WhatsApp message in Hindi when a fix is verified, plus a monthly money report. Nothing else.
  • The vendor: the case notice with its evidence, by email, and the vendor view listing everything they owe.
  • The DISCOM: escalation notices, and the console with the leaderboard and the escalation queue.
  • Anyone: the public Live page , which reads our deployed backend directly and refreshes every 15 seconds. It shows simulated rooftops on real AWS services, the agent's own diagnoses and reasons, and the cases it has filed.

5. Non-functional requirements: the promises underneath

These turned out to be the requirements that decided our architecture.
NFR-1: Scale to every roof in the country. A DISCOM might watch 20 lakh systems. Readings live in DynamoDB with millisecond lookups by system ID at any scale, and old raw readings age out. A nightly rollup summarises readings and cases by vendor, zone and day, so the DISCOM console never scans raw readings.
NFR-2: Cost almost nothing when nothing is happening. Everything is serverless, so cost scales with the number of roofs rather than with servers. The main variable cost is the model, so the agent only calls it on days something changes: between one and four calls per system in a 30-day scenario.
NFR-3: Every decision must be explainable. This was the most important design choice we made: the rules decide, the model explains. The agent can only take the action the rules allow. The model's job is to turn that decision into plain words a vendor or engineer can check, and to act through tools. Every decision is logged with its reason.
NFR-4: Consent before data. Readings are used only with the household's consent, and vendors see only their own customers. We designed these as Cedar policies, checked before every agent tool call.
NFR-5: Never stall a case. If the model is unavailable, the rules still decide and the reason falls back to a template, so a case never waits on an AI. (This one came back to bite us. More in section 7.)
NFR-6: Be honest about the data. Every system, reading and case in the demo and on the site is simulated, built on real Delhi weather patterns, and labelled that way everywhere.

6. How we built it on AWS

This is where "I" becomes "we". Yukti, Mayank and I split the work across a website, a DISCOM console, a device simulator, a CDK app and a set of Python Lambda services, all in one monorepo. Over four days, that came to 119 commits.
We designed SuryaSaathi in four layers, and we followed one rule: every service does one job.
To follow one reading through it: it comes in through IoT Core, is checked by Lambda, explained by an agent, chased by Step Functions, and sent home.
LayerServiceIts one jobStatus
IngestAWS IoT CorePer-device X.509 certificates, readings over MQTT; scales to millions of devices with no serversRunning
IngestAmazon EventBridgeNightly expected-output runs and rollups; daily inverter-cloud pullsRunning
IngestAWS End User Messaging SocialWhatsApp in and out, connected directly to AWSDesigned
AgentsAWS LambdaValidates each reading against the shared schema, stores it, runs the rulesRunning
AgentsStrands AgentsRuns the diagnosis, accountability and messenger agentsRunning
AgentsAmazon BedrockAgent reasoning, reading inverter-screen photos, messages in Hindi and EnglishWired as default
AgentsAmazon TranscribeHindi voice notes from familiesDesigned
Memory & rulesAmazon DynamoDBSystems, readings, cases and the expected-output cacheRunning
Memory & rulesAmazon S3Photos and evidenceDesigned
Memory & rulesAmazon OpenSearchSearchable inverter manuals and fault codesDesigned
Memory & rulesCedarConsent and access checked before every agent tool callDesigned
Act & reportAWS Step FunctionsWaits days for a vendor at near-zero cost, with a visual audit trail per caseRunning
Act & reportAmazon SESCase notices to vendors and the DISCOMRunning
Act & reportAmazon CloudWatchEvery decision logged as structured JSONRunning
Act & reportAmazon Cognito, API Gateway, AmplifySign-in, the console and Live APIs, and hostingRunning
A few of these choices deserve a sentence each.
Step Functions was the perfect fit for vendors. A vendor deadline is a wait measured in days. Every case is one execution, named after the case: notify the vendor, wait, recheck, then verify or escalate and wait again. Each step's input and output is visible in the console, so the accountability trail is something you can actually show a DISCOM officer.
IoT Core keeps each device in its own lane. Each logger or camera clip has its own certificate and a policy that only lets it publish its own readings.
Nothing is billed by the hour. There's no VPC, no NAT gateway and no database waiting for traffic. We even wrote tests that fail the build if anything hourly-billed sneaks into the stack: tables must be on-demand and log groups must have short retention. That's also why OpenSearch is still on the "designed" list.
We leaned on AWS open source throughout: Strands Agents for the agents, Cedar for the consent policies, OpenSearch for the manuals, AWS CDK to define the whole stack so one command deploys it, and FreeRTOS on the camera clip.

7. What broke, and what four days taught us

Most of what we built worked roughly as planned. The parts worth telling you about are the moments the system told us we were wrong.

7.1 The agent that was never actually thinking

Remember NFR-5, never stall a case? We were proud of it. If the model doesn't answer, the rules decide anyway and the reason falls back to a template.
Our first version reached Bedrock through a client endpoint that returned a 404 for every model name on our account. Nothing crashed. Cases were filed, escalated and verified exactly as designed, and the demo looked perfect. But underneath, the agent was falling back to its templates on every single call. The model never answered once.
We caught it because every decision we log carries a field called reasonSource: "agent" if the model wrote the reason, "rules" if the template did. A column full of "rules" told us more than any error message could have.
The fix took two steps. We moved to Strands' own Bedrock model, which calls the Converse API, and addressed Claude by its cross-region inference profile. Then we hit the next wall: Bedrock still refused calls until our account's model-access request for Anthropic was approved. With the deadline close, we added one flag that points the same Strands agent, tools and rules at the Anthropic API directly. The key lives in AWS Secrets Manager and never touches the CloudFormation template, and two tests make sure it never does. Bedrock stays the default and fully wired, so switching back is one flag. Here's a real reason from the deployed agent now that the model is answering:
1
2
3
4
5
6
7
{
"systemId": "SS-SIM-0003",
"diagnosis": "fault",
"action": "open_case",
"reason": "System SS-SIM-0003 produced 3.62 kWh today versus 11.85 kWh expected under normal sunlight, a sudden collapse to just 30.5 percent of expected output. This indicates an inverter or wiring fault, not dirt or weather.",
"reasonSource": "agent"
}

7.2 Two codebases that had to tell the same story

The browser demo simulates a whole month in TypeScript, right in your browser. The backend runs the same rules in Python on Lambda. If the two disagreed by even one day, the demo would be telling a story the real system wouldn't.
So we exported five "golden" scenarios from the TypeScript engine and wrote tests that replay every one of them through the Python rules. They check for the same diagnosis, the same case state and the same wording on every day. We even had to copy JavaScript's rounding (Math.round and toFixed) into Python, because 88.75% rounding differently on each side changes the sentence a family reads.
Those tests caught a real bug almost immediately. A scripted rain day in one scenario wasn't washing the panels, so dust kept piling up through the rain. In the real world, that would have been a false claim against a vendor who'd done nothing wrong, which is exactly what FR-5 exists to prevent.

7.3 The most important day is the boring one

The first time we pointed the Live page at our deployed backend, it showed fifteen rows of "No action". The simulated month ended on a healthy stretch, so every reason the model had written was pushed off the page. We thought it was broken.
It wasn't. It was the product working. In our 30-day run there were 150 readings and 130 decisions, and the model was needed for just 11 of them. Most days a roof is fine, and the right thing to do is nothing. We changed the feed so eventful days come first, and we stopped treating a quiet agent as a broken one.

7.4 What I'd tell myself on day one

Let rules decide and models explain. A DISCOM engineer has to be able to check every claim against a vendor by hand. Keeping the decision in plain rules made the system auditable, and kept the model's job small enough to be cheap.
A graceful fallback is also a silent one. If you build a fallback, log which path ran, every time. Our worst bug produced correct-looking output, and the one field that told the truth recorded how the output was made.
Design for the day nothing happens. Anything that wants your attention every day gets muted, like the family WhatsApp group nobody reads. SuryaSaathi speaks to a family once, when there's good news.

8. Impact: what this changes for Delhi

Per roof, the numbers are small. Across a city, they add up fast.

8.1 For a family

A 3 kW roof in Delhi makes about 4,700 kWh a year. Unchecked dust and faults can quietly take 15–18% of that. Recovering it is 700–850 kWh a year, which is ₹5,000–6,000 back for one family at ₹7 a unit. Add five years of free maintenance that's actually claimed instead of forgotten.
But the change I care most about isn't the money. Right now a family has no way to argue with "it's the pollution." With SuryaSaathi, the evidence arrives before the argument does. And the family doesn't have to fight at all: they just get a message saying it's done.

8.2 For Delhi

Scale that to the 2.20 lakh roofs Delhi plans to add, and it's roughly 150–190 GWh a year of clean electricity recovered from panels that are already on rooftops. That's about ₹110–130 crore a year staying with Delhi households. DISCOMs get a way to meet their new duty without hiring an army of inspectors, and cases reach them already investigated.

8.3 For the environment

At India's grid emission factor of roughly 0.7 kg of CO₂ per kWh, Delhi's recovered energy works out to around 1.1–1.3 lakh tonnes of CO₂ avoided every year. Nationally, India's 14.8 GW of rooftop solar makes roughly 20 TWh a year. Recovering even a tenth of it is about 2 TWh a year of clean energy.
What I find most convincing is where that energy comes from. Every unit SuryaSaathi recovers comes from hardware that already exists. There are no new panels to manufacture, no new land, no new grid connection. It's the cheapest clean energy there is: the energy you were already supposed to be getting. And a panel that's cleaned and repaired lives out its 25-year life instead of being written off early, which means less e-waste.

8.4 Where it meets the Sustainable Development Goals

SDGHow SuryaSaathi contributes
SDG 7: Affordable and clean energyKeeps installed rooftop solar producing at full capacity, raising the real renewable share (target 7.2) and keeping bills low
SDG 13: Climate actionEvery recovered unit displaces mostly coal-fired grid power
SDG 11: Sustainable cities and communitiesGives Delhi's DISCOMs the tool to run the city-scale rooftop programme the policy now requires
SDG 12: Responsible consumption and productionGets the full lifetime value out of panels already made, reducing early replacement and e-waste
SDG 9: Industry, innovation and infrastructureTurns lakhs of scattered rooftops into monitored, accountable infrastructure
The money, energy and CO₂ figures are our estimates, worked from the assumptions above.

9. Appendices

9.1 What's next

Four days got us the full loop: a reading in, a diagnosis, a case chased to a verified fix, and one message home. Here's what we're building next:
  • WhatsApp in both directions through AWS End User Messaging Social, including the photo fallback.
  • Hindi voice notes through Amazon Transcribe, for families who'd rather talk than type.
  • Cedar policies enforced on every agent tool call, so consent is checked by code, not just by design.
  • Inverter manuals and fault codes in OpenSearch, so the agent can name a specific fault code.
  • The camera clip in the field, on real roofs with no logger and no cloud.
  • A pilot on real DSAIN-linked systems. Simulated roofs can only teach you so much.
We're also writing this up as a series. Next posts cover modelling expected output from sunlight and haze, reading an inverter screen with a camera clip, the vendor case workflow on Step Functions, and what's inside the DISCOM console.

9.2 Questions people ask us

Isn't lower output in winter just the smog? Sometimes. But smog lowers expected output too, so performance stays above 90%. When performance falls below that, the sky isn't the explanation: it's dust or a fault.
Who pays for cleaning and repairs? For PM Surya Ghar systems, the vendor owes free maintenance for five years. SuryaSaathi files the claim with evidence and escalates to the DISCOM if the vendor misses the deadline.
Does the family need an app or new hardware? No app. Most roofs already have a data logger or a WiFi inverter. For the rest, there's the camera clip, and a WhatsApp photo as the fallback.
What does the AI actually decide? Nothing on its own. Simple rules decide the diagnosis and the action. The model explains each decision in plain words, and every decision is logged with its reason.
What happens when it rains? Rain washes dust off the panels. If an open dust case's next reading is back to normal, the case closes without a visit.
Is the data real? Not yet. Every system, reading and case is simulated, built on real Delhi weather patterns.

9.3 Try it

9.4 Sources


Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article