AutomationFlowsAI & RAG › Automated Facebook Message Response with Gpt-4o and Airtable Inventory Matching

Automated Facebook Message Response with Gpt-4o and Airtable Inventory Matching

ByRahul Joshi @rahul08 on n8n.io

This workflow automates AI-driven Facebook Messenger product inquiry handling, connecting Facebook DMs with Airtable inventory and returning instant automated replies based on product availability. It runs hourly, fetches new messages, extracts the latest customer query, uses…

Cron / scheduled trigger★★★★☆ complexityAI-powered22 nodesAirtableFacebook Graph ApiAgentLm Chat Azure Open AiGoogle Sheets
AI & RAG Trigger: Cron / scheduled Nodes: 22 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #11321 — we link there as the canonical source.

This workflow follows the Agent → Airtable recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "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
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow automates AI-driven Facebook Messenger product inquiry handling, connecting Facebook DMs with Airtable inventory and returning instant automated replies based on product availability. It runs hourly, fetches new messages, extracts the latest customer query, uses…

Source: https://n8n.io/workflows/11321/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This n8n automation workflow automates the creation, scripting, production, and posting of YouTube videos. It leverages AI (OpenAI), image generation (PIAPI), video rendering (Shotstack), and platform

Agent, OpenAI Chat, Airtable Tool +7
AI & RAG

This workflow is for beauty salons who want consistent, high‑quality social media content without writing every post manually. It also suits agencies and automation builders who manage multiple beauty

Telegram, Google Sheets Trigger, Agent +26
AI & RAG

This workflow automates the creation, rendering, approval, and posting of TikTok-style POV (Point of View) videos to Instagram, with cross-posting to Facebook and YouTube. It eliminates manual video p

OpenAI Chat, Output Parser Item List, HTTP Request +10
AI & RAG

This workflow is designed for marketers, content creators, agencies, and solo founders who want to publish long‑form posts with visuals on autopilot using n8n and AI agents. ​

Tool Http Request, Agent, HTTP Request +27
AI & RAG

Who Is This For?

Telegram, Google Sheets Trigger, Lm Chat Mistral Cloud +17