AutomationFlowsAI & RAG › Generate Comparative Cv Screening Reports with Openai, Google Sheets

Generate Comparative Cv Screening Reports with Openai, Google Sheets

ByYevhenii @neolith2018 on n8n.io

Listens for commands via Telegram to trigger report generation. Parses the received command to determine action parameters. Fetches candidate data from Google Sheets based on parsed input. Prepares the data for report generation through custom logic. Generates a comparative…

Event trigger★★★★☆ complexityAI-powered10 nodesTelegram TriggerGoogle SheetsOpenAITelegram
AI & RAG Trigger: Event Nodes: 10 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Google Sheets → OpenAI 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": "O6cRWX-2bxmYn1yrYt_3T",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "CV Screening \u2014 Comparative Report",
  "tags": [],
  "nodes": [
    {
      "id": "499456fd-44d4-4033-b99b-27c718db16a6",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -608,
        -160
      ],
      "parameters": {
        "width": 480,
        "height": 784,
        "content": "## CV Screening \u2014 Comparative Report\n\n### How it works\n\n1. Listens for commands via Telegram to trigger report generation.\n2. Parses the received command to determine action parameters.\n3. Fetches candidate data from Google Sheets based on parsed input.\n4. Prepares the data for report generation through custom logic.\n5. Generates a comparative report using OpenAI LLM.\n6. Sends the generated report back through Telegram.\n\n### Setup steps\n\n- [ ] Configure Telegram API credentials for the Telegram Trigger node.\n- [ ] Set up Google Sheets credentials and provide access to the required sheet.\n- [ ] Configure OpenAI API credentials to enable the LLM Report Generator.\n\n### Customization\n\nConsider customizing the report generation logic in the 'Prepare Report Data' node to adjust the report format or criteria."
      },
      "typeVersion": 1
    },
    {
      "id": "f04af92d-cd0b-49ca-a6c8-3b5d7ae7df71",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -48,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 304,
        "content": "## Handle Telegram command\n\nListens for and parses commands from Telegram to initiate workflow."
      },
      "typeVersion": 1
    },
    {
      "id": "1465f79c-d0d1-4c0d-86bd-bd2dcff87a56",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        -160
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 320,
        "content": "## Fetch candidate data\n\nRetrieves candidate information from Google Sheets for report preparation."
      },
      "typeVersion": 1
    },
    {
      "id": "aba0051a-b2bc-4e11-a7e0-ba2fad9e8707",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        672,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 752,
        "height": 272,
        "content": "## Generate and send report\n\nProcesses fetched data to generate a report and sends it via Telegram."
      },
      "typeVersion": 1
    },
    {
      "id": "77f0890a-f20e-4a30-9805-a2f8d184f65c",
      "name": "When Telegram Message Received",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        0,
        0
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "4fbad692-a2b0-4667-b660-300cd59d212f",
      "name": "Parse Telegram Command",
      "type": "n8n-nodes-base.code",
      "position": [
        208,
        0
      ],
      "parameters": {
        "jsCode": "const text = $input.first().json.message.text.trim();\n\nif (!text.startsWith('/report')) {\n  throw new Error('SKIP: not a report command');\n}\n\nconst jobId = text.replace('/report', '').trim();\n\nif (!jobId) {\n  throw new Error('Usage: /report JOB-001');\n}\n\nreturn { json: { job_id: jobId } };"
      },
      "typeVersion": 2
    },
    {
      "id": "7db7f1b8-80e7-4455-850b-a479edf60225",
      "name": "Transform Candidate Data",
      "type": "n8n-nodes-base.code",
      "position": [
        720,
        0
      ],
      "parameters": {
        "jsCode": "const items = $input.all().map(item => item.json);\n\nconst summary = items.map(c => \n  `- ${c.Candidate}: Score ${c.Score}/100 (${c.Tier}) | Skills: ${c['Skills Matched']} | Flags: ${c['Red Flags'] || 'None'}`\n).join('\\n');\n\nreturn { \n  json: { \n    job_id: items[0]?.['Job ID'] || 'Unknown',\n    job_title: items[0]?.['Job Title'] || 'Unknown',\n    total_candidates: items.length,\n    candidates_summary: summary,\n    raw_data: JSON.stringify(items)\n  } \n};"
      },
      "typeVersion": 2
    },
    {
      "id": "0acaa63a-a1d3-4fed-a15c-fd7285dcb3fe",
      "name": "Read Candidates from Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        448,
        0
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $('Parse Telegram Command').item.json.job_id }}",
              "lookupColumn": "Job ID"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1PsaktBjJnJ8L06HXmQjqORbgItdpROaXvOBu_svUVAU/edit#gid=0",
          "cachedResultName": "\u041b\u0438\u0441\u04421"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1PsaktBjJnJ8L06HXmQjqORbgItdpROaXvOBu_svUVAU",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1PsaktBjJnJ8L06HXmQjqORbgItdpROaXvOBu_svUVAU/edit?usp=drivesdk",
          "cachedResultName": "CV Screening \u2014 Results"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "ff398057-5362-4ef5-a1e5-0dfb17f9fe35",
      "name": "Generate Comparative Report",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        928,
        0
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {},
        "simplify": false,
        "responses": {
          "values": [
            {
              "role": "system",
              "content": "You are an HR analytics assistant. Generate concise comparative reports about job candidates. Always respond in plain text, not JSON."
            },
            {
              "content": "=Generate a comparative report for the position {{ $json.job_title }} ({{ $json.job_id }}).\n\nTotal candidates: {{ $json.total_candidates }}\n\nCandidates:\n{{ $json.candidates_summary }}\n\nPlease provide:\n1. Ranking of all candidates from best to worst\n2. Top recommendation (who to interview first and why)\n3. Summary of the talent pool quality\nKeep it concise - max 15 lines."
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "cbe245ef-0bde-41c9-af0c-bcf8b2593e6f",
      "name": "Send Report via Telegram",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1280,
        0
      ],
      "parameters": {
        "text": "=\ud83d\udcca COMPARATIVE REPORT\n\n{{ $input.first().json.output[0].content[0].text }}",
        "chatId": "=391064585",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    }
  ],
  "active": true,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "103c0347-9439-4912-af9d-76557767cb0f",
  "connections": {
    "Parse Telegram Command": {
      "main": [
        [
          {
            "node": "Read Candidates from Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transform Candidate Data": {
      "main": [
        [
          {
            "node": "Generate Comparative Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Comparative Report": {
      "main": [
        [
          {
            "node": "Send Report via Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Candidates from Sheets": {
      "main": [
        [
          {
            "node": "Transform Candidate Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When Telegram Message Received": {
      "main": [
        [
          {
            "node": "Parse Telegram Command",
            "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.

Pro

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

About this workflow

Listens for commands via Telegram to trigger report generation. Parses the received command to determine action parameters. Fetches candidate data from Google Sheets based on parsed input. Prepares the data for report generation through custom logic. Generates a comparative…

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

Ask questions like “How much did I spend on food last month?” and get instant answers from your financial data — directly in Telegram.

Telegram Trigger, OpenAI, Google Sheets +2
AI & RAG

&gt; ⚠️ Disclaimer: This workflow uses Community Nodes and must be run on a self-hosted instance of n8n.

HTTP Request, Telegram Trigger, Telegram +2
AI & RAG

Viral Tik Tok Clone Finder. Uses httpRequest, telegramTrigger, openAi, googleSheets. Event-driven trigger; 41 nodes.

HTTP Request, Telegram Trigger, OpenAI +2
AI & RAG

This workflow is designed for content creators, agencies, influencers, and automation builders who want to transform viral videos into personalized avatar-based edits — and automatically publish them

Telegram Trigger, Telegram, HTTP Request +3
AI & RAG

💸 HOW IT WORKS — AI TELEGRAM EXPENSE TRACKER

Telegram Trigger, OpenAI, Google Sheets +1