{
  "id": "C768eUlF4F8d2jOT",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AI-Driven Facebook DM \u2192 Inventory Matching & Automated Messaging System",
  "tags": [],
  "nodes": [
    {
      "id": "3cd8c821-4745-4fa9-b8fb-7c951fdf1c54",
      "name": "Trigger \u2013 Fetch New Facebook Messages (Every Hour)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1024,
        -64
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "3dc4a4a2-f9cd-4d01-80a2-22a078457b12",
      "name": "Fetch Inventory Records from Airtable",
      "type": "n8n-nodes-base.airtable",
      "position": [
        576,
        -32
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appwM60t4Gdm6uXen",
          "cachedResultUrl": "https://airtable.com/appwM60t4Gdm6uXen",
          "cachedResultName": "Lead Manager"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblB6VXcwOisyAiM7",
          "cachedResultUrl": "https://airtable.com/appwM60t4Gdm6uXen/tblB6VXcwOisyAiM7",
          "cachedResultName": "Inventory"
        },
        "options": {},
        "operation": "search"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "7b9c823a-351a-4bea-94e7-a215bb9d1f6c",
      "name": "Fetch Facebook Conversation List",
      "type": "n8n-nodes-base.facebookGraphApi",
      "position": [
        -752,
        -64
      ],
      "parameters": {
        "edge": "conversations",
        "options": {
          "queryParameters": {
            "parameter": [
              {
                "name": "access_token",
                "value": "="
              }
            ]
          }
        },
        "graphApiVersion": "v23.0"
      },
      "credentials": {
        "facebookGraphApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f2d57f59-96b3-4c83-820c-8d2175f11352",
      "name": "Fetch Facebook Conversation Messages",
      "type": "n8n-nodes-base.facebookGraphApi",
      "position": [
        -512,
        -64
      ],
      "parameters": {
        "node": "={{ $json.data[0].id }}",
        "options": {
          "queryParameters": {
            "parameter": [
              {
                "name": "access_token",
                "value": "="
              },
              {
                "name": "fields",
                "value": "messages{message,from,to,created_time}"
              }
            ]
          }
        },
        "graphApiVersion": "v23.0"
      },
      "credentials": {
        "facebookGraphApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "fcf51051-636f-44d6-99fa-7dd4c8855635",
      "name": "AI \u2013 Extract Product & Customer Intent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        496,
        -704
      ],
      "parameters": {
        "text": "=You received this customer message:\n\n\"{{ $json.message }}\"\n\nExtract the following:\n\n1. The product the customer is asking for.\n2. The intent (ex: availability, price inquiry, general question).\n3. The cleaned product name (lowercase, no extra words).\n4. Return ONLY a JSON object.\n\nExample format to return:\n\n{\n  \"query\": \"...\",\n  \"product_name\": \"...\",\n  \"intent\": \"...\",\n  \"found\": false\n}\n",
        "options": {
          "systemMessage": "=You are an AI assistant that extracts product-related information\nfrom a customer's message.\n\nRules:\n1. Identify the product name \u2014 be flexible with typos.\n2. Detect the customer's intent (ex: availability, price, inquiry).\n3. Always return clean JSON only \u2014 no explanation text.\n4. Set \"found\": false because inventory is checked in the next step.\n"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.1
    },
    {
      "id": "a63c4fcb-905b-422e-8df9-1d554ea26066",
      "name": "Extract Latest Facebook Message",
      "type": "n8n-nodes-base.code",
      "position": [
        80,
        -64
      ],
      "parameters": {
        "jsCode": "const msgs = $json.messages.data;\n\n// Sort messages latest \u2192 oldest\nmsgs.sort((a, b) => new Date(b.created_time) - new Date(a.created_time));\n\n// Latest message is msgs[0]\nreturn [{ json: msgs[0] }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "359cd61d-2dbd-48e5-a1b6-a24ef3dca8fb",
      "name": "Configure GPT-4o \u2014 Message Classification Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
      "position": [
        416,
        -480
      ],
      "parameters": {
        "model": "gpt-4o",
        "options": {}
      },
      "credentials": {
        "azureOpenAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d858ed3d-7af7-4c2b-a7f5-4630f994ce76",
      "name": "Merge AI Output With Inventory Dataset",
      "type": "n8n-nodes-base.merge",
      "position": [
        912,
        -48
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "e09616bd-9039-4c0b-87f7-142b638385ad",
      "name": "Build Combined AI + Inventory Payload (",
      "type": "n8n-nodes-base.code",
      "position": [
        1152,
        -48
      ],
      "parameters": {
        "jsCode": "// Input is an array of merged items\nconst items = $input.all();\n\n// 1) Extract and parse the AI output (first item)\nlet aiRaw = items[0].json.output || \"{}\";\nlet aiParsed = {};\n\ntry {\n  aiParsed = JSON.parse(aiRaw);\n} catch (err) {\n  aiParsed = { error: \"AI output JSON parsing failed\", raw: aiRaw };\n}\n\n// 2) Extract all Airtable records (everything except index 0)\nlet inventoryRecords = items.slice(1).map(i => i.json);\n\n// 3) Return a single combined object\nreturn [\n  {\n    json: {\n      ai: aiParsed,\n      inventory: inventoryRecords\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "3b9f0cd9-7fac-45c1-b283-5f3ed5a9ec87",
      "name": "AI \u2013 Match Requested Product in Inventory",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1376,
        -48
      ],
      "parameters": {
        "text": "=Here is the combined data from the customer query and the inventory:\n\nCustomer Query:\n- Product Name: \"{{ $json.ai.product_name }}\"\n- Intent: \"{{ $json.ai.intent }}\"\n\nInventory List:\n{{ JSON.stringify($json.inventory) }}\n\nYour job:\n1. Determine if the requested product exists in the inventory.\n2. If found, return the item details.\n3. If not found, return found: false.\n4. Generate a clear human-friendly message.\n\nReturn ONLY valid JSON in this exact structure:\n\n{\n  \"product_name\": \"\",\n  \"found\": true or false,\n  \"matched_item\": {},     // empty object if not found\n  \"reply\": \"\",\n  \"confidence\": 0-100\n}\n",
        "options": {
          "systemMessage": "=You are an AI product lookup assistant.\n\nYou analyze a customer\u2019s product request and match it against the provided inventory.\n\nRules:\n- Only consider exact or close product name matches.\n- If the product exists, return found: true, and include the matching inventory object.\n- If the product doesn't exist, return found: false and matched_item = {}.\n- Always return clean JSON exactly as requested.\n- No extra explanations.\n"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.1
    },
    {
      "id": "39d742d9-b27e-4a9e-b2e3-8e1b6b06aa02",
      "name": "Configure GPT-4o \u2014 Product Matching Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
      "position": [
        1344,
        192
      ],
      "parameters": {
        "model": "gpt-4o",
        "options": {}
      },
      "credentials": {
        "azureOpenAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "19f65054-e2fb-4edc-9773-c15695179784",
      "name": "Parse AI Product Match JSON",
      "type": "n8n-nodes-base.code",
      "position": [
        1760,
        -48
      ],
      "parameters": {
        "jsCode": "// Get raw string output from the AI node\nconst raw = $json.output;\n\nlet parsed;\n\ntry {\n  // Parse the JSON string into an object\n  parsed = JSON.parse(raw);\n} catch (err) {\n  throw new Error(\"Failed to parse AI output JSON: \" + err.message);\n}\n\n// Return parsed JSON as a clean object for next nodes\nreturn [\n  { json: parsed }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "80acdcee-a973-4587-b452-717fc212f361",
      "name": "Check If Product Exists",
      "type": "n8n-nodes-base.if",
      "position": [
        2000,
        -48
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "63d80014-701a-4269-a0fb-bd0ea57b41b9",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.found }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "9d6bb1c0-6bde-4d24-9a9a-7d35649fcf78",
      "name": "Send Facebook Reply \u2014 Product Found",
      "type": "n8n-nodes-base.facebookGraphApi",
      "position": [
        2304,
        -208
      ],
      "parameters": {
        "edge": "messages",
        "node": "={{ $('Fetch Facebook Conversation Messages').first().json.messages.data[0].to.data[0].id }}",
        "options": {
          "queryParameters": {
            "parameter": [
              {
                "name": "access_token",
                "value": "="
              },
              {
                "name": "recipient",
                "value": "={{ JSON.stringify({ id: $('Extract Latest Facebook Message').first().json.from.id }) }}"
              },
              {
                "name": "message",
                "value": "={{ JSON.stringify({ text: $json.reply }) }}\n"
              }
            ]
          }
        },
        "graphApiVersion": "v23.0",
        "httpRequestMethod": "POST"
      },
      "credentials": {
        "facebookGraphApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0831b1aa-f439-45dc-8045-9c93e3f84f8a",
      "name": "Send Facebook Reply \u2014 Product Not Found",
      "type": "n8n-nodes-base.facebookGraphApi",
      "position": [
        2352,
        144
      ],
      "parameters": {
        "edge": "messages",
        "node": "={{ $('Fetch Facebook Conversation Messages').first().json.messages.data[0].to.data[0].id }}",
        "options": {
          "queryParameters": {
            "parameter": [
              {
                "name": "access_token",
                "value": "="
              },
              {
                "name": "recipient",
                "value": "={{ JSON.stringify({ id: $('Extract Latest Facebook Message').first().json.from.id }) }}"
              },
              {
                "name": "message",
                "value": "={{ JSON.stringify({ text: $json.reply }) }}\n"
              }
            ]
          }
        },
        "graphApiVersion": "v23.0",
        "httpRequestMethod": "POST"
      },
      "credentials": {
        "facebookGraphApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e1d901bd-1c0c-494f-9acd-4512fe4d5e0f",
      "name": "Log Invalid Records to Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -32,
        208
      ],
      "parameters": {
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultUrl": "",
          "cachedResultName": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": ""
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "b431757c-da8b-43b2-8a0f-2999087637ce",
      "name": "Validate Record Structure",
      "type": "n8n-nodes-base.if",
      "position": [
        -224,
        -64
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "e2adb005-2b3c-4d1e-8445-442df1fe925a",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "b7009a76-16c1-4acd-97d1-ef6fec236dd7",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1616,
        -1040
      ],
      "parameters": {
        "width": 704,
        "height": 544,
        "content": "## \ud83e\udd16 AI-Driven Facebook DM \u2192 Inventory Matching & Automated Messaging System\n\nThis workflow automatically fetches new Facebook messages, extracts the customer\u2019s intent,\nmatches product names against Airtable inventory, and sends an instant automated reply.\n\n### \ud83d\udd39 Workflow Summary\n1. Trigger every hour \u2192 fetch latest Facebook conversations  \n2. Extract the most recent customer message  \n3. Use GPT-4o to detect the requested product + intent  \n4. Pull full Inventory list from Airtable  \n5. Merge AI interpretation + inventory dataset  \n6. AI checks if the requested product exists  \n7. Sends a Facebook reply \u2192 \u201cProduct found\u201d or \u201cNot found\u201d  \n8. Invalid or bad-structured messages get logged in Google Sheets  \n\n### \ud83d\udd39 Integrations Used\n\u2022 Facebook Graph API \u2014 Message read/write  \n\u2022 Azure GPT-4o \u2014 Intent extraction + product lookup  \n\u2022 Airtable \u2014 Product catalog  \n\u2022 Google Sheets \u2014 Invalid data logging  \n\nThis workflow enables instant, automated customer support for product availability.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "c4e1c663-b5f7-4f39-939b-132e287a4cb7",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -848,
        -288
      ],
      "parameters": {
        "color": 7,
        "width": 1088,
        "height": 720,
        "content": "## Intake & Validation \u2014 Facebook Messages  \nFetches new customer conversations every hour and retrieves the latest message.  \nValidates message structure (id, fields).  \nIf invalid \u2192 logs to Google Sheets; if valid \u2192 sent to the AI intent extraction step.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "91d8cb01-c909-4d23-a14e-1d6de85e0903",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        256,
        -880
      ],
      "parameters": {
        "color": 7,
        "width": 656,
        "height": 560,
        "content": "## AI Intent Understanding \u2014 Message Analysis  \nUses GPT-4o to identify the product mentioned, customer intent,  \nand generate a clean structured JSON output.  \nEnsures consistent extraction even with typos, slang, or unclear text.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "059a7ff8-b797-42c7-9f47-c05fb5ce4b89",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        512,
        -256
      ],
      "parameters": {
        "color": 7,
        "width": 1632,
        "height": 608,
        "content": "## Inventory Matching \u2014 AI + Airtable Dataset  \nCombines interpreted customer query with full Airtable inventory.  \nAI checks if the requested product exists using clean product-name comparison.  \nOutputs a structured decision object with match details and reply text.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "757f5e84-57ab-49d0-8da8-f78e6c071c12",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2176,
        -432
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 848,
        "content": "## Auto-Reply Delivery \u2014 Facebook Messenger  \nSends a real-time automated Messenger reply based on product availability.  \nIf matched \u2192 sends product details;  \nIf not \u2192 replies with a polite \u201cnot available\u201d message.\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "63715ae5-695d-4b96-90f4-e212cb69c2e5",
  "connections": {
    "Check If Product Exists": {
      "main": [
        [
          {
            "node": "Send Facebook Reply \u2014 Product Found",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Facebook Reply \u2014 Product Not Found",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Record Structure": {
      "main": [
        [
          {
            "node": "Extract Latest Facebook Message",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log Invalid Records to Google Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Product Match JSON": {
      "main": [
        [
          {
            "node": "Check If Product Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Latest Facebook Message": {
      "main": [
        [
          {
            "node": "AI \u2013 Extract Product & Customer Intent",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Inventory Records from Airtable",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Facebook Conversation List": {
      "main": [
        [
          {
            "node": "Fetch Facebook Conversation Messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Facebook Conversation Messages": {
      "main": [
        [
          {
            "node": "Validate Record Structure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Inventory Records from Airtable": {
      "main": [
        [
          {
            "node": "Merge AI Output With Inventory Dataset",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge AI Output With Inventory Dataset": {
      "main": [
        [
          {
            "node": "Build Combined AI + Inventory Payload (",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Combined AI + Inventory Payload (": {
      "main": [
        [
          {
            "node": "AI \u2013 Match Requested Product in Inventory",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI \u2013 Extract Product & Customer Intent": {
      "main": [
        [
          {
            "node": "Merge AI Output With Inventory Dataset",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI \u2013 Match Requested Product in Inventory": {
      "main": [
        [
          {
            "node": "Parse AI Product Match JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Configure GPT-4o \u2014 Product Matching Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI \u2013 Match Requested Product in Inventory",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Configure GPT-4o \u2014 Message Classification Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI \u2013 Extract Product & Customer Intent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Trigger \u2013 Fetch New Facebook Messages (Every Hour)": {
      "main": [
        [
          {
            "node": "Fetch Facebook Conversation List",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}