(This is another advanced user setup)
Continuing the theme using Agentic AI, I encountered a situation where I wanted to use Discord as an interface. My idea was to have a Discord channel listen for a prompt string, then the Agentic AI would execute a workflow containing AI nodes, and then return to the Discord channel the results. For example, a few keywords entered returns a fully prepared Social Media post.
There is no straight forward way to set this up…but WEBHOOKS allow us to integrate Discord and n8n workflows. What is a webhook? It is a specially coded URL that when seen by a server will cause a trigger action…in this case trigger our workflow and return a result.
For this Step-by-Step guide our intent is to Monitor the Discord channel “#theBot” for a key phrase “Punch It!” that Triggers an n8n workflow. (this step-by-step is easily modified to phase variables to the n8n8 server…I added some examples below.
READ THIS ENTIRE POST BEFORE ATTEMPTING….
🔧 1. Set Up the n8n Webhook:
- In n8n, create a new workflow.
- Add a Webhook node and use these settings:
- Method: POST
- Path: (e.g. discord-punch-it)
- Copy the full Production URL (you’ll need this for your Discord bot)
- Any additional nodes/steps in workflow
- Save your workflow and Activate it.
🧠 2. Create a Discord Bot That Listens for “Punch It!
OK, this is the hardest part. For you to pull this off, you must have a Node.js container or server running.
Step Requirements:
- Node.js installed
- Access rights to create a Discord Bot in the Discord Server
- A way to run the bot (e.g., VPS, local machine, Heroku, etc.)
- The following two files in a dedicated directory:
📄 sample bot.js using discord.js:
const { Client, GatewayIntentBits } = require('discord.js');
const axios = require('axios');
require('dotenv').config();
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
]
});
const WEBHOOK_URL = process.env.N8N_WEBHOOK_URL;
client.once('ready', () => {
console.log(`Logged in as ${client.user.tag}`);
});
client.on('messageCreate', async (message) => {
if (message.channel.name === 'thebot' && message.content.includes('Punch It!')) {
console.log('Trigger phrase detected!');
try {
await axios.post(WEBHOOK_URL, {
username: message.author.username,
content: message.content,
timestamp: message.createdAt
});
console.log('Data sent to n8n webhook.');
} catch (err) {
console.error('Error posting to n8n:', err.message);
}
}
});
client.login(process.env.DISCORD_BOT_TOKEN);
📄 sample .env file (for secrets)
DISCORD_BOT_TOKEN=your_discord_bot_token_here
N8N_WEBHOOK_URL=https://your-n8n-domain/webhook/discord-punch-it
⌨️ 3. Set Up the Bot in Discord
- Go to https://discord.com/developers/applications.
- Create a new application → Go to Bot tab → Add Bot.
- Copy the token and paste it into your .env file.
- Set Permissions under OAuth2 → URL Generator: Scopes: bot Bot Permissions:
- Read Messages/View Channels,
- Send Messages,
- Read Message History
- Use the generated URL to invite your bot to your server and make sure it has access to #thebot.
Here’s a step-by-step guide to containerizing and running your bot with Docker:
🧰 Prerequisites:
Before you begin, you need:
- Docker installed on your machine (Docker Desktop on Windows/macOS, or Docker CLI on Linux)
- Your bot code (bot.js, sample above)
- Your .env file (.env, sample above)
Your Project Directory Structure should look like this:
discord-n8n-bot/
├── bot.js
├── .env
└── Dockerfile
1️⃣ Step 1: Create the Dockerfile
Here’s a simple Dockerfile to run your Node.js Discord bot:
# Use official Node.js image
FROM node:20-alpine
# Set working directory
WORKDIR /usr/src/app
# Copy files
COPY package*.json ./
COPY . .
# Install dependencies
RUN npm install
# Start the bot
CMD ["node", "bot.js"]
note: I had to specify what version of Node.js to use for my server for this to work correctly. Refer to Docker Hub Node.js repository for information for your environment.
2️⃣ Step 2: Create package.json
Create the file “package.json” for your bot:
{
"name": "discord-n8n-bot",
"version": "1.0.0",
"main": "bot.js",
"scripts": {
"start": "node bot.js"
},
"dependencies": {
"axios": "^1.6.0",
"discord.js": "^14.0.0",
"dotenv": "^16.0.0"
}
}
3️⃣ Step 3: complete your .env File (Secrets)
Make sure you have this .env file in your project root (DO NOT commit this file to GitHub)…
DISCORD_BOT_TOKEN=your_discord_bot_token_here
N8N_WEBHOOK_URL=https://your-n8n-url.com/webhook/discord-punch-it
4️⃣ Step 4: Build and Run with Docker
From the root of your project directory:
docker build -t discord-n8n-bot .
And then run it:
docker run -d --env-file .env --name discord-bot discord-n8n-bot
This runs your bot in detached mode (-d) and loads environment variables from .env. To view the logs use:
docker logs -f discord-bot
Passing Variables into Your Workflow
Let’s say you send these Discord variables for the user’s name, any channel message content, and a timestamp. Add this to the bot.js file to inform the webhook to pass the variables to n8n:
await axios.post(WEBHOOK_URL, {
username: message.author.username,
content: message.content,
timestamp: message.createdAt
});
In the n8n webhook node, these variables will be available as output JSON:
{
"username": "JohnDoe",
"content": "Punch It!",
"timestamp": "2025-08-04T13:00:00.000Z"
}
How to Use These Variables in n8n
In a Set Node:
Add a Set node after the Webhook. Use expressions like:
{{$json["username"]}} {{$json["content"]}} {{$json["timestamp"]}}
In a Conditional (IF) Node:
You can filter by content or user:
Field. Operation. Value
{{$json["content"]}}. contains. Punch It!
In a Message (e.g., Discord reply or Email)
If you send a response, you can use:
Received command from {{$json["username"]}}: {{$json["content"]}} at {{$json["timestamp"]}}
Want to Pass Custom Parameters?
You can also design your Discord messages like:
Punch It! target=Alpha speed=3
Then in n8n, use a Function node to extract those key-value pairs:
const parts = $json["content"].split(" ");
const data = {};
for (let i = 1; i < parts.length; i++) {
const [key, value] = parts[i].split("=");
data[key] = value;
}
return [{ json: { ...$json, ...data } }];
Resulting node JSON Output:
{
"username": "JohnDoe",
"content": "Punch It! target=Alpha speed=3",
"timestamp": "...",
"target": "Alpha",
"speed": "3"
}
Leave a Reply