AWS Builder Center
The dish nobody eats keeps coming back: a food-waste agent on AWS that mess staff talk to in Hindi

The dish nobody eats keeps coming back: a food-waste agent on AWS that mess staff talk to in Hindi

Mess staff log each meal by answering a Hindi voice call. An AI agent on AWS Step Functions spots the dish that keeps getting wasted, a manager approves a change, and MessLoop measures whether waste really went down. Built for Environmental Hacks 2026.

I Am a student
Our hostel mess cooks the same amount every day. Five kilos of rice, whatever the attendance, whatever is on the menu. At the end of dinner the plates get scraped into a drum. Some of it goes to the bin and some to the animals behind the kitchen. The same unpopular sabzi comes back the next week, and nobody can say how much of it was thrown away last time, or why.
When we asked the mess staff about the leftover food in the cooking vessels, we learned something we hadn't expected: the workers take it home to their families. It isn't wasted at all. The real waste was on the plates, and nobody was measuring that either.
So we built MessLoop for Environmental Hacks 2026 (Waste & Energy track). It finds the dish that keeps getting wasted, lets an AI agent suggest a change, lets a human decide, and then measures whether waste actually went down. Its one rule:
AI recommends. Humans decide. Outcomes prove it.

The serverless app (S3, API Gateway, Lambda, DynamoDB), the agent (DynamoDB Streams, Step Functions, our own model on EC2), the voice call (Polly, Transcribe) and the alerts (SNS, EventBridge).

The first thing we tried failed

Before writing any code we made a Google Form for the student mess committee: what was cooked, how full the drum was, a photo of it. In a week, nobody filled it in once.
That failure became the design brief. If logging takes more than a few seconds, it won't happen. Mess staff are carrying vessels, not typing. So MessLoop lets them talk instead.
How it works, in four moments


1. "Bol ke batao": the worker just talks

The mess staff screens are entirely in Hindi. The worker taps बोल के बताओ ("Bol ke batao", say it out loud). The app runs it like a phone call: Amazon Polly asks five questions in Hindi, there's a beep, and it listens. When the worker stops talking, it moves to the next question on its own.
"Namaste! Aaj khane mein kya bana tha? Kul kitne kilo bana tha? Service ke baad bartanon mein kitne kilo bacha? Aaj kitne bacchon ne khaya? Aapke hisaab se khana kyun bacha?"
The first question asks what was cooked, not just which sabzi, so one answer can name the whole meal: "dal, chawal aur roti". MessLoop picks out every dish it hears from our hostel's real weekly menu (30 dishes, with their Hindi names).
Question 1 of 5 on a worker's phone. Each answer is transcribed while the next question plays, so the form is filled about two seconds after the call ends.
Each answer goes to Amazon Transcribe streaming (Hindi) the moment it ends. Simple rules read the numbers, because Transcribe usually writes them as digits ("50 kg बना था"). Our model only steps in when a rule can't read something. Then the worker sees a filled form with "सुना" (heard) and the words it heard under every field, and presses सेव करें (Save).
That last step matters. In testing, Transcribe heard "तेईस" (23) as "30". Speech-to-text will mishear numbers, so nothing is ever saved without a person checking it.

2. The agent wakes up by itself
Saving the meal writes to DynamoDB. A DynamoDB Stream sees the new record and starts our agent on AWS Step Functions. Nobody presses a button.
First, a fixed rule decides whether anything is wrong: over 35% left in at least 3 of a dish's last 5 meals. Not the AI. If the dish crosses the rule, the agent investigates. Our own model (Qwen3-4B, running on Amazon EC2 with llama.cpp) gets three tools and decides for itself what to look at:
The agent woke up when a meal was logged, chose its own evidence, wrote a suggestion, and paused for the manager.
The tools only return slices of evidence that code has already computed. The model never does arithmetic. Then a validator checks its answer: every number must come from evidence it actually looked at, vote shares must belong to the right dish, and comparisons like "lower waste than Chole" must match the data. If anything fails, a rule-based template is shown instead.

3. A real pause for a human

The agent can't change anything. Step Functions pauses the run on a task token until the manager approves, modifies or rejects. Here is that part of the state machine, from our AWS SAM template:
YAML
WaitForManager:
Type: Task
Comment: Human in the loop. Nothing changes until the manager approves, modifies or rejects.
Resource: arn:aws:states:::lambda:invoke.waitForTaskToken
Parameters:
FunctionName: ${AgentFunctionArn}
Payload:
agentStep: await
SK.$: $.SK
taskToken.$: $$.Task.Token
TimeoutSeconds: 1209600 # 14 days
Next: Decided
When the agent's suggestion is ready, it alerts the manager: on the dashboard, and by email through Amazon SNS. Every day at 3 pm, EventBridge Scheduler checks whether that day's meal was logged and reminds the committee if it wasn't.

