
multi-source scraping
Description
Categories
đ€ AI & Machine Learning
Nodes Used
n8n-nodes-base.setn8n-nodes-base.coden8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNote
PriceGratuit
Views0
Last Updated11/28/2025
workflow.json
{
"id": "SjiPE2lVXmmyh7Ca",
"meta": {
"instanceId": "7578372eeadee5ee5414cdf5a06141eebec63e21f295454563ddce7b1217363f",
"templateCredsSetupCompleted": true
},
"name": "multi-source scraping",
"tags": [],
"nodes": [
{
"id": "bf0013da-2066-45de-8833-fa2927728f00",
"name": "When chat message received",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"position": [
-288,
0
],
"webhookId": "18e5e55a-53be-4afb-adc5-bdc4dabfa067",
"parameters": {
"options": {}
},
"typeVersion": 1.3
},
{
"id": "9fe3e0e0-f5ac-4018-90b7-f2e4fc7b207d",
"name": "Simple Memory",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
224,
144
],
"parameters": {
"contextWindowLength": 30
},
"typeVersion": 1.3
},
{
"id": "c9e95768-ea7c-43f0-b6fd-a824fc64d60d",
"name": "Google Gemini Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
80,
144
],
"parameters": {
"options": {}
},
"credentials": {
"googlePalmApi": {
"id": "89mVPG21GxPFECbN",
"name": "Google Gemini(PaLM) Api account"
}
},
"typeVersion": 1
},
{
"id": "cd7be0c8-f708-42f8-8411-a3622c25a0bf",
"name": "Firecrawl list",
"type": "n8n-nodes-mcp.mcpClientTool",
"position": [
672,
352
],
"parameters": {},
"credentials": {
"mcpClientApi": {
"id": "aFCnpjjzHv0KPnei",
"name": "MCP: Firecrawl"
}
},
"typeVersion": 1
},
{
"id": "4cdda777-345c-4129-9ada-1a9c01b9a104",
"name": "Firecrawl execute",
"type": "n8n-nodes-mcp.mcpClientTool",
"position": [
672,
464
],
"parameters": {
"toolName": "={{ \n$fromAI(\"tool\", \"the selected tool to use\")\n}}",
"operation": "executeTool",
"toolParameters": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Tool_Parameters', ``, 'json') }}"
},
"credentials": {
"mcpClientApi": {
"id": "aFCnpjjzHv0KPnei",
"name": "MCP: Firecrawl"
}
},
"typeVersion": 1
},
{
"id": "35a550c1-8fb7-40c3-af16-bb059c6d1947",
"name": "Brave list",
"type": "n8n-nodes-mcp.mcpClientTool",
"position": [
768,
352
],
"parameters": {},
"credentials": {
"mcpClientApi": {
"id": "wzdpQy5uTbYZQiko",
"name": "MCP: Brave"
}
},
"typeVersion": 1
},
{
"id": "ecd7944c-0de2-4447-b640-7a7caaa30705",
"name": "Brave execute",
"type": "n8n-nodes-mcp.mcpClientTool",
"position": [
768,
464
],
"parameters": {
"toolName": "={{\n$fromAI(\"tool\", \"the selected tool to use\")\n}}",
"operation": "executeTool",
"toolParameters": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Tool_Parameters', ``, 'json') }}"
},
"credentials": {
"mcpClientApi": {
"id": "wzdpQy5uTbYZQiko",
"name": "MCP: Brave"
}
},
"typeVersion": 1
},
{
"id": "3041cd71-2131-4cf5-b21b-7b7decc0a4bb",
"name": "Apify list",
"type": "n8n-nodes-mcp.mcpClientTool",
"position": [
864,
464
],
"parameters": {},
"credentials": {
"mcpClientApi": {
"id": "0HMXUEhEUFLuWqlS",
"name": "MCP : Apify"
}
},
"typeVersion": 1
},
{
"id": "1ba3c633-998b-4ab2-83c1-c6dd0e7c6679",
"name": "Apify execute",
"type": "n8n-nodes-mcp.mcpClientTool",
"position": [
864,
352
],
"parameters": {
"toolName": "={{ $fromAI(\"tool\", \"the selected tool to use\") }}",
"operation": "executeTool",
"toolParameters": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Tool_Parameters', ``, 'json') }}"
},
"credentials": {
"mcpClientApi": {
"id": "aFCnpjjzHv0KPnei",
"name": "MCP: Firecrawl"
}
},
"typeVersion": 1
},
{
"id": "73031a7a-6338-4683-a6e3-efee3819f89e",
"name": "Data Enrichment Request",
"type": "n8n-nodes-base.httpRequest",
"position": [
1296,
0
],
"parameters": {
"url": "=https://sheets.googleapis.com/v4/spreadsheets/{{ $json.spreadsheetId }}/values:batchUpdate",
"method": "POST",
"options": {},
"jsonBody": "={\n \"valueInputOption\": \"USER_ENTERED\",\n \"data\": {{ JSON.stringify($json.valueRanges) }}\n}",
"sendBody": true,
"specifyBody": "json"
},
"typeVersion": 4.2
},
{
"id": "9a7f6cbe-a132-4fef-9af8-b9851227faf6",
"name": "Gemini Research Orchestrator",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
208,
0
],
"parameters": {
"options": {
"systemMessage": "You are a helpful assistant\n\nUse Brave to search into the web\nUse Firecrawl to scrape websites\nUse Apify to scrape websites\n\nthe process is to use the tool node first then the execute node.\n\nAlways refer to the list of tools before attempting to access or use the execute tools"
}
},
"typeVersion": 2.2
},
{
"id": "acf4a537-627a-4d20-8b02-215f8075900b",
"name": "Create Research Report",
"type": "n8n-nodes-base.googleSheets",
"position": [
704,
0
],
"parameters": {
"title": "scrapped ",
"options": {},
"resource": "spreadsheet"
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "FglkISb2md6llLsJ",
"name": "Google Sheets account"
}
},
"typeVersion": 4.7
},
{
"id": "13e00e06-9b7e-4fb2-bbbd-9e7211de9e96",
"name": "Format Research Data",
"type": "n8n-nodes-base.code",
"position": [
880,
0
],
"parameters": {
"jsCode": "// Version sĂ©curisĂ©e qui gĂšre les feuilles existantes\nconst agentOutput = $('Gemini Research Orchestrator').item.json.output;\nconst spreadsheetId = $('Create Research Report').item.json.spreadsheetId;\n\n// Fonction pour parser le markdown (identique)\nfunction parseAgentOutput(output) {\n const lines = output.split('\\n').filter(line => line.trim() !== '');\n const data = {\n title: '',\n categories: [],\n jobs: []\n };\n \n let currentSection = '';\n let inTable = false;\n let tableHeaders = [];\n \n for (let i = 0; i < lines.length; i++) {\n const line = lines[i].trim();\n \n if (line.startsWith('Voici les donnĂ©es extraites')) {\n data.title = line.replace(/\\*\\*/g, '').replace('Voici les donnĂ©es extraites du site ', '').replace(/[`:`]/g, '');\n }\n \n if (line.startsWith('**') && line.endsWith(':**')) {\n currentSection = line.replace(/\\*\\*/g, '').replace(':', '');\n inTable = false;\n }\n \n if (currentSection === 'CatĂ©gories d\\'emploi' && line.startsWith('* ')) {\n data.categories.push(line.replace('* ', ''));\n }\n \n if (line.startsWith('|') && !inTable) {\n const headers = line.split('|').map(h => h.trim()).filter(h => h !== '');\n if (headers.length > 0) {\n tableHeaders = headers;\n inTable = true;\n i++;\n continue;\n }\n }\n \n if (inTable && line.startsWith('|')) {\n const cells = line.split('|').map(c => c.trim()).filter(c => c !== '');\n if (cells.length === tableHeaders.length) {\n const job = {};\n tableHeaders.forEach((header, index) => {\n job[header] = cells[index] || '';\n });\n data.jobs.push(job);\n }\n }\n }\n \n return data;\n}\n\n// Fonction pour crĂ©er ou mettre Ă jour une feuille\nfunction createOrUpdateSheet(sheetName, sheetId, properties = {}) {\n if (sheetId === 0) {\n // Pour la feuille par dĂ©faut (ID 0), on la met Ă jour\n return {\n updateSheetProperties: {\n properties: {\n sheetId: sheetId,\n title: sheetName,\n gridProperties: {\n rowCount: 1000,\n columnCount: 26\n },\n ...properties\n },\n fields: 'title,tabColor,gridProperties'\n }\n };\n } else {\n // Pour les nouvelles feuilles, on les crĂ©e\n return {\n addSheet: {\n properties: {\n sheetId: sheetId,\n title: sheetName,\n gridProperties: {\n rowCount: 1000,\n columnCount: 26\n },\n ...properties\n }\n }\n };\n }\n}\n\n// Fonction pour ajouter des donnĂ©es dans une feuille\nfunction addSheetData(sheetName, range, values, majorDimension = 'ROWS') {\n return {\n range: `'${sheetName}'!${range}`,\n majorDimension: majorDimension,\n values: values\n };\n}\n\n// Fonction pour formater les cellules\nfunction formatCells(sheetId, range, format) {\n return {\n repeatCell: {\n range: {\n sheetId: sheetId,\n startRowIndex: range.startRow,\n endRowIndex: range.endRow,\n startColumnIndex: range.startCol,\n endColumnIndex: range.endCol\n },\n cell: {\n userEnteredFormat: format\n },\n fields: 'userEnteredFormat'\n }\n };\n}\n\n// Fonction pour obtenir les styles de formatage\nfunction getTextFormat(style) {\n const formats = {\n 'TITLE': {\n textFormat: {\n bold: true,\n fontSize: 16,\n foregroundColor: { red: 0.1, green: 0.1, blue: 0.1 }\n },\n horizontalAlignment: 'CENTER',\n backgroundColor: { red: 0.85, green: 0.85, blue: 0.95 }\n },\n 'SECTION_HEADER': {\n textFormat: {\n bold: true,\n fontSize: 14,\n foregroundColor: { red: 0.2, green: 0.2, blue: 0.2 }\n },\n backgroundColor: { red: 0.9, green: 0.9, blue: 0.9 }\n },\n 'TABLE_HEADER': {\n textFormat: {\n bold: true,\n fontSize: 11,\n foregroundColor: { red: 1, green: 1, blue: 1 }\n },\n backgroundColor: { red: 0.2, green: 0.4, blue: 0.8 },\n horizontalAlignment: 'CENTER',\n borders: {\n top: { style: 'SOLID', width: 2 },\n bottom: { style: 'SOLID', width: 2 },\n left: { style: 'SOLID', width: 1 },\n right: { style: 'SOLID', width: 1 }\n }\n },\n 'TABLE_CELL': {\n textFormat: {\n fontSize: 10,\n foregroundColor: { red: 0.1, green: 0.1, blue: 0.1 }\n },\n borders: {\n top: { style: 'SOLID', width: 1 },\n bottom: { style: 'SOLID', width: 1 },\n left: { style: 'SOLID', width: 1 },\n right: { style: 'SOLID', width: 1 }\n },\n verticalAlignment: 'TOP'\n },\n 'CATEGORY': {\n textFormat: {\n fontSize: 11,\n foregroundColor: { red: 0.3, green: 0.3, blue: 0.3 }\n },\n backgroundColor: { red: 0.95, green: 0.98, blue: 0.95 }\n }\n };\n return formats[style] || formats['TABLE_CELL'];\n}\n\n// Parsing des donnĂ©es\nlet parsedData;\ntry {\n parsedData = parseAgentOutput(agentOutput);\n} catch (error) {\n throw new Error(`Erreur lors du parsing des donnĂ©es: ${error.message}`);\n}\n\n// Construction des requĂȘtes et donnĂ©es\nconst requests = [];\nconst valueRanges = [];\n\ntry {\n // D'abord, effacer le contenu de la feuille par dĂ©faut\n requests.push({\n updateCells: {\n range: {\n sheetId: 0\n },\n fields: '*'\n }\n });\n\n // 1. Mise Ă jour de la feuille par dĂ©faut (ID 0) -> \"RĂ©sumĂ©\"\n requests.push(createOrUpdateSheet('Resume', 0, {\n tabColor: { red: 0.2, green: 0.5, blue: 0.8 }\n }));\n\n // DonnĂ©es de la feuille RĂ©sumĂ©\n const summaryData = [\n [parsedData.title || 'DonnĂ©es extraites'],\n [''],\n ['RĂ©sumĂ© des donnĂ©es:'],\n [`Nombre de catĂ©gories: ${parsedData.categories.length}`],\n [`Nombre d'emplois: ${parsedData.jobs.length}`],\n [''],\n ['CatĂ©gories d\\'emploi:']\n ];\n\n parsedData.categories.forEach(category => {\n summaryData.push([`âą ${category}`]);\n });\n\n valueRanges.push(addSheetData('Resume', 'A1', summaryData));\n\n // Formatage de la feuille RĂ©sumĂ©\n requests.push(formatCells(0, { startRow: 0, endRow: 1, startCol: 0, endCol: 3 }, getTextFormat('TITLE')));\n requests.push(formatCells(0, { startRow: 2, endRow: 3, startCol: 0, endCol: 3 }, getTextFormat('SECTION_HEADER')));\n requests.push(formatCells(0, { startRow: 6, endRow: 7, startCol: 0, endCol: 3 }, getTextFormat('SECTION_HEADER')));\n \n const categoryStartRow = 7;\n const categoryEndRow = categoryStartRow + parsedData.categories.length;\n requests.push(formatCells(0, { \n startRow: categoryStartRow, \n endRow: categoryEndRow, \n startCol: 0, \n endCol: 2 \n }, getTextFormat('CATEGORY')));\n\n // 2. CrĂ©ation de la feuille \"CatĂ©gories\"\n requests.push(createOrUpdateSheet('Categories', 1, {\n tabColor: { red: 0.8, green: 0.9, blue: 0.7 }\n }));\n\n const categoriesData = [\n ['CatĂ©gories d\\'emploi'],\n [''],\n ['CatĂ©gorie', 'NumĂ©ro']\n ];\n\n parsedData.categories.forEach((category, index) => {\n categoriesData.push([category, index + 1]);\n });\n\n valueRanges.push(addSheetData('Categories', 'A1', categoriesData));\n\n requests.push(formatCells(1, { startRow: 0, endRow: 1, startCol: 0, endCol: 2 }, getTextFormat('TITLE')));\n requests.push(formatCells(1, { startRow: 2, endRow: 3, startCol: 0, endCol: 2 }, getTextFormat('TABLE_HEADER')));\n \n if (parsedData.categories.length > 0) {\n requests.push(formatCells(1, { \n startRow: 3, \n endRow: 3 + parsedData.categories.length, \n startCol: 0, \n endCol: 2 \n }, getTextFormat('TABLE_CELL')));\n }\n\n // 3. CrĂ©ation de la feuille \"Emplois\"\n requests.push(createOrUpdateSheet('Emplois', 2, {\n tabColor: { red: 0.9, green: 0.7, blue: 0.8 }\n }));\n\n if (parsedData.jobs.length > 0) {\n const jobHeaders = Object.keys(parsedData.jobs[0]);\n const jobsData = [\n ['Liste des emplois disponibles'],\n [''],\n jobHeaders\n ];\n\n parsedData.jobs.forEach(job => {\n const jobRow = jobHeaders.map(header => job[header] || '');\n jobsData.push(jobRow);\n });\n\n valueRanges.push(addSheetData('Emplois', 'A1', jobsData));\n\n requests.push(formatCells(2, { startRow: 0, endRow: 1, startCol: 0, endCol: jobHeaders.length }, getTextFormat('TITLE')));\n requests.push(formatCells(2, { startRow: 2, endRow: 3, startCol: 0, endCol: jobHeaders.length }, getTextFormat('TABLE_HEADER')));\n \n if (parsedData.jobs.length > 0) {\n requests.push(formatCells(2, { \n startRow: 3, \n endRow: 3 + parsedData.jobs.length, \n startCol: 0, \n endCol: jobHeaders.length \n }, getTextFormat('TABLE_CELL')));\n }\n }\n\n // 4. CrĂ©ation de la feuille \"Statistiques\"\n requests.push(createOrUpdateSheet('Statistiques', 3, {\n tabColor: { red: 0.95, green: 0.8, blue: 0.6 }\n }));\n\n const companyCount = [...new Set(parsedData.jobs.map(job => job.Entreprise || job.Company || ''))].length;\n const roleTypes = {};\n \n parsedData.jobs.forEach(job => {\n const role = job.RĂŽle || job.Role || '';\n const roleType = role.split(' ')[0];\n roleTypes[roleType] = (roleTypes[roleType] || 0) + 1;\n });\n\n const statsData = [\n ['Statistiques des donnĂ©es'],\n [''],\n ['MĂ©trique', 'Valeur'],\n ['Nombre total d\\'emplois', parsedData.jobs.length],\n ['Nombre d\\'entreprises uniques', companyCount],\n ['Nombre de catĂ©gories', parsedData.categories.length],\n [''],\n ['Types de rĂŽles les plus frĂ©quents:'],\n ['Type de rĂŽle', 'Occurrences']\n ];\n\n const sortedRoleTypes = Object.entries(roleTypes)\n .sort(([,a], [,b]) => b - a)\n .slice(0, 10);\n\n sortedRoleTypes.forEach(([role, count]) => {\n statsData.push([role, count]);\n });\n\n valueRanges.push(addSheetData('Statistiques', 'A1', statsData));\n\n requests.push(formatCells(3, { startRow: 0, endRow: 1, startCol: 0, endCol: 2 }, getTextFormat('TITLE')));\n requests.push(formatCells(3, { startRow: 2, endRow: 3, startCol: 0, endCol: 2 }, getTextFormat('TABLE_HEADER')));\n requests.push(formatCells(3, { startRow: 7, endRow: 8, startCol: 0, endCol: 2 }, getTextFormat('SECTION_HEADER')));\n requests.push(formatCells(3, { startRow: 8, endRow: 9, startCol: 0, endCol: 2 }, getTextFormat('TABLE_HEADER')));\n\n // Auto-redimensionnement des colonnes\n for (let i = 0; i <= 3; i++) {\n requests.push({\n autoResizeDimensions: {\n dimensions: {\n sheetId: i,\n dimension: 'COLUMNS',\n startIndex: 0,\n endIndex: 10\n }\n }\n });\n }\n\n} catch (error) {\n console.error('Erreur lors de la gĂ©nĂ©ration du contenu:', error);\n throw new Error(`Erreur lors de la gĂ©nĂ©ration du contenu: ${error.message}`);\n}\n\n// Validation finale des donnĂ©es\nif (!requests || requests.length === 0) {\n throw new Error('Aucune requĂȘte gĂ©nĂ©rĂ©e - vĂ©rifiez les donnĂ©es d\\'entrĂ©e');\n}\n\nif (!valueRanges || valueRanges.length === 0) {\n throw new Error('Aucune donnĂ©e gĂ©nĂ©rĂ©e - vĂ©rifiez les donnĂ©es d\\'entrĂ©e');\n}\n\n// Retour des donnĂ©es pour l'API Google Sheets\nreturn {\n json: {\n spreadsheetId: spreadsheetId,\n requests: requests,\n valueRanges: valueRanges,\n totalRequests: requests.length,\n totalValueRanges: valueRanges.length,\n sheetsCreated: 4,\n dataProcessed: {\n title: parsedData.title,\n categoriesCount: parsedData.categories.length,\n jobsCount: parsedData.jobs.length,\n companiesCount: [...new Set(parsedData.jobs.map(job => job.Entreprise || job.Company || ''))].length\n }\n }\n};"
},
"typeVersion": 2
},
{
"id": "eccede4d-c790-4b60-a3cd-5e9f29ac8f0e",
"name": "Populate Research Report",
"type": "n8n-nodes-base.httpRequest",
"position": [
1072,
0
],
"parameters": {
"url": "=https://sheets.googleapis.com/v4/spreadsheets/{{ $json.spreadsheetId }}:batchUpdate",
"method": "POST",
"options": {},
"jsonBody": "={\n \"requests\": {{ JSON.stringify($json.requests) }}\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleSheetsOAuth2Api"
},
"credentials": {
"googleDocsOAuth2Api": {
"id": "osBJI4KIPRu07ngs",
"name": "Google Docs account"
},
"googleSheetsOAuth2Api": {
"id": "bkpmM7RgsOJtIBT5",
"name": "Google Sheets account 2"
}
},
"typeVersion": 4.2
},
{
"id": "c9603254-752b-4f86-8d77-e6231699094b",
"name": "Finalize Output Data",
"type": "n8n-nodes-base.set",
"position": [
1488,
0
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "{\n \"error_message\": \"{{ $json.error.message }}\",\n \"error_code\": \"{{ $json.error.code }}\",\n \"spreadsheet_id\": \"{{ $('Code').item.json.spreadsheetId }}\",\n \"timestamp\": \"{{ new Date().toISOString() }}\"\n}"
},
"typeVersion": 3.4
},
{
"id": "0c07aba4-88c4-4ddd-93e8-26057f6104f8",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-544,
-96
],
"parameters": {
"color": 4,
"width": 400,
"height": 256,
"content": "## Entry point: \n### - The user sends a request in natural language."
},
"typeVersion": 1
},
{
"id": "4a113616-2e51-4bb7-8995-1c657f12fa9b",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-80,
-320
],
"parameters": {
"color": 4,
"width": 256,
"height": 128,
"content": "## âïž PREREQUISITES\n- **Google Gemini API Key**\n- **MCP API keys (Firecrawl, Brave, Apify)**\n- **Google Sheets credentials**\n- **Self-hosted n8n instance**"
},
"typeVersion": 1
},
{
"id": "fadd1418-2831-4856-9913-de61ec11d418",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
240,
-320
],
"parameters": {
"color": 4,
"height": 128,
"content": "## đ DATA FLOW\n1. **Request â AI analysis**\n2. **Tool selection â Collection**\n3. **Aggregation â Structuring** \n4. **Enrichment â Delivery**"
},
"typeVersion": 1
},
{
"id": "6afc44f5-db99-46a8-96ca-5e788e48bfff",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
528,
-320
],
"parameters": {
"color": 4,
"width": 272,
"height": 112,
"content": "## â ïž ERROR HANDLING\n- **MCP timeout: Automatic retry**\n- **API limit: Fallback modes**\n- **Missing data: Validation**"
},
"typeVersion": 1
},
{
"id": "104c3b3a-ae84-4ef5-99fb-b84cf599975a",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-80,
-112
],
"parameters": {
"color": 5,
"width": 544,
"height": 384,
"content": "## Orchestration\n### - When chat message received\n### - Gemini Research Orchestrator\n### - Simple Memory"
},
"typeVersion": 1
},
{
"id": "4bdd58e3-eddd-4fa3-82f4-bc84ec5498fc",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
240,
288
],
"parameters": {
"width": 752,
"height": 304,
"content": "## Data Collection Tools \n### *The agent automatically selects the* \n### *appropriate tools based on the request.*\n### - Firecrawl (list + execute)\n### - Brave (list + execute)\n### - Apify (list + execute)\n\n\n"
},
"typeVersion": 1
},
{
"id": "509c0f30-e634-46d5-83d2-b4aafd8090b8",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
656,
-160
],
"parameters": {
"color": 3,
"width": 544,
"height": 304,
"content": "## Report Generation\n### *The collected data is automatically organized and formatted.*\n### - Create Research Report\n### - Format Research Data\n### - Populate Research Report"
},
"typeVersion": 1
},
{
"id": "7dd445d7-2785-4f0a-a938-e9e9e962e929",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
1264,
-160
],
"parameters": {
"color": 7,
"width": 432,
"height": 304,
"content": "## Post-Processing\n### *Data enrichment and finalization for delivery*\n### - Data Enrichment Request\n### - Finalize Output Data"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "94fda3e6-3671-42e8-9f8a-d9d7688722eb",
"connections": {
"Apify list": {
"ai_tool": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_tool",
"index": 0
}
]
]
},
"Brave list": {
"ai_tool": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_tool",
"index": 0
}
]
]
},
"Apify execute": {
"ai_tool": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_tool",
"index": 0
}
]
]
},
"Brave execute": {
"ai_tool": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_tool",
"index": 0
}
]
]
},
"Simple Memory": {
"ai_memory": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_memory",
"index": 0
}
]
]
},
"Firecrawl list": {
"ai_tool": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_tool",
"index": 0
}
]
]
},
"Firecrawl execute": {
"ai_tool": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_tool",
"index": 0
}
]
]
},
"Finalize Output Data": {
"main": [
[]
]
},
"Format Research Data": {
"main": [
[
{
"node": "Populate Research Report",
"type": "main",
"index": 0
}
]
]
},
"Create Research Report": {
"main": [
[
{
"node": "Format Research Data",
"type": "main",
"index": 0
}
]
]
},
"Data Enrichment Request": {
"main": [
[
{
"node": "Finalize Output Data",
"type": "main",
"index": 0
}
]
]
},
"Google Gemini Chat Model": {
"ai_languageModel": [
[
{
"node": "Gemini Research Orchestrator",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Populate Research Report": {
"main": [
[
{
"node": "Data Enrichment Request",
"type": "main",
"index": 0
}
]
]
},
"When chat message received": {
"main": [
[
{
"node": "Gemini Research Orchestrator",
"type": "main",
"index": 0
}
]
]
},
"Gemini Research Orchestrator": {
"main": [
[
{
"node": "Create Research Report",
"type": "main",
"index": 0
}
]
]
}
}
}