Resumen diario de solicitantes
Este es unAI Summarization, Multimodal AIflujo de automatización del dominio deautomatización que contiene 10 nodos.Utiliza principalmente nodos como Code, Gmail, ScheduleTrigger, ChainLlm, LmChatGoogleGemini. Resumen diario de postulantes clasificados por puesto, extraído con Gemini AI, para uso de gerentes de contratación
- •Cuenta de Google y credenciales de API de Gmail
- •Clave de API de Google Gemini
Nodos utilizados (10)
Categoría
{
"id": "MGgeJBbeovHVQAbq",
"meta": {
"instanceId": "14e4c77104722ab186539dfea5182e419aecc83d85963fe13f6de862c875ebfa",
"templateCredsSetupCompleted": true
},
"name": "Daily-Applicant-Digest",
"tags": [],
"nodes": [
{
"id": "75fe46c9-d9eb-455e-8f9d-7384c4a1d172",
"name": "Disparador programado",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-340,
-80
],
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 6
}
]
}
},
"typeVersion": 1.2
},
{
"id": "ba41cb19-9463-4c8a-a94d-a7d579346b1e",
"name": "Modelo de chat Google Gemini",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
120,
120
],
"parameters": {
"options": {},
"modelName": "models/gemini-1.5-flash"
},
"credentials": {
"googlePalmApi": {
"id": "VbpO5dd6r2AhD52y",
"name": "Google Gemini(PaLM) Api account 2"
}
},
"typeVersion": 1
},
{
"id": "9e2ef974-5183-4e7d-9cd2-8f3872bd0a66",
"name": "Nota adhesiva",
"type": "n8n-nodes-base.stickyNote",
"position": [
-520,
-360
],
"parameters": {
"width": 1720,
"height": 680,
"content": "## Send daily applicant digest by role from Gmail to hiring managers with Google Gemini"
},
"typeVersion": 1
},
{
"id": "4648ef51-49af-40f8-9c82-490c5965e5be",
"name": "fetch_applicant_emails",
"type": "n8n-nodes-base.gmail",
"position": [
-120,
-80
],
"webhookId": "342f1447-19e1-4639-ae6e-a39fc1131b7c",
"parameters": {
"filters": {
"q": "label: applicant newer_than:1d is:unread"
},
"operation": "getAll"
},
"credentials": {
"gmailOAuth2": {
"id": "Kb30iigFce7pjkMZ",
"name": "Gmail account 5"
}
},
"typeVersion": 2.1
},
{
"id": "f479ae8a-490b-4b08-9fe3-dbe6a26b2320",
"name": "readAll_applicant_emails",
"type": "n8n-nodes-base.gmail",
"position": [
120,
-280
],
"webhookId": "801858f2-9076-47a1-88eb-c8c1c930102d",
"parameters": {
"messageId": "={{ $json.id }}",
"operation": "markAsRead"
},
"credentials": {
"gmailOAuth2": {
"id": "Kb30iigFce7pjkMZ",
"name": "Gmail account 5"
}
},
"typeVersion": 2.1
},
{
"id": "2a8e9656-df75-439f-ac16-ba608b29c87d",
"name": "Extract Applicant Details",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
100,
-80
],
"parameters": {
"text": "=You are an assistant that extracts job applicant information from emails.\n\nExtract the following fields and return ONLY valid JSON with these keys:\n- name\n- email\n- phone\n- role\n- years_of_experience\n- top_skills\n- location\n- notice_period\n- summary\n\nApplicant email:\n\"\"\"\n{{$json.snippet }}\n\"\"\"\n",
"batching": {},
"promptType": "define"
},
"typeVersion": 1.7
},
{
"id": "3937cc5c-ea58-4b5d-b22d-591f8097481f",
"name": "Assign Manager Correo electrónicos",
"type": "n8n-nodes-base.code",
"position": [
480,
-80
],
"parameters": {
"jsCode": "function stripMarkdownJson(input) {\n let str = (input || '').trim();\n\n // Remove the ```json at the start and ```\n // This regex removes triple backticks and the 'json' keyword at the start\n str = str.replace(/^```json\\s*/, ''); // Remove starting ```\n str = str.replace(/```$/, ''); // Remove ending ```\n \n return str.trim();\n}\n\nfunction normalizeRole(role) {\n return (role || '').trim().toLowerCase();\n}\n\nconst roleToManagerEmail = {\n 'java team lead': 'javatl@mailinator.com',\n 'python developer': 'pythontl@mailinator.com',\n 'frontend developer': 'frontendtl@mailinator.com',\n // add other roles as needed\n};\n\nconst fallbackManagerEmail = 'fallback@mailinator.com';\n\nreturn items.map(item => {\n const raw = item.json.text || '';\n const jsonStr = stripMarkdownJson(raw);\n\n let parsed;\n try {\n parsed = JSON.parse(jsonStr);\n } catch (e) {\n item.json.error = `JSON parse failed: ${e.message}`;\n return item;\n }\n\n // Merge the parsed JSON fields into the current item\n Object.assign(item.json, parsed);\n\n // Normalize role and assign manager email\n const normalizedRole = normalizeRole(item.json.role);\n const managerEmail = Object.prototype.hasOwnProperty.call(roleToManagerEmail, normalizedRole)\n ? roleToManagerEmail[normalizedRole]\n : fallbackManagerEmail;\n\n item.json.managerEmail = managerEmail;\n\n return item;\n});\n"
},
"typeVersion": 2
},
{
"id": "5943f68f-a39f-4532-a437-732d98d53079",
"name": "Group & Build HTML Tables",
"type": "n8n-nodes-base.code",
"position": [
700,
-80
],
"parameters": {
"jsCode": "function escapeHtml(text) {\n if (!text) return '';\n return text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n\n// Group applicants by managerEmail, then by role\nconst groupedByManager = {};\n\n// Step 1: Group items\nitems.forEach(item => {\n const applicant = item.json;\n const managerEmail = applicant.managerEmail || 'unknown@fallback.com';\n const role = applicant.role || 'Unknown Role';\n\n if (!groupedByManager[managerEmail]) {\n groupedByManager[managerEmail] = {};\n }\n if (!groupedByManager[managerEmail][role]) {\n groupedByManager[managerEmail][role] = [];\n }\n \n groupedByManager[managerEmail][role].push(applicant);\n});\n\n// Step 2: Build HTML per manager with tables per role\nconst output = [];\n\nfor (const [managerEmail, roles] of Object.entries(groupedByManager)) {\n\n let emailHtml = `<h2>Today's New Applicants</h2>`;\n\n for (const [role, applicants] of Object.entries(roles)) {\n emailHtml += `<h3>Role: ${escapeHtml(role)}</h3>`;\n \n // Build table header\n emailHtml += `\n <table border=\"1\" cellpadding=\"5\" cellspacing=\"0\" style=\"border-collapse:collapse; width: 100%;\">\n <thead style=\"background-color:#f0f0f0;\">\n <tr>\n <th>Name</th>\n <th>Email</th>\n <th>Phone</th>\n <th>Years of Experience</th>\n <th>Top Skills</th>\n <th>Location</th>\n <th>Notice Period</th>\n <th>Summary</th>\n </tr>\n </thead>\n <tbody>\n `;\n\n // Add each applicant as a row\n applicants.forEach(app => {\n emailHtml += `\n <tr>\n <td>${escapeHtml(app.name)}</td>\n <td><a href=\"mailto:${escapeHtml(app.email)}\">${escapeHtml(app.email)}</a></td>\n <td>${escapeHtml(app.phone)}</td>\n <td>${escapeHtml(app.years_of_experience?.toString())}</td>\n <td>${Array.isArray(app.top_skills) ? escapeHtml(app.top_skills.join(', ')) : escapeHtml(app.top_skills)}</td>\n <td>${escapeHtml(app.location)}</td>\n <td>${escapeHtml(app.notice_period)}</td>\n <td>${escapeHtml(app.summary)}</td>\n </tr>\n `;\n });\n\n emailHtml += `</tbody></table><br/>`;\n }\n\n // Push one item per manager, as output for the next step (email sending)\n output.push({\n json: {\n managerEmail,\n html: emailHtml\n }\n });\n}\n\nreturn output;\n"
},
"typeVersion": 2
},
{
"id": "9509d5c2-f66f-4294-9432-0b2587283b7a",
"name": "Send Digest to Managers",
"type": "n8n-nodes-base.gmail",
"position": [
900,
-80
],
"webhookId": "7fe812db-f512-4e0d-b4e5-f577fad2511c",
"parameters": {
"sendTo": "={{ $json.managerEmail }}",
"message": "={{ $json.html }}",
"options": {},
"subject": "=Today's Applicants Digest – {{ $now.format('MM-DD') }}"
},
"credentials": {
"gmailOAuth2": {
"id": "Kb30iigFce7pjkMZ",
"name": "Gmail account 5"
}
},
"typeVersion": 2.1
},
{
"id": "17486203-2374-43f0-88eb-80500108d770",
"name": "Nota adhesiva1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-520,
360
],
"parameters": {
"width": 1720,
"height": 780,
"content": "## Workflow Overview: Send daily applicant digest by role from Gmail to hiring managers with Google Gemini\n\n**Purpose:**\nAutomatically fetches new job application emails labeled applicants, extracts structured applicant details using OpenAI, groups candidates by role and manager, then sends a daily HTML summary email to each hiring manager.\n\nDaily Applicant Digest Workflow – Node Overview\n\n**1. Daily Trigger (6PM IST)**\n\nStarts the workflow every day at 18:00 (Asia/Kolkata timezone).\n\n**2. Fetch Applicant Emails**\n\nRetrieves all new application emails labeled applicants from the last 24 hours.\n\n**3. Read All Emails**\n\nRead each email’s labeled applicants which we retrieves\n\n**4. Extract Applicant Details**\n\nUses OpenAI to extract and structure applicant info (name, email, role, skills, etc.) in JSON format.\n\n**5. Assign Manager Emails**\n\nMaps each applicant’s role to a hiring manager’s email address.\n\nUses a fallback email if the role does not match any manager.\n\n**6. Group & Build HTML Tables**\n\nGroups applicants by manager and role.\n\nBuilds a clear, formatted HTML table for each group, summarizing all applicants.\n\n**7. Send Digest to Managers**\n\nSends one HTML summary email per manager, listing all relevant new applicants for the day.\n"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "67d27489-333a-4e73-8d9c-1af780d66304",
"connections": {
"Schedule Trigger": {
"main": [
[
{
"node": "4648ef51-49af-40f8-9c82-490c5965e5be",
"type": "main",
"index": 0
}
]
]
},
"Assign Manager Emails": {
"main": [
[
{
"node": "5943f68f-a39f-4532-a437-732d98d53079",
"type": "main",
"index": 0
}
]
]
},
"4648ef51-49af-40f8-9c82-490c5965e5be": {
"main": [
[
{
"node": "2a8e9656-df75-439f-ac16-ba608b29c87d",
"type": "main",
"index": 0
},
{
"node": "f479ae8a-490b-4b08-9fe3-dbe6a26b2320",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "2a8e9656-df75-439f-ac16-ba608b29c87d",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"2a8e9656-df75-439f-ac16-ba608b29c87d": {
"main": [
[
{
"node": "Assign Manager Emails",
"type": "main",
"index": 0
}
]
]
},
"5943f68f-a39f-4532-a437-732d98d53079": {
"main": [
[
{
"node": "9509d5c2-f66f-4294-9432-0b2587283b7a",
"type": "main",
"index": 0
}
]
]
}
}
}¿Cómo usar este flujo de trabajo?
Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.
¿En qué escenarios es adecuado este flujo de trabajo?
Intermedio - Resumen de IA, IA Multimodal
¿Es de pago?
Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.
Flujos de trabajo relacionados recomendados
WeblineIndia
@weblineindiaA Leading Software Engineering, Consulting & Outsourcing Services Company in USA & India serving Clients Globally since 1999.
Compartir este flujo de trabajo