This workflow corresponds to n8n.io template #10483 — we link there as the canonical source.
This workflow follows the Agent → Google Sheets 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 →
{
"id": "iWO9TnNMXtSwdZ3Y",
"name": "AI-Driven Discord Moderation with Google Sheets Learning & Admin Insights",
"tags": [],
"nodes": [
{
"id": "44a9a680-a894-4d11-9560-805023a4316c",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
240,
240
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "aec37f9f-3869-49b3-9d41-5b8b429c1f84",
"name": "AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1328,
176
],
"parameters": {
"text": "=LEARN FROM THESE EXAMPLES:\n\nMessages to ALWAYS DELETE:\n- {{ $json.badExamples }}\n\nMessages to NEVER DELETE:\n- {{ $json.goodExamples }}\n\nNow analyze these messages:\n{{ $json.messageList }}",
"options": {
"systemMessage": "=You are a content moderator for 'The Daily Hustle' - a forex trading academy Discord community. Your job is to identify and flag messages that violate community standards.\n\nIMPORTANT: Focus on INTENT and CONTEXT, not just language. Profanity in positive/supportive messages is ALLOWED.\n\nDELETE messages that contain:\n- Personal attacks, insults, or harassment toward members/community (e.g., \"you guys are shit\", \"this firm is bad\")\n- Degrading comments about the academy, mentors, or trading strategies\n- Spam, scams, or fraudulent trading schemes\n- Toxic negativity that damages community morale\n- Hate speech, discrimination, or offensive content\n- Messages that undermine the academy's credibility or reputation\n- Threats or aggressive behavior\n\nKEEP messages that:\n- Express positive emotions even with profanity (e.g., \"I fucking love you guys\", \"this is fucking amazing\")\n- Provide constructive criticism or feedback\n- Ask legitimate questions about trading or the academy\n- Share trading experiences (even losses) in a respectful way\n- Engage in healthy debate about trading strategies\n- Show enthusiasm, excitement, or support for the community\n\n{{ $json.trainingExamples }}\n\nMessages to analyze:\n{{ $json.messageList }}\n\nReturn ONLY a JSON array of message indices that should be deleted.\nFormat: [0, 2, 5]\n\nIf all messages are fine, return: []"
},
"promptType": "define"
},
"typeVersion": 2.2
},
{
"id": "85e658f9-cd00-4d64-be35-a2ea56f986d9",
"name": "update admin channel about moderation",
"type": "n8n-nodes-base.discord",
"position": [
2368,
256
],
"parameters": {
"content": "=It seems that a message was deleted for violating community standards.\n\nAuthor: {{ $('Loop Over Items').item.json.author.username }}\nMessage ID: {{ $('Loop Over Items').item.json.messageId }}\nContent: {{ $('Loop Over Items').item.json.content }}",
"guildId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Loop Over Items').item.json.config.discordServerId }}"
},
"options": {},
"resource": "message",
"channelId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Loop Over Items').item.json.config.adminChannelId }}"
},
"authentication": "oAuth2"
},
"credentials": {
"discordOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "d7aba29d-90a4-4dbd-a3ce-51e58395ec5a",
"name": "delete bad content",
"type": "n8n-nodes-base.discord",
"onError": "continueRegularOutput",
"position": [
2064,
256
],
"parameters": {
"guildId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.config.discordServerId }}"
},
"resource": "message",
"channelId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.config.moderatedChannelId }}"
},
"messageId": "={{ $json.messageId }}",
"operation": "deleteMessage",
"authentication": "oAuth2"
},
"credentials": {
"discordOAuth2Api": {
"name": "<your credential>"
}
},
"notesInFlow": false,
"typeVersion": 2
},
{
"id": "6793f1ac-84df-4ac5-a8db-be75592ebedd",
"name": "GPT5 mini",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
1280,
320
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-5-mini-2025-08-07",
"cachedResultName": "gpt-5-mini-2025-08-07"
},
"options": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "4d84bf71-7fd9-4848-8304-0e8f34495f3b",
"name": "Get only the bad messages",
"type": "n8n-nodes-base.code",
"position": [
1664,
240
],
"parameters": {
"jsCode": "// Get the AI's response from the current input\nconst aiOutput = $input.first().json.output;\n\n// Get the original messages from the prep node\nconst allMessages = $('prep messages for AI').first().json.originalMessages;\n\n// Get configuration from prep node\nconst config = $('prep messages for AI').first().json.config;\n\n// Debug logs\nconsole.log('AI Output:', aiOutput);\nconsole.log('All Messages:', allMessages);\n\n// Parse the AI response\nlet badIndices = [];\ntry {\n if (Array.isArray(aiOutput)) {\n badIndices = aiOutput;\n } else if (typeof aiOutput === 'string') {\n badIndices = JSON.parse(aiOutput);\n }\n} catch (error) {\n console.log('Parse error:', error);\n return [];\n}\n\nconsole.log('Bad Indices (before dedup):', badIndices);\n\n// Remove duplicates from badIndices\nbadIndices = [...new Set(badIndices)];\n\nconsole.log('Bad Indices (after dedup):', badIndices);\n\n// Validate indices exist in the array\nbadIndices = badIndices.filter(index => \n index >= 0 && index < allMessages.length && allMessages[index]\n);\n\nconsole.log('Bad Indices (validated):', badIndices);\n\n// Get only the unique bad messages\nconst messagesToDelete = badIndices.map(index => ({\n json: {\n messageId: allMessages[index].id,\n content: allMessages[index].content,\n author: allMessages[index].author,\n config: config // Pass config forward\n }\n}));\n\n// Additional safety: Remove duplicate message IDs\nconst uniqueMessages = [];\nconst seenIds = new Set();\n\nfor (const msg of messagesToDelete) {\n if (!seenIds.has(msg.json.messageId)) {\n seenIds.add(msg.json.messageId);\n uniqueMessages.push(msg);\n }\n}\n\nconsole.log('Final unique messages to delete:', uniqueMessages.length);\n\nreturn uniqueMessages.length > 0 ? uniqueMessages : [];"
},
"typeVersion": 2
},
{
"id": "d7990994-24d8-4ac1-b707-f47779be5737",
"name": "Get sheet knowledgebase",
"type": "n8n-nodes-base.googleSheets",
"position": [
640,
240
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xodthGg8RpQJB62mB6fziuwblG9nn3udZvQvyRquCXM/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1xodthGg8RpQJB62mB6fziuwblG9nn3udZvQvyRquCXM",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1xodthGg8RpQJB62mB6fziuwblG9nn3udZvQvyRquCXM/edit?usp=drivesdk",
"cachedResultName": "discord-AI-moderator-good-bad-samples"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "71656c51-2ec8-4452-8ef4-58721e975678",
"name": "Main Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-256,
-624
],
"parameters": {
"width": 432,
"height": 820,
"content": "# AI-Driven Discord Moderation with Google Sheets Learning & Admin Insights\n\n## How it works:\n\nThis workflow monitors your Discord channel every 3 minutes and uses AI to detect rule-breaking messages. It learns from examples in a Google Sheet to understand what should be deleted (spam, harassment, toxic behavior) vs what's okay (even if it includes profanity in a positive context). Flagged messages are auto-deleted and logged to an admin channel.\n\n## Setup steps\n1. **Copy the training sheet**: [Make a copy of this Google Sheet](https://docs.google.com/spreadsheets/d/1xodthGg8RpQJB62mB6fziuwblG9nn3udZvQvyRquCXM/edit?usp=sharing)\n2. **Add your examples**: Fill in message_content, should_delete (YES/NO), and reason columns\n3. **Set Discord IDs**: Edit the \"Edit Fields\" node with your server ID, monitored channel ID, and admin channel ID\n4. **Connect credentials**: Link Discord OAuth2, Google Sheets, and OpenAI API\n5. **Customize the AI prompt**: Adjust the system message in \"AI Agent\" to match your community rules\n6. **Test**: Run manually first, check admin channel for logs\n\nThe AI understands context and intent, not just keywords."
},
"typeVersion": 1
},
{
"id": "da0b2d16-e6ad-4123-8557-1adc2fb4b44b",
"name": "Training Data Section",
"type": "n8n-nodes-base.stickyNote",
"position": [
576,
16
],
"parameters": {
"color": 4,
"width": 224,
"height": 448,
"content": "## Training Data\nLoads examples from Google Sheets (message_content, should_delete, reason) to teach the AI your moderation standards."
},
"typeVersion": 1
},
{
"id": "e1753b53-7c88-4a60-870b-1b5d732b8f07",
"name": "Analysis Section",
"type": "n8n-nodes-base.stickyNote",
"position": [
832,
16
],
"parameters": {
"color": 7,
"width": 736,
"height": 448,
"content": "## Message Analysis\nFetches recent messages, formats them with training data, and sends to GPT-5 for context-aware moderation."
},
"typeVersion": 1
},
{
"id": "b8ddcc67-1c42-4091-a512-b56f2d07d64c",
"name": "Processing Section",
"type": "n8n-nodes-base.stickyNote",
"position": [
1600,
16
],
"parameters": {
"color": 7,
"width": 944,
"height": 448,
"content": "## Processing & Cleanup\nParses AI results, deduplicates, then loops through each flagged message to delete and notifies admin channel."
},
"typeVersion": 1
},
{
"id": "51453ec4-1a0d-48f2-ad65-bbe24bfa63ea",
"name": "Get recent messages",
"type": "n8n-nodes-base.discord",
"position": [
896,
240
],
"parameters": {
"limit": 10,
"guildId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Set Credentials Here').item.json['discord server ID'] }}"
},
"options": {},
"resource": "message",
"channelId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Set Credentials Here').item.json['discord moderated channel ID'] }}"
},
"operation": "getAll",
"authentication": "oAuth2"
},
"credentials": {
"discordOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "16857487-962f-44bf-b0cf-abf5d4864a14",
"name": "prep messages for AI",
"type": "n8n-nodes-base.code",
"position": [
1104,
240
],
"parameters": {
"jsCode": "// ===== CONFIGURATION - EDIT THESE VALUES =====\nconst CONFIG = {\n discordServerId: '1373767704351346689', // Your Discord Server ID\n moderatedChannelId: '1429758114948841592', // Channel to monitor\n adminChannelId: '1427336562240126976' // Admin notification channel\n};\n// YOUR_AWS_SECRET_KEY_HERE====\n\n// Get training examples from Google Sheets (if available)\nlet badExamples = '';\nlet goodExamples = '';\n\ntry {\n const examples = $('Get sheet knowledgebase').all().map(item => item.json);\n \n // Format bad examples (messages to DELETE)\n const badList = examples\n .filter(e => e.should_delete === 'YES')\n .map(e => `\"${e.message_content}\" (Reason: ${e.reason})`)\n .join('\\n- ');\n \n if (badList) {\n badExamples = `\\n\\nMessages to ALWAYS DELETE:\\n- ${badList}`;\n }\n \n // Format good examples (messages to KEEP)\n const goodList = examples\n .filter(e => e.should_delete === 'NO')\n .map(e => `\"${e.message_content}\" (Reason: ${e.reason})`)\n .join('\\n- ');\n \n if (goodList) {\n goodExamples = `\\n\\nMessages to NEVER DELETE:\\n- ${goodList}`;\n }\n} catch (error) {\n console.log('No training examples found or Google Sheets not connected:', error);\n}\n\n// Get all messages from Discord\nconst messages = $input.all().map(item => item.json);\n\n// Create a formatted list with IDs for the AI\nconst messageList = messages.map((msg, index) => \n `[${index}] ID: ${msg.id}\\nAuthor: ${msg.author.username}\\nContent: ${msg.content}`\n).join('\\n\\n---\\n\\n');\n\nreturn [{\n json: {\n messageList,\n originalMessages: messages,\n trainingExamples: badExamples + goodExamples,\n // Pass config along with the data\n config: CONFIG\n }\n}];"
},
"typeVersion": 2
},
{
"id": "aa9274ce-2432-4868-a03b-579aacee5bd2",
"name": "wait",
"type": "n8n-nodes-base.wait",
"position": [
2224,
256
],
"parameters": {
"amount": 1.5
},
"typeVersion": 1.1
},
{
"id": "53de222e-5f41-4bd2-9ed8-9c3155637f74",
"name": "Set Credentials Here",
"type": "n8n-nodes-base.set",
"position": [
416,
240
],
"parameters": {
"options": {
"ignoreConversionErrors": true
},
"assignments": {
"assignments": [
{
"id": "38a218af-86fc-4b60-9075-3efe1a3b8262",
"name": "discord server ID",
"type": "object",
"value": "=1234567"
},
{
"id": "94e5554f-5352-40fc-b439-0db6f6ca7da7",
"name": "discord moderated channel ID",
"type": "object",
"value": "1234567"
},
{
"id": "5ffdeb80-179f-49f1-9abf-8bce6c855c13",
"name": "=discord admin channel ID",
"type": "object",
"value": "=1234567"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b9a33dd8-a931-44f3-828e-7c9c58d5dcc5",
"name": "Loop Over Items",
"type": "n8n-nodes-base.splitInBatches",
"position": [
1840,
240
],
"parameters": {
"options": {}
},
"typeVersion": 3
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "850ac17c-a6d9-4651-973b-e65c62a57e82",
"connections": {
"wait": {
"main": [
[
{
"node": "update admin channel about moderation",
"type": "main",
"index": 0
}
]
]
},
"AI Agent": {
"main": [
[
{
"node": "Get only the bad messages",
"type": "main",
"index": 0
}
]
]
},
"GPT5 mini": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[],
[
{
"node": "delete bad content",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Set Credentials Here",
"type": "main",
"index": 0
}
]
]
},
"delete bad content": {
"main": [
[
{
"node": "wait",
"type": "main",
"index": 0
}
]
]
},
"Get recent messages": {
"main": [
[
{
"node": "prep messages for AI",
"type": "main",
"index": 0
}
]
]
},
"Set Credentials Here": {
"main": [
[
{
"node": "Get sheet knowledgebase",
"type": "main",
"index": 0
}
]
]
},
"prep messages for AI": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"Get sheet knowledgebase": {
"main": [
[
{
"node": "Get recent messages",
"type": "main",
"index": 0
}
]
]
},
"Get only the bad messages": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"update admin channel about moderation": {
"main": [
[
{
"node": "Loop Over Items",
"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.
discordOAuth2ApigoogleSheetsOAuth2ApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This n8n template demonstrates how to automatically moderate Discord messages using AI-powered content analysis that learns from your community standards. It continuously monitors your server, intelligently flags problematic content while allowing context-appropriate language,…
Source: https://n8n.io/workflows/10483/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow automates the complete blog publishing process. It removes manual work from content creation, image generation, category management, and WordPress publishing by using AI and n8n. It help
Mission-Aligned Task Tracker: Discord + AI + Google Sheets
This n8n workflow is designed for content creators, digital marketers, and social media managers who want to automate their entire content creation and publishing process across multiple platforms. It
This n8n workflow automates the complete blog publishing process from topic research to WordPress publication. It researches topics, writes SEO-optimized content, generates images, publishes posts, an
⚠️ DISCLAIMER: This workflow uses the AnySite LinkedIn community node, which is only available on self-hosted n8n instances. It will not work on n8n.cloud.