Slack候補者評価のためのAI駆動チャットボット構築

上級

これはAI Chatbot, Multimodal AI分野の自動化ワークフローで、29個のノードを含みます。主にIf, Code, Slack, Webhook, GoogleDriveなどのノードを使用。 AI履歴書分析と候補者評価:SlackとGoogleスプレッドシートの統合

前提条件
  • Slack Bot Token または Webhook URL
  • HTTP Webhookエンドポイント(n8nが自動生成)
  • Google Drive API認証情報
  • ターゲットAPIの認証情報が必要な場合あり
  • Google Sheets API認証情報
  • OpenAI API Key
ワークフロープレビュー
ノード接続関係を可視化、ズームとパンをサポート
ワークフローをエクスポート
以下のJSON設定をn8nにインポートして、このワークフローを使用できます
{
  "id": "u6seZCMlUCt4sZqF",
  "meta": {
    "instanceId": "4a2e6764ba7a6bc9890d9225f4b21d570ce88fc9bd57549c89057fcee58fed0f",
    "templateId": "1961",
    "templateCredsSetupCompleted": true
  },
  "name": "Building an AI-Powered Chatbot for Candidate Evaluation on Slack",
  "tags": [],
  "nodes": [
    {
      "id": "97989831-3fc6-4954-ac55-8e0950081b7a",
      "name": "Is user message?",
      "type": "n8n-nodes-base.if",
      "position": [
        -3312,
        880
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1def7344-ce55-450d-a85a-468f746fe31f",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.body.event.type }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "afa6b192-1e25-46b6-8fdc-81dff9a37e74",
      "name": "操作なし, do nothing",
      "type": "n8n-nodes-base.noOp",
      "position": [
        -3088,
        976
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "4a7ec607-1706-4357-aa89-4c44faa98fb8",
      "name": "Webhook トリガー",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -3536,
        880
      ],
      "webhookId": "db3bf3da-b9b7-4823-8c5d-14f5de0272da",
      "parameters": {
        "path": "slack-gilfoyle",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "lastNode"
      },
      "typeVersion": 2
    },
    {
      "id": "04301600-3371-4fba-b2a6-509bfd3809f9",
      "name": "ファイルから抽出",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -2640,
        688
      ],
      "parameters": {
        "options": {},
        "operation": "pdf",
        "binaryPropertyName": "=data"
      },
      "typeVersion": 1
    },
    {
      "id": "1f49b4bf-5a06-42cc-8566-440639d15aeb",
      "name": "Download Candidate Profile From Slack",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -2864,
        688
      ],
      "parameters": {
        "url": "={{ $json.body.event.files[0].url_private_download }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        },
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "slackOAuth2Api"
      },
      "credentials": {
        "slackOAuth2Api": {
          "id": "4JSKt9sIRV1KGswQ",
          "name": "Slack account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "04940f53-05e2-4dbb-8bbe-2c6104cf978b",
      "name": "json parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        -2160,
        912
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"AppliedPosition\": \"Position Name\",\n  \"JobDescription\": \"Job Description URL\",\n  \"Profile\": {\n    \"full_name\": \"\",\n    \"job_title\": \"\",\n    \"summary\": \"\",\n    \"contact\": {\n      \"email\": \"\",\n      \"phone\": \"\",\n      \"address\": \"\",\n      \"linkedin\": \"\",\n      \"website\": \"\"\n    },\n    \"education\": [\n      {\n        \"degree\": \"\",\n        \"field_of_study\": \"\",\n        \"institution\": \"\",\n        \"location\": \"\",\n        \"start_year\": \"\",\n        \"end_year\": \"\"\n      }\n    ],\n    \"certifications\": [\n      {\n        \"name\": \"\",\n        \"issuer\": \"\",\n        \"date_obtained\": \"\",\n        \"expiration_date\": \"\"\n      }\n    ],\n    \"work_experience\": [\n      {\n        \"company\": \"\",\n        \"position\": \"\",\n        \"location\": \"\",\n        \"start_date\": \"\",\n        \"end_date\": \"\",\n        \"responsibilities\": [\n          \"\"\n        ],\n        \"achievements\": [\n          \"\"\n        ]\n      }\n    ],\n    \"skills\": {\n      \"technical_skills\": [\n        \"\"\n      ],\n      \"soft_skills\": [\n        \"\"\n      ],\n      \"languages\": [\n        {\n          \"language\": \"\",\n          \"proficiency\": \"\"\n        }\n      ],\n      \"tools_and_technologies\": [\n        \"\"\n      ]\n    },\n    \"projects\": [\n      {\n        \"name\": \"\",\n        \"description\": \"\",\n        \"technologies_used\": [\n          \"\"\n        ],\n        \"role\": \"\",\n        \"duration\": \"\"\n      }\n    ],\n    \"awards\": [\n      {\n        \"title\": \"\",\n        \"issuer\": \"\",\n        \"date\": \"\",\n        \"description\": \"\"\n      }\n    ],\n    \"volunteer_experience\": [\n      {\n        \"organization\": \"\",\n        \"role\": \"\",\n        \"description\": \"\",\n        \"start_date\": \"\",\n        \"end_date\": \"\"\n      }\n    ],\n    \"additional_information\": {\n      \"availability\": \"\",\n      \"preferred_location\": \"\",\n      \"salary_expectation\": \"\",\n      \"work_authorization\": \"\",\n      \"other_notes\": \"\"\n    }\n  }\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "0609ac69-6003-4948-a847-d6e3fcb326da",
      "name": "gpt4-1 model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -2416,
        912
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "PPSwAKeLQYgAPobT",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "7091e495-668b-4fed-a5f9-de2333908a3d",
      "name": "Download file",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -1952,
        688
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "url",
          "value": "={{ $json.output.JobDescription }}"
        },
        "options": {},
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "fC471es5gk5Mm900",
          "name": "Google Drive account"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "d3067e57-7b79-4dff-bbdd-31ae43228a34",
      "name": "Extract Job Description",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -1728,
        688
      ],
      "parameters": {
        "options": {},
        "operation": "pdf"
      },
      "typeVersion": 1
    },
    {
      "id": "cc30fbc4-c777-4556-a89c-3d782bedc7cf",
      "name": "HR Expert エージェント",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        -1504,
        688
      ],
      "parameters": {
        "text": "=Evaluate the candidate for the following job:\n\n--- Job Description ---\nPosition: {{ $('Profile Analyzer Agent').item.json.output.AppliedPosition }}\nJob Description: {{ $('Extract Job Description').item.json.text }}\n------------------------\n\nBelow is the extracted candidate profile:\n{{ $('Profile Analyzer Agent').item.json.output.Profile.toJsonString() }}",
        "messages": {
          "messageValues": [
            {
              "message": "You are a professional AI hiring assistant tasked with evaluating job candidates based on their structured resume data and a provided job description. Your goal is to assess the candidate’s suitability for the role, identifying key matches and gaps in skills, experience, and qualifications.  You will receive: - `candidate_profile`: a JSON object containing extracted information from the candidate's resume. - `job_description`: a plain text description of the role.  Your job is to: 1. Parse and understand the key job requirements (e.g., required skills, years of experience, qualifications). 2. Match the candidate's profile to the job requirements. 3. Provide a structured evaluation with ratings and reasoning.  Always be objective, use professional language, and format your output clearly using markdown."
            }
          ]
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.5
    },
    {
      "id": "9e39fb8d-e66b-4767-a04b-c35a5cbd37f7",
      "name": "Profile Analyzer エージェント",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -2384,
        688
      ],
      "parameters": {
        "text": "=Please extract all relevant information from this candiadte:\nCV Content:\n===\n{{ $json[\"text\"] }}\n===\nAnd extract applied position from message below:\n{{ $('Webhook').item.json.body.event.text }}\nGiven the tool to get postions from google sheet, conclude final applied position name follw name in the sheet and the job description URL",
        "options": {
          "systemMessage": "You are a smart and reliable assistant for the HR team. Your job is to help evaluate job applicants by processing two main inputs:\n\n1. The candidate’s **user profile** (provided as a block of plain text).\n2. The **request message** (typically a short Slack or email message from a recruiter asking for evaluation).\n\nYou also have access to a **Google Sheets tool** containing a table that maps position names (e.g., \"AI Engineer\") to job details such as:\n- Job title\n- Job description URL\n\n---\n\nYour task is to:\n1. Parse and extract the **candidate’s name, email (if any), and core skills or summary** from the user profile.\n2. From the request message, identify the **applied position**.\n3. Use the Sheets tool to look up and return:\n   - The **applied position** (standardized from the sheet)\n   - The corresponding **Job Description URL**\n\n---\n\nOutput Format:\n- **Candidate Profile**: [Parsed name, email, and summary from resume]\n- **Applied Position**: [From sheet, matched using request message]\n- **Job Description URL**: [From sheet, based on position]\n\nIf the job title from the request is unclear or not found, return a helpful clarification message instead of making assumptions.\n\n---\n\nBe concise, structured, and ensure accurate matching when referencing job titles from the sheet."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "executeOnce": true,
      "typeVersion": 2.1
    },
    {
      "id": "3b996554-5e83-4ffe-9142-f52883e15573",
      "name": "Update evaluation sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -880,
        784
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "overall_fit_score",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "overall_fit_score",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "recommendation",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "recommendation",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "required_experience",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "required_experience",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "skill_match",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "skill_match",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "education_certifications",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "education_certifications",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "soft_skills_traits",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "soft_skills_traits",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "strengths",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "strengths",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "concerns_or_gaps",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "concerns_or_gaps",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "final_notes",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "final_notes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [
            "output"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/1gpuTL7iK2LoDJAdHE-LBFiBEU6hLqSTxWjThMJyi7SY/edit?usp=drive_link"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "L670Nly6gZGo71br",
          "name": "Google Sheets account 2"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "2f406e89-d1d9-458a-839a-f9c612184714",
      "name": "Map Columns",
      "type": "n8n-nodes-base.code",
      "position": [
        -1104,
        688
      ],
      "parameters": {
        "jsCode": "const evalResult = $input.first().json.output\nreturn [\n  {\n    json: {\n      full_name: $('Profile Analyzer Agent').first().json.output.Profile.full_name,\n      email: $('Profile Analyzer Agent').first().json.output.Profile.contact.email || \"Email not available\",\n      phone: $('Profile Analyzer Agent').first().json.output.Profile.contact.phone ||  \"Phone not available\",\n      position: $('Profile Analyzer Agent').first().json.output.AppliedPosition,\n      overall_fit_score: evalResult.overall_fit_score,\n      recommendation: evalResult.recommendation,\n      strengths: evalResult.strengths.join(', '),\n      concerns_or_gaps: evalResult.concerns_or_gaps.join(', '),\n      final_notes: evalResult.final_notes,\n      submitted_date: $now.toFormat(\"yyyyLLdd-HHmmss\")\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "14ddc37b-9286-46a8-bdeb-d333db447d24",
      "name": "gpt-4-1 model 2",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -1472,
        912
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "PPSwAKeLQYgAPobT",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "74430118-e4d3-4966-8703-c2ffa483b895",
      "name": "json parser 2",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        -1344,
        912
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"overall_fit_score\": 0,\n  \"recommendation\": \"\", \n  \"job_match_summary\": {\n    \"required_experience\": \"\",\n    \"skill_match\": \"\",\n    \"education_certifications\": \"\",\n    \"soft_skills_traits\": \"\"\n  },\n  \"strengths\": [\n    \"\"\n  ],\n  \"concerns_or_gaps\": [\n    \"\"\n  ],\n  \"final_notes\": \"\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "83a9bea2-1012-4ad6-a6db-145c74086b30",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        -3088,
        784
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "aa58b881-6e48-488b-a96c-9a85b1504a6e",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.body.event.files[0].id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "d8a4b76d-1bbd-4fee-b024-ffa824829558",
      "name": "Send result in the mentioned channel",
      "type": "n8n-nodes-base.slack",
      "position": [
        -656,
        592
      ],
      "webhookId": "6d1ea29f-86ba-42df-ae9f-3dd510510dae",
      "parameters": {
        "text": "=🎯 *Candidate Evaluation Update*\n\nHi <@{{ $json.id }}>,  \nWe've completed the initial screening and have a qualified candidate for the {{ $('Map Columns').item.json.position }} position:\n\n👤 *Candidate:* {{ $('Map Columns').item.json.full_name }}\n📝 *Summary:*  \n• *Fit Score:* {{ $('Map Columns').item.json.overall_fit_score }}/10  \n• *Recommendation:* {{ $('Map Columns').item.json.recommendation }}\n• *Key Strengths:* {{ $('Map Columns').item.json.strengths }}\n👉 Please advise on next steps (e.g., schedule technical interview, team round, etc.).",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Webhook').item.json.body.event.channel }}"
        },
        "otherOptions": {
          "mrkdwn": true
        }
      },
      "credentials": {
        "slackApi": {
          "id": "Yi3LKjrxH5dH4v1r",
          "name": "BOT Token"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "e41b4a81-7feb-45df-bbe8-ad006e6ebdb8",
      "name": "Inform user that profile is missing",
      "type": "n8n-nodes-base.slack",
      "position": [
        -2864,
        880
      ],
      "webhookId": "6d1ea29f-86ba-42df-ae9f-3dd510510dae",
      "parameters": {
        "text": "=🗂️ Got it — just one more thing!\nI can help read the candidate profile you mentioned, but it looks like I didn’t catch the file in your last message.\n👉 Please upload the file first, wait for it to finish uploading, and then press Enter to send your message.\nThat way, I can grab the profile and help you out right away! 😊",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Webhook').item.json.body.event.channel }}"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "id": "Yi3LKjrxH5dH4v1r",
          "name": "BOT Token"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "64818e9c-f6d3-4b05-8297-b7b9089044ca",
      "name": "Query available positions",
      "type": "n8n-nodes-base.googleSheetsTool",
      "position": [
        -2288,
        912
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/15CZPMbxmz-RVYji1fev_6vYeEwpPa3MjewGEPf6aSoA/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "15CZPMbxmz-RVYji1fev_6vYeEwpPa3MjewGEPf6aSoA",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/15CZPMbxmz-RVYji1fev_6vYeEwpPa3MjewGEPf6aSoA/edit?usp=drivesdk",
          "cachedResultName": "Positions"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "L670Nly6gZGo71br",
          "name": "Google Sheets account 2"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "64560334-5db8-4d2d-b5e7-ad4b865cb0bd",
      "name": "Get information about a user",
      "type": "n8n-nodes-base.slack",
      "position": [
        -880,
        592
      ],
      "webhookId": "5299729f-620c-4984-80be-001f1d7e9740",
      "parameters": {
        "user": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Webhook').item.json.body.event.files[0].user }}"
        },
        "resource": "user",
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "id": "4JSKt9sIRV1KGswQ",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "7e1f48d9-ae9c-43e2-ae89-09d207e3a33f",
      "name": "付箋",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4672,
        -224
      ],
      "parameters": {
        "color": 4,
        "width": 1056,
        "height": 2432,
        "content": "# Building an AI-Powered Chatbot for Candidate Evaluation on Slack\n[![Watch the video](https://wisestackai.s3.ap-southeast-1.amazonaws.com/building-an-ai-powered-chatbot-for-candidate-evaluation-on-slack.jpg)](https://www.youtube.com/watch?v=NAn5BSr15Ks)\n> This workflow connects a Slack chatbot with AI agents and Google Sheets to automate candidate resume evaluation. It extracts resume details, identifies the applied job from the message, fetches the correct job description, and provides a summarized evaluation via Slack and tracking sheet. Perfect for HR teams using Slack.\n\n## **Who’s it for**\nThis workflow is designed for:\n- **HR Teams**, **Recruiters**, and **Hiring Managers**  \n- Working in software or tech companies using **Slack**, **Google Sheets**, and **n8n**\n- Who want to **automate candidate evaluation** based on uploaded profiles and applied job positions\n\n## **How it works / What it does**\nThis workflow is triggered when a **Slack user mentions the HR bot** and attaches a **candidate profile PDF**.\nThe workflow performs the following steps:\n1. **Trigger from Slack Mention**  \n   - A user mentions the bot in Slack with a message like:  \n     `@HRBot Please evaluate this candidate for the AI Engineer role.`  \n     (with PDF attached)\n2. **Input Validation**  \n   - If no file is attached, the bot replies:  \n     _\"Please upload the candidate profile file before sending the message.\"_\n3. **Extract Candidate Profile**  \n   - Downloads the attached PDF from Slack  \n   - Uses `Extract from File` to parse the resume into text\n4. **Profile Analysis (AI Agent)**  \n   - Sends the resume text and message to the `Profile Analyzer Agent`\n   - Identifies:\n     - Candidate name, email, and summary\n     - Applied position (from message)\n   - Looks up the **Job Description PDF URL** using Google Sheets\n5. **Job Description Retrieval**  \n   - Downloads and parses the matching JD PDF\n6. **HR Evaluation (AI Agent)**  \n   - Sends both the **candidate profile** and **job description** to `HR Expert Agent`\n   - Receives a summarized **fit evaluation** and insights\n7. **Output and Logging**  \n   - Sends evaluation result back to Slack in the original thread  \n   - Updates a **Google Sheet** with evaluation data for tracking\n\n## **How to set up**\n1. **Slack Setup**\n   - Create a Slack bot and install it into your workspace\n   - Enable the `app_mention` event and generate a **bot token**\n   - Connect Slack to n8n using **Slack Bot credentials**\n2. **Google Sheets Setup**\n   - Create a sheet mapping `Position Title → Job Description URL`\n   - Create another sheet for logging evaluation results\n3. **n8n Setup**\n   - Add a **Webhook Trigger** for Slack mentions\n   - Connect Slack, Google Sheets, and GPT-4 credentials\n   - Set up agents (`Profile Analyzer Agent`, `HR Expert Agent`) with appropriate prompts\n4. **Deploy & Test**\n   - Mention your bot in Slack with a message and file\n   - Confirm the reply and entry in the evaluation tracking sheet\n\n## **Requirements**\n\n- n8n (self-hosted or cloud)\n- Slack App with Bot Token\n- OpenAI or Azure OpenAI account (for GPT-4)\n- Google Sheets (2 sheets: job mapping + evaluation log)\n- Candidate profiles in PDF format\n- Defined job titles and descriptions\n\n## **How to customize the workflow**\n\nYou can easily adapt this workflow to your team’s needs:\n| Customization Area       | How to Customize                                                                 |\n|--------------------------|----------------------------------------------------------------------------------|\n| Job Mapping Source       | Replace Google Sheet with Airtable or Notion DB                                 |\n| JD Format                | Use Markdown or inline descriptions instead of PDF                              |\n| Evaluation Output Format | Change from Slack message to Email or Notion update                             |\n| HR Agent Prompt          | Customize to match your company tone or include scoring rubrics                 |\n| Language Support         | Add support for bilingual input/output (e.g., Vietnamese & English)             |\n| Workflow Trigger         | Trigger from slash command or form instead of `@mention`                        |"
      },
      "typeVersion": 1
    },
    {
      "id": "9f5d8dfa-905b-4593-b75d-82d4cb826106",
      "name": "付箋1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3616,
        1040
      ],
      "parameters": {
        "width": 272,
        "height": 192,
        "content": "### 1. 🚀 Trigger on Slack Mention\nWhen a Slack user mentions the HR bot and includes a message (e.g. “Please evaluate this candidate for the AI Engineer role”) along with an attached PDF resume, the workflow is triggered via webhook."
      },
      "typeVersion": 1
    },
    {
      "id": "69148cf4-dff4-417d-acf6-a506deadee53",
      "name": "付箋2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3296,
        1136
      ],
      "parameters": {
        "width": 384,
        "height": 128,
        "content": "### 2. 🧾 Validate Input\nThe workflow checks if a file (PDF) is attached. If not, it sends a friendly message back to the user, asking them to upload the resume before sending the request."
      },
      "typeVersion": 1
    },
    {
      "id": "9aba6130-c3b5-4045-8ec1-09ae606f2263",
      "name": "付箋3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2880,
        528
      ],
      "parameters": {
        "width": 352,
        "height": 128,
        "content": "### 3. 📥 Download and Extract Resume\nThe bot downloads the attached PDF resume and uses the `Extract from File` module to convert the document into readable plain text.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "22361750-c673-49e7-927e-e9551724abc1",
      "name": "付箋4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2432,
        416
      ],
      "parameters": {
        "width": 336,
        "height": 240,
        "content": "### 4. 🧠 Analyze Profile (AI Agent)\nThe extracted resume text and user request message are sent to the **Profile Analyzer Agent**, which:\n- Extracts candidate details (name, email, skills, summary)\n- Identifies the **applied job position** from the message\n- Queries a Google Sheet to retrieve the corresponding **Job Description URL**"
      },
      "typeVersion": 1
    },
    {
      "id": "f47d2b7d-00fb-409a-93e6-3d16c65ad918",
      "name": "付箋5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1952,
        880
      ],
      "parameters": {
        "width": 336,
        "height": 128,
        "content": "### 5. 📄 Fetch and Extract Job Description\nUsing the matched Job Description URL from the Google Sheet, the workflow downloads and parses the JD PDF into plain text."
      },
      "typeVersion": 1
    },
    {
      "id": "81d73e30-1b8b-48dc-9fd8-495c2b8a6cee",
      "name": "付箋6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1552,
        480
      ],
      "parameters": {
        "width": 368,
        "content": "### 6. 👩‍💼 Evaluate Candidate (HR Expert Agent)\nThe candidate profile and job description are passed to the **HR Expert Agent**, which:\n- Assesses the fit between the resume and job description\n- Outputs a summary evaluation and insights"
      },
      "typeVersion": 1
    },
    {
      "id": "b1443b1d-e175-4e01-ba34-2002ae23b740",
      "name": "付箋7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -880,
        416
      ],
      "parameters": {
        "width": 272,
        "height": 144,
        "content": "### 7. 📤 Send Results via Slack\nThe evaluation result is posted back to the **Slack thread** where the request originated, notifying the original user with a clean and readable summary."
      },
      "typeVersion": 1
    },
    {
      "id": "5c9af46b-bcf2-403f-a67b-bdf4b3ce9f2d",
      "name": "付箋8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -896,
        960
      ],
      "parameters": {
        "width": 288,
        "height": 128,
        "content": "### 8. 📊 Log to Google Sheet\nThe evaluation result, along with candidate and job data, is saved into a **Google Sheet** for internal tracking, auditing, or reporting purposes."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {},
  "versionId": "862307b9-766b-4c14-bd23-46de364fff6c",
  "connections": {
    "83a9bea2-1012-4ad6-a6db-145c74086b30": {
      "main": [
        [
          {
            "node": "1f49b4bf-5a06-42cc-8566-440639d15aeb",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "e41b4a81-7feb-45df-bbe8-ad006e6ebdb8",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "97989831-3fc6-4954-ac55-8e0950081b7a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2f406e89-d1d9-458a-839a-f9c612184714": {
      "main": [
        [
          {
            "node": "3b996554-5e83-4ffe-9142-f52883e15573",
            "type": "main",
            "index": 0
          },
          {
            "node": "64560334-5db8-4d2d-b5e7-ad4b865cb0bd",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "04940f53-05e2-4dbb-8bbe-2c6104cf978b": {
      "ai_outputParser": [
        [
          {
            "node": "Profile Analyzer Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "0609ac69-6003-4948-a847-d6e3fcb326da": {
      "ai_languageModel": [
        [
          {
            "node": "Profile Analyzer Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "7091e495-668b-4fed-a5f9-de2333908a3d": {
      "main": [
        [
          {
            "node": "d3067e57-7b79-4dff-bbdd-31ae43228a34",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "74430118-e4d3-4966-8703-c2ffa483b895": {
      "ai_outputParser": [
        [
          {
            "node": "HR Expert Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "HR Expert Agent": {
      "main": [
        [
          {
            "node": "2f406e89-d1d9-458a-839a-f9c612184714",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "14ddc37b-9286-46a8-bdeb-d333db447d24": {
      "ai_languageModel": [
        [
          {
            "node": "HR Expert Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "97989831-3fc6-4954-ac55-8e0950081b7a": {
      "main": [
        [
          {
            "node": "83a9bea2-1012-4ad6-a6db-145c74086b30",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract from File": {
      "main": [
        [
          {
            "node": "Profile Analyzer Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Profile Analyzer Agent": {
      "main": [
        [
          {
            "node": "7091e495-668b-4fed-a5f9-de2333908a3d",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "d3067e57-7b79-4dff-bbdd-31ae43228a34": {
      "main": [
        [
          {
            "node": "HR Expert Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "64818e9c-f6d3-4b05-8297-b7b9089044ca": {
      "ai_tool": [
        [
          {
            "node": "Profile Analyzer Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "64560334-5db8-4d2d-b5e7-ad4b865cb0bd": {
      "main": [
        [
          {
            "node": "d8a4b76d-1bbd-4fee-b024-ffa824829558",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "d8a4b76d-1bbd-4fee-b024-ffa824829558": {
      "main": [
        []
      ]
    },
    "1f49b4bf-5a06-42cc-8566-440639d15aeb": {
      "main": [
        [
          {
            "node": "Extract from File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
よくある質問

このワークフローの使い方は?

上記のJSON設定コードをコピーし、n8nインスタンスで新しいワークフローを作成して「JSONからインポート」を選択、設定を貼り付けて認証情報を必要に応じて変更してください。

このワークフローはどんな場面に適していますか?

上級 - AIチャットボット, マルチモーダルAI

有料ですか?

このワークフローは完全無料です。ただし、ワークフローで使用するサードパーティサービス(OpenAI APIなど)は別途料金が発生する場合があります。

ワークフロー情報
難易度
上級
ノード数29
カテゴリー2
ノードタイプ15
難易度説明

上級者向け、16ノード以上の複雑なワークフロー

作成者
Trung Tran

Trung Tran

@trungtran

Empowering small and medium businesses with smart automation and practical AI, no big tech team required.

外部リンク
n8n.ioで表示

このワークフローを共有

カテゴリー

カテゴリー: 34