This workflow corresponds to n8n.io template #6001 — we link there as the canonical source.
This workflow follows the Agent → Form Trigger recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "aDRgA0zAqjUD2yvU",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Smart Restaurant Order & Suggestion System with Gemini AI and Telegram",
"tags": [],
"nodes": [
{
"id": "4492f7c4-0f63-4cc9-9772-b1d8194dd2fb",
"name": "New Order Trigger (Form)",
"type": "n8n-nodes-base.formTrigger",
"position": [
-880,
360
],
"parameters": {
"options": {},
"formTitle": "Oneclick Restaurant Order - Table number 1",
"formFields": {
"values": [
{
"fieldLabel": "Please enter your name",
"placeholder": "John doe",
"requiredField": true
},
{
"fieldType": "number",
"fieldLabel": "Please enter your phone number",
"placeholder": "123456789"
},
{
"fieldType": "number",
"fieldLabel": "Tandoori Chicken - 250 Rupees"
},
{
"fieldType": "number",
"fieldLabel": "Biryani - 200 Rupees"
},
{
"fieldType": "number",
"fieldLabel": "Masala Dosa - 150 Rupees"
},
{
"fieldType": "number",
"fieldLabel": "Idli vada - 100 Rupees"
},
{
"fieldType": "number",
"fieldLabel": "Dal Tadka - 150 Rupees"
},
{
"fieldType": "number",
"fieldLabel": "Steam Rice - 100 Rupees"
},
{
"fieldLabel": "Paratha - 30 Rupees"
},
{
"fieldType": "number",
"fieldLabel": "Paneer butter masal - 250 Rupees"
},
{
"fieldType": "number",
"fieldLabel": "Fix Thali - 150 Rupees"
}
]
},
"formDescription": "Please add your dish quantity and submit to place your order"
},
"typeVersion": 2.2
},
{
"id": "1e2209ba-20d6-4d2a-9f03-6a62b3c98f4e",
"name": "Extract & Format Order Data",
"type": "n8n-nodes-base.code",
"position": [
-660,
360
],
"parameters": {
"jsCode": "const input = $input.all();\nconst formData = input[0].json;\n\nconst name = formData[\"Please enter your name\"];\nconst mobile = String(formData[\"Please enter your phone number\"]);\n\nfunction generateCustomerId() {\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';\n let id = '';\n for (let i = 0; i < 6; i++) {\n id += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return `CUST-${id}`;\n}\n\nconst customerId = generateCustomerId();\n\nconst dishes = Object.entries(formData)\n .map(([key, value]) => {\n const match = key.match(/^(.*)\\s*-\\s*(\\d+)\\s*Rupees$/);\n if (!match) return null;\n const rawQty = Number(value);\n if (isNaN(rawQty) || rawQty < 1) return null; // only >1\n const unitPrice = Number(match[2]);\n return {\n dishName: match[1].trim(),\n quantity: rawQty,\n unitPrice,\n totalPrice: rawQty * unitPrice\n };\n })\n .filter(item => item !== null);\n\nreturn [\n {\n json: {\n customerId,\n name,\n mobile,\n dishes,\n },\n },\n];\n"
},
"typeVersion": 2
},
{
"id": "fc25b5bf-717a-40b9-9cf3-69bd12c3fc52",
"name": "Save Customer Info",
"type": "n8n-nodes-base.googleSheets",
"position": [
-440,
360
],
"parameters": {
"columns": {
"value": {
"Customer id": "={{ $json.customerId }}",
"Customer name": "={{ $json.name }}",
"costomer mobile number": "={{ $json.mobile }}"
},
"schema": [
{
"id": "Customer id",
"type": "string",
"display": true,
"required": false,
"displayName": "Customer id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Customer name",
"type": "string",
"display": true,
"required": false,
"displayName": "Customer name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "costomer mobile number",
"type": "string",
"display": true,
"required": false,
"displayName": "costomer mobile number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1QztyOVgP8vIAQGLeBNErIHqJ77fq4vDRVD1DvHJdGaI/edit#gid=0",
"cachedResultName": "customer details"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1QztyOVgP8vIAQGLeBNErIHqJ77fq4vDRVD1DvHJdGaI",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1QztyOVgP8vIAQGLeBNErIHqJ77fq4vDRVD1DvHJdGaI/edit?usp=drivesdk",
"cachedResultName": "restaurant order placement "
},
"authentication": "serviceAccount"
},
"credentials": {
"googleApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.6
},
{
"id": "844defa5-d868-4397-a52e-9a165932aba0",
"name": "Save Dish Info",
"type": "n8n-nodes-base.code",
"position": [
-220,
360
],
"parameters": {
"jsCode": "// Input comes from the previous node\nconst data = $('Extract & Format Order Data').first().json.dishes;\n\nreturn data;\n"
},
"typeVersion": 2
},
{
"id": "c5d5435a-2d99-48f0-b5c2-48531fb12670",
"name": "Prepare Dish Details for AI",
"type": "n8n-nodes-base.googleSheets",
"position": [
0,
360
],
"parameters": {
"columns": {
"value": {
"dish name": "={{ $json.dishName }}",
"Customer id": "={{ $('Extract & Format Order Data').item.json.customerId }}",
"actual price": "={{ $json.totalPrice }}",
"dish quantity": "={{ $json.quantity }}",
"per unit price": "={{ $json.unitPrice }}"
},
"schema": [
{
"id": "Customer id",
"type": "string",
"display": true,
"required": false,
"displayName": "Customer id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "dish name",
"type": "string",
"display": true,
"required": false,
"displayName": "dish name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "dish quantity",
"type": "string",
"display": true,
"required": false,
"displayName": "dish quantity",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "per unit price",
"type": "string",
"display": true,
"required": false,
"displayName": "per unit price",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "actual price",
"type": "string",
"display": true,
"required": false,
"displayName": "actual price",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1326050181,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1QztyOVgP8vIAQGLeBNErIHqJ77fq4vDRVD1DvHJdGaI/edit#gid=1326050181",
"cachedResultName": "customer order details"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1QztyOVgP8vIAQGLeBNErIHqJ77fq4vDRVD1DvHJdGaI",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1QztyOVgP8vIAQGLeBNErIHqJ77fq4vDRVD1DvHJdGaI/edit?usp=drivesdk",
"cachedResultName": "restaurant order placement "
},
"authentication": "serviceAccount"
},
"credentials": {
"googleApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.6
},
{
"id": "560536c7-a876-4418-9ad7-f4d3461d85f3",
"name": "Clean Data for AI Input",
"type": "n8n-nodes-base.code",
"position": [
220,
360
],
"parameters": {
"jsCode": "// Fetch all incoming items\nconst items = $input.all();\n\n// Extract the raw row data (each item.json is one row)\nconst rawRows = items.map(item => item.json);\n\n// Bundle everything into a single field\nconst payload = { rows: rawRows };\n\n// Return a single output item whose json contains your full dataset\nreturn [{ json: { data: payload } }];"
},
"typeVersion": 2
},
{
"id": "c0a4ab92-9ae3-45ca-806c-f4e1e5e396cc",
"name": "Gemini AI Dish Suggestion Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
440,
360
],
"parameters": {
"text": "={{ $json.data }}",
"options": {
"systemMessage": "You are a friendly AI assistant for a restaurant, designed to suggest dishes that customers might enjoy based on their recent order. \n\nWe will provide you with structured JSON input representing a customer\u2019s previous order, for example:\n\nYou are a friendly AI assistant for a restaurant, designed to suggest dishes that customers might enjoy based on their recent order. \n\nWe will provide you with structured JSON input representing a customer\u2019s previous order, for example:\n\n{\n \"customerId\": \"CUST-1D0RWH\",\n \"name\": \"ajay\",\n \"mobile\": \"9898989898\",\n \"dishes\": [\n { \"dishName\": \"Tandoori Chicken\", \"quantity\": 1, \"unitPrice\": 250, \"totalPrice\": 250 },\n { \"dishName\": \"Masala Dosa\", \"quantity\": 1, \"unitPrice\": 150, \"totalPrice\": 150 },\n { \"dishName\": \"Idli vada\", \"quantity\": 1, \"unitPrice\": 100, \"totalPrice\": 100 },\n { \"dishName\": \"Dal Tadka\", \"quantity\": 1, \"unitPrice\": 150, \"totalPrice\": 150 },\n { \"dishName\": \"Paratha\", \"quantity\": 2, \"unitPrice\": 30, \"totalPrice\": 60 },\n { \"dishName\": \"Paneer butter masal\",\"quantity\":1, \"unitPrice\": 250,\"totalPrice\":250 }\n ]\n}\n\nYour job:\n1. Analyze the dishes\u2014look at cuisine types, flavors, categories, and quantities.\n2. Recommend **3\u20135 other dishes** likely to appeal to this customer, explaining *why* (e.g., complementary flavors, similar cuisines, balancing variety).\n3. Output JSON with:\n - `suggestions`: an array of objects each with `dishName` and `reason`\n\n**Important formatting rules:**\n- Output must be strictly valid JSON (no extra text).\n- Follow this structure exactly:\n\n\nYour job:\n1. Analyze the dishes\u2014look at cuisine types, flavors, categories, and quantities.\n2. Recommend **3\u20135 other dishes** likely to appeal to this customer, explaining *why* (e.g., complementary flavors, similar cuisines, balancing variety).\n3. Output JSON with:\n - `suggestions`: an array of objects each with `dishName` and `reason`\n\n**Important formatting rules:**\n- Output must be strictly valid JSON (no extra text).\n- Follow this structure exactly:"
},
"promptType": "define"
},
"typeVersion": 1.9
},
{
"id": "d80e5505-1f6d-4904-b497-b62530f284e2",
"name": "Format AI Suggestions for Telegram",
"type": "n8n-nodes-base.code",
"position": [
816,
360
],
"parameters": {
"jsCode": "// Step 1: Fetch the raw output from the AI Agent node\nconst aiResponse = $node[\"Gemini AI Dish Suggestion Agent\"].json.output; // Update \"AI Agent\" to your node name\n\n// Step 2: Strip Markdown fences if present\nconst markdownPattern = /^```json\\s*([\\s\\S]*)\\s*```$/;\nconst cleaned = aiResponse.replace(markdownPattern, \"$1\");\n\n// Step 3: Parse JSON safely\nlet parsed;\ntry {\n parsed = JSON.parse(cleaned);\n} catch (err) {\n throw new Error(`Failed to parse AI response JSON: ${err.message}`);\n}\n\n// Step 4: Return each suggestion as its own item (n8n format)\nreturn parsed.suggestions.map(s => ({\n json: {\n customerId: parsed.customerId,\n ...s\n }\n}));\n"
},
"typeVersion": 2
},
{
"id": "c902fee2-f89a-42c8-92ea-4bced23561b7",
"name": "Send Suggestions via Telegram",
"type": "n8n-nodes-base.telegram",
"position": [
1036,
360
],
"parameters": {
"text": "={{ $json.dishName }}\n\n{{ $json.reason }}",
"chatId": "newchatid",
"additionalFields": {}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "068d712a-eddc-4021-8c3f-b601e767af92",
"name": "Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
468,
580
],
"parameters": {
"options": {},
"modelName": "models/gemini-2.5-pro"
},
"credentials": {
"googlePalmApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "29206de4-5ee1-44e0-9e48-6440f390a981",
"name": "Think Tool",
"type": "@n8n/n8n-nodes-langchain.toolThink",
"position": [
588,
580
],
"parameters": {},
"typeVersion": 1
},
{
"id": "9f542a6c-37d5-4acb-a27d-64c1043e7b2e",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-910,
0
],
"parameters": {
"color": 5,
"width": 160,
"height": 520,
"content": "Triggered when a customer submits their dish order form."
},
"typeVersion": 1
},
{
"id": "4d847217-066e-4323-afbd-03fe71074cc3",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-470,
0
],
"parameters": {
"color": 4,
"width": 160,
"height": 520,
"content": "Adds customer details to the Google Sheet.\n"
},
"typeVersion": 1
},
{
"id": "63dd550d-71bd-4599-858d-6c1336bd4aed",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-30,
0
],
"parameters": {
"color": 5,
"width": 160,
"height": 520,
"content": "Gathers final dish data to send to the AI agent.\n"
},
"typeVersion": 1
},
{
"id": "a954f2da-409f-4a5e-b31e-70ffd34ff718",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
190,
0
],
"parameters": {
"width": 160,
"height": 520,
"content": "Reformats the data to improve AI understanding."
},
"typeVersion": 1
},
{
"id": "f85f9bc1-c82a-475d-bfd5-5e1cc68b67c3",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
786,
0
],
"parameters": {
"color": 4,
"width": 160,
"height": 520,
"content": "Converts Gemini output into Telegram-friendly message format."
},
"typeVersion": 1
},
{
"id": "7ba85c44-5f48-482b-b385-81f819290c54",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
1006,
0
],
"parameters": {
"color": 3,
"width": 160,
"height": 520,
"content": "Sends dish suggestions directly to the customer."
},
"typeVersion": 1
},
{
"id": "7e499f3f-1037-4d71-a40a-45669b4ac16c",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-250,
0
],
"parameters": {
"color": 3,
"width": 160,
"height": 520,
"content": "Stores ordered dish quantities and types to a separate sheet."
},
"typeVersion": 1
},
{
"id": "587a6136-fc12-4c0a-8fb1-a3b06026cb11",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
440,
0
],
"parameters": {
"color": 6,
"width": 260,
"height": 520,
"content": "Uses Gemini AI to recommend related dishes or offers."
},
"typeVersion": 1
},
{
"id": "5f0d16a4-be36-4a56-8b4e-05093cfeaa68",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-690,
0
],
"parameters": {
"width": 160,
"height": 520,
"content": "Formats incoming form fields for further processing."
},
"typeVersion": 1
},
{
"id": "286198a1-70dc-4d08-babf-dc24b127bf72",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
-360,
-540
],
"parameters": {
"color": 2,
"width": 800,
"height": 320,
"content": "### This workflow helps automate restaurant order processing and customer engagement by:\n\n- Saving Time: Automatically records customer and dish data without manual entry.\n\n- Personalizing Experience: AI suggests relevant dishes or combos to upsell or enhance the order.\n\n- Centralized Tracking: All order data is logged into Google Sheets for real-time access and analytics.\n\n- Instant Outreach: Sends dish suggestions directly to customers via Telegram within seconds.\n\n- Scalability: Easily handles multiple orders with AI-driven intelligence\u2014ideal for growing restaurants.\n\n"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "3910b529-9989-490f-ba6d-ed97e80f157a",
"connections": {
"Chat Model": {
"ai_languageModel": [
[
{
"node": "Gemini AI Dish Suggestion Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Think Tool": {
"ai_tool": [
[
{
"node": "Gemini AI Dish Suggestion Agent",
"type": "ai_tool",
"index": 0
}
]
]
},
"Save Dish Info": {
"main": [
[
{
"node": "Prepare Dish Details for AI",
"type": "main",
"index": 0
}
]
]
},
"Save Customer Info": {
"main": [
[
{
"node": "Save Dish Info",
"type": "main",
"index": 0
}
]
]
},
"Clean Data for AI Input": {
"main": [
[
{
"node": "Gemini AI Dish Suggestion Agent",
"type": "main",
"index": 0
}
]
]
},
"New Order Trigger (Form)": {
"main": [
[
{
"node": "Extract & Format Order Data",
"type": "main",
"index": 0
}
]
]
},
"Extract & Format Order Data": {
"main": [
[
{
"node": "Save Customer Info",
"type": "main",
"index": 0
}
]
]
},
"Prepare Dish Details for AI": {
"main": [
[
{
"node": "Clean Data for AI Input",
"type": "main",
"index": 0
}
]
]
},
"Gemini AI Dish Suggestion Agent": {
"main": [
[
{
"node": "Format AI Suggestions for Telegram",
"type": "main",
"index": 0
}
]
]
},
"Format AI Suggestions for Telegram": {
"main": [
[
{
"node": "Send Suggestions via Telegram",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
googleApigooglePalmApitelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
In this guide, we’ll walk you through setting up a smart workflow that triggers on new restaurant orders, extracts and formats customer and dish details from Google Sheets, uses Gemini AI to recommend dishes or offers, and sends suggestions via Telegram. Ready to automate your…
Source: https://n8n.io/workflows/6001/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow contains community nodes that are only compatible with the self-hosted version of n8n.
Tired of scrolling through messy notes and bookmarks to find your favorite recipes? Wish you had a personal chef's assistant to help you in the kitchen?
This workflow automates Facebook posting and appointment booking directly from a Telegram bot, making it especially useful for pet grooming businesses that want to keep their social media active while
Sign up for Decodo — get better pricing here
🎯 Create viral TikToks, Shorts, Reels, podcasts, and ASMR videos in minutes — all on autopilot.