From 3b13bdcc87ea3591b2cf7f2ee86d0e67947af92d Mon Sep 17 00:00:00 2001 From: happybell80 Date: Wed, 18 Mar 2026 23:44:45 +0900 Subject: [PATCH] =?UTF-8?q?workflow:=20n8n=20Slack=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EB=8C=80=ED=99=94=20=EC=9B=8C=ED=81=AC=ED=94=8C=EB=A1=9C?= =?UTF-8?q?=EC=9A=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made-with: Cursor --- .../n8n_slack_basic_dialogue_workflow.json | 437 ++++++++++++++++++ 1 file changed, 437 insertions(+) create mode 100644 workflow/n8n_slack_basic_dialogue_workflow.json diff --git a/workflow/n8n_slack_basic_dialogue_workflow.json b/workflow/n8n_slack_basic_dialogue_workflow.json new file mode 100644 index 0000000..ad84ef7 --- /dev/null +++ b/workflow/n8n_slack_basic_dialogue_workflow.json @@ -0,0 +1,437 @@ +{ + "name": "robeing-slack-basic-dialogue", + "nodes": [ + { + "parameters": { + "channelId": { + "__rl": true, + "mode": "list", + "value": "" + }, + "options": {} + }, + "id": "a1c3d2f0-b5e0-4f40-85fd-79f147ec0001", + "name": "Slack Trigger", + "type": "n8n-nodes-base.slackTrigger", + "typeVersion": 1, + "position": [ + 240, + 260 + ] + }, + { + "parameters": { + "jsCode": "const event = $json.event || {};\nconst headers = $json.headers || {};\nconst text = event.text || '';\nconst question = text.replace(/<@[^>]+>/g, '').trim();\nconst isBotMessage = Boolean(event.bot_id) || event.subtype === 'bot_message';\nconst isEditedMessage = event.subtype === 'message_changed';\nconst isDeletedMessage = event.subtype === 'message_deleted';\nconst isRetry = headers['x-slack-retry-num'] !== undefined || headers['X-Slack-Retry-Num'] !== undefined;\nconst shouldProcess = Boolean(event.channel) && Boolean(event.user) && Boolean(question) && !isBotMessage && !isEditedMessage && !isDeletedMessage && !isRetry;\n\nreturn {\n raw_event: event,\n headers,\n should_process: shouldProcess,\n skip_reason: shouldProcess ? null : {\n missing_channel: !event.channel,\n missing_user: !event.user,\n empty_question: !question,\n bot_message: isBotMessage,\n edited_message: isEditedMessage,\n deleted_message: isDeletedMessage,\n retry_event: isRetry\n },\n team_id: event.team || event.team_id || '',\n channel: event.channel || '',\n user_id: event.user || '',\n event_ts: event.ts || '',\n thread_ts: event.thread_ts || event.ts || '',\n original_text: text,\n question,\n mention_removed_text: question,\n robeing_id: 'rb8001',\n source: 'slack',\n response_mode: event.thread_ts ? 'reply_in_existing_thread' : 'reply_in_new_thread'\n};" + }, + "id": "a1c3d2f0-b5e0-4f40-85fd-79f147ec0002", + "name": "Normalize Slack Event", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 500, + 260 + ] + }, + { + "parameters": { + "conditions": { + "boolean": [ + { + "value1": "={{ $json.should_process }}", + "value2": true + } + ] + } + }, + "id": "a1c3d2f0-b5e0-4f40-85fd-79f147ec0003", + "name": "Should Process?", + "type": "n8n-nodes-base.if", + "typeVersion": 2, + "position": [ + 760, + 260 + ] + }, + { + "parameters": { + "method": "GET", + "url": "=http://192.168.219.45:9000/api/slack/mapping/{{$json.user_id}}", + "options": { + "response": { + "response": { + "fullResponse": true + } + }, + "timeout": 10000 + } + }, + "id": "a1c3d2f0-b5e0-4f40-85fd-79f147ec0004", + "name": "Get Slack User Mapping", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 1020, + 180 + ] + }, + { + "parameters": { + "jsCode": "const mappingResponse = $json;\nconst eventData = $('Normalize Slack Event').item.json;\nconst body = mappingResponse.body || {};\nconst userUuid = body.user_id || body.id || body.uuid || '';\nconst username = body.username || `slack_${eventData.user_id}`;\nconst ok = mappingResponse.statusCode >= 200 && mappingResponse.statusCode < 300 && Boolean(userUuid);\n\nreturn {\n ...eventData,\n mapping_status_code: mappingResponse.statusCode,\n mapping_ok: ok,\n mapped_user_uuid: userUuid,\n mapped_username: username,\n mapped_user_payload: body\n};" + }, + "id": "a1c3d2f0-b5e0-4f40-85fd-79f147ec0005", + "name": "Parse Mapping Response", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1260, + 180 + ] + }, + { + "parameters": { + "conditions": { + "boolean": [ + { + "value1": "={{ $json.mapping_ok }}", + "value2": true + } + ] + } + }, + "id": "a1c3d2f0-b5e0-4f40-85fd-79f147ec0006", + "name": "Mapping Found?", + "type": "n8n-nodes-base.if", + "typeVersion": 2, + "position": [ + 1500, + 180 + ] + }, + { + "parameters": { + "jsCode": "return {\n channel: $json.channel,\n thread_ts: $json.thread_ts,\n text: 'Slack 사용자 매핑을 찾지 못했습니다. 관리자에게 문의해주세요.',\n response_kind: 'mapping_error',\n metadata: {\n user_id: $json.user_id,\n team_id: $json.team_id,\n mapping_status_code: $json.mapping_status_code\n }\n};" + }, + "id": "a1c3d2f0-b5e0-4f40-85fd-79f147ec0007", + "name": "Build Mapping Error Reply", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1740, + 340 + ] + }, + { + "parameters": { + "jsCode": "return {\n channel: $json.channel,\n user_uuid: $json.mapped_user_uuid,\n thread_ts: $json.thread_ts,\n message: $json.question,\n robeing_id: $json.robeing_id,\n request_body: {\n message: $json.question,\n source: 'slack',\n context: {\n slack: {\n team_id: $json.team_id,\n channel: $json.channel,\n user_id: $json.user_id,\n event_ts: $json.event_ts,\n thread_ts: $json.thread_ts,\n response_mode: $json.response_mode\n },\n robeing: {\n robeing_id: $json.robeing_id,\n mapped_username: $json.mapped_username\n }\n }\n }\n};" + }, + "id": "a1c3d2f0-b5e0-4f40-85fd-79f147ec0008", + "name": "Build Robeing Request", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1740, + 100 + ] + }, + { + "parameters": { + "method": "POST", + "url": "=http://192.168.219.45:8100/api/chat", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "Content-Type", + "value": "application/json" + }, + { + "name": "X-User-Id", + "value": "={{ $json.user_uuid }}" + } + ] + }, + "sendBody": true, + "specifyBody": "json", + "jsonBody": "={{ $json.request_body }}", + "options": { + "response": { + "response": { + "fullResponse": true + } + }, + "timeout": 60000 + } + }, + "id": "a1c3d2f0-b5e0-4f40-85fd-79f147ec0009", + "name": "Call Robeing Gateway", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 1990, + 100 + ] + }, + { + "parameters": { + "jsCode": "const gatewayResponse = $json;\nconst request = $('Build Robeing Request').item.json;\nconst body = gatewayResponse.body || {};\nconst replyText = body.reply || body.response || body.message || body.text || body.answer || body.content || '';\nconst ok = gatewayResponse.statusCode >= 200 && gatewayResponse.statusCode < 300 && Boolean(replyText);\n\nreturn {\n channel: request.channel,\n thread_ts: request.thread_ts,\n success: ok,\n status_code: gatewayResponse.statusCode,\n text: ok ? replyText : '지금은 응답을 생성하지 못했습니다. 잠시 후 다시 시도해주세요.',\n raw_gateway_body: body,\n metadata: {\n user_uuid: request.user_uuid,\n robeing_id: request.robeing_id,\n source: 'slack',\n status_code: gatewayResponse.statusCode\n }\n};" + }, + "id": "a1c3d2f0-b5e0-4f40-85fd-79f147ec0010", + "name": "Parse Robeing Reply", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2240, + 100 + ] + }, + { + "parameters": { + "conditions": { + "boolean": [ + { + "value1": "={{ $json.success }}", + "value2": true + } + ] + } + }, + "id": "a1c3d2f0-b5e0-4f40-85fd-79f147ec0011", + "name": "Reply Ready?", + "type": "n8n-nodes-base.if", + "typeVersion": 2, + "position": [ + 2480, + 100 + ] + }, + { + "parameters": { + "jsCode": "return {\n channel: $json.channel,\n thread_ts: $json.thread_ts,\n text: $json.text,\n response_kind: 'agent_reply',\n metadata: $json.metadata\n};" + }, + "id": "a1c3d2f0-b5e0-4f40-85fd-79f147ec0012", + "name": "Build Slack Reply", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2720, + 20 + ] + }, + { + "parameters": { + "jsCode": "return {\n channel: $json.channel,\n thread_ts: $json.thread_ts,\n text: '로빙 응답 생성 중 오류가 발생했습니다. 잠시 후 다시 시도해주세요.',\n response_kind: 'agent_error',\n metadata: $json.metadata\n};" + }, + "id": "a1c3d2f0-b5e0-4f40-85fd-79f147ec0013", + "name": "Build Agent Error Reply", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 2720, + 180 + ] + }, + { + "parameters": { + "resource": "message", + "operation": "post", + "channel": "={{ $json.channel }}", + "text": "={{ $json.text }}", + "otherOptions": { + "threadTs": "={{ $json.thread_ts }}" + } + }, + "id": "a1c3d2f0-b5e0-4f40-85fd-79f147ec0014", + "name": "Reply to Slack", + "type": "n8n-nodes-base.slack", + "typeVersion": 2, + "position": [ + 2980, + 100 + ] + }, + { + "parameters": { + "jsCode": "return {\n skipped: true,\n reason: $json.skip_reason || 'ignored_event',\n original_event_ts: $json.event_ts,\n channel: $json.channel || null\n};" + }, + "id": "a1c3d2f0-b5e0-4f40-85fd-79f147ec0015", + "name": "Skip Event", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1030, + 380 + ] + } + ], + "connections": { + "Slack Trigger": { + "main": [ + [ + { + "node": "Normalize Slack Event", + "type": "main", + "index": 0 + } + ] + ] + }, + "Normalize Slack Event": { + "main": [ + [ + { + "node": "Should Process?", + "type": "main", + "index": 0 + } + ] + ] + }, + "Should Process?": { + "main": [ + [ + { + "node": "Get Slack User Mapping", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Skip Event", + "type": "main", + "index": 0 + } + ] + ] + }, + "Get Slack User Mapping": { + "main": [ + [ + { + "node": "Parse Mapping Response", + "type": "main", + "index": 0 + } + ] + ] + }, + "Parse Mapping Response": { + "main": [ + [ + { + "node": "Mapping Found?", + "type": "main", + "index": 0 + } + ] + ] + }, + "Mapping Found?": { + "main": [ + [ + { + "node": "Build Robeing Request", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Build Mapping Error Reply", + "type": "main", + "index": 0 + } + ] + ] + }, + "Build Mapping Error Reply": { + "main": [ + [ + { + "node": "Reply to Slack", + "type": "main", + "index": 0 + } + ] + ] + }, + "Build Robeing Request": { + "main": [ + [ + { + "node": "Call Robeing Gateway", + "type": "main", + "index": 0 + } + ] + ] + }, + "Call Robeing Gateway": { + "main": [ + [ + { + "node": "Parse Robeing Reply", + "type": "main", + "index": 0 + } + ] + ] + }, + "Parse Robeing Reply": { + "main": [ + [ + { + "node": "Reply Ready?", + "type": "main", + "index": 0 + } + ] + ] + }, + "Reply Ready?": { + "main": [ + [ + { + "node": "Build Slack Reply", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Build Agent Error Reply", + "type": "main", + "index": 0 + } + ] + ] + }, + "Build Slack Reply": { + "main": [ + [ + { + "node": "Reply to Slack", + "type": "main", + "index": 0 + } + ] + ] + }, + "Build Agent Error Reply": { + "main": [ + [ + { + "node": "Reply to Slack", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "pinData": {}, + "meta": { + "templateCredsSetupCompleted": true, + "instanceId": "robeing-docs-workflow" + } +}