4. Did it actually work?
After the change, every meal of the new dish wakes the agent again. Code computes the before and after; the agent writes one plain sentence about it; code always adds the caveat.
In the demo story, waste fell from 18.2 to 11.3 kg per 100 plates after Aloo Gobi was swapped for Chole. Simulated data, one meal, labelled as an observed change.
We show the result as kg per 100 plates, not raw kilos, so a low-attendance day doesn't look like success. Food saved is also shown as plates (about 28 here, worked out from what each student actually ate) and as an estimated CO₂e footprint (about 21 kg, using FAO's global average of roughly 2.5 kg CO₂e per kg of wasted food). Both carry an Estimated label.
Students have a screen too: "Aaj ki sabzi kaisi thi?" One tap for a rating and one for a reason ("bahut teekha", "thanda tha"). They can also vote for what should be cooked instead, choosing from dishes served at the same meal, or suggest a dish of their own. Students know the food best. Their reasons and votes go straight into the agent's evidence, and their ideas show up on the manager's dashboard.

Why each AWS service is there

Service
Its job in MessLoop
Why this one
API Gateway (HTTP API) + Lambda
The whole API, in TypeScript
Pay per request; a mess logs a few meals a day
DynamoDB
One table: meals, ratings, suggestions, trials
Single-digit-millisecond reads, nothing to manage
DynamoDB Streams
Wakes the agent when a meal is logged
The agent reacts to data, not to a button
Step Functions
Runs the agent: investigate, pause, measure
The human-approval pause is a real task token, visible in the console
Amazon EC2
Hosts our own model (Qwen3-4B, llama.cpp)
The evidence never leaves our AWS account
Polly + Transcribe streaming
Asks in Hindi, transcribes each answer live
Hindi voices and Hindi speech-to-text, no audio stored
SNS + EventBridge Scheduler
Emails alerts; the 3 pm daily check
The agent can reach people, not just a dashboard
S3
Hosts the React site
Static files, a few cents
CloudWatch
Logs every request, agent run and AI call
One place to see what the agent did
AWS SAM (open source) + CloudFormation
Every piece defined as code
One template, one deploy, judges can read it
The EC2 model server is the only real cost, about $0.36 an hour on a c7i.2xlarge, so it gets stopped after the hackathon. Everything else rounds to almost nothing at mess scale.
Amazon Bedrock wasn't available on our new account ( NOT_AUTHORIZED ), and the organisers confirmed any inference hosted on AWS counts. So we self-hosted a small open model behind the same validation. The model sits behind one small module, so moving to Bedrock later means changing that module and nothing else.

What fought back

Problem
What happened
Fix
The 1.5B model got facts wrong
Qwen2.5-1.5B wrote "Aloo Gobi received 61% of votes". That 61% was Chole's.
Moved to Qwen3-4B, and taught the validator to tie each vote share to its dish
Comparisons were the weakest spot
Qwen3-4B said Mixed Veg had "lower waste than Chole" (22% vs 14%)
A check that compares claims against the numbers, and a prompt that asks for each dish's own numbers instead
API Gateway's 30-second limit
A CPU model answer takes about 25 s
The API stores a template suggestion at once; the agent replaces it in the background
The voice call was slow
Batch Transcribe jobs started after the call and took 10–15 s each, about 25 s of waiting
Streaming Transcribe per answer during the call, plus rules before the model: about 2 s
A race between two writes
The agent's pause token and the manager's decision could overwrite each other
DynamoDB update expressions on separate fields, conditional on status
One bad deploy
 cloudformation package  ignored a  CodeUri  in SAM  Globals , so both Lambdas deployed without code
 CodeUri  on each function; an end-to-end check after every deploy
A judge couldn't log in
At the DTU build day the demo stopped at the login screen because the role codes hadn't been shared
One-click "Try the demo" buttons, safe because all demo data is simulated and resettable
The engineering numbers in this post come from our own runs. The end-to-end check (24 steps: log a meal, agent wakes up, pause, approve, measure, report) passes on the live deployment, alongside 59 unit tests.

What we don't claim

  • The meal data in the demo is simulated, and the app says so on every screen. The voice call, agent and alerts are real and running; the history behind the story is not.
  • One meal after a change is an observed change, not proof. The app always shows how many meals the comparison is based on.
  • The CO₂e figure is a global average, not a measurement of our mess.

What we learned

  • Ask the people who do the work before you measure anything. The leftovers we planned to weigh weren't waste.
  • If logging takes more than a few seconds, it won't happen. Talking beat typing.
  • Let rules decide what's wrong and let the AI explain it. The alert is a fixed rule; the agent never decides on its own.
  • Validate what the model looked at, not just what it said. Numbers it never fetched get rejected.
  • A human-in-the-loop step should be a real pause. A task token is harder to skip than a button.
  • Run the whole loop after every deploy. It caught a broken release within minutes.

Try it

Open the live app, tap Mess staff under "Try the demo", choose बोल के बताओ, and answer in Hindi. Then log in as Manager and watch the agent's activity fill in.
Or watch the whole loop in under three minutes:  https://youtu.be/1IT8X0xW6p8 
Built by Vipul Yadav, Vidushi Singh and Parth Negi for Environmental Hacks 2026 (Bharat Builds Tour). We used Claude Code as a coding assistant throughout.
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