AutomationFlowsAI & RAG › Facebook Comment AI Moderator with Notion & Gemini

Facebook Comment AI Moderator with Notion & Gemini

ByAbdullah Alshiekh @abdullah01 on n8n.io

Eliminates the slow, inconsistent, and error-prone process of manually replying to Facebook comments by automating it with AI, ensuring fast, accurate, and on-brand customer engagement 24/7.

Cron / scheduled trigger★★★★☆ complexityAI-powered23 nodesAgentGoogle Gemini ChatNotionHTTP RequestFacebook Graph Api
AI & RAG Trigger: Cron / scheduled Nodes: 23 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Agent → Facebookgraphapi 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": "oWTmtu5Euv0y5n13",
  "name": "Facebook Comments Moderator",
  "tags": [],
  "nodes": [
    {
      "id": "01df470c-f637-4065-af99-291dc56f4796",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1312,
        224
      ],
      "parameters": {
        "text": "=You are a helpful, friendly, and empathetic customer support agent for [COMPANY_NAME], a [COMPANY_TYPE] company in [COUNTRY].  \n\nYour job is to read the customer's comment and reply in [TARGET_LANGUAGE] in a natural, unisex, and humanized way that feels warm and personal.  \n\nGuidelines for your replies:\n- Always reply as if you are a [NATIONALITY] person talking naturally.  \n- Keep the tone friendly, respectful, and caring.  \n- Use short, conversational sentences (don't sound like a machine).  \n- Mention [COMPANY_NAME] naturally when relevant.  \n- Always write in a *unisex style*.  \n- Match the *tone of the customer's comment*.  \n- Never use [FORBIDDEN_EXPRESSIONS]. Always use [PREFERRED_EXPRESSIONS] instead. \n- The word \"[SPECIFIC_FORBIDDEN_WORD]\" is strictly forbidden. Never use it in replies. Always use \"[PREFERRED_ALTERNATIVE]\" or another [TARGET_LANGUAGE] greeting instead.\n\n Whenever the customer asks about products, prices, or descriptions, use the Knowledge Base \"\" {{ $('KB Arrange').item.json.knowledgeContext }}\"\" to look up the correct information **before replying**.  \n If the Knowledge Base does not contain the answer, reply politely and naturally without inventing details.  \n\nHere is the customer's comment:  \n\"\"{{ \n  $('Last Post Fetcher').first().json.data\n    .sort((a, b) => new Date(b.created_time) - new Date(a.created_time))[0].message || \"\"\n}}\n\"\"  \n\nNow generate a reply in [TARGET_LANGUAGE] only.\n",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 2.1
    },
    {
      "id": "6c83bfa2-e7b6-4846-97c5-c21f62a6f56e",
      "name": "AI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1232,
        464
      ],
      "parameters": {
        "options": {
          "temperature": 0.2
        },
        "modelName": "[AI_MODEL_NAME]"
      },
      "typeVersion": 1
    },
    {
      "id": "189eb862-ad36-4ea4-992e-e5111a0767f3",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -656,
        224
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "seconds",
              "secondsInterval": 10
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "27f33e5c-06ac-44f0-a6e0-44c6f376ba82",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        336,
        224
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "7a18fcb5-df50-46f6-a8aa-de653b070786",
      "name": "Knowledge Base",
      "type": "n8n-nodes-base.notion",
      "position": [
        80,
        368
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "operation": "getAll",
        "returnAll": true,
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "[KNOWLEDGE_BASE_DATABASE_ID]",
          "cachedResultUrl": "[KNOWLEDGE_BASE_URL]",
          "cachedResultName": "Knowledge Base"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "829dd83a-58f8-44cd-a961-a1a0e2bd5c6e",
      "name": "Last Post Fetcher",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -240,
        224
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v21.0/{{$json[\"data\"][0].id}}/comments?access_token=[FACEBOOK_ACCESS_TOKEN]",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "facebookGraphApi"
      },
      "typeVersion": 4.2
    },
    {
      "id": "eb84d700-a32e-43a3-b4a9-781274635bab",
      "name": "CommentID Checker",
      "type": "n8n-nodes-base.notion",
      "position": [
        80,
        96
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "key": "Comment ID|rich_text",
              "condition": "equals",
              "richTextValue": "={{    $('Last Post Fetcher').first().json.data     .sort((a, b) => new Date(b.created_time) - new Date(a.created_time))[0].id  }}"
            }
          ]
        },
        "options": {},
        "resource": "databasePage",
        "operation": "getAll",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "[PROCESSED_COMMENTS_DATABASE_ID]",
          "cachedResultUrl": "[PROCESSED_COMMENTS_DATABASE_URL]",
          "cachedResultName": "Processed Facebook Comments"
        },
        "filterType": "manual"
      },
      "typeVersion": 2.2,
      "alwaysOutputData": true
    },
    {
      "id": "b81bc886-a42c-4c7d-9e99-844340dc205d",
      "name": "KB Arrange",
      "type": "n8n-nodes-base.code",
      "position": [
        544,
        224
      ],
      "parameters": {
        "jsCode": "// Get the Knowledge Base data from the Notion node\nconst kbPages = $input.all().map(item => item.json);\n\n// Helper function to extract text from Notion properties\nfunction extractText(property) {\n  if (!property) return '';\n  \n  // Handle rich_text properties\n  if (property.rich_text && property.rich_text.length > 0) {\n    return property.rich_text[0].plain_text || '';\n  }\n  \n  // Handle title properties\n  if (property.title && property.title.length > 0) {\n    return property.title[0].plain_text || '';\n  }\n  \n  // Handle select properties\n  if (property.select) {\n    return property.select.name || '';\n  }\n  \n  // Handle number properties\n  if (property.number) {\n    return property.number.toString();\n  }\n  \n  return '';\n}\n\n// Create a linear array of knowledge base entries\nconst knowledgeArray = kbPages.map(page => {\n  const properties = page.properties || {};\n  \n  // Extract information based on your actual Notion properties\n  const productName = page.property_products || '';\n  const price = page.property_prices || '';\n  const description = page.property_description || '';\n  const name = page.name || '';\n  \n  // Create a formatted knowledge entry\n  const knowledgeEntry = {\n    name: name,\n    product: productName,\n    price: price,\n    description: description,\n    // Create a searchable text string\n    searchableText: [name, productName, price, description]\n      .filter(Boolean)\n      .join(' | ')\n  };\n  \n  return knowledgeEntry;\n}).filter(entry => entry.name || entry.product); // Only include entries with names or products\n\n// Create a simple string array for easy searching\nconst knowledgeStrings = knowledgeArray.map(entry => \n  `NAME: ${entry.name || 'N/A'}` +\n  (entry.product ? ` | PRODUCT: ${entry.product}` : '') +\n  (entry.price ? ` | PRICE: ${entry.price}` : '') +\n  (entry.description ? ` | DESCRIPTION: ${entry.description}` : '')\n);\n\n// Output the processed data\nreturn [{\n  json: {\n    // Original data passthrough\n    ...($input.first()?.json || {}),\n    \n    // Structured knowledge base data\n    knowledgeBase: {\n      entries: knowledgeArray,\n      searchableStrings: knowledgeStrings,\n      totalProducts: knowledgeArray.length\n    },\n    \n    // Simple concatenated string for memory context\n    knowledgeContext: knowledgeStrings.join('\\n\\n'),\n    \n    // Alternative: Create a more concise version for memory\n    compactKnowledge: knowledgeArray.map(entry => \n      `${entry.name || entry.product}: ${entry.description || 'No description'} (${entry.price || 'Price not available'})`\n    ).join('\\n')\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "91e25c71-a594-4bdc-a33c-c66857b62751",
      "name": "New Comment Conditioner",
      "type": "n8n-nodes-base.if",
      "position": [
        784,
        224
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "e566ada9-1a12-41b8-aa9a-55bb7e14a10c",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.property_comment_id }}",
              "rightValue": ""
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "83aa9b95-6671-4813-90e8-3820202324e6",
      "name": "Latest Comment",
      "type": "n8n-nodes-base.facebookGraphApi",
      "position": [
        1024,
        240
      ],
      "parameters": {
        "edge": "comments",
        "node": "={{ \n  $('Last Post Fetcher').first().json.data\n    .sort((a, b) => new Date(b.created_time) - new Date(a.created_time))[0].id \n}}",
        "options": {},
        "graphApiVersion": "v23.0"
      },
      "typeVersion": 1
    },
    {
      "id": "c0420da3-170b-4741-a71d-69998b34b13b",
      "name": "Reply Writer",
      "type": "n8n-nodes-base.facebookGraphApi",
      "position": [
        1712,
        224
      ],
      "parameters": {
        "edge": "comments",
        "node": "={{ \n  $('Last Post Fetcher').first().json.data\n    .sort((a, b) => new Date(b.created_time) - new Date(a.created_time))[0].id \n}}",
        "options": {
          "queryParameters": {
            "parameter": [
              {
                "name": "message",
                "value": "={{ $('AI Agent').first().json.output }}"
              }
            ]
          }
        },
        "graphApiVersion": "v23.0",
        "httpRequestMethod": "POST"
      },
      "typeVersion": 1
    },
    {
      "id": "15eb2020-9963-4ae8-adf4-445d5506ae07",
      "name": "CommentID to DB",
      "type": "n8n-nodes-base.notion",
      "position": [
        1968,
        224
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "[PROCESSED_COMMENTS_DATABASE_ID]",
          "cachedResultUrl": "[PROCESSED_COMMENTS_DATABASE_URL]",
          "cachedResultName": "Processed Facebook Comments"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Comment ID|rich_text",
              "textContent": "={{    $('Last Post Fetcher').first().json.data     .sort((a, b) => new Date(b.created_time) - new Date(a.created_time))[0].id  }}"
            },
            {
              "key": "Response Status|status",
              "statusValue": "Done"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "1cbe6d39-f106-4320-b9a0-7520e7ea4a17",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -512,
        128
      ],
      "parameters": {
        "color": 4,
        "width": 214,
        "content": "Initiates the workflow by retrieving all posts from the specified Facebook Page via the Graph API."
      },
      "typeVersion": 1
    },
    {
      "id": "db015463-5489-4b59-aca8-8f648a6dc40e",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -272,
        128
      ],
      "parameters": {
        "color": 5,
        "width": 176,
        "content": "Processes the list of posts to isolate the most recently published one."
      },
      "typeVersion": 1
    },
    {
      "id": "a3a44851-6263-47b0-bd4e-e1e931cd9033",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "color": 4,
        "width": 256,
        "content": "Queries a database to verify if the latest comment's unique ID has already been processed, preventing duplicate replies."
      },
      "typeVersion": 1
    },
    {
      "id": "8d5f94d9-f8d1-44d5-baba-683c8d2d625e",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        16,
        288
      ],
      "parameters": {
        "color": 5,
        "width": 230,
        "height": 192,
        "content": "Fetches the complete, up-to-date product information and knowledge base from the connected Notion database."
      },
      "typeVersion": 1
    },
    {
      "id": "a7c140a5-42cb-4709-a761-077ea5aacf4c",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        448,
        144
      ],
      "parameters": {
        "color": 5,
        "content": "Transforms the raw knowledge base data into a structured and easily searchable format for the AI model."
      },
      "typeVersion": 1
    },
    {
      "id": "2c1e6e91-6bf3-4b11-bc89-da414ee8709c",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        720,
        128
      ],
      "parameters": {
        "color": 4,
        "width": 224,
        "height": 192,
        "content": " A conditional gate; it only allows the workflow to proceed if the comment is new"
      },
      "typeVersion": 1
    },
    {
      "id": "2eee31fa-d437-4c18-9328-1f447b447d9a",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        976,
        144
      ],
      "parameters": {
        "color": 5,
        "width": 208,
        "content": "Extracts the full content and metadata of the most recent comment from the latest post."
      },
      "typeVersion": 1
    },
    {
      "id": "8ce9e8cb-b20f-4efa-97b2-eba6e3c47ede",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1280,
        112
      ],
      "parameters": {
        "color": 6,
        "width": 288,
        "height": 208,
        "content": "The core processing unit. It analyzes the customer's comment, consults the knowledge base for factual responses, and generates a personalized, empathetic reply in the target language."
      },
      "typeVersion": 1
    },
    {
      "id": "101a2030-dbd0-44af-8116-9bd1bf1a874d",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1616,
        144
      ],
      "parameters": {
        "color": 4,
        "content": "Takes the AI-generated response and posts it as a reply to the customer's comment on Facebook."
      },
      "typeVersion": 1
    },
    {
      "id": "5104091f-7597-4413-a5b6-28da90821b66",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1888,
        128
      ],
      "parameters": {
        "color": 5,
        "width": 272,
        "height": 208,
        "content": " Logs the ID of the newly processed comment into the database to mark it as complete and prevent reprocessing in the future."
      },
      "typeVersion": 1
    },
    {
      "id": "c2a5a6cb-79a4-4c7b-9475-4681b45bd3d3",
      "name": "Posts Fetcher",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -432,
        224
      ],
      "parameters": {
        "url": "=https://graph.facebook.com/v21.0/[FACEBOOK_PAGE_ID]/posts?access_token=[FACEBOOK_ACCESS_TOKEN]\n",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "facebookGraphApi"
      },
      "credentials": {
        "facebookGraphApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "0e48350f-f5ab-4cdd-83e8-5b4b16974fdd",
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "KB Arrange",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Reply Writer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "KB Arrange": {
      "main": [
        [
          {
            "node": "New Comment Conditioner",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Reply Writer": {
      "main": [
        [
          {
            "node": "CommentID to DB",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Posts Fetcher": {
      "main": [
        [
          {
            "node": "Last Post Fetcher",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Knowledge Base": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Latest Comment": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Posts Fetcher",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "CommentID Checker": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Last Post Fetcher": {
      "main": [
        [
          {
            "node": "CommentID Checker",
            "type": "main",
            "index": 0
          },
          {
            "node": "Knowledge Base",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New Comment Conditioner": {
      "main": [
        [],
        [
          {
            "node": "Latest Comment",
            "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

Eliminates the slow, inconsistent, and error-prone process of manually replying to Facebook comments by automating it with AI, ensuring fast, accurate, and on-brand customer engagement 24/7.

Source: https://n8n.io/workflows/7660/ — 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

LinkedIn_Job_Hunt_and_Cover_Letter. Uses outputParserStructured, outputParserAutofixing, googleDrive, agent. Scheduled trigger; 85 nodes.

Output Parser Structured, Output Parser Autofixing, Google Drive +6
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

Who Is This For?

Telegram, Google Sheets Trigger, Lm Chat Mistral Cloud +17
AI & RAG

Transform your festival marketing with this comprehensive automation workflow that creates and posts culturally authentic social media content across multiple platforms daily.

Google Sheets, Output Parser Structured, Chain Llm +5
AI & RAG

Reddit-Insights-N8N. Uses @brightdata/n8n-nodes-brightdata, agent, lmChatGoogleGemini, rssFeedRead. Scheduled trigger; 29 nodes.

@Brightdata/N8N Nodes Brightdata, Agent, Google Gemini Chat +3