AutomationFlowsAI & RAG › AI Resume Screening Workflow

AI Resume Screening Workflow

AI Resume Screening Workflow. Uses openAi, emailSend, httpRequest, postgres. Webhook trigger; 14 nodes.

Webhook trigger★★★★☆ complexityAI-powered14 nodesOpenAIEmail SendHTTP RequestPostgresEmail Read Imap
AI & RAG Trigger: Webhook Nodes: 14 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Emailreadimap → Emailsend recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "AI Resume Screening Workflow",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "resume-screening",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "node-webhook-trigger",
      "name": "Resume Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        100,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.event }}",
              "operation": "equal",
              "value2": "new_candidate"
            }
          ]
        }
      },
      "id": "node-check-event",
      "name": "Validate Event",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        320,
        300
      ]
    },
    {
      "parameters": {
        "resource": "chat",
        "model": "gpt-4o",
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are an expert HR assistant. Analyze candidate profiles and provide actionable insights for recruiters. Be concise and professional. Respond with valid JSON only."
            },
            {
              "role": "user",
              "content": "=Generate a recruiter briefing for this candidate:\n\nName: {{ $json.candidate.name }}\nScore: {{ $json.candidate.score }}/100\nRecommendation: {{ $json.candidate.recommendation }}\nPosition: {{ $json.job?.title || 'Open Position' }}\n\nProvide a JSON response with:\n{\n  \"subject\": \"concise email subject line\",\n  \"briefing\": \"2-3 sentences professional briefing for the recruiter\",\n  \"priority\": \"high|medium|low\",\n  \"next_action\": \"specific recommended next step\"\n}"
            }
          ]
        },
        "options": {
          "temperature": 0.3,
          "responseFormat": "json_object"
        }
      },
      "id": "node-openai-briefing",
      "name": "AI Recruiter Briefing",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.3,
      "position": [
        540,
        200
      ],
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Parse AI briefing and prepare notification data\nconst webhook = $('Resume Webhook').first().json;\nlet briefing = {};\n\ntry {\n  const aiContent = $('AI Recruiter Briefing').first().json?.message?.content || '{}';\n  briefing = JSON.parse(aiContent);\n} catch (e) {\n  briefing = {\n    subject: `New Application: ${webhook.candidate?.name}`,\n    briefing: `${webhook.candidate?.name} applied with a score of ${webhook.candidate?.score}/100.`,\n    priority: webhook.candidate?.score >= 75 ? 'high' : webhook.candidate?.score >= 50 ? 'medium' : 'low',\n    next_action: 'Review candidate profile in the dashboard'\n  };\n}\n\nconst scoreColor = webhook.candidate?.score >= 75 ? '#22c55e' :\n                   webhook.candidate?.score >= 50 ? '#f59e0b' : '#ef4444';\n\nconst recommendationLabel = {\n  'strong_yes': 'Strong Yes',\n  'yes': 'Yes',\n  'maybe': 'Maybe',\n  'no': 'No'\n}[webhook.candidate?.recommendation] || 'N/A';\n\nreturn [{\n  json: {\n    candidate_id: webhook.candidate_id,\n    candidate_name: webhook.candidate?.name,\n    candidate_email: webhook.candidate?.email,\n    score: webhook.candidate?.score,\n    recommendation: webhook.candidate?.recommendation,\n    recommendation_label: recommendationLabel,\n    job_title: webhook.job?.title || 'Open Position',\n    score_color: scoreColor,\n    briefing: briefing.briefing,\n    subject: briefing.subject,\n    priority: briefing.priority,\n    next_action: briefing.next_action,\n    dashboard_url: `${$env.APP_URL || 'http://localhost:3000'}/dashboard.html`,\n    timestamp: new Date().toISOString()\n  }\n}];"
      },
      "id": "node-prepare-data",
      "name": "Prepare Notification",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        760,
        200
      ]
    },
    {
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{ $json.score }}",
              "operation": "largerEqual",
              "value2": 60
            }
          ]
        }
      },
      "id": "node-score-check",
      "name": "High Score?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        980,
        200
      ]
    },
    {
      "parameters": {
        "fromEmail": "={{ $env.EMAIL_FROM || 'ai-screening@company.com' }}",
        "toEmail": "={{ $env.RECRUITER_EMAIL || 'recruiter@company.com' }}",
        "subject": "=[{{ $json.priority === 'high' ? 'HIGH' : $json.priority === 'medium' ? 'MEDIUM' : 'LOW' }}] {{ $json.subject }}",
        "emailType": "html",
        "html": "=<!DOCTYPE html>\n<html>\n<head>\n<meta charset='utf-8'>\n<style>\nbody { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; margin: 0; background: #f8fafc; }\n.container { max-width: 580px; margin: 30px auto; background: white; border-radius: 16px; overflow: hidden; box-shadow: 0 4px 20px rgba(0,0,0,0.08); }\n.header { background: linear-gradient(135deg, #1e293b 0%, #334155 100%); padding: 28px 32px; }\n.header h1 { color: white; margin: 0; font-size: 20px; font-weight: 700; }\n.header p { color: #94a3b8; margin: 4px 0 0; font-size: 13px; }\n.body { padding: 28px 32px; }\n.score-big { font-size: 56px; font-weight: 900; color: {{ $json.score_color }}; line-height: 1; }\n.score-label { color: #94a3b8; font-size: 12px; margin-top: 4px; text-transform: uppercase; letter-spacing: 1px; }\n.info-row { display: flex; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid #f1f5f9; }\n.info-label { color: #94a3b8; font-size: 13px; }\n.info-value { color: #1e293b; font-size: 13px; font-weight: 600; }\n.briefing { background: #f8fafc; border-left: 4px solid #6366f1; padding: 14px 16px; border-radius: 0 8px 8px 0; color: #475569; font-size: 14px; line-height: 1.6; margin: 16px 0; }\n.action-box { background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 10px; padding: 14px; margin: 16px 0; }\n.action-box p { color: #1d4ed8; font-size: 13px; margin: 0; font-weight: 500; }\n.btn { display: inline-block; background: linear-gradient(135deg, #6366f1, #8b5cf6); color: white; padding: 12px 28px; border-radius: 8px; text-decoration: none; font-weight: 600; font-size: 14px; margin-top: 16px; }\n.footer { background: #f8fafc; padding: 16px 32px; text-align: center; border-top: 1px solid #e2e8f0; }\n.footer p { color: #94a3b8; font-size: 11px; margin: 2px 0; }\n.badge { display: inline-block; padding: 4px 12px; border-radius: 20px; font-size: 12px; font-weight: 600; background: {{ $json.score >= 75 ? 'rgba(34,197,94,0.15)' : $json.score >= 50 ? 'rgba(245,158,11,0.15)' : 'rgba(239,68,68,0.15)' }}; color: {{ $json.score_color }}; }\n</style>\n</head>\n<body>\n<div class='container'>\n  <div class='header'>\n    <h1>New Candidate Alert</h1>\n    <p>AI Resume Screening System - n8n Workflow</p>\n  </div>\n  <div class='body'>\n    <div style='display:flex;align-items:flex-start;gap:24px;margin-bottom:24px;'>\n      <div>\n        <div class='score-big'>{{ $json.score }}</div>\n        <div class='score-label'>AI Score / 100</div>\n        <div class='badge' style='margin-top:8px;'>{{ $json.recommendation_label }}</div>\n      </div>\n      <div style='flex:1;'>\n        <h2 style='margin:0 0 4px;color:#1e293b;font-size:20px;font-weight:700;'>{{ $json.candidate_name }}</h2>\n        <p style='margin:0;color:#64748b;font-size:14px;'>{{ $json.candidate_email }}</p>\n        <p style='margin:8px 0 0;color:#64748b;font-size:13px;'>Applied for: <strong>{{ $json.job_title }}</strong></p>\n      </div>\n    </div>\n    <div class='info-row'>\n      <span class='info-label'>Priority</span>\n      <span class='info-value'>{{ $json.priority === 'high' ? 'High' : $json.priority === 'medium' ? 'Medium' : 'Low' }}</span>\n    </div>\n    <div class='info-row'>\n      <span class='info-label'>Received</span>\n      <span class='info-value'>{{ new Date($json.timestamp).toLocaleString() }}</span>\n    </div>\n    <div class='briefing'>{{ $json.briefing }}</div>\n    <div class='action-box'>\n      <p>Recommended Action: {{ $json.next_action }}</p>\n    </div>\n    <a href='{{ $json.dashboard_url }}' class='btn'>View Full Profile</a>\n  </div>\n  <div class='footer'>\n    <p>Automated by n8n - AI Resume Screening System</p>\n    <p>This alert was triggered because the candidate scored {{ $json.score }}/100</p>\n  </div>\n</div>\n</body>\n</html>"
      },
      "id": "node-send-recruiter-email",
      "name": "Alert Recruiter",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2,
      "position": [
        1200,
        100
      ],
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "url": "={{ $env.APP_URL || 'http://localhost:3000' }}/api/webhook/n8n-callback",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "candidate_id",
              "value": "={{ $json.candidate_id }}"
            },
            {
              "name": "action",
              "value": "update_status"
            },
            {
              "name": "data",
              "value": "={{ JSON.stringify({ status: 'reviewing', n8n_processed: true, processed_at: new Date().toISOString() }) }}"
            }
          ]
        },
        "options": {}
      },
      "id": "node-callback-api",
      "name": "Update Backend Status",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4,
      "position": [
        1200,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// Log workflow completion\nconst data = $('Prepare Notification').first().json;\nconsole.log(`Workflow completed for candidate: ${data.candidate_name} (Score: ${data.score})`);\n\nreturn [{\n  json: {\n    success: true,\n    message: 'Workflow completed successfully',\n    candidate_id: data.candidate_id,\n    score: data.score,\n    processed_at: new Date().toISOString()\n  }\n}];"
      },
      "id": "node-log-completion",
      "name": "Log Completion",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1420,
        300
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ success: true, message: 'Workflow triggered', candidate_id: $('Resume Webhook').first().json.candidate_id }) }}"
      },
      "id": "node-webhook-response",
      "name": "Webhook Response",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        320,
        500
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "=INSERT INTO workflow_events (candidate_id, event_type, payload, status)\nVALUES ('{{ $('Resume Webhook').first().json.candidate_id }}', 'n8n_processed', '{{ JSON.stringify($('Prepare Notification').first().json) }}', 'success')\nON CONFLICT DO NOTHING;"
      },
      "id": "node-db-log",
      "name": "Save to Database",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        1420,
        100
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "triggerTimes": {
          "item": [
            {
              "mode": "everyHour"
            }
          ]
        }
      },
      "id": "node-cron-trigger",
      "name": "Hourly Check (IMAP)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.1,
      "position": [
        100,
        600
      ]
    },
    {
      "parameters": {
        "mailbox": "INBOX",
        "subject": "resume OR cv OR application OR job",
        "downloadAttachments": true,
        "format": "resolved",
        "options": {
          "allowUnauthorizedCerts": false
        }
      },
      "id": "node-email-read",
      "name": "Check Email Inbox",
      "type": "n8n-nodes-base.emailReadImap",
      "typeVersion": 2,
      "position": [
        320,
        600
      ],
      "credentials": {
        "imap": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.attachments && $json.attachments.length > 0 }}",
              "value2": true
            }
          ]
        }
      },
      "id": "node-has-attachment",
      "name": "Has Attachment?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        540,
        600
      ]
    },
    {
      "parameters": {
        "url": "={{ $env.APP_URL || 'http://localhost:3000' }}/api/email-resume",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"sender\": \"{{ $json.from.value[0].address }}\",\n  \"subject\": \"{{ $json.subject }}\",\n  \"resume_text\": \"{{ $json.text || $json.textAsHtml || '' }}\",\n  \"attachments\": {{ JSON.stringify(($json.attachments || []).map(a => ({ filename: a.filename, mimeType: a.mimeType }))) }}\n}",
        "options": {}
      },
      "id": "node-process-email",
      "name": "Send to Backend",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4,
      "position": [
        760,
        550
      ]
    }
  ],
  "connections": {
    "Resume Webhook": {
      "main": [
        [
          {
            "node": "Validate Event",
            "type": "main",
            "index": 0
          },
          {
            "node": "Webhook Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Event": {
      "main": [
        [
          {
            "node": "AI Recruiter Briefing",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "AI Recruiter Briefing": {
      "main": [
        [
          {
            "node": "Prepare Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Notification": {
      "main": [
        [
          {
            "node": "High Score?",
            "type": "main",
            "index": 0
          },
          {
            "node": "Update Backend Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "High Score?": {
      "main": [
        [
          {
            "node": "Alert Recruiter",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Alert Recruiter": {
      "main": [
        [
          {
            "node": "Save to Database",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Backend Status": {
      "main": [
        [
          {
            "node": "Log Completion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hourly Check (IMAP)": {
      "main": [
        [
          {
            "node": "Check Email Inbox",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Email Inbox": {
      "main": [
        [
          {
            "node": "Has Attachment?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Attachment?": {
      "main": [
        [
          {
            "node": "Send to Backend",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "callerPolicy": "workflowsFromSameOwner",
    "errorWorkflow": ""
  },
  "staticData": null,
  "tags": [
    {
      "name": "HR Automation"
    },
    {
      "name": "AI"
    },
    {
      "name": "Resume Screening"
    }
  ],
  "meta": {
    "description": "Complete AI-powered resume screening workflow. Processes form submissions and email resumes, triggers AI analysis, sends recruiter alerts, and updates the hiring database."
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

AI Resume Screening Workflow. Uses openAi, emailSend, httpRequest, postgres. Webhook trigger; 14 nodes.

Source: https://github.com/GitRoarr/-ai-resume-screening-workflow-/blob/f4f37cf231c38ba48af564fad6ce53b0d014bdf4/n8n-workflows/ai_resume_screening.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Send-Outreach. Uses postgres, openAi, httpRequest, emailSend. Webhook trigger; 15 nodes.

Postgres, OpenAI, HTTP Request +1
AI & RAG

User Signup & Verification: The workflow starts when a user signs up. It generates a verification code and sends it via SMS using Twilio. Code Validation: The user replies with the code. The workflow

Postgres, HTTP Request, OpenAI +2
AI & RAG

Watch on Youtube▶️

HTTP Request, Email Send, Google Sheets +3
AI & RAG

Automatically detects missed Zoom demos booked via Calendly and triggers AI-powered follow-up sequences.

HTTP Request, OpenAI, Email Send +3
AI & RAG

Pyragogy AI Village - Orchestrazione Master (Architettura Profonda V2). Uses start, postgres, openAi, emailSend. Webhook trigger; 35 nodes.

Start, Postgres, OpenAI +3