Automatisation de l'évaluation des candidats avec le scoring GPT-4 et les notifications Gmail

Intermédiaire

Ceci est unHR, AI Summarizationworkflow d'automatisation du domainecontenant 12 nœuds.Utilise principalement des nœuds comme If, Set, Code, Gmail, Webhook. Automatisation de l'évaluation des candidats avec un score GPT-4 et des notifications Gmail

Prérequis
  • Compte Google et informations d'identification Gmail API
  • Point de terminaison HTTP Webhook (généré automatiquement par n8n)
  • Peut nécessiter les informations d'identification d'authentification de l'API cible
Aperçu du workflow
Visualisation des connexions entre les nœuds, avec support du zoom et du déplacement
Exporter le workflow
Copiez la configuration JSON suivante dans n8n pour importer et utiliser ce workflow
{
  "nodes": [
    {
      "id": "1",
      "name": "Soumission CV Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        240,
        300
      ],
      "parameters": {
        "path": "cv-received",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 1
    },
    {
      "id": "2",
      "name": "Note adhésive",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        140,
        180
      ],
      "parameters": {
        "width": 240,
        "height": 160,
        "content": "## Recruitment AI Config\n\n⚙️ **Customize scoring:**\n- Technical skills weights\n- Experience requirements\n- Education priorities\n- Cultural fit criteria"
      },
      "typeVersion": 1
    },
    {
      "id": "3",
      "name": "Exigences du poste",
      "type": "n8n-nodes-base.set",
      "position": [
        440,
        300
      ],
      "parameters": {
        "values": {
          "number": [
            {
              "name": "minExperience",
              "value": 5
            },
            {
              "name": "passingScore",
              "value": 75
            }
          ],
          "string": [
            {
              "name": "requiredSkills",
              "value": "JavaScript,React,Node.js,Python"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4",
      "name": "Analyse du CV avec IA",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        640,
        300
      ],
      "parameters": {
        "url": "https://api.openai.com/v1/chat/completions",
        "body": {
          "model": "gpt-4",
          "messages": [
            {
              "role": "system",
              "content": "You are a CV parsing expert. Extract key information from CVs and return structured JSON data."
            },
            {
              "role": "user",
              "content": "Parse this CV and extract: name, email, phone, skills, experience_years, education, previous_roles. CV content: {{ $json.cv_content }}"
            }
          ],
          "response_format": {
            "type": "json_object"
          }
        },
        "method": "POST",
        "headers": {
          "Content-Type": "application/json",
          "Authorization": "Bearer {{ $credentials.openai.apiKey }}"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5",
      "name": "Noter le candidat",
      "type": "n8n-nodes-base.code",
      "position": [
        840,
        300
      ],
      "parameters": {
        "jsCode": "// Intelligent candidate scoring algorithm\nconst candidate = $json.choices[0].message.content;\nconst requirements = $node['Job Requirements'].json;\nconst candidateData = JSON.parse(candidate);\n\nlet totalScore = 0;\n\n// Skills matching (40% weight)\nconst requiredSkills = requirements.requiredSkills.split(',');\nconst candidateSkills = candidateData.skills || [];\nconst skillsMatch = requiredSkills.filter(skill => \n  candidateSkills.some(cSkill => cSkill.toLowerCase().includes(skill.toLowerCase()))\n);\nconst skillsScore = (skillsMatch.length / requiredSkills.length) * 40;\ntotalScore += skillsScore;\n\n// Experience scoring (30% weight)\nconst experienceYears = candidateData.experience_years || 0;\nlet experienceScore = 0;\nif (experienceYears >= requirements.minExperience) {\n  experienceScore = 30;\n} else if (experienceYears >= requirements.minExperience * 0.8) {\n  experienceScore = 25;\n} else if (experienceYears >= requirements.minExperience * 0.6) {\n  experienceScore = 20;\n} else {\n  experienceScore = 10;\n}\ntotalScore += experienceScore;\n\n// Education scoring (20% weight)\nconst education = candidateData.education || '';\nlet educationScore = 0;\nif (education.toLowerCase().includes('master') || education.toLowerCase().includes('phd')) {\n  educationScore = 20;\n} else if (education.toLowerCase().includes('bachelor') || education.toLowerCase().includes('degree')) {\n  educationScore = 15;\n} else {\n  educationScore = 10;\n}\ntotalScore += educationScore;\n\n// Role relevance (10% weight)\nconst previousRoles = candidateData.previous_roles || [];\nconst roleRelevance = previousRoles.some(role => \n  role.toLowerCase().includes('engineer') || role.toLowerCase().includes('developer')\n) ? 10 : 5;\ntotalScore += roleRelevance;\n\n// Determine recommendation\nlet recommendation = 'reject';\nlet priority = 'low';\n\nif (totalScore >= 85) {\n  recommendation = 'hire';\n  priority = 'high';\n} else if (totalScore >= requirements.passingScore) {\n  recommendation = 'interview';\n  priority = 'medium';\n} else if (totalScore >= 60) {\n  recommendation = 'phone_screen';\n  priority = 'low';\n}\n\nreturn {\n  candidateData,\n  scoring: {\n    skillsScore,\n    experienceScore,\n    educationScore,\n    roleRelevance,\n    totalScore: Math.round(totalScore),\n    recommendation,\n    priority\n  },\n  jobTitle: requirements.jobTitle,\n  evaluatedAt: new Date().toISOString()\n};"
      },
      "typeVersion": 1
    },
    {
      "id": "6",
      "name": "Vérifier si candidat optimal",
      "type": "n8n-nodes-base.if",
      "position": [
        1040,
        200
      ],
      "parameters": {
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.scoring.recommendation }}",
              "rightValue": "hire"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "7",
      "name": "Alerter l'équipe RH",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1240,
        100
      ],
      "parameters": {
        "sendTo": "={{ $node['Job Requirements'].json.hrEmail }}",
        "message": "=<!DOCTYPE html>\n<html>\n<head>\n  <style>\n    body { font-family: Arial, sans-serif; margin: 20px; background-color: #f8f9fa; }\n    .container { max-width: 600px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; }\n    .top-candidate { background: linear-gradient(45deg, #28a745, #20c997); color: white; padding: 20px; text-align: center; margin: 20px 0; border-radius: 10px; }\n    .candidate-info { background: #d4edda; padding: 15px; margin: 15px 0; border-radius: 5px; }\n    .score-breakdown { background: #f8f9fa; padding: 15px; margin: 15px 0; border-radius: 5px; }\n    .cta { background: #007bff; color: white; padding: 15px 30px; text-decoration: none; border-radius: 5px; display: inline-block; margin: 20px 0; }\n  </style>\n</head>\n<body>\n  <div class=\"container\">\n    <div class=\"top-candidate\">\n      <h2>🌟 EXCEPTIONAL CANDIDATE</h2>\n      <p>High-priority candidate for {{ $json.jobTitle }}</p>\n    </div>\n    \n    <div class=\"candidate-info\">\n      <h3>👤 Candidate Profile</h3>\n      <p><strong>Name:</strong> {{ $json.candidateData.name }}</p>\n      <p><strong>Email:</strong> {{ $json.candidateData.email }}</p>\n      <p><strong>Phone:</strong> {{ $json.candidateData.phone }}</p>\n      <p><strong>Experience:</strong> {{ $json.candidateData.experience_years }} years</p>\n      <p><strong>Education:</strong> {{ $json.candidateData.education }}</p>\n    </div>\n    \n    <div class=\"score-breakdown\">\n      <h3>📊 Scoring Breakdown</h3>\n      <p><strong>Overall Score:</strong> {{ $json.scoring.totalScore }}/100</p>\n      <p><strong>Skills Match:</strong> {{ $json.scoring.skillsScore }}/40</p>\n      <p><strong>Experience:</strong> {{ $json.scoring.experienceScore }}/30</p>\n      <p><strong>Education:</strong> {{ $json.scoring.educationScore }}/20</p>\n      <p><strong>Role Relevance:</strong> {{ $json.scoring.roleRelevance }}/10</p>\n    </div>\n    \n    <div style=\"text-align: center;\">\n      <a href=\"mailto:{{ $json.candidateData.email }}\" class=\"cta\">📧 Contact Candidate</a>\n      <a href=\"https://calendly.com/interview-{{ $json.candidateData.name }}\" class=\"cta\">📅 Schedule Interview</a>\n    </div>\n    \n    <p style=\"color: #666; font-size: 14px; margin-top: 30px;\">\n      Recommendation: {{ $json.scoring.recommendation }} | Priority: {{ $json.scoring.priority }}\n    </p>\n  </div>\n</body>\n</html>",
        "options": {
          "contentType": "html"
        },
        "subject": "🌟 Top Candidate Alert - {{ $json.jobTitle }}"
      },
      "typeVersion": 1
    },
    {
      "id": "8",
      "name": "Vérifier si éligible à l'entretien",
      "type": "n8n-nodes-base.if",
      "position": [
        1040,
        300
      ],
      "parameters": {
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.scoring.recommendation }}",
              "rightValue": "interview"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "9",
      "name": "Envoyer l'invitation à l'entretien",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1240,
        300
      ],
      "parameters": {
        "sendTo": "={{ $json.candidateData.email }}",
        "message": "=<!DOCTYPE html>\n<html>\n<head>\n  <style>\n    body { font-family: Arial, sans-serif; margin: 20px; background-color: #f8f9fa; }\n    .container { max-width: 600px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; }\n    .interview-invite { background: #007bff; color: white; padding: 20px; text-align: center; margin: 20px 0; border-radius: 8px; }\n    .next-steps { background: #e8f4f8; padding: 15px; margin: 15px 0; border-radius: 5px; }\n    .cta { background: #28a745; color: white; padding: 15px 30px; text-decoration: none; border-radius: 5px; display: inline-block; margin: 20px 0; }\n  </style>\n</head>\n<body>\n  <div class=\"container\">\n    <div class=\"interview-invite\">\n      <h2>🎉 Interview Invitation</h2>\n      <p>Congratulations! We'd like to interview you for the {{ $json.jobTitle }} position.</p>\n    </div>\n    \n    <p>Dear {{ $json.candidateData.name }},</p>\n    \n    <p>We were impressed by your profile and would like to invite you for an interview.</p>\n    \n    <div class=\"next-steps\">\n      <h3>📅 Next Steps</h3>\n      <ul>\n        <li>Schedule your interview using the link below</li>\n        <li>Prepare for technical questions about your experience</li>\n        <li>Review our company culture and values</li>\n        <li>Prepare questions about the role and team</li>\n      </ul>\n    </div>\n    \n    <div style=\"text-align: center;\">\n      <a href=\"https://calendly.com/interview-{{ $json.candidateData.name }}\" class=\"cta\">\n        📅 Schedule Your Interview\n      </a>\n    </div>\n    \n    <p>Looking forward to meeting you!</p>\n    \n    <p style=\"color: #666; font-size: 14px; margin-top: 30px;\">\n      Best regards,<br>\n      HR Team\n    </p>\n  </div>\n</body>\n</html>",
        "options": {
          "contentType": "html"
        },
        "subject": "Interview Invitation - {{ $json.jobTitle }} Position"
      },
      "typeVersion": 1
    },
    {
      "id": "10",
      "name": "Vérifier si rejeté",
      "type": "n8n-nodes-base.if",
      "position": [
        1040,
        400
      ],
      "parameters": {
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.scoring.recommendation }}",
              "rightValue": "reject"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "11",
      "name": "Envoyer l'email de refus",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1240,
        400
      ],
      "parameters": {
        "sendTo": "={{ $json.candidateData.email }}",
        "message": "=<!DOCTYPE html>\n<html>\n<head>\n  <style>\n    body { font-family: Arial, sans-serif; margin: 20px; background-color: #f8f9fa; }\n    .container { max-width: 600px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; }\n    .thank-you { background: #6c757d; color: white; padding: 20px; text-align: center; margin: 20px 0; border-radius: 8px; }\n    .feedback { background: #f8f9fa; padding: 15px; margin: 15px 0; border-radius: 5px; }\n  </style>\n</head>\n<body>\n  <div class=\"container\">\n    <div class=\"thank-you\">\n      <h2>Thank You for Your Interest</h2>\n      <p>We appreciate you taking the time to apply for the {{ $json.jobTitle }} position.</p>\n    </div>\n    \n    <p>Dear {{ $json.candidateData.name }},</p>\n    \n    <p>Thank you for your application. While your background is impressive, we have decided to move forward with other candidates who more closely match our current requirements.</p>\n    \n    <div class=\"feedback\">\n      <h3>💡 For Future Opportunities</h3>\n      <p>We encourage you to:</p>\n      <ul>\n        <li>Continue developing your technical skills</li>\n        <li>Gain more relevant experience in your field</li>\n        <li>Apply for future positions that match your expertise</li>\n      </ul>\n    </div>\n    \n    <p>We'll keep your resume on file and will reach out if a suitable position becomes available.</p>\n    \n    <p style=\"color: #666; font-size: 14px; margin-top: 30px;\">\n      Best regards,<br>\n      HR Team\n    </p>\n  </div>\n</body>\n</html>",
        "options": {
          "contentType": "html"
        },
        "subject": "Thank you for your application - {{ $json.jobTitle }}"
      },
      "typeVersion": 1
    },
    {
      "id": "12",
      "name": "Note adhésive 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1140,
        60
      ],
      "parameters": {
        "width": 240,
        "height": 160,
        "content": "## AI-Powered Decisions\n\n🤖 **Automated actions:**\n- Top candidates: HR alert\n- Interview worthy: Auto-invite\n- Rejected: Polite decline\n- Phone screen: Initial contact"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "1": {
      "main": [
        [
          {
            "node": "3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3": {
      "main": [
        [
          {
            "node": "4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4": {
      "main": [
        [
          {
            "node": "5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5": {
      "main": [
        [
          {
            "node": "6",
            "type": "main",
            "index": 0
          },
          {
            "node": "8",
            "type": "main",
            "index": 0
          },
          {
            "node": "10",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6": {
      "main": [
        [
          {
            "node": "7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8": {
      "main": [
        [
          {
            "node": "9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "10": {
      "main": [
        [
          {
            "node": "11",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Foire aux questions

Comment utiliser ce workflow ?

Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.

Dans quelles scénarios ce workflow est-il adapté ?

Intermédiaire - Ressources Humaines, Résumé IA

Est-ce payant ?

Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.

Informations sur le workflow
Niveau de difficulté
Intermédiaire
Nombre de nœuds12
Catégorie2
Types de nœuds7
Description de la difficulté

Adapté aux utilisateurs expérimentés, avec des workflows de complexité moyenne contenant 6-15 nœuds

Liens externes
Voir sur n8n.io

Partager ce workflow

Catégories

Catégories: 34