{
  "name": "VietlinhAI | Chatbot Facebook nhận đặt món cho quán ăn",
  "nodes": [
    {
      "parameters": {
        "path": "ec3a8974-2ba4-44ff-af4c-b4df643f9b94",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "e5f10a87-6b81-47d6-be1a-dd91dfea4ba1",
      "name": "Facebook Webhook Verify",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        192,
        224
      ],
      "webhookId": "26678735-9767-4be8-a595-483cb059a36a"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "cond_verify",
              "leftValue": "={{ $json.query['hub.mode'] }}",
              "rightValue": "subscribe",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            },
            {
              "id": "cond_verify_token",
              "leftValue": "={{ $json.query['hub.verify_token'] }}",
              "rightValue": "YOUR_VERIFY_TOKEN",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "990c3047-0307-4145-9c29-26b795d8fe61",
      "name": "Is Verify Request?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        416,
        224
      ]
    },
    {
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{ $json.query['hub.challenge'] }}",
        "options": {
          "responseCode": 200
        }
      },
      "id": "63029c40-8cee-4c44-8c89-185354b453c3",
      "name": "Respond Verify",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        672,
        80
      ]
    },
    {
      "parameters": {
        "respondWith": "text",
        "responseBody": "Invalid verify token",
        "options": {
          "responseCode": 403
        }
      },
      "id": "1ab92c0a-72a7-4006-886c-0b298b91ce49",
      "name": "Respond Verify Failed",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        672,
        336
      ]
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "ec3a8974-2ba4-44ff-af4c-b4df643f9b94",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "a797dfaa-d563-4d15-b09b-1ebf31b5fa08",
      "name": "Facebook Webhook Messages",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        224,
        864
      ],
      "webhookId": "8446631e-d4bd-41ee-8527-e8b25e270cf4"
    },
    {
      "parameters": {
        "jsCode": "const input = $input.first().json;\nconst body = input.body || input;\n\nif (!body.entry) return [];\n\nconst results = [];\n\nfor (const entry of body.entry) {\n  for (const messaging of (entry.messaging || [])) {\n    // Chỉ lấy tin nhắn text thật từ khách\n    if (!messaging.message) continue;\n    if (messaging.message.is_echo) continue;\n    if (!messaging.message.text) continue;\n\n    results.push({\n      json: {\n        sender_id: messaging.sender.id,\n        recipient_id: messaging.recipient.id,\n        timestamp: messaging.timestamp,\n        message_text: messaging.message.text,\n        message_id: messaging.message.mid,\n        page_id: entry.id\n      }\n    });\n  }\n}\n\nreturn results;"
      },
      "id": "9acb197a-02c8-4077-bae3-b067074a42e8",
      "name": "Parse FB Message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        544,
        1024
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "{ \"status\": \"ok\" }",
        "options": {
          "responseCode": 200
        }
      },
      "id": "5e3a7086-dea7-40f2-a792-c03e166f323f",
      "name": "Respond 200 OK",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        544,
        736
      ]
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "",
          "mode": "list",
          "cachedResultName": "-- Chọn của bạn --",
          "cachedResultUrl": ""
        },
        "sheetName": {
          "__rl": true,
          "value": "",
          "mode": "list",
          "cachedResultName": "-- Chọn của bạn --",
          "cachedResultUrl": ""
        },
        "filtersUI": {
          "values": [
            {
              "lookupColumn": "sender_id",
              "lookupValue": "={{ $json.sender_id }}"
            }
          ]
        },
        "options": {}
      },
      "id": "ba797e9e-894e-4a67-aff0-04530d1f7856",
      "name": "Check Customer in Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        1088,
        736
      ],
      "alwaysOutputData": true,
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "jsCode": "const sheetData = $input.first().json;\nconst parsedData = $('Parse FB Message').first().json;\nconst isNewCustomer = !sheetData.sender_id;\nreturn [{\n  json: {\n    is_new_customer: isNewCustomer,\n    sender_id: parsedData.sender_id,\n    message_text: parsedData.message_text,\n    message_id: parsedData.message_id,\n    page_id: parsedData.page_id\n  }\n}];"
      },
      "id": "53bb179d-a431-4ab4-8759-70cae8d6c1a9",
      "name": "Check Is New Customer",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1312,
        736
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "cond-new",
              "leftValue": "={{ $json.is_new_customer }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "2c2c7dd9-065e-43c0-8aea-e96b12bc8d99",
      "name": "Is New Customer?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1456,
        512
      ]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "",
          "mode": "list",
          "cachedResultName": "-- Chọn của bạn --",
          "cachedResultUrl": ""
        },
        "sheetName": {
          "__rl": true,
          "value": "",
          "mode": "list",
          "cachedResultName": "-- Chọn của bạn --",
          "cachedResultUrl": ""
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "sender_id": "={{ $('Parse FB Message').item.json.sender_id }}",
            "status": "new"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "order_id",
              "displayName": "order_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "sender_id",
              "displayName": "sender_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "customer_name",
              "displayName": "customer_name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "phone",
              "displayName": "phone",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "address",
              "displayName": "address",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "menu_items",
              "displayName": "menu_items",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "total",
              "displayName": "total",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "note",
              "displayName": "note",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "order_time",
              "displayName": "order_time",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "status",
              "displayName": "status",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "id": "4f0bc45f-c3d5-4819-b4e9-643522073930",
      "name": "Append New Customer to Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        1648,
        256
      ]
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ 'restaurant_chat_' + $json.sender_id }}",
        "contextWindowLength": 15
      },
      "id": "1ed9f5c3-924a-4035-b88d-d502c5841870",
      "name": "Window Buffer Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "typeVersion": 1.3,
      "position": [
        1936,
        912
      ]
    },
    {
      "parameters": {
        "modelName": "models/gemini-3.5-flash",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        1712,
        912
      ],
      "id": "1f78513c-731d-4a54-a4eb-9e0785300045",
      "name": "Google Gemini Chat Model"
    },
    {
      "parameters": {
        "jsCode": "const input = $input.first().json || {};\nconst aiOutput = input.output || input.text || input.ai_response || '';\nconst senderId = $('Parse FB Message').first().json.sender_id;\nconst hasOrder = aiOutput.includes('---ORDER_CONFIRMED---') && aiOutput.includes('---END_ORDER---');\nif (hasOrder) {\n  const orderMatch = aiOutput.match(/---ORDER_CONFIRMED---([\\s\\S]*?)---END_ORDER---/);\n  const orderText = orderMatch ? orderMatch[1].trim() : '';\n  const nameMatch = orderText.match(/KHÁCH HÀNG:\\s*(.+)/i);\n  const phoneMatch = orderText.match(/SĐT:\\s*(.+)/i);\n  const addressMatch = orderText.match(/ĐỊA CHỈ:\\s*(.+)/i);\n  const totalMatch = orderText.match(/TỔNG TIỀN:\\s*(.+)/i);\n  const noteMatch = orderText.match(/GHI CHÚ:\\s*(.+)/i);\n  const menuMatch = orderText.match(/MÓN ĐẶT:\\s*\\n?([\\s\\S]*?)\\n?\\s*TỔNG TIỀN:/i);\n  const menuItems = menuMatch ? menuMatch[1].trim() : '';\n  return [{ json: {\n    has_order: true, sender_id: senderId, ai_response: aiOutput,\n    customer_name: nameMatch ? nameMatch[1].trim() : 'Không rõ',\n    phone: phoneMatch ? phoneMatch[1].trim() : 'Không rõ',\n    address: addressMatch ? addressMatch[1].trim() : 'Không rõ',\n    menu_items: menuItems,\n    total: totalMatch ? totalMatch[1].trim() : 'Không rõ',\n    note: noteMatch ? noteMatch[1].trim() : 'Không có',\n    order_time: new Date().toLocaleString('vi-VN', { timeZone: 'Asia/Ho_Chi_Minh' })\n  }}];\n}\nreturn [{ json: { has_order: false, sender_id: senderId, ai_response: aiOutput } }];"
      },
      "id": "06df70c9-8891-4cac-9577-cc37babe1db6",
      "name": "Check Order Confirmed",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2144,
        528
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "cond_order",
              "leftValue": "={{ $json.has_order }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "0dcdf3f2-d4bb-4cce-9c1e-527ec1954a23",
      "name": "Has Confirmed Order?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        3024,
        528
      ]
    },
    {
      "parameters": {
        "jsCode": "const data = $input.first().json || {};\nconst senderId = data.sender_id || $('Parse FB Message').first().json.sender_id;\nconst aiResponse = data.ai_response_clean || data.ai_response || '';\n\nlet userMessage = aiResponse\n  .replace(/\\[MENU_IMAGE:\\s*(menu_1|menu_2|menu_goi_them|none)\\]/gi, '')\n  .replace(/\\r\\n/g, '\\n')\n  .replace(/\\n{3,}/g, '\\n\\n')\n  .trim();\n\nif (!userMessage) {\n  userMessage = 'Dạ em cảm ơn anh/chị đã nhắn tin ạ. Khi nào anh/chị cần tư vấn set ăn hoặc đặt món, anh/chị cứ nhắn cho [TÊN QUÁN CỦA BẠN] nhé. Chúc anh/chị một ngày vui vẻ và hẹn gặp anh/chị lần sau ạ!';\n}\n\nconst maxLength = 1900;\nconst messages = [];\n\nif (userMessage.length > maxLength) {\n  for (let i = 0; i < userMessage.length; i += maxLength) {\n    messages.push(userMessage.substring(i, i + maxLength).trim());\n  }\n} else {\n  messages.push(userMessage);\n}\n\nreturn messages.map(msg => ({\n  json: {\n    sender_id: senderId,\n    message_text: msg\n  }\n}));"
      },
      "id": "cceb6158-7140-49d6-af95-0b5e01843148",
      "name": "Prepare FB Reply (Chat)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3840,
        944
      ]
    },
    {
      "parameters": {
        "jsCode": "const data = $input.first().json || {};\nconst senderId = data.sender_id || $('Parse FB Message').first().json.sender_id;\nconst aiResponse = data.ai_response_clean || data.ai_response || '';\n\nlet userMessage = aiResponse\n  .replace(/\\[MENU_IMAGE:\\s*(menu_1|menu_2|menu_goi_them|none)\\]/gi, '')\n  .replace(/---ORDER_CONFIRMED---[\\s\\S]*?---END_ORDER---/g, '')\n  .replace(/\\n{3,}/g, '\\n\\n')\n  .trim();\n\nif (!userMessage) {\n  userMessage = 'Dạ đặt hàng thành công ạ! Bên em sẽ giao hàng luôn, chúc anh/chị ngon miệng ạ!';\n}\n\nreturn [\n  {\n    json: {\n      sender_id: senderId,\n      message_text: userMessage\n    }\n  }\n];"
      },
      "id": "e9868984-91c2-48ae-9adc-3102c22a6ef8",
      "name": "Prepare FB Reply (Order)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3824,
        656
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://graph.facebook.com/v19.0/me/messages",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ { recipient: { id: $json.sender_id }, message: { text: $json.message_text }, messaging_type: \"RESPONSE\" } }}",
        "options": {}
      },
      "id": "fa3765f2-782e-4e46-85a8-7dbe9ddaca6e",
      "name": "Send FB Reply",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        4176,
        768
      ]
    },
    {
      "parameters": {
        "chatId": "YOUR_CHATID",
        "text": "=Don hang moi - [TÊN QUÁN CỦA BẠN]\nKhach: {{ $json.customer_name }}\nSDT: {{ $json.phone }}\nDia chi: {{ $json.address }}\nMon dat:\n{{ $json.menu_items }}\nTong tien: {{ $json.total }}\nGhi chu: {{ $json.note }}\nThoi gian: {{ $json.order_time }}\nVui long xu ly don ngay!",
        "additionalFields": {}
      },
      "id": "b035286e-022a-4dde-b932-58fd5911b37a",
      "name": "Telegram Notify Owner",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        3824,
        416
      ],
      "webhookId": "03f9f162-a80f-4871-9d62-ec0b30637eea"
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "",
          "mode": "list",
          "cachedResultName": "-- Chọn của bạn --",
          "cachedResultUrl": ""
        },
        "sheetName": {
          "__rl": true,
          "value": "",
          "mode": "list",
          "cachedResultName": "-- Chọn của bạn --",
          "cachedResultUrl": ""
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "order_id": "={{ 'ORD-' + $now.toMillis() }}",
            "sender_id": "={{ $('Check Order Confirmed').first().json.sender_id }}",
            "customer_name": "={{ $('Check Order Confirmed').first().json.customer_name }}",
            "phone": "={{ $('Check Order Confirmed').first().json.phone }}",
            "address": "={{ $('Check Order Confirmed').first().json.address }}",
            "menu_items": "={{ $('Check Order Confirmed').first().json.menu_items }}",
            "total": "={{ $('Check Order Confirmed').first().json.total }}",
            "note": "={{ $('Check Order Confirmed').first().json.note }}",
            "order_time": "={{ $('Check Order Confirmed').first().json.order_time }}",
            "status": "pending"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "order_id",
              "displayName": "order_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "sender_id",
              "displayName": "sender_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false
            },
            {
              "id": "customer_name",
              "displayName": "customer_name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false
            },
            {
              "id": "phone",
              "displayName": "phone",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false
            },
            {
              "id": "address",
              "displayName": "address",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false
            },
            {
              "id": "menu_items",
              "displayName": "menu_items",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false
            },
            {
              "id": "total",
              "displayName": "total",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false
            },
            {
              "id": "note",
              "displayName": "note",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false
            },
            {
              "id": "order_time",
              "displayName": "order_time",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false
            },
            {
              "id": "status",
              "displayName": "status",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": false
            }
          ]
        },
        "options": {}
      },
      "id": "ec31e459-d39c-4453-ab0f-175323643b33",
      "name": "Log Order to Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        3824,
        192
      ]
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $('Parse FB Message').item.json.message_text }}",
        "options": {
          "systemMessage": "=Bạn là chatbot tư vấn bán hàng cho cửa hàng [TÊN QUÁN CỦA BẠN].\n\nVai trò của bạn:\n\n* Tư vấn các set lẩu, hải sản và món gọi thêm theo đúng menu của cửa hàng.\n* Luôn xưng là \"em\", gọi khách là \"anh/chị\".\n* Trả lời lễ phép, thân thiện, ngắn gọn, không lan man.\n* Luôn hướng khách chọn set ăn phù hợp nhất và chốt đơn.\n* Không trả lời dài quá mức. Mỗi lần trả lời tối đa khoảng 1-2 câu, trừ khi cần xác nhận đơn hàng.\n* Không tư vấn sang lĩnh vực không liên quan đến menu, đặt món, giao hàng, giá, số người ăn, khẩu vị.\n\nCách tư vấn:\n\n1. Nếu khách hỏi món/set mà chưa nói ăn mấy người, hãy hỏi trước: \"Dạ anh/chị cho em hỏi mình ăn khoảng mấy người để em tư vấn set vừa đủ nhất ạ?\"\n2. Nếu khách đã nói số người ăn, hãy đề xuất 1-2 set phù hợp nhất, nêu ngắn gọn món chính, giá và lý do phù hợp.\n3. Nếu khách phân vân, hãy hỏi thêm khẩu vị:\n\n* Thích lẩu chua cay đậm vị: gợi ý Lẩu Thái Yum Yum.\n* Thích vị béo thơm, dễ ăn, nhiều tôm: gợi ý Lẩu Tôm Bầu.\n* Thích hải sản sốt, tôm/cua: gợi ý Menu Hải Sản.\n\n4. Nếu khách hỏi giá, trả lời đúng theo menu.\n5. Nếu khách muốn đặt, hãy hỏi lần lượt các thông tin còn thiếu:\n\n* Tên khách hàng\n* Số điện thoại\n* Địa chỉ giao hàng\n* Set/món muốn đặt\n* Ghi chú đặc biệt nếu có\n\n6. Khi khách xác nhận đặt hàng, phải xác nhận lại đơn rõ ràng, sau đó trả về đúng format đơn hàng bên dưới để hệ thống ghi nhận.\n7. Nếu khách chê đắt, phân vân, nói để suy nghĩ, bên khác rẻ hơn, không lấy nữa hoặc có ý từ chối, bạn KHÔNG được cảm ơn và kết thúc ngay. Bạn phải xử lý tối đa 3 lần theo hướng nhẹ nhàng, không ép khách:\n\n* Lần 1: Giải thích ngắn gọn vì sao giá hợp lý. Nhấn mạnh set đã gồm nhiều món, nước lẩu/sốt, rau/đậu/mỳ/miến đi kèm. Có thể quy đổi theo số người ăn nếu phù hợp. Sau đó gợi ý lại 1 lựa chọn phù hợp hơn.\n* Lần 2: Nếu khách vẫn chê đắt hoặc phân vân, hãy đề xuất phương án tiết kiệm hơn như set nhỏ hơn, đổi sang lẩu/set phù hợp hơn, hoặc gọi món lẻ/gọi thêm. Hỏi ngân sách hoặc số người ăn để chỉnh đơn.\n* Lần 3: Nếu khách tiếp tục từ chối, hãy níu nhẹ lần cuối bằng ưu điểm tiện lợi, phù hợp bữa ăn gia đình/nhóm bạn, giao tận nơi. Có thể gợi ý khách lưu menu hoặc đặt sau.\n* Chỉ sau khi khách từ chối rõ ràng đủ 3 lần, mới cảm ơn và hẹn khách lần sau.\n\nVí dụ xử lý khi khách chê đắt:\n\"Dạ em hiểu ạ. Set này giá nhìn một lần hơi cao nhưng mình ăn được khoảng 4-5 người, đã gồm tôm, bò/sụn, mọc tôm, rau đậu và nước lẩu rồi nên tính ra mỗi người khá hợp lý ạ. Nếu mình muốn mềm hơn, em có thể tư vấn set nhỏ hơn cho vừa ngân sách ạ.\"\n\nVí dụ xử lý khi khách vẫn phân vân:\n\"Dạ nếu mình muốn tiết kiệm hơn, em gợi ý mình lấy set nhỏ hơn trước, thiếu thì gọi thêm sau sẽ đỡ lãng phí hơn ạ. Anh/chị cho em xin khoảng ngân sách mình muốn đặt, em canh set vừa tiền nhất cho mình ạ.\"\n\nVí dụ níu lần cuối:\n\"Dạ em hiểu ạ. Món bên em hợp nhất khi mình muốn có sẵn một bữa lẩu/hải sản đủ đồ, không cần chuẩn bị nhiều, giao tới là dùng được luôn. Anh/chị có thể lưu menu lại, khi nào cần bữa ăn gia đình hoặc tụ tập bạn bè thì nhắn em tư vấn set vừa người, vừa tiền nhất ạ.\"\n\nMENU MẪU (thay bằng menu của quán bạn)\n\nA. LẨU THÁI YUM YUM\nLưu ý: Set lẩu chưa bao gồm cua. Cua tính theo thời giá.\n\nSet 3 người - 450K:\n\n* 150gr tôm\n* 200gr ngao\n* 100gr râu bạch tuộc\n* 100gr thịt bò\n* 100gr sụn\n* Rau, đậu, miến đi kèm\n* 2,4L nước lẩu Thái Yum đặc biệt\n\nSet 5 người - 650K:\n\n* 300gr tôm\n* 400gr ngao\n* 200gr râu bạch tuộc\n* 100gr thịt bò\n* 100gr sụn\n* Rau, đậu, miến đi kèm\n* 2,4L nước lẩu Thái Yum đặc biệt\n\nSet 7 người - 850K:\n\n* 500gr tôm\n* 400gr ngao\n* 400gr râu bạch tuộc\n* 200gr thịt bò\n* 200gr sụn\n* Rau, đậu, miến đi kèm\n* 4L nước lẩu Thái Yum đặc biệt\n\nCốt lẩu Thái Yum mua thêm: 190K / 3 lít.\n\nB. LẨU TÔM BẦU\nLưu ý: Định lượng gạch tôm và rau trong mỗi set khác nhau.\n\nSet 2-3 người - 390K:\n\n* 100gr vai bò mềm\n* 100gr sụn non\n* 150gr tôm tươi\n* 100gr mọc tôm\n* Mỳ chũ đi kèm\n* Rau, đậu đi kèm\n* 2,4L nước cốt gạch tôm\n\nSet 4-5 người - 590K:\n\n* 100gr vai bò mềm\n* 100gr sụn non\n* 300gr tôm tươi\n* 200gr mọc tôm tươi\n* Mỳ chũ đi kèm\n* Rau, đậu đi kèm\n* 2,4L nước cốt gạch tôm\n\nSet 6-7 người - 790K:\n\n* 500gr tôm tươi\n* 300gr mọc tôm\n* 200gr sụn non\n* 200gr vai bò mềm\n* Mỳ chũ đi kèm\n* Rau, đậu đi kèm\n* 2,4L nước cốt gạch tôm\n* 1 bịch nước cốt xương hầm\n\nCốt lẩu Tôm Bầu mua thêm: 140K / 2,4 lít.\n\nC. MENU HẢI SẢN\nCó 2 vị sốt:\n\n* Cajun: cay nhẹ, béo bơ, thơm tỏi kiểu Mỹ.\n* Tứ Xuyên: cay tê, đậm vị tiêu ớt Trung Hoa.\n\nSet Tôm Hùm Đất:\n\n* S2 cho 2 người: 400gr tôm - 380K\n* S3 cho 3 người: 600gr tôm - 570K\n* S4 cho 4 người: 800gr tôm - 770K\n* S6 cho 6 người: 1200gr tôm - 1140K\n\nSet Cua Tuyết:\n\n* S2 cho 2 người: 200gr cua - 480K\n* S3 cho 3 người: 450gr cua - 690K\n* S4 cho 4 người: 650gr cua - 980K\n\nSet Mix Tôm - Cua:\n\n* S2 cho 2 người: 200gr cua + 200gr tôm - 520K\n* S3 cho 3 người: 200gr cua + 300gr tôm - 730K\n* S5 cho 5 người: 400gr cua + 400gr tôm - 1100K\n* S7 cho 7 người: 550gr cua + 600gr tôm - 1410K\n\nMón gọi thêm:\n\n* Tôm hùm đất: 200gr / 149K\n* Cua tuyết: 200gr / 249K\n* Vẹm xanh New Zealand: 1 con / 25K\n* Bào ngư: 1 con / 30K\n* Ốc Bulot: 1 con / 20K\n* Tôm thẻ: 200gr / 180K\n* Sốt Tứ Xuyên: 500ml / 119K\n* Xốt Cajun: 500ml / 119K\n* Khoai tây: 1 phần / 15K\n* Ngô Mỹ: 1 phần / 24K\n* Coca Cola: 1 lon / 15K\n* Pepsi: 1 lon / 15K\n\nSố điện thoại giao hàng của cửa hàng: [SỐ ĐIỆN THOẠI CỦA QUÁN].\n\nQUY TẮC GỬI ẢNH MENU:\nKhi tư vấn cho khách, nếu phù hợp thì bạn phải trả về thêm một dòng tín hiệu nội bộ ở cuối câu trả lời.\n\nDùng:\n[MENU_IMAGE: menu_1]\nkhi khách hỏi hoặc quan tâm đến Lẩu Thái Yum Yum.\n\nDùng:\n[MENU_IMAGE: menu_2]\nkhi khách hỏi hoặc quan tâm đến Lẩu Tôm Bầu.\n\nDùng:\n[MENU_IMAGE: menu_goi_them]\nkhi khách hỏi món hải sản, món gọi thêm, gọi lẻ, sốt, nước ngọt hoặc các món ngoài set lẩu.\n\nDùng:\n[MENU_IMAGE: none]\nkhi chưa cần gửi ảnh menu.\n\nNếu khách chỉ hỏi chung về combo/lẩu mà chưa rõ thích vị nào, hãy tư vấn theo số người ăn trước. Nếu đang gợi ý Lẩu Thái Yum Yum thì dùng [MENU_IMAGE: menu_1]. Nếu đang gợi ý Lẩu Tôm Bầu thì dùng [MENU_IMAGE: menu_2].\n\nDòng [MENU_IMAGE: ...] chỉ dùng để hệ thống xử lý, không giải thích dòng này cho khách.\n\nTRƯỜNG HỢP KHÁCH CHỦ ĐỘNG YÊU CẦU XEM ẢNH:\nNếu khách chủ động xin xem ảnh/hình minh hoạ (ví dụ: \"cho em xem ảnh với\", \"có hình không\", \"gửi ảnh menu cho em\", \"cho xem hình set này\", \"gửi menu coi xem\", \"cho xin menu\"...), bạn PHẢI luôn gửi lại ảnh, kể cả khi trước đó hệ thống đã từng gửi ảnh đó cho khách rồi.\n\nCách chọn đúng loại ảnh:\n* Nếu khách nói rõ tên set/món trong chính câu xin ảnh đó → dùng đúng set đó.\n* Nếu khách xin ảnh chung chung (không nhắc lại tên set, ví dụ chỉ nói \"gửi menu coi xem\", \"cho xem ảnh với\") NHƯNG trong 1-3 tin nhắn gần nhất của hội thoại đã có nhắc đến hoặc đang tư vấn một set cụ thể → PHẢI mặc định lấy ảnh của set đó ngay, KHÔNG được hỏi lại khách lần nữa.\n* CHỈ được hỏi lại khách muốn xem ảnh set nào trong trường hợp duy nhất: từ đầu hội thoại đến giờ CHƯA hề nhắc đến bất kỳ set/món cụ thể nào.\n\nDùng tag đặc biệt thay vì tag thường:\n[MENU_IMAGE_FORCE: menu_1]\n[MENU_IMAGE_FORCE: menu_2]\n[MENU_IMAGE_FORCE: menu_goi_them]\n\nTag [MENU_IMAGE_FORCE: ...] cũng chỉ dùng để hệ thống xử lý, không giải thích dòng này cho khách. Không được viết câu kiểu \"em gửi anh/chị thêm ảnh...\" mà lại không gắn tag — nếu đã nói sẽ gửi ảnh thì bắt buộc phải có tag tương ứng trong cùng câu trả lời đó.\n\nQuy tắc chốt đơn:\nKhi khách đồng ý đặt hàng và đã có đủ thông tin cần thiết, bạn phải trả lời theo đúng format sau:\n\n---ORDER_CONFIRMED---\nKHÁCH HÀNG: [tên khách]\nSĐT: [số điện thoại]\nĐỊA CHỈ: [địa chỉ giao hàng]\nMÓN ĐẶT:\n[danh sách set/món - số lượng - giá]\nTỔNG TIỀN: [tổng tiền]\nGHI CHÚ: [ghi chú nếu có, nếu không có ghi \"Không có\"]\n---END_ORDER---\n\nSau format trên, thêm một câu ngắn gọn, lịch sự:\n\"Dạ bên em đã xác nhận đơn ạ. Bên em sẽ giao hàng luôn, chúc anh/chị ngon miệng ạ!\"\n\nLưu ý quan trọng:\n\n* Không tự bịa món ngoài menu.\n* Không tự bịa giá ngoài menu.\n* Nếu chưa rõ số người ăn, phải hỏi số người ăn trước.\n* Nếu khách chỉ hỏi chung \"có món gì ngon\", hãy hỏi số người ăn và khẩu vị trước, sau đó mới tư vấn.\n* Nếu khách hỏi ngoài phạm vi đặt món, hãy trả lời ngắn gọn rằng em chỉ hỗ trợ tư vấn menu và đặt món cho [TÊN QUÁN CỦA BẠN].\n* Luôn ưu tiên chốt set phù hợp nhất, không liệt kê toàn bộ menu nếu khách không yêu cầu.\n* Khi khách chê đắt hoặc từ chối, không kết thúc ngay ở lần đầu.\n* Phải cố gắng xử lý từ chối tối đa 3 lần theo hướng: giải thích giá trị → gợi ý phương án rẻ hơn → níu nhẹ lần cuối.\n* Không tranh cãi, không nói khách sai, không ép mua.\n* Nếu khách đã từ chối rõ ràng đủ 3 lần thì mới cảm ơn và hẹn khách lần sau.\n* Khi khách nói “đắt quá”, ưu tiên tư vấn theo hướng tiết kiệm hơn thay vì dừng cuộc trò chuyện.\n"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        1808,
        528
      ],
      "id": "bd27a001-5d4a-43de-b8a1-ee6903d2efa1",
      "name": "AI Agent"
    },
    {
      "parameters": {
        "jsCode": "const data = $input.first().json || {};\nconst parsed = $('Parse FB Message').first().json;\nconst senderId = data.sender_id || parsed.sender_id;\nconst customerMsg = (parsed.message_text || '').toLowerCase();\nconst rawResponse = data.ai_response || data.output || data.text || '';\n\n// DÁN LINK ẢNH MENU CÔNG KHAI CỦA QUÁN BẠN VÀO 3 DÒNG DƯỚI (bắt đầu bằng https://).\nconst MENU_URLS = {\n  menu_1: 'YOUR_MENU_1_IMAGE_URL',\n  menu_2: 'YOUR_MENU_2_IMAGE_URL',\n  menu_goi_them: 'YOUR_MENU_GOI_THEM_IMAGE_URL',\n};\n\nconst SESSION_TIMEOUT_MINUTES = 60;\nconst SESSION_TIMEOUT_MS = SESSION_TIMEOUT_MINUTES * 60 * 1000;\n\n// Bỏ dấu tiếng Việt để so khớp cho chắc (khách gõ có dấu / không dấu đều nhận).\nconst norm = (s) => (s || '')\n  .normalize('NFD').replace(/[\\u0300-\\u036f]/g, '')\n  .replace(/\\u0111/g, 'd').replace(/\\u0110/g, 'd');\nconst msgNoAccent = norm(customerMsg);\n\n// --- 1. Tag do AI Agent phát ra (nếu có) ---\nconst forceMatch = rawResponse.match(/\\[MENU_IMAGE_FORCE:\\s*(menu_1|menu_2|menu_goi_them)\\]/i);\nconst normalMatch = rawResponse.match(/\\[MENU_IMAGE:\\s*(menu_1|menu_2|menu_goi_them|none)\\]/i);\nconst tagImage = forceMatch ? forceMatch[1].toLowerCase()\n  : (normalMatch ? normalMatch[1].toLowerCase() : 'none');\n\n// --- 2. Khách CHỦ ĐỘNG xin menu? (không phụ thuộc thứ tự chữ, không phụ thuộc AI) ---\nfunction customerAsksMenu(m) {\n  if (/\\bmenu\\b/.test(m)) return true;                         // có nhắc \"menu\"\n  if (m.includes('thuc don') || m.includes('bang gia') || m.includes('thuc an')) return true;\n  const verb = /(gui|xem|coi|cho xem|cho xin|xin|co )/;        // xin ảnh/hình nói chung\n  const noun = /(anh|hinh)/;\n  return verb.test(m) && noun.test(m);\n}\nconst customerAsksForMenu = customerAsksMenu(msgNoAccent);\n\n// --- 3. Suy ra loại menu từ ngữ cảnh ---\nfunction detectMenu(text) {\n  const t = norm((text || '').toLowerCase());\n  if (t.includes('goi them') || t.includes('hai san') || t.includes('cua tuyet') ||\n      t.includes('tom hum') || t.includes('goi le') || t.includes('goi mon') ||\n      t.includes('xot ') || t.includes('sot cajun') || t.includes('tu xuyen')) return 'menu_goi_them';\n  if (t.includes('tom bau')) return 'menu_2';\n  if (t.includes('thai') || t.includes('yum')) return 'menu_1';\n  return null;\n}\n\n// --- 4. Quyết định ảnh cuối cùng ---\nlet requestedImage = 'none';\nlet isForced = false;\n\nif (customerAsksForMenu) {\n  isForced = true; // khách xin -> BẮT BUỘC gửi, bỏ qua chống trùng\n  requestedImage =\n    detectMenu(customerMsg) ||\n    (tagImage !== 'none' ? tagImage : null) ||\n    detectMenu(rawResponse) ||\n    'menu_1';\n} else if (forceMatch) {\n  isForced = true;\n  requestedImage = tagImage;\n} else if (normalMatch && tagImage !== 'none') {\n  requestedImage = tagImage;\n}\n\nconst cleanResponse = rawResponse\n  .replace(/\\[MENU_IMAGE_FORCE:\\s*(menu_1|menu_2|menu_goi_them)\\]/gi, '')\n  .replace(/\\[MENU_IMAGE:\\s*(menu_1|menu_2|menu_goi_them|none)\\]/gi, '')\n  .replace(/\\n{3,}/g, '\\n\\n')\n  .trim();\n\n// --- 5. Chống gửi trùng theo phiên ---\nconst staticData = $getWorkflowStaticData('global');\nif (!staticData.menuImageSentByCustomer) staticData.menuImageSentByCustomer = {};\nif (!staticData.lastInteractionAt) staticData.lastInteractionAt = {};\n\nconst now = Date.now();\nconst lastTime = staticData.lastInteractionAt[senderId] || 0;\nconst isNewSession = (now - lastTime) > SESSION_TIMEOUT_MS;\nif (isNewSession) staticData.menuImageSentByCustomer[senderId] = {};\nstaticData.lastInteractionAt[senderId] = now;\nif (!staticData.menuImageSentByCustomer[senderId]) staticData.menuImageSentByCustomer[senderId] = {};\n\nlet shouldSendImage = false;\nlet menuImageUrl = '';\nlet menuImageError = '';\n\nif (requestedImage !== 'none') {\n  const url = MENU_URLS[requestedImage] || '';\n  const hasValidUrl = /^https?:\\/\\//i.test(url);\n  if (!hasValidUrl) {\n    menuImageError = 'Chua cau hinh link anh cho ' + requestedImage;\n  } else if (isForced || !staticData.menuImageSentByCustomer[senderId][requestedImage]) {\n    shouldSendImage = true;\n    menuImageUrl = url;\n    staticData.menuImageSentByCustomer[senderId][requestedImage] = true;\n  }\n}\n\nreturn [{\n  json: {\n    ...data,\n    sender_id: senderId,\n    ai_response: cleanResponse,\n    ai_response_clean: cleanResponse,\n    menu_image_key: requestedImage,\n    should_send_image: shouldSendImage,\n    menu_image_url: menuImageUrl,\n    menu_image_error: menuImageError,\n    is_new_session: isNewSession,\n    is_forced_image: isForced,\n    customer_asks_menu: customerAsksForMenu,\n  }\n}];"
      },
      "id": "75b0c50b-1a6f-426d-a073-9af0ad01c724",
      "name": "Decide Menu Image",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2368,
        528
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "cond_send_menu_image",
              "leftValue": "={{ $json.should_send_image }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "c89f62c2-23d4-4d63-a334-983814e5b569",
      "name": "Should Send Menu Image?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        2176,
        928
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://graph.facebook.com/v19.0/me/messages",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ { recipient: { id: $json.sender_id }, message: { attachment: { type: \"image\", payload: { url: $json.menu_image_url, is_reusable: true } } }, messaging_type: \"RESPONSE\" } }}",
        "options": {}
      },
      "id": "4c45819a-a662-48ca-b92c-3aa628fb4290",
      "name": "Send FB Menu Image",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2400,
        912
      ]
    },
    {
      "parameters": {
        "content": "## LẮNG NGHE WEBHOOK\n  \n",
        "height": 608,
        "width": 1008,
        "color": 4
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        0,
        0
      ],
      "id": "c0fa5e90-0b28-42e4-aec3-192f8ecbd165",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "content": "## GỬI THÔNG TIN LÊN WEBHOOK\n\n",
        "height": 592,
        "width": 1008,
        "color": 4
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        0,
        656
      ],
      "id": "10f05c2c-dca4-4ed9-9256-d37d0f07c744",
      "name": "Sticky Note1"
    },
    {
      "parameters": {
        "content": "## CHAT VỚI KHÁCH HÀNG\n\n",
        "height": 1248,
        "width": 1632,
        "color": "#151127"
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1072,
        0
      ],
      "id": "0a4771fb-0317-449b-93a1-cd36bda62769",
      "name": "Sticky Note2"
    },
    {
      "parameters": {
        "content": "## CHỐT ĐƠN VÀ THỐNG BÁO\n\n",
        "height": 1296,
        "width": 1776,
        "color": 2
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        2832,
        0
      ],
      "id": "a0b6507a-6ae8-4419-a2c2-6f2e95c7bcef",
      "name": "Sticky Note3"
    }
  ],
  "pinData": {},
  "connections": {
    "Facebook Webhook Verify": {
      "main": [
        [
          {
            "node": "Is Verify Request?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Verify Request?": {
      "main": [
        [
          {
            "node": "Respond Verify",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond Verify Failed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Facebook Webhook Messages": {
      "main": [
        [
          {
            "node": "Respond 200 OK",
            "type": "main",
            "index": 0
          },
          {
            "node": "Parse FB Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse FB Message": {
      "main": [
        [
          {
            "node": "Check Customer in Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Customer in Sheet": {
      "main": [
        [
          {
            "node": "Check Is New Customer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Is New Customer": {
      "main": [
        [
          {
            "node": "Is New Customer?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is New Customer?": {
      "main": [
        [
          {
            "node": "Append New Customer to Sheet",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append New Customer to Sheet": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Window Buffer Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Check Order Confirmed": {
      "main": [
        [
          {
            "node": "Decide Menu Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Confirmed Order?": {
      "main": [
        [
          {
            "node": "Log Order to Sheet",
            "type": "main",
            "index": 0
          },
          {
            "node": "Telegram Notify Owner",
            "type": "main",
            "index": 0
          },
          {
            "node": "Prepare FB Reply (Order)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Prepare FB Reply (Chat)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare FB Reply (Order)": {
      "main": [
        [
          {
            "node": "Send FB Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare FB Reply (Chat)": {
      "main": [
        [
          {
            "node": "Send FB Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Check Order Confirmed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Decide Menu Image": {
      "main": [
        [
          {
            "node": "Has Confirmed Order?",
            "type": "main",
            "index": 0
          },
          {
            "node": "Should Send Menu Image?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Should Send Menu Image?": {
      "main": [
        [
          {
            "node": "Send FB Menu Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send FB Menu Image": {
      "main": [
        []
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "availableInMCP": false
  },
  "nodeGroups": [],
  "tags": []
}
