This workflow corresponds to n8n.io template #6207 — we link there as the canonical source.
This workflow follows the Agent → Gmail Tool 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 →
{
"id": "z7quMO0WgEu3Kkyv",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "\ud83d\udca5 AI-Powered HR Workflow: CV Analysis and Evaluation from Gmail to Sheets - vide",
"tags": [],
"nodes": [
{
"id": "2ebf8f4d-1000-4c40-8d5f-e31fa0ada941",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
2540,
-240
],
"parameters": {
"width": 920,
"height": 400,
"content": "# \ud83d\udfe1 Step 1 \u2014 Detect and Process New CV from Email"
},
"typeVersion": 1
},
{
"id": "175a65ff-d1c4-404e-bab1-7805123a0ce9",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
2540,
200
],
"parameters": {
"color": 3,
"width": 920,
"height": 500,
"content": "# \ud83d\udd34 Step 2 \u2014 Extract and Store Candidate Data\n"
},
"typeVersion": 1
},
{
"id": "1061bc84-9cb8-4391-a057-04e7d1aac10e",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
3520,
200
],
"parameters": {
"color": 6,
"width": 920,
"height": 500,
"content": "# \ud83d\udfe3 Step 3 \u2014 Evaluate and Qualify the Candidate\n"
},
"typeVersion": 1
},
{
"id": "a6395a4c-3c06-4175-8927-3f80bde21bcc",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
3520,
-240
],
"parameters": {
"width": 920,
"height": 400,
"content": " ## AI-Powered HR Workflow: CV Analysis and Evaluation from Gmail to Sheets\n\n### \ud83d\udccb Before you get started, make sure you have:\n\n- \u2705 [n8n installed](https://www.hostg.xyz/SHHOJ) *(self-hosted required for Gmail + OpenAI + Google integrations)*\n- \u2705 [OpenAI API Key](https://platform.openai.com/api-keys)\n- \u2705 [Google Sheets API enabled](https://console.cloud.google.com/apis/api/sheets.googleapis.com/overview) in Google Cloud Console\n- \u2705 [Google Drive API enabled](https://console.cloud.google.com/apis/api/drive.googleapis.com/overview) in Google Cloud Console\n- \u2705 [OAuth 2.0 Client ID and Secret](https://console.cloud.google.com/apis/credentials) created in Google Cloud (required for Gmail, Drive, and Sheets nodes)\n\n> Make sure you\u2019ve authorized n8n to access these services using the credentials above before running the workflow.\n"
},
"typeVersion": 1
},
{
"id": "3575cc8d-18b8-436d-a026-b022814fbd3d",
"name": "Gmail: Watch for new CV",
"type": "n8n-nodes-base.gmailTrigger",
"position": [
2640,
-140
],
"parameters": {
"simple": false,
"filters": {
"q": "has:attachment",
"labelIds": [
"UNREAD"
],
"readStatus": "unread"
},
"options": {
"downloadAttachments": true
},
"pollTimes": {
"item": [
{
"mode": "everyHour",
"minute": 1
}
]
}
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "e1d682f8-9723-4dd6-ad45-e8959a273d32",
"name": "Classify Email Type",
"type": "@n8n/n8n-nodes-langchain.textClassifier",
"position": [
2860,
-140
],
"parameters": {
"options": {
"systemPromptTemplate": "Classify the user's text into one of the following categories: {categories}.\nFollow the formatting instructions provided below exactly.\nDo not include any explanation \u2014 output only the final JSON result."
},
"inputText": "={{ $json.text }}",
"categories": {
"categories": [
{
"category": "Doesn't apply",
"description": "The candidate is not a job application"
},
{
"category": "Apply",
"description": "This is a job application submitted by a candidate applying for a position at our organization, included as an attached file."
}
]
}
},
"typeVersion": 1
},
{
"id": "5f241a19-c30a-4cc4-a2c0-7e9d97711c78",
"name": "OpenAI Model \u2013 Email Classifier",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
2860,
20
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "848188ac-52fa-43b7-953f-b2cd45c727f1",
"name": "Skip (If not a job application)",
"type": "n8n-nodes-base.noOp",
"position": [
3280,
-140
],
"parameters": {},
"typeVersion": 1
},
{
"id": "fe0e8d5c-e3f6-4098-891b-0fb3594b71c8",
"name": "Extract Resume Text (PDF)",
"type": "n8n-nodes-base.extractFromFile",
"position": [
2900,
520
],
"parameters": {
"options": {},
"operation": "pdf",
"binaryPropertyName": "attachment_0"
},
"typeVersion": 1
},
{
"id": "49107c53-eb76-4082-9d52-88d3fc391153",
"name": "Save Resume to Google Drive",
"type": "n8n-nodes-base.googleDrive",
"position": [
2900,
300
],
"parameters": {
"name": "={{ $('Gmail: Watch for new CV').item.json.from.value[0].address }}",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive",
"cachedResultUrl": "https://drive.google.com/drive/my-drive",
"cachedResultName": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "1G0KjVS_NAnqbqzYlV93KpX3498G5J8b1",
"cachedResultUrl": "https://drive.google.com/drive/folders/1G0KjVS_NAnqbqzYlV93KpX3498G5J8b1",
"cachedResultName": "CV - HR"
},
"inputDataFieldName": "=attachment_0"
},
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 3
},
{
"id": "b5d472bf-4acf-4e86-aeb7-5d1604ded5ff",
"name": "Retrieve Job Offer Details (Google Sheets)",
"type": "n8n-nodes-base.googleSheets",
"position": [
3280,
520
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "id",
"value": "="
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "="
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.6,
"alwaysOutputData": true
},
{
"id": "9b09d2ba-7669-4f64-8a77-ee5ff5280d72",
"name": "AI Agent: Score Resume",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
3620,
300
],
"parameters": {
"text": "=Here is the resume:\n{{ $('Extract Resume Text (PDF)').item.json.text }}\n\nAnalyze the current information from the received candidate and score between 0 to 10 the said candidate, 0 meaning not a good fit for the position, 10 being outstanding for the job.\n\nJob Tile : {{ $json['Title offer'] }}\nJob Description: {{ $json.Description }}\n\nReply by Email : \nSend a reply to the candidate to confirm that we have received their application and that we will get back to them as soon as possible.",
"options": {
"systemMessage": "=You are an invaluable assistant. You were given a resume. You have to help me analyze the resume and give it a score based on the details available in the resume. Also, extract the name, email, phone, location and LinkedIn profile from the resume.\n\nReply by Email : \nSend a reply to the candidate to confirm that we have received their application and that we will get back to them as soon as possible."
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 1.8
},
{
"id": "85edf215-bfa3-4b93-8f4f-7cede1132797",
"name": "OpenAI Model \u2013 Resume Scoring",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
3580,
540
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "o4-mini",
"cachedResultName": "o4-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "90da624b-9653-444f-a36b-9bfe6df4922a",
"name": "Send Confirmation Email",
"type": "n8n-nodes-base.gmailTool",
"position": [
3760,
540
],
"parameters": {
"sendTo": "={{ $('Gmail: Watch for new CV').item.json.from.value[0].address }}",
"message": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Message', ``, 'string') }}",
"options": {},
"subject": "Application Received"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "119808cc-82fb-43d2-931f-351f8e2e3267",
"name": "Parse Resume Evaluation Result",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
3900,
540
],
"parameters": {
"schemaType": "manual",
"inputSchema": "{\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"name\": {\n\t\t\t\"type\": \"string\"\n\t\t},\n \"email\": {\n\t\t\t\"type\": \"string\"\n\t\t},\n \"linkedin\": {\n\t\t\t\"type\": \"string\"\n\t\t},\n \"score\": {\n\t\t\t\"type\": \"string\"\n\t\t},\n \"Phone\": {\n\t\t\t\"type\": \"string\"\n\t\t},\n \"Location\": {\n\t\t\t\"type\": \"string\"\n\t\t}\n\t\t\n\t}\n}"
},
"typeVersion": 1.2
},
{
"id": "e9d2dfb0-0202-422c-a1f1-8d25a19bacc3",
"name": "Save Score to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
4120,
300
],
"parameters": {
"columns": {
"value": {
"Name": "={{ $json.output.name }}",
"Email": "={{ $('Gmail: Watch for new CV').item.json.from.value[0].address }}",
"Phone": "='{{ $json.output.Phone }}",
"Score": "={{ $json.output.score }}",
"LinkedIn": "={{ $json.output.linkedin }}",
"Location": "={{ $json.output.Location }}",
"Resume text": "={{ $('Extract Resume Text (PDF)').item.json.text }}"
},
"schema": [
{
"id": "Name",
"type": "string",
"display": true,
"required": false,
"displayName": "Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "LinkedIn",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "LinkedIn",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Phone",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Phone",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Location",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Location",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Score",
"type": "string",
"display": true,
"required": false,
"displayName": "Score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Resume text",
"type": "string",
"display": true,
"required": false,
"displayName": "Resume text",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Link CV",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Link CV",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Email"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {
"useAppend": true
},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "="
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "="
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
},
{
"id": "c931b4a0-a1a4-4c59-85b8-9099064a74d0",
"name": "Switch",
"type": "n8n-nodes-base.switch",
"position": [
2640,
400
],
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "e9debd3b-3fa3-425a-bd61-6bf23a3a652b",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "attachment_0",
"rightValue": ""
}
]
}
},
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "f0eabfca-ff5e-4e5d-9b4e-f3f80c7fa5b4",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "attachment_0",
"rightValue": ""
}
]
}
}
]
},
"options": {
"allMatchingOutputs": true
}
},
"typeVersion": 3.2
},
{
"id": "260dae6d-9234-4bab-bb79-d15b4923d801",
"name": "Save CV to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
3280,
300
],
"parameters": {
"columns": {
"value": {
"Email": "={{ $('Gmail: Watch for new CV').item.json.from.value[0].address }}",
"Link CV": "={{ $('Save Resume to Google Drive').item.json.webViewLink }}"
},
"schema": [
{
"id": "Name",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "LinkedIn",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "LinkedIn",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Phone",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Phone",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Location",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Location",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Score",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Resume text",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "Resume text",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Link CV",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Link CV",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {
"useAppend": true
},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "="
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "="
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "07121905-4a3c-4301-b88e-e1db76c119e3",
"connections": {
"Switch": {
"main": [
[
{
"node": "Save Resume to Google Drive",
"type": "main",
"index": 0
}
],
[
{
"node": "Extract Resume Text (PDF)",
"type": "main",
"index": 0
}
]
]
},
"Classify Email Type": {
"main": [
[
{
"node": "Skip (If not a job application)",
"type": "main",
"index": 0
}
],
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"AI Agent: Score Resume": {
"main": [
[
{
"node": "Save Score to Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Gmail: Watch for new CV": {
"main": [
[
{
"node": "Classify Email Type",
"type": "main",
"index": 0
}
]
]
},
"Send Confirmation Email": {
"ai_tool": [
[
{
"node": "AI Agent: Score Resume",
"type": "ai_tool",
"index": 0
}
]
]
},
"Save CV to Google Sheets": {
"main": [
[]
]
},
"Extract Resume Text (PDF)": {
"main": [
[
{
"node": "Retrieve Job Offer Details (Google Sheets)",
"type": "main",
"index": 0
}
]
]
},
"Save Resume to Google Drive": {
"main": [
[
{
"node": "Save CV to Google Sheets",
"type": "main",
"index": 0
}
]
]
},
"Parse Resume Evaluation Result": {
"ai_outputParser": [
[
{
"node": "AI Agent: Score Resume",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"OpenAI Model \u2013 Resume Scoring": {
"ai_languageModel": [
[
{
"node": "AI Agent: Score Resume",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"OpenAI Model \u2013 Email Classifier": {
"ai_languageModel": [
[
{
"node": "Classify Email Type",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Retrieve Job Offer Details (Google Sheets)": {
"main": [
[
{
"node": "AI Agent: Score Resume",
"type": "main",
"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.
gmailOAuth2googleDriveOAuth2ApigoogleSheetsOAuth2ApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow is designed for HR professionals, recruiters, startup founders, and operations teams who receive candidate resumes by email and want to automate the evaluation process using AI.
Source: https://n8n.io/workflows/6207/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Enterprise-grade resume screening automation built for production environments. This workflow combines intelligent AI analysis with comprehensive error handling to ensure reliable processing of candid
AI Agents Vs AI Workflow. Uses lmChatOpenAi, gmailTrigger, gmail, gmailTool. Event-driven trigger; 30 nodes.
This template is for founders, finance teams, and solo operators who receive lots of invoices by email and want them captured automatically in a single, searchable source of truth. If you’re tired of
This template is for HR teams, recruiters, and companies that receive job applications via email and want to automatically screen and evaluate candidates using AI. Ideal for organisations processing a
Colombian Invoices Processing. Uses splitInBatches, lmChatOpenAi, toolCalculator, outputParserStructured. Event-driven trigger; 23 nodes.