
A customer sends a voice note on Telegram (WhatsApp later). The bot takes the order, confirms every charge before the customer taps Confirm, and replies in the founder's voice.
Every message below is the real bot text. Buttons replace typing wherever a tap works. Prices come from the demo catalog.
/start the bot sends a voice note. It is cloned from Shyam Gupta's voice with Sarvam. Every voice message carries the AI label in its caption.Item Qty Price Atta 1 kg ₹48 Roti 2 pcs ₹20 Bhindi 3 kg ₹120 -------------------------------- Items subtotal ₹188 Delivery fee (demo) ₹25 Handling fee (demo) ₹5 -------------------------------- TOTAL ₹218📦 Delivery: kal, morning slot 💳 Payment: COD (cash on delivery) 🏠 Area: Kankarbagh 👤 Naam: Ramesh | 📱 98xxxxxx10 Prices and fees are demo values. Order confirm karne se pehle sab kuch dekh lijiye.
Scroll inside the phone to see the whole flow, including the 60-second change window.
Telegram calls a 21-node n8n workflow on an Oracle Cloud box. Speech-to-text, the FAQ bot and the voice service run on the same box. Nothing leaves it except Telegram, the Sarvam voice call, and the DeepSeek fallback for hard-to-parse orders.
Telegram messages. One Sarvam API call per new voice line (then cached). One DeepSeek v3.2 call via OpenRouter when rules cannot read the order.
Every voice note, every transcript, the FAQ knowledge base, the catalog, sessions and orders. Secrets sit in a 0600 file on the box, never inside n8n nodes.
One Config flag stops the whole bot. Fees, swap window, model names and the greeting text are Config values, not buried in code.
These rules come from the spec and each one has a unit test behind it.
The clone is used only after Shyam Gupta's consent is on file in a private folder. Every voice reply carries the caption "AI-generated voice (Shyam Gupta ki awaaz)". It is never used to make a customer believe they are speaking to him personally. Without consent the bot falls back to text.
The catalog is loaded through a column allowlist. The stock flag only hides unavailable items and is dropped before anything else runs. "Kitna stock hai?" gets a refusal: "Stock ki jaankari main nahi de sakta." Tested in T-06 and T-22.
Phone numbers show only the last two digits in every customer message (98xxxxxx10) and are stored masked. Tested in T-10.
No real customer Telegram IDs are stored in the repo. Sessions live in n8n static data for the demo only. Real payments and real dispatch are out of scope.
Bot token, Sarvam key and voice id live in a 0600 file on the Oracle box. n8n nodes never hold them. The STT, FAQ and voice servers listen on 127.0.0.1 only.
200 characters per voice message, 100 voice messages per day. Over the cap the same message goes out as text. Audio is cached by text hash, so a repeated line costs nothing again.
Measured on the Oracle Cloud machine: aarch64 Linux, 4 CPU, no GPU. Only numbers we recorded ourselves are shown.
node n8n/test/test_brain.js. Run again on 8 Oct, all pass.The greeting voice line (121 characters) was generated once and is served from cache. Extraction uses rules first; the DeepSeek fallback via OpenRouter is only called when rules find nothing, so most orders make no LLM call at all.
31 question and answer pairs were taken from Kuiklo's public pages on 8 Oct 2026. The bot finds the closest 3 with MiniLM embeddings and writes a Hinglish reply with gemma3:4b. A question that scores under 0.30 is turned away with "Yeh sawal Kuiklo ke baare mein nahi lag raha."
Customer: delivery charge kitna hai?
Bot (gemma3:4b, 24 s): "Koi delivery charge nahi hai! Kuch hidden fees bhi nahi hain, aap jo checkout pe de..."
Customer: kaunse area mein deliver karte ho?
Bot (gemma3:4b, 31 s): "Kuiklo Patna mein hi kaam karta hai. Hum Kankarbagh, Boring Road, Fraser Road, Kidw..."
Ten of the rows the bot reads today. The list is synthetic: real brands, made-up prices. It will be replaced by Kuiklo's real list. The stock flag is never shown to a customer.
| SKU | Product | Brand | Variant | Unit | Price (demo) | Category |
|---|---|---|---|---|---|---|
| ATA-001 | atta | Aashirvaad | Select Sharbati | kg | ₹48 | staples |
| ATA-002 | atta | Pillsbury | Chakki Fresh | kg | ₹52 | staples |
| DAL-001 | dal | Tata Sampann | Toor (Arhar) | kg | ₹160 | staples |
| TEL-001 | tel | Fortune | Sunflower 1 L | pcs | ₹140 | staples |
| DUD-001 | doodh | Sudha | Toned 500 ml | pcs | ₹26 | dairy |
| PNR-001 | paneer | Sudha | Paneer 200 g | pcs | ₹80 | dairy |
| BRD-001 | bread | Harvest Gold | White 400 g | pcs | ₹40 | bakery |
| ROT-001 | roti | Kuiklo Kitchen | Tawa Roti | pcs | ₹10 | ready |
| BHI-001 | bhindi | Farm Fresh | Loose | kg | ₹40 | vegetables |
| KEL-001 | kela | Farm Fresh | Dozen | pcs | ₹50 | fruits |
Columns the bot may read: sku, product, brand, variant, unit, unit_price_inr, category, in_stock_flag. The flag only hides an item. Quantities are never read.
Pending manual checks: a typed order and a 60-second swap in a real Telegram chat from the owner's phone (M-01, M-03). The workflow is live and the webhook is set; unit tests and a real voice bubble with buttons are confirmed.