AutomationFlowsAI & RAG › Telegram Research Agent 02 Research Processor

Telegram Research Agent 02 Research Processor

19-telegram-research-agent-02-research-processor. Uses googleSheets, agent, lmChatGoogleGemini, chainLlm. Scheduled trigger; 25 nodes.

Cron / scheduled trigger★★★★☆ complexityAI-powered25 nodesGoogle SheetsAgentGoogle Gemini ChatChain LlmGoogle DriveTelegram@Mendable/N8N Nodes Firecrawl
AI & RAG Trigger: Cron / scheduled Nodes: 25 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Agent → Chainllm 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": "19-telegram-research-agent-02-research-processor",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 15
            }
          ]
        }
      },
      "id": "68ffd3bd-0007-464b-8488-419614799530",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        -2352,
        3344
      ]
    },
    {
      "parameters": {},
      "id": "d50501cb-2b71-4bf1-b0ad-724f917e4e4c",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -2352,
        3568
      ]
    },
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "={{ $json.SHEET_ID }}",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "={{ $json.SHEET_NAME }}",
          "mode": "name"
        },
        "options": {}
      },
      "id": "d3c4693c-178b-4de8-ac4b-3953d035a801",
      "name": "Sheets: Get All Rows",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        -1792,
        3472
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// L\u1ecdc c\u00e1c y\u00eau c\u1ea7u c\u00f3 status=queue v\u00e0 l\u1ea5y y\u00eau c\u1ea7u \u0111\u1ea7u ti\u00ean (oldest first)\nconst config = $('Set: Config Vars1').first().json;\nconst allItems = $input.all();\n\nconst queueItems = allItems\n  .filter(item => item.json.Status === 'queue')\n  .sort((a, b) => {\n    const dateA = new Date(a.json.Created_At || 0);\n    const dateB = new Date(b.json.Created_At || 0);\n    return dateA - dateB; // oldest first\n  });\n\nif (queueItems.length === 0) {\n  return [{ json: { has_pending: false, config } }];\n}\n\nconst first = queueItems[0].json;\nreturn [{\n  json: {\n    has_pending: true,\n    request_id: first.Request_ID,\n    title: first.Title,\n    raw_request: first.Raw_Request,\n    research_type: first.Research_Type || 'other',\n    chat_id: first.Chat_ID,\n    user_id: first.User_ID,\n    created_at: first.Created_At,\n    // Pass config\n    SHEET_ID: config.SHEET_ID,\n    SHEET_NAME: config.SHEET_NAME,\n    DRIVE_ROOT_FOLDER_ID: config.DRIVE_ROOT_FOLDER_ID,\n    RESEARCH_SOURCES: config.RESEARCH_SOURCES,\n    MAX_SEARCH_RESULTS: config.MAX_SEARCH_RESULTS,\n    TOP_URLS_TO_SCRAPE: config.TOP_URLS_TO_SCRAPE,\n    REPORT_LANGUAGE: config.REPORT_LANGUAGE\n  }\n}];"
      },
      "id": "4d4d3824-76d1-4b4a-ae02-bb5dbb4f7a03",
      "name": "Code: Filter Queue",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1504,
        3472
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "check-pending",
              "leftValue": "={{ $json.has_pending }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "2d026c1d-745e-4abd-aa24-43f4e67cefce",
      "name": "IF: Has Pending?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        -1232,
        3472
      ]
    },
    {
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "={{ $json.SHEET_ID }}",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "={{ $json.SHEET_NAME }}",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Request_ID": "={{ $json.request_id }}",
            "Status": "processing",
            "Updated_At": "={{ new Date().toISOString() }}"
          },
          "matchingColumns": [
            "Request_ID"
          ],
          "schema": [
            {
              "id": "Request_ID",
              "displayName": "Request_ID",
              "required": false,
              "defaultMatch": true,
              "canBeUsedToMatch": true,
              "display": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "Status",
              "displayName": "Status",
              "required": false,
              "defaultMatch": false,
              "canBeUsedToMatch": true,
              "display": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "Updated_At",
              "displayName": "Updated_At",
              "required": false,
              "defaultMatch": false,
              "canBeUsedToMatch": true,
              "display": true,
              "type": "string",
              "removed": false
            }
          ]
        },
        "options": {}
      },
      "id": "fecf9d07-31e8-4f56-b0e8-580b3cb233de",
      "name": "Sheets: Update \u2192 Processing",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        -944,
        3344
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.raw_request }}",
        "options": {
          "systemMessage": "=B\u1ea1n l\u00e0 chuy\u00ean gia research th\u1ecb tr\u01b0\u1eddng v\u00e0 ph\u00e2n t\u00edch d\u1eef li\u1ec7u h\u00e0ng \u0111\u1ea7u.\n\nNHI\u1ec6M V\u1ee4: Nghi\u00ean c\u1ee9u to\u00e0n di\u1ec7n v\u1ec1 ch\u1ee7 \u0111\u1ec1 sau:\nTITLE: {{ $json.title }}\nTYPE: {{ $json.research_type }}\n\nNGU\u1ed2N \u01afU TI\u00caN: {{ $json.RESEARCH_SOURCES }}\n\nQUY TR\u00ccNH B\u1eaeT BU\u1ed8C:\n1. T\u1ea1o 3-4 keyword t\u00ecm ki\u1ebfm ph\u00f9 h\u1ee3p v\u1edbi ch\u1ee7 \u0111\u1ec1 (ti\u1ebfng Vi\u1ec7t v\u00e0 ti\u1ebfng Anh n\u1ebfu c\u1ea7n), \u01b0u ti\u00ean domain t\u1eeb NGU\u1ed2N \u01afU TI\u00caN\n2. D\u00f9ng c\u00f4ng c\u1ee5 \"/search in Firecrawl\" v\u1edbi t\u1eebng keyword \u0111\u1ec3 l\u1ea5y danh s\u00e1ch URLs li\u00ean quan\n3. T\u1eeb k\u1ebft qu\u1ea3 search, ch\u1ecdn 4-5 URLs c\u00f3 n\u1ed9i dung c\u1ee5 th\u1ec3 v\u00e0 uy t\u00edn nh\u1ea5t v\u1ec1 ch\u1ee7 \u0111\u1ec1\n4. D\u00f9ng c\u00f4ng c\u1ee5 \"/scrape in Firecrawl2\" \u0111\u1ec3 \u0111\u1ecdc n\u1ed9i dung \u0111\u1ea7y \u0111\u1ee7 t\u1eebng URL \u0111\u00f3\n5. Thu th\u1eadp s\u1ed1 li\u1ec7u c\u1ee5 th\u1ec3, th\u1ed1ng k\u00ea, d\u1eef li\u1ec7u \u0111\u1ecbnh l\u01b0\u1ee3ng t\u1eeb c\u00e1c b\u00e0i vi\u1ebft\n\nY\u00caU C\u1ea6U:\n- \u01afu ti\u00ean t\u00ecm: s\u1ed1 li\u1ec7u th\u1ecb tr\u01b0\u1eddng, xu h\u01b0\u1edbng, \u0111\u1ed1i th\u1ee7, c\u01a1 h\u1ed9i, r\u1ee7i ro\n- M\u1ed7i URL scrape, gi\u1eef l\u1ea1i ph\u1ea7n n\u1ed9i dung quan tr\u1ecdng nh\u1ea5t\n- T\u1ed5ng h\u1ee3p v\u00e0 tr\u1ea3 v\u1ec1 k\u1ebft qu\u1ea3 research ho\u00e0n ch\u1ec9nh b\u1eb1ng ti\u1ebfng Vi\u1ec7t bao g\u1ed3m:\n  * C\u00e1c ph\u00e1t hi\u1ec7n ch\u00ednh v\u1edbi d\u1eabn ch\u1ee9ng t\u1eeb ngu\u1ed3n\n  * S\u1ed1 li\u1ec7u, th\u1ed1ng k\u00ea quan tr\u1ecdng\n  * Danh s\u00e1ch URLs \u0111\u00e3 s\u1eed d\u1ee5ng",
          "maxIterations": 15
        }
      },
      "id": "4d74712d-50e7-45e1-bc45-f08c53d0455b",
      "name": "AI Agent: Research",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 1.7,
      "position": [
        -368,
        3344
      ],
      "onError": "continueErrorOutput"
    },
    {
      "parameters": {
        "modelName": "models/gemini-3-flash-preview",
        "options": {
          "maxOutputTokens": 8192,
          "temperature": 0.3
        }
      },
      "id": "34b3d9a3-072d-4ee5-99d5-5746769fc388",
      "name": "Gemini Flash (Agent)",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        -496,
        3648
      ],
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=D\u1ef1a tr\u00ean k\u1ebft qu\u1ea3 research sau \u0111\u00e2y, vi\u1ebft m\u1ed9t B\u00c1O C\u00c1O CHUY\u00caN S\u00c2U HO\u00c0N CH\u1ec8NH b\u1eb1ng ti\u1ebfng Vi\u1ec7t.\n\n--- D\u1eee LI\u1ec6U RESEARCH ---\n{{ $json.output }}\n--- K\u1ebeT TH\u00daC D\u1eee LI\u1ec6U ---\n\nTH\u00d4NG TIN B\u00c1O C\u00c1O:\n- Ti\u00eau \u0111\u1ec1: {{ $node['Code: Filter Queue'].json.title }}\n- Lo\u1ea1i nghi\u00ean c\u1ee9u: {{ $node['Code: Filter Queue'].json.research_type }}\n- Ng\u00e0y: {{ new Date().toLocaleDateString('vi-VN') }}\n\nVi\u1ebft b\u00e1o c\u00e1o theo \u0111\u00fang format Markdown sau:\n\n# {{ $node['Code: Filter Queue'].json.title }}\n\n**Ng\u00e0y b\u00e1o c\u00e1o:** [ng\u00e0y h\u00f4m nay] | **Lo\u1ea1i:** [research_type] | **Tr\u1ea1ng th\u00e1i:** Ho\u00e0n th\u00e0nh\n\n---\n\n## T\u00f3m T\u1eaft \u0110i\u1ec1u H\u00e0nh\n[3-5 bullet points v\u1edbi c\u00e1c ph\u00e1t hi\u1ec7n quan tr\u1ecdng nh\u1ea5t]\n\n## B\u1ed1i C\u1ea3nh & T\u1ed5ng Quan\n[Gi\u1edbi thi\u1ec7u v\u1ec1 ch\u1ee7 \u0111\u1ec1, t\u1ea1i sao quan tr\u1ecdng]\n\n## Ph\u00e2n T\u00edch Chi Ti\u1ebft\n[N\u1ed9i dung ph\u00e2n t\u00edch s\u00e2u v\u1edbi d\u1eabn ch\u1ee9ng v\u00e0 s\u1ed1 li\u1ec7u]\n\n## D\u1eef Li\u1ec7u & S\u1ed1 Li\u1ec7u Quan Tr\u1ecdng\n[B\u1ea3ng ho\u1eb7c danh s\u00e1ch c\u00e1c s\u1ed1 li\u1ec7u, th\u1ed1ng k\u00ea c\u1ee5 th\u1ec3]\n\n## Xu H\u01b0\u1edbng & C\u01a1 H\u1ed9i\n[C\u00e1c xu h\u01b0\u1edbng \u0111ang n\u1ed5i l\u00ean v\u00e0 c\u01a1 h\u1ed9i ti\u1ec1m n\u0103ng]\n\n## R\u1ee7i Ro & Th\u00e1ch Th\u1ee9c\n[C\u00e1c r\u1ee7i ro c\u1ea7n l\u01b0u \u00fd]\n\n## K\u1ebft Lu\u1eadn & Khuy\u1ebfn Ngh\u1ecb\n[3-5 khuy\u1ebfn ngh\u1ecb h\u00e0nh \u0111\u1ed9ng c\u1ee5 th\u1ec3]\n\n## Ngu\u1ed3n Tham Kh\u1ea3o\n[Danh s\u00e1ch c\u00e1c URLs \u0111\u00e3 s\u1eed d\u1ee5ng]\n\nY\u00caU C\u1ea6U:\n- Ng\u00f4n ng\u1eef ti\u1ebfng Vi\u1ec7t chu\u1ea9n, chuy\u00ean nghi\u1ec7p\n- T\u1ed5ng \u0111\u1ed9 d\u00e0i 2000-3500 t\u1eeb\n- Tr\u00edch d\u1eabn s\u1ed1 li\u1ec7u v\u1edbi ngu\u1ed3n r\u00f5 r\u00e0ng\n- S\u1eed d\u1ee5ng format Markdown chu\u1ea9n (heading ##, bold **text**, bullet -, b\u1ea3ng |---|)"
      },
      "id": "9461c57c-e0f8-4648-8041-e110d707be69",
      "name": "Gemini: Write Report",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "typeVersion": 1.5,
      "position": [
        -16,
        3088
      ]
    },
    {
      "parameters": {
        "modelName": "models/gemini-3-flash-preview",
        "options": {
          "maxOutputTokens": 8192,
          "temperature": 0.4
        }
      },
      "id": "fcec3fc3-5936-4856-8987-4fe36238a0e9",
      "name": "Gemini Flash (Report)",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        -16,
        3264
      ],
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Chu\u1ea9n b\u1ecb n\u1ed9i dung file b\u00e1o c\u00e1o v\u00e0 t\u00ean folder\nconst reportMarkdown = $input.first().json.text || '';\nconst req = $('Code: Rebuild Context').first().json;\n\n// T\u1ea1o t\u00ean folder: RequestID - Title - YYYY-MM-DD\nconst dateStr = new Date().toISOString().split('T')[0]; // YYYY-MM-DD\nconst safeTitle = req.title\n  .replace(/[/\\\\:*?\"<>|]/g, '-') // k\u00fd t\u1ef1 kh\u00f4ng h\u1ee3p l\u1ec7 cho t\u00ean folder\n  .substring(0, 60);\nconst folderName = `${req.request_id} - ${safeTitle} - ${dateStr}`;\n\n// Encode report sang base64 \u0111\u1ec3 upload Drive\nconst reportBuffer = Buffer.from(reportMarkdown, 'utf-8');\nconst reportBase64 = reportBuffer.toString('base64');\n\n// Tr\u00edch xu\u1ea5t overview (200 k\u00fd t\u1ef1 \u0111\u1ea7u c\u1ee7a n\u1ed9i dung sau header)\nconst lines = reportMarkdown.split('\\n').filter(l => l.trim());\nlet overview = '';\nfor (const line of lines) {\n  if (!line.startsWith('#') && !line.startsWith('---') && !line.startsWith('**')) {\n    overview += line.replace(/[*_#]/g, '').trim() + ' ';\n    if (overview.length > 200) break;\n  }\n}\noverview = overview.trim().substring(0, 250);\n\nreturn [{\n  json: {\n    folder_name: folderName,\n    report_filename: `report-${req.request_id}.md`,\n    report_markdown: reportMarkdown,\n    overview: overview || req.title,\n    request_id: req.request_id,\n    chat_id: req.chat_id,\n    title: req.title,\n    DRIVE_ROOT_FOLDER_ID: req.DRIVE_ROOT_FOLDER_ID,\n    SHEET_ID: req.SHEET_ID,\n    SHEET_NAME: req.SHEET_NAME\n  },\n  binary: {\n    reportFile: {\n      data: reportBase64,\n      mimeType: 'text/markdown',\n      fileName: `report-${req.request_id}.md`,\n      fileExtension: 'md'\n    }\n  }\n}];"
      },
      "id": "29d8b57d-c409-4fec-93c4-eba5a7d7942e",
      "name": "Code: Prepare Files",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        256,
        3088
      ]
    },
    {
      "parameters": {
        "jsCode": "// L\u01b0u folder ID v\u00e0 chu\u1ea9n b\u1ecb d\u1eef li\u1ec7u cho upload\nconst folderResponse = $input.first().json;\nconst prevData = $('Code: Prepare Files').first().json;\nconst prevBinary = $('Code: Prepare Files').first().binary;\n\nconst folderId = folderResponse.id || '';\nconst folderLink = folderId ? `https://drive.google.com/drive/folders/${folderId}` : '';\n\nreturn [{\n  json: {\n    ...prevData,\n    folder_id: folderId,\n    folder_link: folderLink\n  },\n  binary: prevBinary\n}];"
      },
      "id": "4bd39986-a8ac-4bed-9f65-32237bd75516",
      "name": "Code: Save Folder ID",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        592,
        3088
      ]
    },
    {
      "parameters": {
        "inputDataFieldName": "reportFile",
        "name": "={{ $json.report_filename }}",
        "driveId": {
          "__rl": true,
          "value": "My Drive",
          "mode": "list",
          "cachedResultName": "My Drive"
        },
        "folderId": {
          "__rl": true,
          "value": "={{ $json.folder_id }}",
          "mode": "id"
        },
        "options": {}
      },
      "id": "49dbab36-7159-4c95-b0ac-ba29ddfd6cf5",
      "name": "Drive: Upload Report",
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        768,
        3088
      ],
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "onError": "continueErrorOutput"
    },
    {
      "parameters": {
        "jsCode": "// Build final data sau khi upload\nconst uploadResp = $input.first().json;\nconst prev = $('Code: Save Folder ID').first().json;\n\nconst fileId = uploadResp.id || '';\nconst fileLink = uploadResp.webViewLink || (fileId ? `https://drive.google.com/file/d/${fileId}/view` : '');\n\nreturn [{\n  json: {\n    request_id: prev.request_id,\n    title: prev.title,\n    overview: prev.overview,\n    chat_id: prev.chat_id,\n    folder_link: prev.folder_link,\n    folder_id: prev.folder_id,\n    file_link: fileLink,\n    file_id: fileId,\n    SHEET_ID: prev.SHEET_ID,\n    SHEET_NAME: prev.SHEET_NAME\n  }\n}];"
      },
      "id": "839d9690-84ba-4182-9087-aec7be90072c",
      "name": "Code: Build Final Data",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        960,
        3072
      ]
    },
    {
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "={{ $json.SHEET_ID }}",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "={{ $json.SHEET_NAME }}",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Request_ID": "={{ $json.request_id }}",
            "Status": "done",
            "Overview": "={{ $json.overview }}",
            "Drive_Folder_Link": "={{ $json.folder_link }}",
            "Report_Link": "={{ $json.file_link }}",
            "Updated_At": "={{ new Date().toISOString() }}"
          },
          "matchingColumns": [
            "Request_ID"
          ],
          "schema": [
            {
              "id": "Request_ID",
              "displayName": "Request_ID",
              "required": false,
              "defaultMatch": true,
              "canBeUsedToMatch": true,
              "display": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "Status",
              "displayName": "Status",
              "required": false,
              "defaultMatch": false,
              "canBeUsedToMatch": true,
              "display": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "Overview",
              "displayName": "Overview",
              "required": false,
              "defaultMatch": false,
              "canBeUsedToMatch": true,
              "display": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "Drive_Folder_Link",
              "displayName": "Drive_Folder_Link",
              "required": false,
              "defaultMatch": false,
              "canBeUsedToMatch": true,
              "display": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "Report_Link",
              "displayName": "Report_Link",
              "required": false,
              "defaultMatch": false,
              "canBeUsedToMatch": true,
              "display": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "Updated_At",
              "displayName": "Updated_At",
              "required": false,
              "defaultMatch": false,
              "canBeUsedToMatch": true,
              "display": true,
              "type": "string",
              "removed": false
            }
          ]
        },
        "options": {}
      },
      "id": "53d3819e-2aac-452f-849b-0988b47e5c7f",
      "name": "Sheets: Update \u2192 Done",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        1168,
        3072
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $node['Code: Build Final Data'].json.chat_id }}",
        "text": "=\ud83d\udcca *B\u00e1o c\u00e1o Research Ho\u00e0n Th\u00e0nh!*\n\n\ud83d\udccc *Ch\u1ee7 \u0111\u1ec1:* {{ $node['Code: Build Final Data'].json.title }}\n\ud83c\udd94 *ID:* `{{ $node['Code: Build Final Data'].json.request_id }}`\n\n\ud83d\udcdd *T\u00f3m t\u1eaft:*\n{{ $node['Code: Build Final Data'].json.overview }}\n\n\ud83d\udcc1 *Folder Drive:* [Xem t\u1ea1i \u0111\u00e2y]({{ $node['Code: Build Final Data'].json.folder_link }})\n\ud83d\udcc4 *File B\u00e1o C\u00e1o:* [T\u1ea3i v\u1ec1]({{ $node['Code: Build Final Data'].json.file_link }})\n\n\u2705 Nghi\u00ean c\u1ee9u ho\u00e0n t\u1ea5t! M\u1eddi b\u1ea1n xem chi ti\u1ebft b\u00e1o c\u00e1o.",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "075b56e7-6e40-474d-b3b5-4b9b6b3a842c",
      "name": "Telegram: Notify Done",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1376,
        3072
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Kh\u00f4ng c\u00f3 y\u00eau c\u1ea7u \u0111ang ch\u1edd \u2192 d\u1eebng l\u1ea1i\nconsole.log('[Research Processor] Kh\u00f4ng c\u00f3 y\u00eau c\u1ea7u n\u00e0o trong queue.');\nreturn [];"
      },
      "id": "345dac17-3130-4508-b9a5-1ce2c83c01b4",
      "name": "No Op: No Pending",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -944,
        3568
      ]
    },
    {
      "parameters": {
        "jsCode": "// X\u1eed l\u00fd l\u1ed7i - l\u1ea5y data t\u1eeb $input (ch\u1ee9a full context t\u1eeb Code: Rebuild Context)\n// KH\u00d4NG d\u00f9ng $node[] reference v\u00ec error branch c\u00f3 th\u1ec3 kh\u00f4ng truy c\u1eadp \u0111\u01b0\u1ee3c\nconst failedItem = $input.first();\nconst data = failedItem.json || {};\n\n// L\u1ea5y th\u00f4ng tin l\u1ed7i t\u1eeb field error (n8n th\u00eam v\u00e0o khi continueErrorOutput)\nconst errorObj = data.error || {};\nconst errorMessage = typeof errorObj === 'string'\n  ? errorObj\n  : (errorObj.message || errorObj.description || JSON.stringify(errorObj) || 'Unknown error');\n\nreturn [{\n  json: {\n    request_id: data.request_id || 'UNKNOWN',\n    title: data.title || 'Unknown request',\n    chat_id: data.chat_id || '',\n    error_message: String(errorMessage).substring(0, 500),\n    SHEET_ID: data.SHEET_ID || '',\n    SHEET_NAME: data.SHEET_NAME || ''\n  }\n}];"
      },
      "id": "4f4b1d71-a997-4269-aaaf-c7a338e82f7c",
      "name": "Code: Handle Error",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        960,
        3360
      ]
    },
    {
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "={{ $json.SHEET_ID }}",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "={{ $json.SHEET_NAME }}",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Request_ID": "={{ $json.request_id }}",
            "Status": "error",
            "Overview": "=L\u1ed7i x\u1eed l\u00fd: {{ $json.error_message.substring(0, 200) }}",
            "Updated_At": "={{ new Date().toISOString() }}"
          },
          "matchingColumns": [
            "Request_ID"
          ],
          "schema": [
            {
              "id": "Request_ID",
              "displayName": "Request_ID",
              "required": false,
              "defaultMatch": true,
              "canBeUsedToMatch": true,
              "display": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "Status",
              "displayName": "Status",
              "required": false,
              "defaultMatch": false,
              "canBeUsedToMatch": true,
              "display": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "Overview",
              "displayName": "Overview",
              "required": false,
              "defaultMatch": false,
              "canBeUsedToMatch": true,
              "display": true,
              "type": "string",
              "removed": false
            },
            {
              "id": "Updated_At",
              "displayName": "Updated_At",
              "required": false,
              "defaultMatch": false,
              "canBeUsedToMatch": true,
              "display": true,
              "type": "string",
              "removed": false
            }
          ]
        },
        "options": {}
      },
      "id": "9233a352-43e1-43e8-b530-4024fd3be55f",
      "name": "Sheets: Update \u2192 Error",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        1184,
        3360
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $json.chat_id }}",
        "text": "=\u274c *C\u00f3 l\u1ed7i khi x\u1eed l\u00fd y\u00eau c\u1ea7u!*\n\n\ud83c\udd94 *ID:* `{{ $json.request_id }}`\n\ud83d\udccc *Ch\u1ee7 \u0111\u1ec1:* {{ $json.title }}\n\n\u26a0\ufe0f Vui l\u00f2ng ki\u1ec3m tra l\u1ea1i sau ho\u1eb7c th\u1eed l\u1ea1i y\u00eau c\u1ea7u.\n\n_Chi ti\u1ebft l\u1ed7i \u0111\u00e3 \u0111\u01b0\u1ee3c ghi nh\u1eadn trong h\u1ec7 th\u1ed1ng._",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "5aee0456-f2e2-4c60-a10c-9b71b85c0e83",
      "name": "Telegram: Notify Error",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1376,
        3360
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Sheets Update node ch\u1ec9 pass qua {Request_ID, Status, Updated_At} \u2192 c\u1ea7n restore full context\n// D\u00f9ng $() accessor (n8n v1+ recommended) \u0111\u1ec3 l\u1ea5y data t\u1eeb Code: Filter Queue \u0111\u00e3 ch\u1ea1y tr\u01b0\u1edbc\nlet queue;\ntry {\n  // C\u00e1ch 1: n8n v1+ item accessor - recommended\n  queue = $('Code: Filter Queue').first().json;\n} catch (e1) {\n  try {\n    // C\u00e1ch 2: node reference accessor - fallback\n    queue = $('Code: Filter Queue').first().json;\n  } catch (e2) {\n    throw new Error('Cannot restore context. Err1: ' + e1.message + ' | Err2: ' + e2.message);\n  }\n}\n\nif (!queue || !queue.request_id) {\n  throw new Error('Context empty after restore - check Code: Filter Queue output');\n}\n\nreturn [{ json: queue }];"
      },
      "id": "acf568ad-3468-4c7b-998c-d0e905bddba6",
      "name": "Code: Rebuild Context",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -672,
        3344
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "c01",
              "name": "SHEET_ID",
              "value": "YOUR_SHEET_ID",
              "type": "string"
            },
            {
              "id": "c02",
              "name": "SHEET_NAME",
              "value": "Research Queue",
              "type": "string"
            },
            {
              "id": "c03",
              "name": "DRIVE_ROOT_FOLDER_ID",
              "value": "YOUR_DRIVE_ROOT_FOLDER_ID",
              "type": "string"
            },
            {
              "id": "c05",
              "name": "RESEARCH_SOURCES",
              "value": "vnexpress.net,cafef.vn,tuoitre.vn,thanhnien.vn,mof.gov.vn,gso.gov.vn,statista.com,reuters.com,bloomberg.com,techcrunch.com,mckinsey.com,deloitte.com",
              "type": "string"
            },
            {
              "id": "c06",
              "name": "MAX_SEARCH_RESULTS",
              "value": "8",
              "type": "string"
            },
            {
              "id": "c07",
              "name": "TOP_URLS_TO_SCRAPE",
              "value": "5",
              "type": "string"
            },
            {
              "id": "c08",
              "name": "REPORT_LANGUAGE",
              "value": "Vietnamese",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "44d2ad08-c14e-48b0-9dbf-40f773267f04",
      "name": "Set: Config Vars1",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -2064,
        3472
      ],
      "notes": "\u2699\ufe0f C\u1ea4U H\u00ccNH CH\u00cdNH: \u0110i\u1ec1n SHEET_ID, DRIVE_ROOT_FOLDER_ID v\u00e0 danh s\u00e1ch ngu\u1ed3n \u01b0u ti\u00ean RESEARCH_SOURCES t\u1ea1i \u0111\u00e2y. Firecrawl API Key c\u1ea5u h\u00ecnh trong Credentials c\u1ee7a node Firecrawl."
    },
    {
      "parameters": {
        "operation": "scrape",
        "url": "={{ $fromAI('url', 'URL \u0111\u1ea7y \u0111\u1ee7 c\u1ee7a trang c\u1ea7n \u0111\u1ecdc n\u1ed9i dung, v\u00ed d\u1ee5: https://vnexpress.net/bai-viet-123') }}",
        "requestOptions": {}
      },
      "type": "@mendable/n8n-nodes-firecrawl.firecrawlTool",
      "typeVersion": 1,
      "position": [
        -144,
        3648
      ],
      "id": "d8de1969-a98b-40d7-baba-5e81b974bbbc",
      "name": "/scrape in Firecrawl2",
      "credentials": {
        "firecrawlApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "MapSearch",
        "operation": "search",
        "query": "={{ $fromAI('query', 'T\u1eeb kh\u00f3a t\u00ecm ki\u1ebfm th\u00f4ng tin, v\u00ed d\u1ee5: th\u1ecb tr\u01b0\u1eddng xe \u0111i\u1ec7n Vi\u1ec7t Nam 2025') }}",
        "requestOptions": {}
      },
      "type": "@mendable/n8n-nodes-firecrawl.firecrawlTool",
      "typeVersion": 1,
      "position": [
        -304,
        3648
      ],
      "id": "8f4d62ed-5921-4abb-acda-2da91b7803d9",
      "name": "/search in Firecrawl",
      "credentials": {
        "firecrawlApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "folder",
        "name": "={{ $json.folder_name }}",
        "driveId": {
          "__rl": true,
          "value": "={{ $json.DRIVE_ROOT_FOLDER_ID }}",
          "mode": "id"
        },
        "folderId": {
          "__rl": true,
          "value": "={{ $json.DRIVE_ROOT_FOLDER_ID }}",
          "mode": "id"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        432,
        3088
      ],
      "id": "38da1467-a362-40fc-859b-9e09f671c090",
      "name": "Create folder",
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Set: Config Vars1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Set: Config Vars1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sheets: Get All Rows": {
      "main": [
        [
          {
            "node": "Code: Filter Queue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: Filter Queue": {
      "main": [
        [
          {
            "node": "IF: Has Pending?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF: Has Pending?": {
      "main": [
        [
          {
            "node": "Sheets: Update \u2192 Processing",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Op: No Pending",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sheets: Update \u2192 Processing": {
      "main": [
        [
          {
            "node": "Code: Rebuild Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Flash (Agent)": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent: Research",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent: Research": {
      "main": [
        [
          {
            "node": "Gemini: Write Report",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Code: Handle Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Flash (Report)": {
      "ai_languageModel": [
        [
          {
            "node": "Gemini: Write Report",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Gemini: Write Report": {
      "main": [
        [
          {
            "node": "Code: Prepare Files",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: Prepare Files": {
      "main": [
        [
          {
            "node": "Create folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: Save Folder ID": {
      "main": [
        [
          {
            "node": "Drive: Upload Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Drive: Upload Report": {
      "main": [
        [
          {
            "node": "Code: Build Final Data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Code: Handle Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: Build Final Data": {
      "main": [
        [
          {
            "node": "Sheets: Update \u2192 Done",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sheets: Update \u2192 Done": {
      "main": [
        [
          {
            "node": "Telegram: Notify Done",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: Handle Error": {
      "main": [
        [
          {
            "node": "Sheets: Update \u2192 Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sheets: Update \u2192 Error": {
      "main": [
        [
          {
            "node": "Telegram: Notify Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: Rebuild Context": {
      "main": [
        [
          {
            "node": "AI Agent: Research",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set: Config Vars1": {
      "main": [
        [
          {
            "node": "Sheets: Get All Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "/scrape in Firecrawl2": {
      "ai_tool": [
        [
          {
            "node": "AI Agent: Research",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "/search in Firecrawl": {
      "ai_tool": [
        [
          {
            "node": "AI Agent: Research",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Create folder": {
      "main": [
        [
          {
            "node": "Code: Save Folder ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "availableInMCP": false
  },
  "versionId": "a429f0ce-3922-438c-b892-f5d5e29e3dfd",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "evvOm6EdqHzoPPYU",
  "tags": [
    {
      "updatedAt": "2026-05-29T07:46:11.087Z",
      "createdAt": "2026-05-29T07:46:11.087Z",
      "id": "pHmdbe3WVnvAQV7N",
      "name": "research-agent"
    }
  ]
}

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

19-telegram-research-agent-02-research-processor. Uses googleSheets, agent, lmChatGoogleGemini, chainLlm. Scheduled trigger; 25 nodes.

Source: https://github.com/congdinh2008/n8n-compose/blob/981f311fd5a6a76e50dbc259afccd1bdf346a833/workflows/enterprise/19-telegram-research-agent/02-research-processor.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

Sign up for Decodo — get better pricing here

@Decodo/N8N Nodes Decodo, Google Gemini Chat, Output Parser Structured +5
AI & RAG

Customer support calls contain a wealth of valuable feedback and urgent issues, but manually reviewing audio files is inefficient. This workflow acts as an AI assistant for your call log, transforming

Google Drive, Google Gemini Chat, Output Parser Structured +4
AI & RAG

This workflow creates a multi-talented AI assistant named Simran that interacts with users via Telegram. It can handle text and voice messages, understand the user's intent, and perform various tasks.

MongoDB, Chain Llm, Google Gemini Chat +11
AI & RAG

Arvifund - Supabase. Uses httpRequest, telegram, googleSheets, telegramTrigger. Event-driven trigger; 90 nodes.

HTTP Request, Telegram, Google Sheets +8
AI & RAG

Arvifund - Supabase (Fixed v2). Uses httpRequest, telegram, googleSheets, telegramTrigger. Event-driven trigger; 90 nodes.

HTTP Request, Telegram, Google Sheets +9