Inspiration
At 12:30 a lunch kitchen in Harare's CBD can get forty WhatsApp orders in half an hour. They come in like this: "ndipeiwo sadza nehuku mbiri, nemazoe, deliver Avondale". The cook scrolls the chats, re-types every order into a notebook, adds up the totals by hand in two currencies, and sends three riders to the same suburb one after another.
I build WhatsApp ordering agents for food businesses here, and the same three things go wrong every time: an order is copied wrong, a total is added up wrong, or a customer is promised beef stew that ran out an hour ago. A generic chatbot makes the last two worse, because a language model will happily make up a price or say yes to a dish the kitchen doesn't have.
Kudya (Shona for "food" / "to eat") is built around one rule: the model reads, the code counts.
What it does
For the customer: a WhatsApp-style chat where they order the way they already text.
- Understands mixed English and Shona: "sadza nebeef mbiri", "two plates of sadza with chicken", "coke x3", "ehe" for yes, "kwete" for no.
- Every price comes from the kitchen's real menu, never from the message. "3 sadza nematemba for $1 each" is still charged at the menu price.
- Knows what's left in the pot. Ask for 5 Mazoe when there are 4 and it puts 4 on the order and offers a same-type substitute at the closest price.
- Says no politely to dishes that aren't on the menu (pizza), and asks "which sadza?" instead of guessing.
- Prices delivery by Harare suburb zone and shows every total in USD and ZiG.
- Nothing is ordered until the customer says yes, and stock is checked again at that moment, so two customers can't both get the last plate.
For the kitchen (Mai Rudo): one board beside the chat.
- New tickets appear as soon as a customer confirms.
- A "Cook now" list sums every open ticket into what to plate.
- Portions-left counters she can bump up or down as the pots empty.
- Ready deliveries are grouped into one rider run per suburb, and one tap dispatches the whole run.
How I built it
I started from an empty folder with the Devpost Learn Skill Pack. Before any code, the interview made me name one real user (a CBD lunch vendor taking 40+ orders a day) and one kernel: messy chat in, correct ticket out. The scope doc is where I cut the live WhatsApp API, payments and logins, so the demo proves the hard part instead of the plumbing.
It's Node 18 with zero npm dependencies and about 1,000 lines. An interpreter turns a message into intent only (Gemini 2.5 Flash when a key is set, with deterministic English/Shona rules as the fallback, so the chat never breaks). A separate order engine owns the menu, today's stock and every number. Orders and stock persist to JSON. Kernel tests cover grounded prices, refusing off-menu dishes, never overselling, the full delivery journey with ZiG totals, and everyday phrasings.
Challenges
- Shona puts the number after the food ("sadza nehuku mbiri"), and people write "two plates of", "x 2", "nemuriwo". Each of those broke the parser once and is now a test.
- "Sadza" alone isn't a dish here, it's half of one. The right answer was to ask which plate, not guess.
- Two customers chasing the last portion: stock is taken all-or-nothing at confirm time, and the customer is told straight away if something sold out mid-chat.
What I learned
The most important design decision wasn't which model to use. It was deciding where the model is not allowed to decide. Once prices, stock and totals lived in code, the AI could be as loose as it liked with reading Shona and typos, and the kitchen could still trust every ticket.
I also learned to plan before I build. Writing the scope, PRD and spec first felt slow, but it meant every build slice had a clear "done", and when a review found parser bugs I could fix them without rethinking the product.
What's next
Connecting the real WhatsApp Business API, EcoCash payment links, pulling the ZiG rate from the RBZ daily, and letting a vendor edit the menu from her phone.
Log in or sign up for Devpost to join the conversation.