AutomationFlowsAI & RAG › Match Job Descriptions with Resumes Using Google Gemini and Log Scores to…

Match Job Descriptions with Resumes Using Google Gemini and Log Scores to…

Original n8n title: Match Job Descriptions with Resumes Using Google Gemini and Log Scores to Google Sheets

ByPratyush Kumar Jha @pratyush on n8n.io

Smart Resume Screener ingests a candidate resume and a job description link, extracts clean text from both, runs an LLM-powered screening agent to produce a structured assessment (strengths, weaknesses, risk/reward, justification, and a 0–10 fit score), extracts contact details,…

Event trigger★★★★☆ complexityAI-powered16 nodesAgentOutput Parser StructuredInformation ExtractorGoogle SheetsForm TriggerHTTP RequestGoogle Gemini Chat
AI & RAG Trigger: Event Nodes: 16 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #13507 — we link there as the canonical source.

This workflow follows the Agent → Form Trigger 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
{
  "id": "6NgPkjl85BJqhJA5",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Smart Resume Screener \u2014 JD \u2194 Resume AI Match & Sheet Logger",
  "tags": [],
  "nodes": [
    {
      "id": "c32296bd-5d48-4b4e-93e1-d65871c27b4c",
      "name": "Set Resume",
      "type": "n8n-nodes-base.set",
      "position": [
        -848,
        320
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "0f9e36f9-60cb-4593-a586-723124d69ff8",
              "name": "resume",
              "type": "string",
              "value": "={{ $json.text }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "757ef828-06d7-4491-9232-b46838a8c337",
      "name": "Recruiter Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -80,
        336
      ],
      "parameters": {
        "text": "=Candidate Resume:\n{{ $json.data[0].resume }}\n",
        "options": {
          "systemMessage": "=# Overview\nYou are an expert recruiter. You have been given a job description and a candidate resume. Your task is to analyze the resume in relation to the job description and provide a detailed screening report. \n\nFocus specifically on how well the candidate matches the core requirements and ideal profile outlined in the job description. Evaluate both technical skill alignment and business-context understanding. Use reasoning grounded in the actual content of the resume and job post \u2014 avoid making assumptions.\n\n## Output\nYour output should follow this exact format:\n\nCandidate Strengths:  \nList the top strengths or relevant qualifications the candidate brings to the table. Be specific.\n\nCandidate Weaknesses:\nList areas where the candidate is lacking or mismatched based on the job description.\n\nRisk Factor:\n- Assign a risk score (Low / Medium / High)  \n- Explain the worst-case scenario if this candidate is hired.\n\nReward Factor: \n- Assign a reward score (Low / Medium / High)  \n- Describe the best-case scenario \u2014 what value could this candidate unlock?  \n- Does the candidate appear to be a short-term or long-term fit?\n\nOverall Fit Rating (0\u201310):  \nAssign a number between 0 (terrible match) and 10 (perfect match). Do not give decimals.\n\nJustification for Rating:\nExplain clearly why this candidate received that score. Reference specific resume content and how it aligns or doesn't with the job description.\n\n## Job Description\n{{ $json.data[1].output['Job description'] }}\n\n"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2
    },
    {
      "id": "fdfaf5f0-4342-4a73-a3e3-508e18d73716",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        48,
        160
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"name\": \"resume_screening_evaluation\",\n  \"description\": \"Analyzes a candidate's resume against a job description and outputs strengths, weaknesses, risk/reward assessment, and an overall fit score.\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"candidate_strengths\": {\n      \"type\": \"array\",\n      \"description\": \"A list of specific strengths or qualifications that match the job description.\",\n      \"items\": {\n        \"type\": \"string\"\n      }\n    },\n    \"candidate_weaknesses\": {\n      \"type\": \"array\",\n      \"description\": \"A list of areas where the candidate falls short or lacks alignment with the job requirements.\",\n      \"items\": {\n        \"type\": \"string\"\n      }\n    },\n    \"risk_factor\": {\n      \"type\": \"object\",\n      \"description\": \"An evaluation of the potential risks of hiring this candidate.\",\n      \"properties\": {\n        \"score\": {\n          \"type\": \"string\",\n          \"enum\": [\"Low\", \"Medium\", \"High\"],\n          \"description\": \"The risk level of hiring this candidate.\"\n        },\n        \"explanation\": {\n          \"type\": \"string\",\n          \"description\": \"A brief explanation of the worst-case scenario if the candidate is hired.\"\n        }\n      },\n      \"required\": [\"score\", \"explanation\"]\n    },\n    \"reward_factor\": {\n      \"type\": \"object\",\n      \"description\": \"An evaluation of the potential upside of hiring this candidate.\",\n      \"properties\": {\n        \"score\": {\n          \"type\": \"string\",\n          \"enum\": [\"Low\", \"Medium\", \"High\"],\n          \"description\": \"The reward level of hiring this candidate.\"\n        },\n        \"explanation\": {\n          \"type\": \"string\",\n          \"description\": \"A description of the best-case scenario and whether the candidate is a short-term or long-term fit.\"\n        }\n      },\n      \"required\": [\"score\", \"explanation\"]\n    },\n    \"overall_fit_rating\": {\n      \"type\": \"integer\",\n      \"description\": \"A rating from 0 to 10 indicating how well the candidate matches the job description.\",\n      \"minimum\": 0,\n      \"maximum\": 10\n    },\n    \"justification_for_rating\": {\n      \"type\": \"string\",\n      \"description\": \"A summary explaining why the candidate received the specific fit rating, referencing resume and job description alignment.\"\n    }\n  },\n  \"required\": [\n    \"candidate_strengths\",\n    \"candidate_weaknesses\",\n    \"risk_factor\",\n    \"reward_factor\",\n    \"overall_fit_rating\",\n    \"justification_for_rating\"\n  ]\n}\n"
      },
      "typeVersion": 1.3
    },
    {
      "id": "4de5dbd7-385b-488e-9926-b3a1856eec57",
      "name": "Information Extractor",
      "type": "@n8n/n8n-nodes-langchain.informationExtractor",
      "position": [
        384,
        336
      ],
      "parameters": {
        "text": "={{ $('Set Resume').item.json.resume }}",
        "options": {},
        "attributes": {
          "attributes": [
            {
              "name": "First Name",
              "required": true,
              "description": "first name of the candidate"
            },
            {
              "name": "Last Name",
              "required": true,
              "description": "last name of the candidate"
            },
            {
              "name": "Email Address",
              "required": true,
              "description": "candidate's email address"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "e2038b38-cfd0-41da-be93-75fc2e456789",
      "name": "Append Data",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        736,
        336
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $now.format('yyyy-MM-dd hh:m a') }}",
            "Email": "={{ $json.output['Email Address'] }}",
            "Last Name": "={{ $json.output['Last Name'] }}",
            "Strengths": "={{ $('Recruiter Agent').item.json.output.candidate_strengths.join(\"\\n\\n\") }}",
            "First Name": "={{ $json.output['First Name'] }}",
            "Weaknesses": "={{ $('Recruiter Agent').item.json.output.candidate_weaknesses.join(\"\\n\\n\") }}",
            "Overall Fit": "={{ $('Recruiter Agent').item.json.output.overall_fit_rating }}",
            "Risk Factor": "={{ $('Recruiter Agent').item.json.output.risk_factor.score }}\n\n{{ $('Recruiter Agent').item.json.output.risk_factor.explanation }}",
            "Justification": "={{ $('Recruiter Agent').item.json.output.justification_for_rating }}",
            "Reward Factor": "={{ $('Recruiter Agent').item.json.output.reward_factor.score }}\n\n{{ $('Recruiter Agent').item.json.output.reward_factor.explanation }}"
          },
          "schema": [
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "First Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "First Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Last Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Last Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Strengths",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Strengths",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Weaknesses",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Weaknesses",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Risk Factor",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Risk Factor",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Reward Factor",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Reward Factor",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Overall Fit",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Overall Fit",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Justification",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Justification",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1_a0HFGiv-D7_WqlmrL50CGrTW5W_8QeKW-YqbmdBjSs/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1_a0HFGiv-D7_WqlmrL50CGrTW5W_8QeKW-YqbmdBjSs",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1_a0HFGiv-D7_WqlmrL50CGrTW5W_8QeKW-YqbmdBjSs/edit?usp=drivesdk",
          "cachedResultName": " Resume Screener"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "a471ca58-f0b5-4c0d-93c7-ac2a3ab958dd",
      "name": "Extract from File2",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -1440,
        176
      ],
      "parameters": {
        "options": {},
        "operation": "pdf",
        "binaryPropertyName": "=Resume"
      },
      "typeVersion": 1
    },
    {
      "id": "11960013-de20-4f1e-95ce-872cce293c69",
      "name": "On form submission",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -1664,
        336
      ],
      "parameters": {
        "options": {},
        "formTitle": "Check Your Resume Score",
        "formFields": {
          "values": [
            {
              "fieldType": "file",
              "fieldLabel": "Resume",
              "requiredField": true
            },
            {
              "fieldLabel": "Job Description Link",
              "requiredField": true
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "470a4835-b9a5-4eb6-ab62-306e155e6bc2",
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1440,
        336
      ],
      "parameters": {
        "url": "={{ $json['Job Description Link'] }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "3680f0a7-4a91-47ef-8c47-f203ea941d52",
      "name": "Information Extractor1",
      "type": "@n8n/n8n-nodes-langchain.informationExtractor",
      "position": [
        -1232,
        336
      ],
      "parameters": {
        "text": "={{ $json.data }}",
        "options": {},
        "attributes": {
          "attributes": [
            {
              "name": "Job description",
              "required": true,
              "description": "Job description"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "1febc5bc-879b-4608-bf78-b380df273299",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        -528,
        336
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "40278ccc-d227-4b14-9e16-265443836f2a",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -304,
        336
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "0dd33d75-e6ef-49e0-beb9-fb920680d0ae",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2256,
        -32
      ],
      "parameters": {
        "width": 454,
        "height": 1328,
        "content": "# Smart Resume Screener \u2014 JD \u2194 Resume AI Match & Sheet Logger\n\nSmart Resume Screener ingests a candidate resume and a job description link, extracts clean text from both, runs an LLM-powered screening agent to produce a structured assessment (strengths, weaknesses, risk/reward, justification, and a 0\u201310 fit score), extracts contact details, and appends a single, validated row to a Google Sheet for tracking.\n\n---\n\n# How It Works (Step-by-Step)\n\n## 1. Trigger \u2014 On Form Submission\n\n## 2. Extract & Fetch Content\n\n## 3. Prepare and Aggregate\n\n## 4. AI Evaluation\n\n## 5. Identity Extraction & Logging\n\n## 6. (Optional) Notifications / Follow-Ups\n\n# Quick Setup Guide\n\ud83d\udc49 [Demo & Setup Video](https://drive.google.com/file/d/11YmCsQhNmDaF_O_LoTvDV4gxCbPMOGJt/view?usp=sharing)\n\ud83d\udc49 [Sheet Template](https://docs.google.com/spreadsheets/d/1_a0HFGiv-D7_WqlmrL50CGrTW5W_8QeKW-YqbmdBjSs/edit?usp=sharing)\n\ud83d\udc49 [Course](https://www.udemy.com/course/n8n-automation-mastery-build-ai-powered-enterprise-ready/?referralCode=2EAE71591D3BEB80F2CC)\n"
      },
      "typeVersion": 1
    },
    {
      "id": "174dac47-8d79-43d8-92e7-eb03484338a0",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        -528,
        192
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "bb39d3db-781e-41ff-ba55-7be8e29cef14",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1728,
        -32
      ],
      "parameters": {
        "color": 6,
        "width": 784,
        "height": 544,
        "content": "# Data Ingestion & Content Extraction\n## Collect candidate inputs and convert everything into structured, usable text."
      },
      "typeVersion": 1
    },
    {
      "id": "e9e07857-66be-400d-983f-7babf59e6aee",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -912,
        -32
      ],
      "parameters": {
        "color": 6,
        "width": 1120,
        "height": 544,
        "content": "# AI Evaluation & Structured Screening\n## Evaluate candidate suitability using an AI recruiter agent."
      },
      "typeVersion": 1
    },
    {
      "id": "56739da7-7238-4112-97ee-83fe762a756f",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        256,
        -32
      ],
      "parameters": {
        "color": 6,
        "width": 688,
        "height": 544,
        "content": "# Data Structuring & Recruitment Logging\n## Extract candidate identity details and log final screening data."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "3cd5ce36-ed29-443d-84aa-f495387288b6",
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "Recruiter Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Resume": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Information Extractor1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Recruiter Agent": {
      "main": [
        [
          {
            "node": "Information Extractor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract from File2": {
      "main": [
        [
          {
            "node": "Set Resume",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On form submission": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          },
          {
            "node": "Extract from File2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Information Extractor": {
      "main": [
        [
          {
            "node": "Append Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Information Extractor1": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Information Extractor1",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Recruiter Agent",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Information Extractor",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Recruiter Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    }
  }
}

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

Smart Resume Screener ingests a candidate resume and a job description link, extracts clean text from both, runs an LLM-powered screening agent to produce a structured assessment (strengths, weaknesses, risk/reward, justification, and a 0–10 fit score), extracts contact details,…

Source: https://n8n.io/workflows/13507/ — 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

🎯 Create viral TikToks, Shorts, Reels, podcasts, and ASMR videos in minutes — all on autopilot.

OpenAI, HTTP Request, Form Trigger +7
AI & RAG

Digistars - Scrape & Crawl. Uses httpRequest, n8n-nodes-firecrawl-scraper, googleSheets, lmChatOpenAi. Event-driven trigger; 63 nodes.

HTTP Request, N8N Nodes Firecrawl Scraper, Google Sheets +5
AI & RAG

This is an automated blog post generation system that: Researches topics using AI agents and web search tools Writes complete blog posts with proper SEO structure Generates custom images for each post

Output Parser Structured, Google Gemini Chat, HTTP Request Tool +11
AI & RAG

CV → Match → Screen → Decide, all automated

HTTP Request, Information Extractor, Google Sheets +7
AI & RAG

This workflow automatically creates hours-long wave music videos by combining AI-generated music from Suno with a background video, fully automated using n8n and ffmpeg-api.

Form Trigger, HTTP Request, Agent +4