TL;DR
- まずはこの記事の方法でSlackBotを作ります。
- n8nにWebhookのWorkflowを作成します。
- Slack の Socket Mode を使って、メッセージを中継します。
方法
Slack Botの作成
上記の記事は詳しく作成方法を書いています。読みたくない場合は、 このリンク をクリックし、 「From a manifest」 を選び、下記の設定ファイルを 「YAML」タブ に貼り付ければOKです。


display_information:
name: Slack-Bot-Demo
features:
bot_user:
display_name: Slack-Bot-Demo
always_online: false
oauth_config:
scopes:
bot:
- channels:history
- groups:history
- im:history
- mpim:history
- chat:write
- app_mentions:read
settings:
event_subscriptions:
bot_events:
- message.channels
- message.groups
- message.im
- message.mpim
- app_mention
interactivity:
is_enabled: true
org_deploy_enabled: false
socket_mode_enabled: true
token_rotation_enabled: false
n8n Workflowの作成
下記のような簡単な時報AIを作りました。
Slack-Local-Demo.json
Slack-Local-Demo.json
{
"name": "Slack Local Demo",
"nodes": [
{
"parameters": {
"promptType": "define",
"text": "={{ $json.body.text }}",
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 3,
"position": [
208,
0
],
"id": "c48e2a7b-4d27-4fb7-95b5-a1b95bb5c746",
"name": "AI Agent"
},
{
"parameters": {
"options": {}
},
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"typeVersion": 1,
"position": [
208,
176
],
"id": "1b78944e-db02-4a10-bc31-a86472472312",
"name": "Google Gemini Chat Model",
"credentials": {
"googlePalmApi": {
"id": "bNX3Ng40XeUKUnU8",
"name": "Google Gemini(PaLM) Api account"
}
}
},
{
"parameters": {
"httpMethod": "POST",
"path": "eb43abea-835e-4356-bbae-eb2b15cb5439",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
-48,
0
],
"id": "920d4473-f7bb-44fd-aacf-3db32dd810bb",
"name": "Webhook",
"webhookId": "eb43abea-835e-4356-bbae-eb2b15cb5439"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={\n \"text\": \"{{$json.output}}\",\n \"thread\": {\n \"channelId\": \"{{ $('Webhook').item.json.body.thread.channelId }}\",\n \"threadId\": \"{{ $('Webhook').item.json.body.thread.threadId }}\"\n }\n}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.4,
"position": [
560,
0
],
"id": "5b559af6-d383-45a8-bb9b-88ed22a895f1",
"name": "Respond to Webhook"
},
{
"parameters": {
"options": {}
},
"type": "n8n-nodes-base.dateTimeTool",
"typeVersion": 2,
"position": [
352,
192
],
"id": "04352eeb-d01a-4d6b-8d56-3d95e1344066",
"name": "Date & Time"
}
],
"pinData": {},
"connections": {
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Webhook": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"AI Agent": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Date & Time": {
"ai_tool": [
[
{
"node": "AI Agent",
"type": "ai_tool",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "807ed4c6-05b3-4e0c-89a3-1d8fa69c27d6",
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "733f4543cc2716ce03aee7a2723a7a38c8dd841e95dddcbe1403304743cd54e1"
},
"id": "0spOf0unGMovJr9v",
"tags": []
}
API テスト
下記のような感じでAPIの動作を確認します。
POST http://localhost:5678/webhook-test/eb43abea-835e-4356-bbae-eb2b15cb5439
Content-Type: application/json
{
"text": "Hello, What's the time now!",
"thread": {
"channelId": "TEST-CHANNEL",
"threadId": "TEST-THREAD"
}
}
こんな感じでレスポンスが来たらOKです。
{
"text": "The current date and time is 2025-12-26T02:10:40.580-05:00.",
"thread": {
"channelId": "TEST-CHANNEL",
"threadId": "TEST-THREAD"
}
}
注意すべきのは、必ず channelId と threadId (threadTs)をメッセージに持たせることです。
今回は簡易的な同期的実装にしていましたが、将来非同期的な実装をしようとする時、チャネルやスレッド情報を持っていると便利です。
中継 Scriptの作成
同期的な実装にしていますが、ExpressなどでAPIサーバーを立てれば、非同期的な実装も可能です。
import bolt from '@slack/bolt';
import { config } from 'dotenv';
config({ quiet: true });
const { App } = bolt;
const slackApp = new App({
token: process.env.SLACK_BOT_TOKEN, // xoxb-XXXXX
appToken: process.env.SLACK_APP_TOKEN, // xapp-XXXXX
socketMode: true,
});
await slackApp.start();
console.log('⚡️ Bolt app started');
const n8nUrl = `http://localhost:5678/webhook/eb43abea-835e-4356-bbae-eb2b15cb5439`;
slackApp.event('app_mention', async ({ event, say }) => {
console.log('App mentioned:', event);
const text = removeSlackMention(removeSlackUrlTag(event.text));
const threadId = event.thread_ts || event.ts;
const response = await sendToN8n(n8nUrl, text, { channelId: event.channel, threadId });
// スレッドを作成して返信する
await say({
thread_ts: event.ts,
text: `<@${event.user}> ${response.text}`,
});
});
async function sendToN8n(url, text, thread = { channelId: null, threadId: null }) {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ text, thread }),
});
const data = await response.json();
console.log(data);
return data;
}
// SlackのURLタグをプレーンのURLに還元する
function removeSlackUrlTag(text) {
return text.replace(/<https?:\/\/[^|]+?\|([^>]+)>/g, '$1').replace(/<(https?:\/\/[^>]+)>/g, '$1');
}
// Slackのメンションタグを削除
function removeSlackMention(text) {
return text.replace(/<@[^>]+>/g, '').trim();
}

