
"The children's breath is the sensor: building Khidki on AWS in four days" (about 1,250 words, four figures)
How Khidki tells a Delhi teacher the exact minute to open or close the classroom windows on a bad-air day, then confirms it from the CO₂ curve with no sensor on the window. Covers the physics model, AWS Step Functions and Cedar, and what went wrong along the way.
The children's breath is the sensor: building Khidki on AWS in four days
Built for Environmental Hacks (WeMakeDevs × AWS, Bharat Builds Tour), Air track.
On a bad-air morning in Delhi, a teacher with 44 children has one question: open the window, or keep it

shut?
Both answers are wrong. Keep it shut, and the children's own breath pushes CO₂ past 2,000 ppm within one
40-minute period. The room turns stuffy and attention drops. Open it, and about 97% of the smog outside ends
up inside. Teachers decide by feel, usually by temperature.
Khidki (खिड़की, Hindi for "window") tells the teacher the exact minute to open or close, and then checks
that the air really changed. This post is about how it works, where AWS fits, and the four things that
fought back.
How it decides, with no hardware
The decision of when needs no hardware at all. Khidki keeps a physics model of the classroom: 44 children
add roughly 3,450 ppm of CO₂ an hour to a 166 m³ room, and each window setting has an air-change rate (0.7
an hour shut, 10 with both sides open). More air out also means more smog in.

Every morning at 06:00 it takes the outdoor air forecast (CAMS, through Open-Meteo) and the school
timetable, and runs dynamic programming over the day in 5-minute steps to find the plan with the best
balance of stuffy air and smog, in six changes or fewer. A teacher who is asked fifteen times a day stops
listening, so the number of requests is part of the cost.
School safety rules sit on top as Cedar policies. "Outdoor PE moves indoors when forecast PM2.5 is above
90" is a
forbid with a when clause, not an if buried in a planner.

How it checks, with no sensor on the window
This is the part I like most. When the teacher taps "I've opened them", how do you know they did?
You do not need a sensor on the window. The children's breath is a tracer gas. With one ordinary CO₂ meter
in the room, the rate at which CO₂ falls tells you the room's air-change rate, and that tells you how open
the room is. Khidki fits that rate with a closed-form least-squares fit, compares it with what the
instruction should have produced, and if only one side opened, asks for the other.
In the demo the classroom and the meter are simulated; the outdoor air is real. The figure above is from a
run where the simulated teacher opened only one side: Khidki noticed, asked for the corridor side, and
verified after the second tap.
Where AWS fits
- AWS Step Functions runs every instruction. The
waitForTaskTokencallback is an exact fit for "wait for a human to tap a button". Then a Wait state gives the air time to change, a task fits the curve, and a Choice state branches to Verified, a follow-up, or a re-plan.
- AWS Lambda holds the engine (API, sensor ingest, daily planner, workflow task), behind an API Gateway HTTP API, with state in one DynamoDB table.
- EventBridge Scheduler starts the 06:00 plan with a cron in
Asia/Kolkata, so there is no UTC arithmetic.
- Amazon Polly speaks the instruction in Hindi (the Kajal neural voice), cached in S3.
- Cedar decides the policies, Powertools for AWS Lambda handles routing, logs and metrics, and the whole stack is one AWS CDK app in Python.
What fought back
1. The "verification hold" that was a region lock
For a day, every AWS call failed with "explicit deny in a service control policy". I assumed my new account
was still being verified. It was not. Accounts created through the new sign-up experience carry a managed
policy that denies almost everything outside one home region, and mine was not Mumbai. I found it by probing
DynamoDB in every region until one answered:
ap-southeast-2 . So a Delhi product is hosted in Sydney. If
you are starting a hackathon on a fresh account, check which region actually answers before you write any
infrastructure code.Amazon Bedrock had its own lock: "Operation not allowed" on every model, which only a Support case can
lift. Khidki's question-answering agent is written with the Strands Agents SDK, with a guard that rejects any
number not present in tool output, but on this account it answers from verified templates and says so.
2. The tracer-gas trick has blind spots
Running a whole simulated morning found bugs the unit tests did not:
- Just after closing, indoor CO₂ is only about 200 ppm above outdoor, and a sensor's ±3% error is enough to read "closed" as "slightly open". Closing is now verified against a boundary, not a point.
- "Go from both sides to one side" passed while both were still open, because the check ignored direction.
- During PE the room was empty, and Khidki "verified" a closing from a flat line. An empty room near outdoor CO₂ now counts as inconclusive, and nobody is asked to act on an empty room.
One is still open: when the fit is inconclusive, Khidki trusts the tap. An audit I ran on the last evening
caught the one-side case being missed in three of six runs, depending on timing. That is next on the list.
3. The benchmark said "trade-off", not "win"
I wanted the headline to be "less pollution". On 48 real Delhi school days in a simulated classroom, against
a CO₂ alarm, Khidki cut stuffy minutes from 65 a day to 17 with 4 requests to the teacher instead of 15.
But it let in slightly more PM2.5: 93% of an always-open room against the alarm's 89%.
Physics explains it. 44 children need about 3.3 air changes an hour, and at that rate indoor PM2.5 is
already near the outdoor level. Without a purifier, window timing cannot cut smog much. So the honest
headline is fewer stuffy minutes and fewer interruptions, and the product says that on its own landing
page.
4. Cedar will tell you which policy decided, if you ask
Cedar's diagnostics list internal ids like
policy0 . Add @id("S2") annotations and read them back through
the diagnostics, and every decision carries a human policy id. Add @en and @hi annotations and the policy
file also holds the bilingual explanation. The principal's page shows "PE moved indoors, S2, forecast 97"
straight from the policy, with no language model involved.One more Cedar lesson: "a principal manages their own school" is not
resource in principal . Rooms belong
to schools, not to users. Give the user a school attribute and write resource in principal.school .What I would do next
Put a real CO₂ meter in a real classroom for a week. Everything above is a simulation on real outdoor data,
and it is labelled that way everywhere, but a teacher's first reaction is worth more than another benchmark.
For schools with no sensor at all, Khidki already prints the day's window timetable on one A4 page. That may
turn out to be the feature that matters most.
Code: github.com/bhavya-jpg/khidki . Built with Claude Code as an AI
coding assistant. Outdoor air data: CAMS via Open-Meteo, CC BY 4.0. Khidki is not a medical device.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article