{
  "nodes": [
    {
      "id": "a1bb9718-a390-4b5f-8534-b8a973ce8695",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -3104,
        1984
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 1
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "33e9808c-510f-4b1c-883e-f0a569248ab7",
      "name": "Append or update slot",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -2496,
        1696
      ],
      "parameters": {
        "columns": {
          "value": {
            "day": "={{ $json.days }}",
            "time": "={{ $json.time }}",
            "service": "={{ $json.service }}"
          },
          "schema": [
            {
              "id": "service",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "service",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "time",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "day",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "day",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "service"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1HCl3CvMnzILIrcjnFK-AwLqWuKfMwezM1yXWkJ4KG9Q/edit#gid=0",
          "cachedResultName": "slots"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1HCl3CvMnzILIrcjnFK-AwLqWuKfMwezM1yXWkJ4KG9Q",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1HCl3CvMnzILIrcjnFK-AwLqWuKfMwezM1yXWkJ4KG9Q/edit?usp=drivesdk",
          "cachedResultName": "CRM"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "fdd67b6a-4301-4fff-bf04-5fd448f768db",
      "name": "Get lead",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -2704,
        1888
      ],
      "parameters": {
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "16bAoJicIDEPak46",
          "cachedResultUrl": "/projects/0WLzulivX2ChGmk8/datatables/16bAoJicIDEPak46",
          "cachedResultName": "leads"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a96ea4f0-f1c0-42c3-813b-7fc6ac28ac0d",
      "name": "Append or update lead",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -2496,
        1888
      ],
      "parameters": {
        "columns": {
          "value": {
            "name": "={{ $json.name }}",
            "phone": "={{ $json.phone }}",
            "short sum": "={{ $json.short_sum }}",
            "lead category": "={{ $json.lead_category }}"
          },
          "schema": [
            {
              "id": "name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "lead category",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "lead category",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "phone",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "short sum",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "short sum",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "phone"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1596543480,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1HCl3CvMnzILIrcjnFK-AwLqWuKfMwezM1yXWkJ4KG9Q/edit#gid=1596543480",
          "cachedResultName": "leads"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1HCl3CvMnzILIrcjnFK-AwLqWuKfMwezM1yXWkJ4KG9Q",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1HCl3CvMnzILIrcjnFK-AwLqWuKfMwezM1yXWkJ4KG9Q/edit?usp=drivesdk",
          "cachedResultName": "CRM"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "8bf64824-9d63-4c35-a9ff-0a23fd927bb7",
      "name": "Get human call",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -2704,
        2064
      ],
      "parameters": {
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "ygicufEiNou6tVCb",
          "cachedResultUrl": "/projects/0WLzulivX2ChGmk8/datatables/ygicufEiNou6tVCb",
          "cachedResultName": "human"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "aa6042af-187c-4326-bfe5-d46e783acdfa",
      "name": "Append or update human call",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -2496,
        2064
      ],
      "parameters": {
        "columns": {
          "value": {
            "name": "={{ $json.name }}",
            "phone": "={{ $json.phone }}",
            "description": "={{ $json.descreption }}"
          },
          "schema": [
            {
              "id": "name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "phone",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "description",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "phone"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 292004918,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1HCl3CvMnzILIrcjnFK-AwLqWuKfMwezM1yXWkJ4KG9Q/edit#gid=292004918",
          "cachedResultName": "human call"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1HCl3CvMnzILIrcjnFK-AwLqWuKfMwezM1yXWkJ4KG9Q",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1HCl3CvMnzILIrcjnFK-AwLqWuKfMwezM1yXWkJ4KG9Q/edit?usp=drivesdk",
          "cachedResultName": "CRM"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "9f4c7fec-7444-4b95-aa2c-0cfc70903c1c",
      "name": "Get human appointment",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -2688,
        2240
      ],
      "parameters": {
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "XICUlFpXl76eV2Dm",
          "cachedResultUrl": "/projects/0WLzulivX2ChGmk8/datatables/XICUlFpXl76eV2Dm",
          "cachedResultName": "appointments"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "9ae86536-5815-4b76-bc4d-e1371866bcda",
      "name": "Append or update appointment",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -2496,
        2240
      ],
      "parameters": {
        "columns": {
          "value": {
            "day": "={{ $json.day }}",
            "date": "={{ $json.date }}",
            "name": "={{ $json.name }}",
            "time": "={{ $json.times }}",
            "phone": "={{ $json.phone }}",
            "service": "={{ $json.service }}"
          },
          "schema": [
            {
              "id": "name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "phone",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "time",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "day",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "day",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "service",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "service",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "phone"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1977548840,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1HCl3CvMnzILIrcjnFK-AwLqWuKfMwezM1yXWkJ4KG9Q/edit#gid=1977548840",
          "cachedResultName": "appointments"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1HCl3CvMnzILIrcjnFK-AwLqWuKfMwezM1yXWkJ4KG9Q",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1HCl3CvMnzILIrcjnFK-AwLqWuKfMwezM1yXWkJ4KG9Q/edit?usp=drivesdk",
          "cachedResultName": "CRM"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "7685907b-6ffe-43f2-8963-eac68e4ff6f4",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "disabled": true,
      "position": [
        -3248,
        1456
      ],
      "parameters": {
        "color": 7,
        "width": 1296,
        "height": 1168,
        "content": "## SENDING new rows to google sheet"
      },
      "typeVersion": 1
    },
    {
      "id": "5577ae1c-5d66-4905-8fa3-71d4d7d2e283",
      "name": "Booked Appointment",
      "type": "n8n-nodes-base.dataTableTool",
      "position": [
        -864,
        880
      ],
      "parameters": {
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "XICUlFpXl76eV2Dm",
          "cachedResultUrl": "/projects/0WLzulivX2ChGmk8/datatables/XICUlFpXl76eV2Dm",
          "cachedResultName": "appointments"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "1e612891-e43a-4153-8098-22f0326a3883",
      "name": "AI Summarizer1",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        128,
        1264
      ],
      "parameters": {
        "text": "={{ $('Format Context').item.json.formatted_output }}",
        "options": {
          "systemMessage": "=# Customer Message Analyzer\n\nAnalyze customer messages and return only JSON:\n```json\n{\"summary\": \"brief description\", \"category\": \"category_name\"}\n```\n\n## Categories\n- **appointment**: booking request\n- **pricing**: price inquiry\n- **discount**: discount request\n- **teeth_whitening**: whitening inquiry\n- **skincare**: skincare inquiry\n- **staff_request**: staff contact request\n- **out_of_scope**: unrelated topic\n\n## Instructions\n- Summary: one clear sentence describing the customer's request\n- Output: JSON only, no additional text\n- answer with the user's language "
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "c0e92bbc-42cb-4a40-b403-27150e290bb2",
      "name": "Check Appointment1",
      "type": "n8n-nodes-base.if",
      "position": [
        304,
        352
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.has_appointment }}",
              "rightValue": "YES"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "98e8a42a-9e2c-4468-87f4-8f7b441a94d3",
      "name": "AI Data Extractor",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -208,
        352
      ],
      "parameters": {
        "text": "={{ $json.output }}",
        "options": {
          "systemMessage": "=// System Prompt for AI Data Extractor Node\n-- today is {{ $now }}\nYou are a precise data extractor. Extract information in JSON format ONLY.\n-- **if there was no date**  return the correct date of the nearest day that was chosen. \n\u26a0\ufe0f Return ONLY valid JSON, no markdown or extra text.\n\n\ud83d\udccb Required Format:\n{\n  \"has_appointment\": true or false,\n  \"is_reschedule\": true or false,\n  \"needs_human\": true or false,\n  \"appointment_date\": \"YYYY-MM-DD\" or null,\n  \"appointment_day\": \"\u0627\u0644\u0623\u062d\u062f/\u0627\u0644\u0627\u062b\u0646\u064a\u0646/etc\" or null,\n  \"appointment_time\": \"HH:MM\" or null,\n  \"service\": \"service name in Arabic\" or null,\n  \"lead_category\": \"only one of those booking/reschedule/pricing/discount/teeth_whitening/skin_care/ask_agent/out_of_scope/other\",\n  \"description\": \"brief description in Arabic\",\n  \"notes\": \"additional notes\" or null\n}\n\n\ud83d\udcdd Rules:\n**has_appointment:**\n- true if booking confirmed: \"\u062a\u0645 \u062d\u062c\u0632 \u0645\u0648\u0639\u062f\u0643\" OR \"\u062a\u0645 \u062a\u0639\u062f\u064a\u0644 \u0645\u0648\u0639\u062f\u0643\"\n- false otherwise\n\n**is_reschedule:**\n- true if customer changed existing appointment\n- false for new bookings\n\n**needs_human:**\n\u26a0\ufe0f BE VERY STRICT - only true if:\n- EXPLICIT request: \"\u0628\u062f\u064a \u0645\u0648\u0638\u0641\" / \"\u0648\u062f\u064a\u0646\u064a \u0639\u0644\u0649 \u062d\u062f\u0627\" / \"\u0628\u062f\u064a \u0623\u062d\u0643\u064a \u0645\u0639 \u0634\u062e\u0635\" / \"\u0627\u062a\u0635\u0644 \u0641\u064a\u0646\u064a\"\n- Clear anger/frustration: cursing, multiple complaints, \"\u0645\u0634 \u0631\u0627\u0636\u064a\" / \"\u0632\u0647\u0642\u062a\"\n- Medical emergency: \"\u0648\u062c\u0639 \u0634\u062f\u064a\u062f\" / \"\u062d\u0627\u0644\u0629 \u0637\u0627\u0631\u0626\u0629\" / \"\u0645\u0631\u064a\u0636 \u0643\u062b\u064a\u0631\"\n- Bot explicitly failed multiple times\n\n\u26d4 DO NOT set true for:\n- Simple questions about services\n- Asking about prices or discounts\n- General inquiries (\"\u0634\u0648 \u0639\u0646\u062f\u0643\u0645\u061f\" / \"\u0643\u064a\u0641\u061f\")\n- Booking/rescheduling requests\n- Normal conversation\n\n**appointment_date/day/time/service:**\n- Extract as before\n- null if not mentioned\n\n**lead_category:**\n- \"reschedule\": if modifying existing appointment\n- \"booking\": new appointment booking\n- \"pricing\": price inquiry\n- \"discount\": discount request\n- \"teeth_whitening\": teeth whitening inquiry\n- \"skin_care\": skin care inquiry\n- \"ask_agent\": wants to speak with staff (ONLY if explicit request)\n- \"out_of_scope\": outside clinic specialty\n- \"other\": anything else\n\n**description:**\n- One sentence in Arabic\n- Examples:\n  - \"\u0627\u0644\u0639\u0645\u064a\u0644 \u0642\u0627\u0645 \u0628\u062a\u0639\u062f\u064a\u0644 \u0645\u0648\u0639\u062f\u0647 \u0644\u062a\u0628\u064a\u064a\u0636 \u0627\u0644\u0623\u0633\u0646\u0627\u0646\"\n  - \"\u0637\u0644\u0628 \u062a\u063a\u064a\u064a\u0631 \u0627\u0644\u0645\u0648\u0639\u062f \u0645\u0646 \u0627\u0644\u0623\u062d\u062f \u0625\u0644\u0649 \u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621\"\n  - \"\u0637\u0644\u0628 \u0627\u0644\u062a\u062d\u062f\u062b \u0645\u0639 \u0645\u0648\u0638\u0641 \u0628\u0634\u0643\u0644 \u0635\u0631\u064a\u062d\"\n\n\ud83c\udfaf Example - Normal Question (needs_human = FALSE):\nUser: \"\u0634\u0648 \u0639\u0646\u062f\u0643\u0645 \u062e\u062f\u0645\u0627\u062a\u061f\"\n{\n  \"has_appointment\": false,\n  \"is_reschedule\": false,\n  \"needs_human\": false,\n  \"appointment_date\": null,\n  \"appointment_day\": null,\n  \"appointment_time\": null,\n  \"service\": null,\n  \"lead_category\": \"other\",\n  \"description\": \"\u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u0639\u0627\u0645 \u0639\u0646 \u0627\u0644\u062e\u062f\u0645\u0627\u062a\",\n  \"notes\": null\n}\n\n\ud83c\udfaf Example - Explicit Human Request (needs_human = TRUE):\nUser: \"\u0628\u062f\u064a \u0623\u062d\u0643\u064a \u0645\u0639 \u0645\u0648\u0638\u0641 \u0645\u0634 \u0645\u0639\u0643\"\n{\n  \"has_appointment\": false,\n  \"is_reschedule\": false,\n  \"needs_human\": true,\n  \"appointment_date\": null,\n  \"appointment_day\": null,\n  \"appointment_time\": null,\n  \"service\": null,\n  \"lead_category\": \"ask_agent\",\n  \"description\": \"\u0637\u0644\u0628 \u0635\u0631\u064a\u062d \u0644\u0644\u062a\u062d\u062f\u062b \u0645\u0639 \u0645\u0648\u0638\u0641\",\n  \"notes\": \"\u064a\u062d\u062a\u0627\u062c \u062a\u062f\u062e\u0644 \u0628\u0634\u0631\u064a \u0641\u0648\u0631\u064a\"\n}\n\n\ud83c\udfaf Example - Frustration (needs_human = TRUE):\nUser: \"\u064a\u0627 \u0632\u0644\u0645\u0629 \u0645\u0634 \u0641\u0627\u0647\u0645 \u0639\u0644\u064a\u0643\u060c \u0648\u062f\u064a\u0646\u064a \u0639\u0644\u0649 \u062d\u062f\u0627 \u0628\u0641\u0647\u0645\"\n{\n  \"has_appointment\": false,\n  \"is_reschedule\": false,\n  \"needs_human\": true,\n  \"appointment_date\": null,\n  \"appointment_day\": null,\n  \"appointment_time\": null,\n  \"service\": null,\n  \"lead_category\": \"ask_agent\",\n  \"description\": \"\u0625\u062d\u0628\u0627\u0637 \u0648\u0637\u0644\u0628 \u0627\u0644\u062a\u062d\u062f\u062b \u0645\u0639 \u0634\u062e\u0635\",\n  \"notes\": \"\u0639\u062f\u0645 \u0631\u0636\u0627 \u0648\u0627\u0636\u062d\"\n}"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "56670131-4402-4ae7-ad14-22f67064e4b6",
      "name": "Send via WhatsApp",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -80,
        48
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v22.0/{{ $('Format Context').item.json.wa_id }}/messages",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"messaging_product\": \"whatsapp\",\n  \"to\": \"{{ $('Format Context').item.json.sender }}\",\n  \"type\": \"text\",\n  \"text\":{  \"body\":{{ JSON.stringify($json.output) }}}\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "44b6b15f-d026-4710-8e2a-0878df5a6aa6",
      "name": "Pinecone Vector Store",
      "type": "@n8n/n8n-nodes-langchain.vectorStorePinecone",
      "position": [
        -1328,
        2016
      ],
      "parameters": {
        "mode": "insert",
        "options": {
          "pineconeNamespace": "1"
        },
        "pineconeIndex": {
          "__rl": true,
          "mode": "list",
          "value": "n8n",
          "cachedResultName": "n8n"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4bdb5738-0c36-40cb-ae81-315d54320894",
      "name": "Default Data Loader",
      "type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
      "position": [
        -1168,
        2240
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "d31374e1-7546-4dbb-8df8-50e88ae64338",
      "name": "Recursive Character Text Splitter",
      "type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter",
      "position": [
        -1184,
        2448
      ],
      "parameters": {
        "options": {},
        "chunkOverlap": 100
      },
      "typeVersion": 1
    },
    {
      "id": "1d149211-15e0-4925-aeb7-5a946fbe24ce",
      "name": "Get a document",
      "type": "n8n-nodes-base.googleDocs",
      "position": [
        -1552,
        2016
      ],
      "parameters": {
        "operation": "get",
        "documentURL": "=https://docs.google.com/document/d/1M2VXsD_gLRDbRv8VU2S2IfnCkPl5NaPqX_QulHV-050/edit?tab=t.0"
      },
      "typeVersion": 2
    },
    {
      "id": "07700abc-c2bd-44a1-8188-3d51a4022d9e",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -1744,
        2016
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "80e81e5e-e2f0-4bbc-80dc-02dbf0b2bca4",
      "name": "Embeddings OpenAI",
      "type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
      "position": [
        -1504,
        2256
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ffa2a0af-0af3-4466-a009-2ab4522bb72e",
      "name": "Vector Store Tool",
      "type": "@n8n/n8n-nodes-langchain.toolVectorStore",
      "position": [
        -1248,
        976
      ],
      "parameters": {
        "name": "company_documents_tool",
        "description": "Retrieve information from any company documents"
      },
      "typeVersion": 1
    },
    {
      "id": "80bd0f37-5df9-4430-adb8-253585287dbb",
      "name": "Pinecone Vector Store (Retrieval)",
      "type": "@n8n/n8n-nodes-langchain.vectorStorePinecone",
      "position": [
        -1344,
        1152
      ],
      "parameters": {
        "options": {},
        "pineconeIndex": {
          "__rl": true,
          "mode": "list",
          "value": "clinic",
          "cachedResultName": "clinic"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e60712a2-3949-4719-8ac1-a4b218f1f192",
      "name": "Embeddings OpenAI1",
      "type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
      "position": [
        -1280,
        1376
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "6b947bca-a0ec-486e-b483-f9e239987032",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1888,
        1952
      ],
      "parameters": {
        "color": 7,
        "width": 1024,
        "height": 656,
        "content": "## RAG System\n"
      },
      "typeVersion": 1
    },
    {
      "id": "e78bf1f5-33f0-409a-901d-d7f8257e32ae",
      "name": "Verify \u2022 WA (hub.challenge)",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -3824,
        272
      ],
      "parameters": {
        "options": {
          "responseCode": 200,
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/plain"
              }
            ]
          }
        },
        "respondWith": "text",
        "responseBody": "={{ $json.query['hub.challenge'] || 'OK' }}"
      },
      "typeVersion": 1.4
    },
    {
      "id": "e13b4e56-2078-4a94-8b6a-c3e4cd1080f5",
      "name": "filter text messages",
      "type": "n8n-nodes-base.if",
      "position": [
        -3136,
        256
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.body.entry[0].changes[0].value.messages[0].type }}",
              "rightValue": "text"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "f43e83f8-161b-4231-9dbc-79962676b2d5",
      "name": "If Audio",
      "type": "n8n-nodes-base.if",
      "position": [
        -3552,
        464
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.body.entry[0].changes[0].value.messages[0].type }}",
              "rightValue": "audio"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "13e1d14a-d5ed-4d42-b437-ff3de78ed653",
      "name": "Get Audio",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -3328,
        448
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v22.0/{{ $('WhatsApp Webhook').item.json.body.entry[0].changes[0].value.messages[0].audio.id }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "8e96d4bb-2210-44c6-a28d-6bcb780bf1f9",
      "name": "Download Audio",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -3136,
        448
      ],
      "parameters": {
        "url": "={{$json.url}}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "1da24395-e5e2-4b21-8629-11a63baab66f",
      "name": "Transcribe Audio",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        -2928,
        448
      ],
      "parameters": {
        "options": {
          "language": "ar",
          "temperature": 0.6
        },
        "resource": "audio",
        "operation": "transcribe"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "1ebf7b18-abb1-44cf-8638-36dca9cf28c5",
      "name": "If Image",
      "type": "n8n-nodes-base.if",
      "position": [
        -3536,
        704
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.body.entry[0].changes[0].value.messages[0].image.mime_type }}",
              "rightValue": "image"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "2105b13a-d511-4626-bc32-019d94e63749",
      "name": "If Video/PDF",
      "type": "n8n-nodes-base.if",
      "position": [
        -3520,
        880
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "1",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.body.entry[0].changes[0].value.messages[0].document.mime_type }}",
              "rightValue": "application"
            },
            {
              "id": "a584f702-7224-400b-85ff-eeff8eca35b3",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.body.entry[0].changes[0].value.messages[0].document.mime_type }}",
              "rightValue": "video"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "0d717c38-68da-47a7-a79f-7caac828e8aa",
      "name": "Get Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -3296,
        688
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v22.0/{{ $('WhatsApp Webhook').item.json.body.entry[0].changes[0].value.messages[0].image.id }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "1f019d11-f137-4fce-983e-8940de919d2b",
      "name": "Download Image",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -3072,
        688
      ],
      "parameters": {
        "url": "={{$json.url}}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "4c2cf8bd-065a-4320-8e79-770d7cc9e4c2",
      "name": "Get file",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -3296,
        864
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v22.0/{{ $('WhatsApp Webhook').item.json.body.entry[0].changes[0].value.messages[0].document.id }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "b6ebf3af-7914-4962-84d5-a883507b3111",
      "name": "Download file",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -3088,
        864
      ],
      "parameters": {
        "url": "={{$json.url}}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "=httpBearerAuth"
      },
      "typeVersion": 4.2
    },
    {
      "id": "2d8c8b15-7149-4904-8368-b2c04423001b",
      "name": "Prepare Email With Attachment",
      "type": "n8n-nodes-base.code",
      "position": [
        -2864,
        864
      ],
      "parameters": {
        "jsCode": "// \u0627\u0642\u0631\u0623 \u0628\u064a\u0627\u0646\u0627\u062a \u0627\u0644\u0648\u0650\u0628\u0647\u0648\u0643 \u0648\u0627\u0644\u0640 input\nconst webhookData = $('WhatsApp Webhook').first().json;\nconst firstItem = $input.first();\n\nconst name = webhookData.body?.entry?.[0]?.changes?.[0]?.value?.contacts?.[0]?.profile?.name || \"\";\nconst phone = webhookData.body?.entry?.[0]?.changes?.[0]?.value?.contacts?.[0]?.wa_id || firstItem.json.phone || \"\";\n\n// \u0644\u0648 \u0641\u064a\u0647 binary \u062c\u0627\u0647\u0632 \u0645\u0646 \u0639\u0642\u062f\u0629 \u0633\u0627\u0628\u0642\u0629\u060c \u062e\u0630\u0647\nconst bin = firstItem.binary || {};\nconst binaryKey = Object.keys(bin)[0] || \"\"; // \u0645\u062b\u0627\u0644: \"file\" \u0623\u0648 \"data\"\nif (!name || !phone || !binaryKey) {\n  throw new Error(\"\u0645\u0637\u0644\u0648\u0628 name \u0648 phone \u0648 \u0645\u0644\u0641 binary \u0645\u0646 \u0627\u0644\u0639\u0642\u062f\u0629 \u0627\u0644\u0633\u0627\u0628\u0642\u0629.\");\n}\n\nconst subject = \"\u0625\u0634\u0639\u0627\u0631 \u062a\u0648\u0627\u0635\u0644 \u062c\u062f\u064a\u062f\";\nconst html = `\n<!doctype html>\n<html lang=\"ar\" dir=\"rtl\">\n<head>\n  <meta charset=\"utf-8\"><title>${subject}</title>\n  <style>\n    body { background:#e8f3ff; direction:rtl; text-align:right; font-family:'Segoe UI',Roboto,Helvetica,Arial,sans-serif; margin:0; padding:0; }\n    .container { max-width:600px; margin:24px auto; background:#fff; border-radius:12px; overflow:hidden; box-shadow:0 4px 16px rgba(13,71,161,0.15); }\n    .header { background:linear-gradient(135deg,#0D47A1,#00B894); padding:20px; color:#fff; }\n    .content { padding:24px; }\n    .row { margin:0 0 12px 0; }\n    .label { color:#0D47A1; font-weight:600; }\n    .footer { background:#f7fafc; padding:16px; font-size:12px; color:#555; border-top:1px solid #e9eef8; }\n    .brand { color:#0D47A1; font-weight:600; }\n  </style>\n</head>\n<body>\n  <div class=\"container\">\n    <div class=\"header\">\n      <h2 style=\"margin:0;\">${subject}</h2>\n      <p style=\"margin:6px 0 0 0;\">\u0644\u0642\u062f \u062a\u0645 \u0627\u0633\u062a\u0644\u0627\u0645 \u0637\u0644\u0628 \u062c\u062f\u064a\u062f \u0645\u0646 \u0645\u0648\u0642\u0639\u0643</p>\n    </div>\n    <div class=\"content\">\n      <p class=\"row\"><span class=\"label\">\u0627\u0644\u0627\u0633\u0645:</span> ${name}</p>\n      <p class=\"row\"><span class=\"label\">\u0631\u0642\u0645 \u0627\u0644\u0647\u0627\u062a\u0641:</span> ${phone}</p>\n      <p class=\"row\">\u0627\u0644\u0645\u0631\u0641\u0642 \u062a\u0645 \u0625\u0631\u0641\u0627\u0642\u0647 \u0645\u0639 \u0647\u0630\u0627 \u0627\u0644\u0628\u0631\u064a\u062f.</p>\n    </div>\n    <div class=\"footer\">\n      \u062a\u0645 \u0627\u0644\u0625\u0631\u0633\u0627\u0644 \u0628\u0648\u0627\u0633\u0637\u0629 <span class=\"brand\">\u062a\u0648\u0627\u0635\u0644 \u0627\u0644\u0639\u064a\u0627\u062f\u0627\u062a</span>\n    </div>\n  </div>\n</body>\n</html>\n`;\n\n// \u0631\u062c\u0651\u0639 \u0646\u0641\u0633 \u0627\u0644\u0640 binary \u062d\u062a\u0649 \u064a\u0644\u062a\u0642\u0637\u0647 Email node \u0643\u0645\u0631\u0641\u0642\nreturn [\n  {\n    json: { subject, html },\n    binary: { [binaryKey]: bin[binaryKey] },\n  },\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "f197f696-3c15-4bdf-aa64-15a87523b055",
      "name": "Send Email with attachment",
      "type": "n8n-nodes-base.gmail",
      "position": [
        -2640,
        864
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "={{ $json.html }}",
        "options": {
          "attachmentsUi": {
            "attachmentsBinary": [
              {}
            ]
          }
        },
        "subject": "\u0647\u0646\u0627\u0643 \u0639\u0645\u064a\u0644 \u0623\u0631\u0633\u0644 \u0645\u0644\u0641 "
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "49ed334f-d0dd-43ac-90aa-0ad08d9f6ead",
      "name": "Edit Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        -2640,
        688
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "05294dc6-587a-4631-b03a-395ffad76a89",
              "name": "text",
              "type": "string",
              "value": "=image description:  {{ $json.content }}\nuser's message: {{ $('WhatsApp Webhook').item.json.body.entry[0].changes[0].value.messages[0].image.caption }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "4055776e-6283-472a-bfbc-374ad20cc555",
      "name": "Analyze image",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        -2848,
        688
      ],
      "parameters": {
        "text": "Here is an image sent by the user. Describe the image and transcribe any text visible in the image.",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {
          "maxTokens": 50
        },
        "resource": "image",
        "inputType": "=base64",
        "operation": "analyze"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "98fa0d1d-cea9-4f2f-a8dc-4cd997ebb1ce",
      "name": "Prepare Text Data",
      "type": "n8n-nodes-base.code",
      "position": [
        -2112,
        576
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\n\n// Get phone number from webhook\nconst phoneNumber = $('WhatsApp Webhook').first().json.body.entry[0].changes[0].value.messages[0].from || '';\n\n// Try to get text from different sources\nlet textFromWhisper;\nlet textFromWebhook;\nlet textFromImage;\n\n// 1. Try to get transcribed voice from Whisper\ntry {\n  textFromWhisper = $('Transcribe Audio').first().json.text;\n  console.log('Voice text found:', textFromWhisper);\n} catch (e) {\n  textFromWhisper = undefined;\n}\n\n// 2. Try to get regular text message from webhook\ntry {\n  textFromWebhook = $('WhatsApp Webhook').first().json.body.entry[0].changes[0].value.messages[0].text.body;\n  console.log('Text message found:', textFromWebhook);\n} catch (e) {\n  textFromWebhook = undefined;\n}\n\n// 3. Try to get image analysis from Edit Fields node\ntry {\n  textFromImage = $('Edit Fields').first().json.text;\n  console.log('Image analysis found:', textFromImage);\n} catch (e) {\n  textFromImage = undefined;\n}\n\n// Combine all available text sources\n// Priority: voice > image > text message\nlet finalText = textFromWhisper || textFromImage || textFromWebhook || '';\n\n// Add source indicator for debugging\nlet source = '';\nif (textFromWhisper) {\n  source = 'voice';\n} else if (textFromImage) {\n  source = 'image';\n} else if (textFromWebhook) {\n  source = 'text';\n}\n\nconsole.log('Final text source:', source);\nconsole.log('Final text:', finalText);\n\nreturn items.map(item => {\n  return {\n    json: {\n      phone: phoneNumber,\n      text: finalText,\n      source: source, // \u0644\u0644\u0645\u0639\u0631\u0641\u0629 \u0645\u0646 \u0648\u064a\u0646 \u062c\u0627\u064a \u0627\u0644\u0646\u0635\n      timestamp: new Date().toISOString()\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "4f37fbd4-21f2-4f31-ae58-8774cf8c21bc",
      "name": "Insert Row Memory",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -1920,
        576
      ],
      "parameters": {
        "columns": {
          "value": {
            "phone": "={{ $('WhatsApp Webhook').item.json.body.entry[0].changes[0].value.contacts[0].wa_id }}",
            "sender": "={{ $json.text }}"
          },
          "schema": [
            {
              "id": "sender",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "sender",
              "defaultMatch": false
            },
            {
              "id": "reciever",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "reciever",
              "defaultMatch": false
            },
            {
              "id": "phone",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "l6biIqkSE1qLJvaZ",
          "cachedResultUrl": "/projects/0WLzulivX2ChGmk8/datatables/l6biIqkSE1qLJvaZ",
          "cachedResultName": "test table"
        }
      },
      "executeOnce": true,
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "3ed7200b-b2d4-490c-b26d-92fbebc6c607",
      "name": "Get History",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -1728,
        576
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "phone",
              "keyValue": "={{ $('Prepare Text Data').item.json.phone }}"
            }
          ]
        },
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "l6biIqkSE1qLJvaZ",
          "cachedResultUrl": "/projects/0WLzulivX2ChGmk8/datatables/l6biIqkSE1qLJvaZ",
          "cachedResultName": "test table"
        }
      },
      "executeOnce": true,
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "5f0569e7-dde9-41ed-9b16-544a7b7013b8",
      "name": "Format Context",
      "type": "n8n-nodes-base.code",
      "position": [
        -1360,
        576
      ],
      "parameters": {
        "jsCode": "// \u0627\u0633\u062a\u062e\u0631\u0627\u062c \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0627\u0644\u0623\u0633\u0627\u0633\u064a\u0629\nconst jsText = $('Prepare Text Data').first().json.text || '';\nconst phoneNumber = $('Prepare Text Data').first().json.phone || '';\nconst wa_id = $('WhatsApp Webhook').item.json.body.entry[0].changes[0].value.metadata.phone_number_id;\nconst name = $('WhatsApp Webhook').first().json.body.entry[0].changes[0].value.contacts[0].profile.name;\n\n// Get available slots\nlet availableSlots = [];\ntry {\n  const slotsData = $('Get Slots1').all();\n  console.log('Get Slots1 data:', JSON.stringify(slotsData.map(s => s.json)));\n  \n  availableSlots = slotsData.map(slot => {\n    console.log('Slot structure:', Object.keys(slot.json));\n    \n    const date = slot.json['\u0627\u0644\u062a\u0627\u0631\u064a\u062e (A)'] || slot.json.date || slot.json.\u0627\u0644\u062a\u0627\u0631\u064a\u062e || '';\n    const time = slot.json['\u0627\u0644\u0648\u0642\u062a (B)'] || slot.json.time || slot.json.\u0627\u0644\u0648\u0642\u062a || '';\n    const service = slot.json['\u0627\u0644\u062e\u062f\u0645\u0629 (C)'] || slot.json.service || slot.json.\u0627\u0644\u062e\u062f\u0645\u0629 || '';\n    \n    return `${date} - ${time} (${service})`;\n  });\n  \n  console.log('Available slots formatted:', availableSlots);\n} catch (e) {\n  console.error('Error fetching slots:', e.message);\n  availableSlots = [];\n}\n\n// Get existing appointments for this customer\nlet existingAppointments = [];\ntry {\n  const appointmentsData = $('Get appointment1').all();\n  console.log('Get History1 appointments:', appointmentsData.length);\n  \n  existingAppointments = appointmentsData.map(apt => {\n    console.log('Appointment structure:', Object.keys(apt.json));\n    \n    const date = apt.json.date || '';\n    const time = apt.json.times || apt.json.time || '';\n    const service = apt.json.service || '';\n    const name = apt.json.name || '';\n    \n    return `${date} at ${time} - ${service} (${name})`;\n  });\n  \n  console.log('Existing appointments formatted:', existingAppointments);\n} catch (e) {\n  console.error('Error fetching existing appointments:', e.message);\n  existingAppointments = [];\n}\n\n// Format conversation history from Get History1\nlet formattedHistory = '';\nlet historyCount = 0;\ntry {\n  const historyData = $('Get History').all().slice(0, 10);\n  historyCount = historyData.length;\n  console.log('Get History1 data:', historyCount);\n  \n  formattedHistory = historyData.map(entry => {\n    const createdAt = entry.json.createdAt || '';\n    const aiResponse = entry.json.reciever || entry.json.ai || '';\n    const userMessage = entry.json.sender || entry.json.user || '';\n    \n    // Format timestamp as yyyy-mm-dd:HH:MM\n    let formattedTime = '';\n    if (createdAt) {\n      const date = new Date(createdAt);\n      const year = date.getFullYear();\n      const month = String(date.getMonth() + 1).padStart(2, '0');\n      const day = String(date.getDate()).padStart(2, '0');\n      const hours = String(date.getHours()).padStart(2, '0');\n      const minutes = String(date.getMinutes()).padStart(2, '0');\n      formattedTime = `${year}-${month}-${day}:${hours}:${minutes}`;\n    }\n    \n    return `( ${formattedTime}, ai: ${aiResponse}, user: ${userMessage})`;\n  }).join('\\n');\n  \n  console.log('Formatted history:', formattedHistory);\n} catch (e) {\n  console.error('Error formatting history:', e.message);\n  formattedHistory = '';\n  historyCount = 0;\n}\n\n// \u26a0\ufe0f FIX: Get ALL user appointments and format them\nlet userAppointments = '';\nlet userAppointmentsCount = 0;\ntry {\n  const userAppts = $input.all(); // Get ALL appointments\n  userAppointmentsCount = userAppts.length;\n  \n  if (userAppointmentsCount > 0) {\n    userAppointments = userAppts.map((apt, index) => {\n      const aptName = apt.json.name || '';\n      const aptService = apt.json.service || '';\n      const aptDate = apt.json.date ? apt.json.date.split('T')[0] : '';\n      const aptDay = apt.json.day || '';\n      const aptTime = apt.json.times || '';\n      \n      return `\n\u0645\u0648\u0639\u062f ${index + 1}:\n\u0627\u0644\u0627\u0633\u0645: ${aptName}\n\u0627\u0644\u062e\u062f\u0645\u0629: ${aptService}\n\ud83d\udcc5 \u0627\u0644\u062a\u0627\u0631\u064a\u062e: ${aptDate} | ${aptDay}\n\ud83d\udd50 \u0627\u0644\u0648\u0642\u062a: ${aptTime}`;\n    }).join('\\n---\\n');\n  } else {\n    userAppointments = '\u0644\u0627 \u064a\u0648\u062c\u062f \u0645\u0648\u0627\u0639\u064a\u062f \u0645\u062d\u062c\u0648\u0632\u0629 \u062d\u0627\u0644\u064a\u0627\u064b';\n  }\n  \n  console.log('User appointments formatted:', userAppointments);\n} catch (e) {\n  console.error('Error fetching user appointments:', e.message);\n  userAppointments = '\u0644\u0627 \u064a\u0648\u062c\u062f \u0645\u0648\u0627\u0639\u064a\u062f \u0645\u062d\u062c\u0648\u0632\u0629 \u062d\u0627\u0644\u064a\u0627\u064b';\n  userAppointmentsCount = 0;\n}\nlet type = $('Prepare Text Data').first().json.source;\nlet users_id = $('Insert Row Memory').first().json.id;\n\nconst result = {\n  sender: phoneNumber,\n  text: jsText,\n  available_slots: availableSlots.join('\\n'), \n  available_slots_count: availableSlots.length,\n  existing_appointments: existingAppointments.join('\\n'),\n  existing_appointments_count: existingAppointments.length,\n  formatted_output: formattedHistory,\n  history_count: historyCount,\n  name,\n  wa_id,\n  users_appointments: userAppointments, // \u2705 All appointments formatted\n  users_appointments_count: userAppointmentsCount, // \u2705 Count of appointments\n  users_id,\n  type\n};\n\nconsole.log('Final output:', JSON.stringify(result, null, 2));\n\nreturn [\n  {\n    json: result\n  }\n];\n"
      },
      "executeOnce": true,
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "ac272c74-a855-4a88-ae47-71b12ef39ab2",
      "name": "Main AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -1120,
        576
      ],
      "parameters": {
        "text": "={{ $json.text }}",
        "options": {
          "systemMessage": "=## Medical Clinic Bot\nToday: {{ $now }}\nUser: {{ $json.name }} ({{ $json.sender }})\n\n## Knowledge source:\n\n- Use the **Pinecone vector store** to answer anything about the clinic (services, policies, offers, location, doctors, instructions, etc.).\n-Always use this Memory/last conversations:\n{{ $json.formatted_output }}\n----\nSlots:\n{{ $json.available_slots }}\n-----\nAppointments:\n{{ $json.users_appointments }}\n-----\n\nRules: Arabic only, no markdown, verify data, 2-digit time (12=twelve), different services for multiple bookings\nImportant Rule:\n--- you do not invent dates, think twice before makeing up a date make sure it is correct \n\n-\u062a\u0642\u062f\u0645 \u062b\u0644\u0627\u062b \u062e\u062f\u0645\u0627\u062a, feller, \u0639\u0646\u0627\u064a\u0629 \u0628\u0627\u0644\u0628\u0634\u0631\u0629, \u062a\u0628\u064a\u064a\u0636 \u0623\u0633\u0646\u0627\u0646\n\nBooking: \u062a\u0645 \u062d\u062c\u0632 \u0645\u0648\u0639\u062f\u0643! \u2705 \ud83d\udcc5 [date]|[day] \ud83d\udd50 [time] \ud83d\udc89 [service]\nReschedule: \u062a\u0645 \u062a\u0639\u062f\u064a\u0644 \u0645\u0648\u0639\u062f\u0643 \ud83d\udcc5 [date]|[day] \ud83d\udd50 [time] \ud83d\udc89 [service]\n\n## IMPORTANT: if image is equal to  {{ $json.type }} then answer with a short answer of the image and user message if existed"
        },
        "promptType": "=define",
        "hasOutputParser": true
      },
      "executeOnce": true,
      "typeVersion": 2.2
    },
    {
      "id": "7ff93428-5292-47ec-8084-c56bd2ccd6ec",
      "name": "Simple Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        -1264,
        784
      ],
      "parameters": {
        "sessionKey": "={{ $json.sender }}",
        "sessionIdType": "customKey",
        "contextWindowLength": 1
      },
      "typeVersion": 1.3
    },
    {
      "id": "bc33c7ae-22a5-417f-bc02-e4e59cc96eb6",
      "name": "save appointment - different service",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        1024,
        320
      ],
      "parameters": {
        "columns": {
          "value": {
            "day": "={{ $json.appointment_day }}",
            "date": "={{ $json.appointment_date }}",
            "name": "={{ $('Output Format Text').item.json.customer_name }}",
            "phone": "={{ $json.phone }}",
            "times": "={{ $json.appointment_time }}",
            "service": "={{ $json.service }}"
          },
          "schema": [
            {
              "id": "name",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "name",
              "defaultMatch": false
            },
            {
              "id": "phone",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false
            },
            {
              "id": "date",
              "type": "dateTime",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "date",
              "defaultMatch": false
            },
            {
              "id": "day",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "day",
              "defaultMatch": false
            },
            {
              "id": "service",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "service",
              "defaultMatch": false
            },
            {
              "id": "times",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "times",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "XICUlFpXl76eV2Dm",
          "cachedResultUrl": "/projects/0WLzulivX2ChGmk8/datatables/XICUlFpXl76eV2Dm",
          "cachedResultName": "appointments"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "96690897-ea79-4060-b288-f532b516a0af",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4688,
        96
      ],
      "parameters": {
        "width": 480,
        "height": 704,
        "content": "## \ud83c\udfe5\ud83e\udd16 Medical Clinic WhatsApp Agent + CRM Sync\n\nThis workflow receives WhatsApp Cloud API messages via a Webhook and processes them based on message type (\ud83d\udcdd Text / \ud83c\udf99\ufe0f Audio / \ud83d\uddbc\ufe0f Image / \ud83d\udcce Document).  \nFor audio messages \ud83c\udf99\ufe0f, it downloads the media and transcribes it into Arabic text (Whisper).  \nFor images \ud83d\uddbc\ufe0f, it downloads the image and analyzes it to describe the content and extract any visible text (Vision).  \nFor documents/PDFs \ud83d\udcce, it downloads the file and sends a Gmail notification \u2709\ufe0f to staff with the attachment.\n\nAfter normalizing the final customer text (\ud83c\udf99\ufe0f voice > \ud83d\uddbc\ufe0f image > \ud83d\udcdd text), the workflow builds a structured context \ud83e\udde0 that includes customer data \ud83d\udc64, recent conversation history \ud83d\udcac (memory), the customer\u2019s upcoming appointments \ud83d\udcc5, and available booking slots \ud83d\udd50. The message is then sent to the Main AI Agent \ud83e\udd16 (Arabic only \ud83c\uddf8\ud83c\udde6/\ud83c\uddef\ud83c\uddf4), with RAG enabled \ud83d\udcda using Pinecone \ud83c\udf32 to answer clinic-related questions from uploaded clinic documents (Google Docs).\n\nThe AI response is sent back to the customer via WhatsApp \u2705. In parallel, a strict JSON extractor \ud83e\uddfe parses key fields (booking/reschedule details, service \ud83d\udc89, date/time \u23f0, lead category \ud83e\uddf2, and human escalation \ud83e\uddd1\u200d\u2695\ufe0f). If `needs_human` is true \ud83d\udea8, the workflow emails staff \u2709\ufe0f and stores the case in a \u201chuman\u201d queue table \ud83d\udce5.  \nA scheduled sync \u23f2\ufe0f (every 1 minute) updates a Google Sheets CRM \ud83d\udcca from n8n Data Tables (slots/leads/human/appointments).\n\n**Requirements:** WhatsApp Cloud API token \ud83d\udd11 + phone_number_id \ud83d\udcf1, Gmail \u2709\ufe0f + Google Sheets \ud83d\udcca credentials, Pinecone \ud83c\udf32 index/namespace, and the referenced n8n Data Tables \ud83d\uddc2\ufe0f.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "e5d403fa-47d3-4d8f-a4f5-96c7feb21782",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4016,
        48
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 208,
        "content": "## Section 1 \u2014 Webhook & Verification\nReceives WhatsApp webhooks, responds to `hub.challenge` verification, and routes incoming messages by type.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "ad430754-6c6a-4838-ad0e-52b3d367977d",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -368,
        -256
      ],
      "parameters": {
        "color": 7,
        "width": 1552,
        "height": 752,
        "content": "## Section 5 \u2014 Extraction + Appointment Save\n\n- **AI Data Extractor**: reads the agent output and extracts strict JSON fields (date/day/time/service, booking vs reschedule, needs_human, lead_category).\n- **Code in JavaScript1**: parses the JSON safely, enriches it with customer metadata (phone/name/timestamps), and normalizes YES/NO flags.\n- **Check Appointment1**: routes only when `has_appointment = true`.\n- **save appointment - same service (upsert)**: updates/creates an appointment row matched by `(phone + service)` so each service has its own record.\n- **If Appointment is ready**: compares the new service vs previous/checked service; if different, allows creating another booking record.\n- **save appointment - different service (insert)**: inserts a new appointment row for an additional service (separate from existing one).\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "82315f3e-7edb-4ece-a709-2dc2b12782ac",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -384,
        736
      ],
      "parameters": {
        "color": 7,
        "width": 1568,
        "height": 736,
        "content": "## Section 6 \u2014 Leads + Human Escalation + Logging\n\n- **Get leads**: fetches existing lead rows for this phone to prevent duplicates.\n- **Check if Lead**: decides if a new lead should be created (based on existence/conditions).\n- **AI Summarizer1**: produces compact JSON `{summary, category}` for the customer message.\n- **Format output**: parses/cleans the summarizer JSON and outputs `summary` + `category`.\n- **Insert Lead**: stores the lead with `short_sum`, `lead_category`, and customer identity.\n- **Check Human is called**: routes only when `needs_human = true`.\n- **Send Email Notification If Human is called**: emails staff with the customer details (HTML template).\n- **Add row for Human Call (upsert)**: upserts the request into the \u201chuman\u201d queue table keyed by phone.\n- **Update Row**: writes the final AI reply back into the conversation/memory table row (stores receiver text).\n- **Send via WhatsApp**: sends the final reply to the customer through WhatsApp Cloud A"
      },
      "typeVersion": 1
    },
    {
      "id": "378909c2-d5e4-42eb-9272-07885946c4c3",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2336,
        320
      ],
      "parameters": {
        "color": 7,
        "width": 1152,
        "height": 400,
        "content": "## Section 3 \u2014 Memory & Context Builder\n\n- **Prepare Text Data (Code):** merges message sources into `finalText` (voice \u2192 image \u2192 text) + adds `phone`, `source`, `timestamp`.\n- **Insert Row Memory (Data Table):** saves the incoming message (`phone`, `sender = finalText`) to the memory table.\n- **Get History (Data Table):** pulls recent messages for the same `phone` for short-term context.\n- **Get only users appointment (Data Table):** fetches upcoming appointments for that `phone` (`date >= now`).\n- **Format Context (Code):** builds one AI-ready JSON (last 10 messages + upcoming appointments + `name`, `wa_id`, `users_id`, `type`).\n"
      },
      "typeVersion": 1
    },
    {
      "id": "323bf31d-8d4d-486a-b5b9-0e2934be1f2c",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "disabled": true,
      "position": [
        -3888,
        1456
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 240,
        "content": "## Section 7 \u2014 CRM Sync to Google Sheets\nScheduled job that syncs n8n Data Tables (slots/leads/human/appointments) into a Google Sheets CRM every minute.\n\nFollow this like for the google sheets sheet: https://docs.google.com/spreadsheets/d/1HCl3CvMnzILIrcjnFK-AwLqWuKfMwezM1yXWkJ4KG9Q/edit?usp=sharing\n\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "bd14901c-b388-48b7-9d23-229494a98d78",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3584,
        -96
      ],
      "parameters": {
        "color": 6,
        "width": 1088,
        "height": 1152,
        "content": "## Section 2 \u2014 Media Handling (Audio / Image / File)\nFetches media metadata from Graph API, downloads files, transcribes audio, analyzes images, and emails staff when a document/PDF is received.\n\n- Detects message type and routes:\n  - \ud83d\udcdd Text \u2192 Normalize text\n  - \ud83c\udf99\ufe0f Audio \u2192 Download + Transcribe\n  - \ud83d\uddbc\ufe0f Image \u2192 Download + Analyze\n  - \ud83d\udcce Document/PDF \u2192 Download + Email staff\n\n**Nodes:** `filter text messages`, `If Audio`, `If Image`, `If Video/PDF`\n"
      },
      "typeVersion": 1
    },
    {
      "id": "fe6c6619-55d4-4ad5-8eb1-2f6bfb1816da",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -848,
        1952
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 192,
        "content": "## Section 8 \u2014 RAG Knowledge Base (Manual Run)\nLoads a Google Doc, splits it into chunks, generates embeddings, and inserts them into Pinecone for retrieval (RAG).\n"
      },
      "typeVersion": 1
    },
    {
      "id": "d4396a87-8377-4f3f-9628-791ed648e6f4",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1952,
        800
      ],
      "parameters": {
        "color": 6,
        "width": 624,
        "height": 416,
        "content": "## Section 4 \u2014 AI Agent + Tools (RAG + Appointments + Memory)\n\n- **OpenAI Chat Model**: the LLM that powers the agent responses.\n- **Main AI Agent**: orchestrates the conversation, enforces rules, and decides when to call tools.\n- **Simple Memory**: keeps a tiny per-user context window (`sender` as session key).\n- **Tools**\n  - **Vector Store Tool**: retrieves answers from stored documents (RAG).\n  - **Booked Appointment**: reads appointments from the Data Table for booking/reschedule checks.\n- **Embeddings OpenAI**: embeddings configuration used by the vector retrieval layer (when enabled).\n"
      },
      "typeVersion": 1
    },
    {
      "id": "da9b02bf-731c-40aa-a518-d3cef220f116",
      "name": "WhatsApp Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -4096,
        528
      ],
      "parameters": {
        "path": "whatsapp",
        "options": {},
        "responseMode": "responseNode",
        "multipleMethods": true
      },
      "typeVersion": 2.1
    },
    {
      "id": "c2e8fd84-9286-4f9e-8387-910e400f96d7",
      "name": "Get only users appointment",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -1520,
        576
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "date",
              "keyValue": "={{ $now.toISO() }}",
              "condition": "gte"
            },
            {
              "keyName": "phone",
              "keyValue": "={{ $json.phone }}"
            }
          ]
        },
        "matchType": "allConditions",
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "XICUlFpXl76eV2Dm",
          "cachedResultUrl": "/projects/0WLzulivX2ChGmk8/datatables/XICUlFpXl76eV2Dm",
          "cachedResultName": "appointments"
        }
      },
      "executeOnce": true,
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "a436cab9-3496-4c75-8943-2b48df24c9a9",
      "name": "Get leads",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -320,
        1280
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "phone",
              "keyValue": "={{ $('Format Context').item.json.sender }}"
            }
          ]
        },
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "16bAoJicIDEPak46",
          "cachedResultUrl": "/projects/0WLzulivX2ChGmk8/datatables/16bAoJicIDEPak46",
          "cachedResultName": "leads"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "75465bfb-f042-4d82-bf84-a4b316188926",
      "name": "Send Email Notification If Human is called",
      "type": "n8n-nodes-base.gmail",
      "position": [
        176,
        1072
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "=<!doctype html>\n<html lang=\"ar\" dir=\"rtl\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"x-apple-disable-message-reformatting\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n  <title>\u0625\u0634\u0639\u0627\u0631 \u062c\u062f\u064a\u062f</title>\n  <style>\n    body, table, td, p { margin:0; padding:0; }\n    img { border:0; line-height:100%; outline:none; text-decoration:none; }\n    table { border-collapse:collapse; }\n    body { background:#e8f3ff; direction:rtl; text-align:right; font-family:'Segoe UI',Roboto,Helvetica,Arial,sans-serif; }\n    .wrap { width:100%; background:#e8f3ff; }\n    .container { width:100%; max-width:600px; background:#ffffff; border-radius:16px; overflow:hidden; box-shadow:0 6px 24px rgba(13,71,161,0.15); text-align:right; }\n    .p-32 { padding:32px 12px; }\n    .p-card { padding:28px; }\n    .header { background:linear-gradient(135deg,#0D47A1 0%,#00B894 100%); padding:24px; text-align:right; }\n    .h1 { margin:0; font-size:22px; line-height:1.3; color:#ffffff; text-align:right; }\n    .muted { margin:6px 0 0 0; font-size:13px; color:#e3f7ff; opacity:0.9; text-align:right; }\n    .text { font-size:15px; line-height:1.6; color:#0f172a; text-align:right; }\n    .small { font-size:12px; color:#64748b; text-align:right; }\n    .info { width:100%; border-collapse:separate; border-spacing:0 10px; }\n    .key { width:160px; padding:12px 14px; font-size:13px; font-weight:600; border-radius:0 12px 12px 0; border:1px solid; border-left:0; vertical-align:top; background:#f1f8ff; text-align:right; }\n    .val { padding:12px 14px; font-size:14px; color:#0f172a; background:#fff; border-radius:12px 0 0 12px; border:1px solid; border-right:0; vertical-align:top; text-align:right; }\n    .key-blue { background:#f1f8ff; color:#0D47A1; border-color:#d7e7ff; }\n    .val-blue { border-color:#d7e7ff; }\n    .key-green { background:#eefcf6; color:#007f67; border-color:#ccefe2; }\n    .val-green { border-color:#ccefe2; }\n    .desc { padding:14px; line-height:1.7; text-align:right; }\n    .hr { border:none; border-top:1px solid #e6eefc; margin:26px 0; }\n    .btn { display:inline-block; padding:12px 18px; font-size:14px; color:#ffffff; text-decoration:none; background:#00B894; border-radius:10px; text-align:center; }\n    .foot { background:#f7fafc; border-top:1px solid #e9eef8; padding:16px 24px; text-align:right; }\n    .brand { color:#0D47A1; font-weight:600; }\n    @media (prefers-color-scheme: dark) {\n      body { background:#0b1220; }\n      .wrap { background:#0b1220; }\n      .container { background:#0f172a; color:#e5e7eb; }\n      .text { color:#e5e7eb; }\n      .small { color:#94a3b8; }\n    }\n  </style>\n</head>\n<body>\n  <div style=\"display:none;max-height:0;overflow:hidden;opacity:0;color:transparent;\">\n    \u0625\u0634\u0639\u0627\u0631 \u062c\u062f\u064a\u062f \u0645\u0646 \u0646\u0645\u0648\u0630\u062c \u0645\u0648\u0642\u0639\u0643\u060c \u064a\u062d\u062a\u0648\u064a \u0639\u0644\u0649 \u0627\u0644\u0627\u0633\u0645\u060c \u0627\u0644\u0647\u0627\u062a\u0641\u060c \u0648\u0627\u0644\u0648\u0635\u0641.\n  </div>\n\n  <table role=\"presentation\" class=\"wrap\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n    <tr>\n      <td align=\"center\" class=\"p-32\">\n        <table role=\"presentation\" class=\"container\" width=\"600\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\">\n          <tr>\n            <td class=\"header\">\n              <h1 class=\"h1\">\u0625\u0634\u0639\u0627\u0631 \u062a\u0648\u0627\u0635\u0644 \u062c\u062f\u064a\u062f</h1>\n              <p class=\"muted\">\u0644\u0642\u062f \u0627\u0633\u062a\u0642\u0628\u0644\u062a \u0631\u0633\u0627\u0644\u0629 \u062c\u062f\u064a\u062f\u0629 \u0645\u0646 \u0646\u0645\u0648\u0630\u062c \u0645\u0648\u0642\u0639\u0643</p>\n            </td>\n          </tr>\n\n          <tr>\n            <td class=\"p-card\">\n              <p class=\"text\">\u0645\u0631\u062d\u0628\u0627\u064b\u060c \u062a\u0645 \u0625\u0631\u0633\u0627\u0644 \u0637\u0644\u0628 \u062c\u062f\u064a\u062f\u060c \u0627\u0644\u062a\u0641\u0627\u0635\u064a\u0644 \u0623\u062f\u0646\u0627\u0647:</p>\n\n              <table role=\"presentation\" class=\"info\">\n                <tr>\n\n                  <td class=\"val val-blue\">{{ $json.customer_name }}</td>\n                  <td class=\"key key-blue\">\u0627\u0644\u0627\u0633\u0645</td>\n                </tr>\n                <tr>\n                  \n                  <td class=\"val val-green\">\n                    <a style=\"color:#0D47A1; text-decoration:none; border-bottom:1px dotted #0D47A1;\">\n                      {{ $json.phone }}\n                    </a>\n                  </td>\n<td class=\"key key-green\">\u0631\u0642\u0645 \u0627\u0644\u0647\u0627\u062a\u0641</td>\n                </tr>\n                <tr>\n\n                  <td class=\"val val-blue desc\">{{ $json.description }}</td>\n                  <td class=\"key key-blue\">\u0627\u0644\u0648\u0635\u0641</td>\n\n                </tr>\n\n              </table>\n\n              <hr class=\"hr\">\n\n              <a class=\"btn\" href=\"{{VIEW_LINK}}\">\u0639\u0631\u0636 \u0641\u064a \u0644\u0648\u062d\u0629 \u0627\u0644\u062a\u062d\u0643\u0645</a>\n\n              <p class=\"small\" style=\"margin-top:18px;\">\u0625\u0630\u0627 \u0644\u0645 \u062a\u0643\u0646 \u062a\u062a\u0648\u0642\u0639 \u0647\u0630\u0647 \u0627\u0644\u0631\u0633\u0627\u0644\u0629\u060c \u064a\u0645\u0643\u0646\u0643 \u062a\u062c\u0627\u0647\u0644\u0647\u0627 \u0628\u0623\u0645\u0627\u0646.</p>\n            </td>\n          </tr>\n\n          <tr>\n            <td class=\"foot\">\n              <table role=\"presentation\" width=\"100%\">\n                <tr>\n                  <td class=\"small\">\u062a\u0645 \u0627\u0644\u0625\u0631\u0633\u0627\u0644 \u0628\u0648\u0627\u0633\u0637\u0629 <span class=\"brand\">\u062a\u0648\u0627\u0635\u0644 \u0627\u0644\u0639\u064a\u0627\u062f\u0627\u062a</span></td>\n                  <td align=\"left\">\n                    <a href=\"{{UNSUBSCRIBE_LINK}}\" class=\"small\" style=\"color:#00B894; text-decoration:none;\">\u0625\u0644\u063a\u0627\u0621 \u0627\u0644\u0627\u0634\u062a\u0631\u0627\u0643</a>\n                  </td>\n                </tr>\n              </table>\n            </td>\n          </tr>\n\n        </table>\n      </td>\n    </tr>\n  </table>\n</body>\n</html>\n",
        "options": {},
        "subject": "\u0647\u0646\u0627\u0643 \u0639\u0645\u064a\u0644 \u064a\u062d\u062a\u0627\u0627\u062c \u062a\u0648\u0627\u0635\u0644 \u0628\u0634\u0631\u064a "
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "fd2b5e7e-fed0-4157-94c4-f2c92fe324f5",
      "name": "Add row for Human Call",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        384,
        1072
      ],
      "parameters": {
        "columns": {
          "value": {
            "name": "={{ $('Output Format Text').item.json.customer_name }}",
            "phone": "={{ $('Output Format Text').item.json.phone }}"
          },
          "schema": [
            {
              "id": "name",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "name",
              "defaultMatch": false
            },
            {
              "id": "phone",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false
            },
            {
              "id": "descreption",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "descreption",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "filters": {
          "conditions": [
            {
              "keyName": "phone",
              "keyValue": "={{ $('Output Format Text').item.json.phone }}"
            }
          ]
        },
        "options": {},
        "operation": "upsert",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "ygicufEiNou6tVCb",
          "cachedResultUrl": "/projects/0WLzulivX2ChGmk8/datatables/ygicufEiNou6tVCb",
          "cachedResultName": "human"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f7b05031-28df-4e57-8974-a79adbe55168",
      "name": "If Appointment is ready",
      "type": "n8n-nodes-base.if",
      "position": [
        752,
        336
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "2266b20d-675a-4443-87d0-04e550575d2f",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $('Output Format Text').item.json.service }}",
              "rightValue": "={{ $('Check Appointment1').item.json.service }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a7599be1-1a29-4fe8-b051-adb3b4792450",
      "name": "save appointment - same service",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        592,
        336
      ],
      "parameters": {
        "columns": {
          "value": {
            "day": "={{ $json.appointment_day }}",
            "date": "={{ $json.appointment_date }}",
            "name": "={{ $('Output Format Text').item.json.customer_name }}",
            "phone": "={{ $json.phone }}",
            "times": "={{ $json.appointment_time }}",
            "service": "={{ $json.service }}"
          },
          "schema": [
            {
              "id": "name",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "name",
              "defaultMatch": false
            },
            {
              "id": "phone",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false
            },
            {
              "id": "date",
              "type": "dateTime",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "date",
              "defaultMatch": false
            },
            {
              "id": "day",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "day",
              "defaultMatch": false
            },
            {
              "id": "service",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "service",
              "defaultMatch": false
            },
            {
              "id": "times",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "times",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "filters": {
          "conditions": [
            {
              "keyName": "phone",
              "keyValue": "={{ $json.phone }}"
            },
            {
              "keyName": "service",
              "keyValue": "={{ $json.service }}"
            }
          ]
        },
        "options": {},
        "matchType": "allConditions",
        "operation": "upsert",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "XICUlFpXl76eV2Dm",
          "cachedResultUrl": "/projects/0WLzulivX2ChGmk8/datatables/XICUlFpXl76eV2Dm",
          "cachedResultName": "appointments"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "3de13584-3543-4ffc-9d3d-8a07bb9c0180",
      "name": "Check Human is called",
      "type": "n8n-nodes-base.if",
      "position": [
        -48,
        1088
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "7119e222-a2a0-4fdb-930f-eb16877c448e",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.needs_human }}",
              "rightValue": "YES"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a903f878-9619-4f5e-8b6a-cd2d5cd6dd81",
      "name": "Check if Lead",
      "type": "n8n-nodes-base.if",
      "position": [
        -112,
        1280
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "ebc66b41-b8e2-4dc8-83e9-12f3e7593c6d",
              "operator": {
                "type": "string",
                "operation": "notExists",
                "singleValue": true
              },
              "leftValue": "={{ $json.name }}",
              "rightValue": "={{ $('Format Context').item.json.sender.toNumber() }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "8b4f5ac0-4358-47df-a009-7f7c14c219a0",
      "name": "Insert Lead",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        624,
        1264
      ],
      "parameters": {
        "columns": {
          "value": {
            "name": "={{ $('Format Context').item.json.name }}",
            "phone": "={{ $('Format Context').item.json.sender }}",
            "short_sum": "={{ $json.summary }}",
            "lead_category": "={{ $json.category }}"
          },
          "schema": [
            {
              "id": "name",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "name",
              "defaultMatch": false
            },
            {
              "id": "phone",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false
            },
            {
              "id": "lead_category",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "lead_category",
              "defaultMatch": false
            },
            {
              "id": "short_sum",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "short_sum",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "16bAoJicIDEPak46",
          "cachedResultUrl": "/projects/0WLzulivX2ChGmk8/datatables/16bAoJicIDEPak46",
          "cachedResultName": "leads"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "314743b6-dd00-46e6-b7bc-25f5f994312b",
      "name": "Update Row",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -80,
        192
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "sender",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "sender",
              "defaultMatch": false
            },
            {
              "id": "reciever",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "reciever",
              "defaultMatch": false
            },
            {
              "id": "phone",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "phone",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "filters": {
          "conditions": [
            {
              "keyValue": "={{ $('Format Context').item.json.users_id }}"
            }
          ]
        },
        "options": {},
        "operation": "upsert",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "l6biIqkSE1qLJvaZ",
          "cachedResultUrl": "/projects/0WLzulivX2ChGmk8/datatables/l6biIqkSE1qLJvaZ",
          "cachedResultName": "test table"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "d514e95e-b150-4291-8a6c-f93abfcb871a",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -704,
        1232
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "2c70c555-a008-4e5b-a955-5ddd78ffd054",
      "name": "Output Format Text",
      "type": "n8n-nodes-base.code",
      "position": [
        80,
        352
      ],
      "parameters": {
        "jsCode": "// Parse JSON from AI Data Extractor and add metadata\nconst raw = $input.first().json.output || '{}';\nconst phone = $('Format Context').first().json.sender || '';\nconst name = $('Format Context').first().json.name || '';\n\nlet data;\n\ntry {\n  // Try parsing as-is first\n  data = typeof raw === 'object' ? raw : JSON.parse(raw);\n} catch (e) {\n  // Clean and retry if initial parse fails\n  try {\n    let cleaned = raw\n      .replace(/```json\\n?/g, '')\n      .replace(/```\\n?/g, '')\n      .trim();\n    \n    // Extract JSON object\n    const jsonMatch = cleaned.match(/\\{[\\s\\S]*\\}/);\n    cleaned = jsonMatch ? jsonMatch[0] : cleaned;\n    \n    data = JSON.parse(cleaned);\n  } catch (e2) {\n    // Fallback to default structure\n    console.error('JSON parse failed:', e2.message);\n    console.error('Raw input:', raw);\n    \n    data = {\n      has_appointment: false,\n      is_reschedule: false,\n      needs_human: false,\n      appointment_date: null,\n      appointment_day: null,\n      appointment_time: null,\n      service: null,\n      lead_category: 'other',\n      description: '\u0641\u0634\u0644 \u0641\u064a \u0627\u0633\u062a\u062e\u0631\u0627\u062c \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a',\n      notes: '\u062e\u0637\u0623 \u0641\u064a \u062a\u062d\u0644\u064a\u0644 \u0627\u0644\u0631\u062f'\n    };\n  }\n}\n\n// Enrich with metadata\nconst enrichedData = {\n  ...data,\n  phone,\n  customer_name: name,\n  created_at: new Date().toISOString(),\n  has_appointment_text: data.has_appointment ? 'YES' : 'NO',\n  is_reschedule_text: data.is_reschedule ? 'YES' : 'NO',\n  needs_human_text: data.needs_human ? 'YES' : 'NO'\n};\n\n// Replace null/undefined with empty strings\nObject.keys(enrichedData).forEach(key => {\n  if (enrichedData[key] === null || enrichedData[key] === undefined) {\n    enrichedData[key] = '';\n  }\n});\n\nconsole.log('Enriched data:', JSON.stringify(enrichedData, null, 2));\n\nreturn [{ json: enrichedData }];"
      },
      "typeVersion": 2
    },
    {
      "id": "06ff90e2-b5bd-46aa-9d31-78bed0257dba",
      "name": "Format output",
      "type": "n8n-nodes-base.code",
      "position": [
        432,
        1264
      ],
      "parameters": {
        "jsCode": "// Split into two separate message outputs\nconst input = $input.first().json;\nlet response = input.output || input.text || input.response || input;\n\nconsole.log('Raw input:', JSON.stringify(input, null, 2));\n\ntry {\n  if (typeof response === 'object' && response !== null && (response.summary || response.category)) {\n    // Return as single output with both fields\n    return {\n      json: {\n        summary: response.summary || \"\",\n        category: response.category || \"\"\n      }\n    };\n  }\n  \n  if (typeof response === 'string') {\n    response = response.replace(/```json\\n?/g, '').replace(/```\\n?/g, '').trim();\n    const data = JSON.parse(response);\n    \n    return {\n      json: {\n        summary: data.summary || \"\",\n        category: data.category || \"\"\n      }\n    };\n  }\n  \n  throw new Error('Unexpected response format');\n  \n} catch (error) {\n  console.error('Parse error:', error.message);\n  return {\n    json: {\n      summary: \"Error parsing response\",\n      category: \"error\"\n    }\n  };\n}"
      },
      "typeVersion": 2
    },
    {
      "id": "505865d1-a9bd-40a9-90bb-246de0e44704",
      "name": "Get slots",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -2704,
        1696
      ],
      "parameters": {
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "DySLjqEPX2i5RBdj",
          "cachedResultUrl": "/projects/0WLzulivX2ChGmk8/datatables/DySLjqEPX2i5RBdj",
          "cachedResultName": "slots"
        }
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Get file": {
      "main": [
        [
          {
            "node": "Download file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get lead": {
      "main": [
        [
          {
            "node": "Append or update lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Audio": {
      "main": [
        [
          {
            "node": "Get Audio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Image": {
      "main": [
        [
          {
            "node": "Get Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Audio": {
      "main": [
        [
          {
            "node": "Download Audio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Image": {
      "main": [
        [
          {
            "node": "Download Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get leads": {
      "main": [
        [
          {
            "node": "Check if Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get slots": {
      "main": [
        [
          {
            "node": "Append or update slot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Prepare Text Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get History": {
      "main": [
        [
          {
            "node": "Get only users appointment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Video/PDF": {
      "main": [
        [
          {
            "node": "Get file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze image": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if Lead": {
      "main": [
        [
          {
            "node": "AI Summarizer1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download file": {
      "main": [
        [
          {
            "node": "Prepare Email With Attachment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format output": {
      "main": [
        [
          {
            "node": "Insert Lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Main AI Agent": {
      "main": [
        [
          {
            "node": "Send via WhatsApp",
            "type": "main",
            "index": 0
          },
          {
            "node": "Update Row",
            "type": "main",
            "index": 0
          },
          {
            "node": "AI Data Extractor",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get leads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory": {
      "ai_memory": [
        [
          {
            "node": "Main AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "AI Summarizer1": {
      "main": [
        [
          {
            "node": "Format output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Audio": {
      "main": [
        [
          {
            "node": "Transcribe Audio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Image": {
      "main": [
        [
          {
            "node": "Analyze image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Context": {
      "main": [
        [
          {
            "node": "Main AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get a document": {
      "main": [
        [
          {
            "node": "Pinecone Vector Store",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get human call": {
      "main": [
        [
          {
            "node": "Append or update human call",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Get slots",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get lead",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get human call",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get human appointment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transcribe Audio": {
      "main": [
        [
          {
            "node": "Prepare Text Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "WhatsApp Webhook": {
      "main": [
        [
          {
            "node": "Verify \u2022 WA (hub.challenge)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "If Audio",
            "type": "main",
            "index": 0
          },
          {
            "node": "filter text messages",
            "type": "main",
            "index": 0
          },
          {
            "node": "If Image",
            "type": "main",
            "index": 0
          },
          {
            "node": "If Video/PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Data Extractor": {
      "main": [
        [
          {
            "node": "Output Format Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings OpenAI": {
      "ai_embedding": [
        [
          {
            "node": "Pinecone Vector Store",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Insert Row Memory": {
      "main": [
        [
          {
            "node": "Get History",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Summarizer1",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "AI Data Extractor",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Main AI Agent",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Vector Store Tool",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Text Data": {
      "main": [
        [
          {
            "node": "Insert Row Memory",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Vector Store Tool": {
      "ai_tool": [
        [
          {
            "node": "Main AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Booked Appointment": {
      "ai_tool": [
        [
          {
            "node": "Main AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Check Appointment1": {
      "main": [
        [
          {
            "node": "save appointment - same service",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings OpenAI1": {
      "ai_embedding": [
        [
          {
            "node": "Pinecone Vector Store (Retrieval)",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Output Format Text": {
      "main": [
        [
          {
            "node": "Check Appointment1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Check Human is called",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Default Data Loader": {
      "ai_document": [
        [
          {
            "node": "Pinecone Vector Store",
            "type": "ai_document",
            "index": 0
          }
        ]
      ]
    },
    "filter text messages": {
      "main": [
        [
          {
            "node": "Prepare Text Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Human is called": {
      "main": [
        [
          {
            "node": "Send Email Notification If Human is called",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get human appointment": {
      "main": [
        [
          {
            "node": "Append or update appointment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Appointment is ready": {
      "main": [
        [
          {
            "node": "save appointment - different service",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get only users appointment": {
      "main": [
        [
          {
            "node": "Format Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Email With Attachment": {
      "main": [
        [
          {
            "node": "Send Email with attachment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "save appointment - same service": {
      "main": [
        [
          {
            "node": "If Appointment is ready",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pinecone Vector Store (Retrieval)": {
      "ai_vectorStore": [
        [
          {
            "node": "Vector Store Tool",
            "type": "ai_vectorStore",
            "index": 0
          }
        ]
      ]
    },
    "Recursive Character Text Splitter": {
      "ai_textSplitter": [
        [
          {
            "node": "Default Data Loader",
            "type": "ai_textSplitter",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Get a document",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Email Notification If Human is called": {
      "main": [
        [
          {
            "node": "Add row for Human Call",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}