This workflow corresponds to n8n.io template #13608 — we link there as the canonical source.
This workflow follows the Chainllm → Form Trigger 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 →
{
"name": "Research any topic and email an AI report with self-healing scraper",
"tags": [],
"nodes": [
{
"id": "p-main-sticky",
"name": "Main Guide",
"type": "n8n-nodes-base.stickyNote",
"position": [
-416,
-80
],
"parameters": {
"color": 4,
"width": 380,
"height": 532,
"content": "## Research any topic and email an AI report with self-healing scraper\n\n## How it works\n1. Submit a research topic via the form (topic, number of sources, recipient email)\n2. SerpApi searches Google and returns results\n3. Junk domains (Reddit, YouTube, PDFs) are filtered out\n4. Each URL is processed **one at a time** in a loop:\n - Jina.ai scrapes the page (free, no key needed)\n - Claude analyzes the content and extracts key findings\n - If a CAPTCHA or block is detected, Firecrawl retries automatically\n - If still blocked after 2 attempts, the source is marked as unavailable\n5. All findings are aggregated and Claude writes a structured executive report\n6. The report is converted to styled HTML and emailed to the recipient\n\n## Setup steps\n1. **SerpApi** \u2014 sign up at serpapi.com, paste your API key into the `SerpApi Search` node (query param `api_key`)\n2. **Firecrawl** \u2014 sign up at firecrawl.dev, paste your key into the `Firecrawl` node (`Authorization: Bearer YOUR_KEY`)\n3. **Anthropic** \u2014 create an Anthropic API credential in n8n and connect it to the three Claude nodes\n4. **Gmail** \u2014 create a Gmail OAuth2 credential in n8n and connect it to `Send Gmail`"
},
"typeVersion": 1
},
{
"id": "p-err-note",
"name": "Error Handler Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-416,
464
],
"parameters": {
"color": 5,
"width": 556,
"height": 388,
"content": "## Error handler\nCatches any workflow failure and extracts the error message, node name, and execution URL.\n\n**To enable:** Workflow Settings \u2192 Error Workflow \u2192 select this workflow.\n\n**Extend:** Add a Slack or Gmail node after `Format Error` to receive failure alerts."
},
"typeVersion": 1
},
{
"id": "p-s1",
"name": "S1",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
-80
],
"parameters": {
"color": 7,
"width": 804,
"height": 80,
"content": "**1 \u2014 Input & search**"
},
"typeVersion": 1
},
{
"id": "p-s2",
"name": "S2",
"type": "n8n-nodes-base.stickyNote",
"position": [
880,
-80
],
"parameters": {
"color": 7,
"width": 1480,
"height": 80,
"content": "**2 \u2014 Self-healing loop** (one URL at a time \u00b7 output[0]=done \u2192 Aggregate \u00b7 output[1]=loop body \u00b7 Enrich feeds back)"
},
"typeVersion": 1
},
{
"id": "p-s3",
"name": "S3",
"type": "n8n-nodes-base.stickyNote",
"position": [
2464,
-80
],
"parameters": {
"color": 5,
"width": 1252,
"height": 80,
"content": "**3 \u2014 Firecrawl fallback** (only runs if Jina is blocked)"
},
"typeVersion": 1
},
{
"id": "p-s4",
"name": "S4",
"type": "n8n-nodes-base.stickyNote",
"position": [
3792,
-80
],
"parameters": {
"color": 7,
"width": 1128,
"height": 80,
"content": "**4 \u2014 Synthesis & delivery**"
},
"typeVersion": 1
},
{
"id": "p1",
"name": "Research Form",
"type": "n8n-nodes-base.formTrigger",
"position": [
32,
128
],
"parameters": {
"options": {},
"formTitle": "Self-Healing Research Agent",
"formFields": {
"values": [
{
"fieldLabel": "Research Topic",
"placeholder": "e.g. Best project management tools 2025",
"requiredField": true
},
{
"fieldType": "dropdown",
"fieldLabel": "Number of Sources",
"fieldOptions": {
"values": [
{
"option": "5"
},
{
"option": "6"
},
{
"option": "7"
}
]
},
"requiredField": true
},
{
"fieldType": "email",
"fieldLabel": "Recipient Email",
"requiredField": true
}
]
},
"formDescription": "Enter a research topic to receive an AI-synthesized executive report by email."
},
"typeVersion": 2.5
},
{
"id": "p2",
"name": "Set Config",
"type": "n8n-nodes-base.set",
"position": [
240,
128
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "a1",
"name": "topic",
"type": "string",
"value": "={{ $json['Research Topic'] }}"
},
{
"id": "a2",
"name": "numSources",
"type": "number",
"value": "={{ parseInt($json['Number of Sources']) || 5 }}"
},
{
"id": "a3",
"name": "recipientEmail",
"type": "string",
"value": "={{ $json['Recipient Email'] }}"
},
{
"id": "a4",
"name": "runId",
"type": "string",
"value": "={{ $now.toFormat('yyyyMMddHHmmss') }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "p3",
"name": "SerpApi Search",
"type": "n8n-nodes-base.httpRequest",
"position": [
464,
128
],
"parameters": {
"url": "https://serpapi.com/search",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "={{ $json.topic }}"
},
{
"name": "num",
"value": "={{ $json.numSources * 2 + 3 }}"
},
{
"name": "engine",
"value": "google"
},
{
"name": "api_key",
"value": "YOUR_SERPAPI_KEY"
}
]
}
},
"typeVersion": 4.4
},
{
"id": "p4",
"name": "Parse & Filter URLs",
"type": "n8n-nodes-base.code",
"position": [
688,
128
],
"parameters": {
"jsCode": "const data = $input.first().json;\nconst config = $('Set Config').first().json;\nconst SKIP = ['.pdf','twitter.com','x.com','facebook.com','instagram.com','tiktok.com','youtube.com','reddit.com'];\nconst results = (data.organic_results || []).filter(r => !SKIP.some(s => (r.link || '').toLowerCase().includes(s))).slice(0, config.numSources);\nif (results.length === 0) throw new Error('No valid URLs found for topic: ' + config.topic);\nreturn results.map((r, i) => ({json:{urlIndex:i+1,url:r.link,title:r.title||'',snippet:r.snippet||'',topic:config.topic,recipientEmail:config.recipientEmail,runId:config.runId}}));\n"
},
"typeVersion": 2
},
{
"id": "p5",
"name": "Loop Over URLs",
"type": "n8n-nodes-base.splitInBatches",
"position": [
912,
128
],
"parameters": {
"options": {},
"batchSize": 1
},
"typeVersion": 3
},
{
"id": "p6",
"name": "Jina Reader (Primary)",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
1120,
128
],
"parameters": {
"url": "=https://r.jina.ai/{{ $json.url }}",
"options": {
"timeout": 30000,
"response": {
"response": {
"responseFormat": "text"
}
}
},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Accept",
"value": "text/plain"
},
{
"name": "X-Return-Format",
"value": "markdown"
},
{
"name": "X-Timeout",
"value": "25"
}
]
}
},
"typeVersion": 4.4
},
{
"id": "p7",
"name": "Normalize Jina Response",
"type": "n8n-nodes-base.code",
"position": [
1344,
128
],
"parameters": {
"jsCode": "const item = $input.first().json;\nconst orig = $('Loop Over URLs').first().json;\nconst raw = item.body || item.data || '';\nreturn [{json:{...orig,content:raw.substring(0,14000),contentLength:raw.length,scrapeMethod:'jina',scrapeOk:!item.error&&raw.length>300}}];"
},
"typeVersion": 2
},
{
"id": "p8",
"name": "Page Analyzer (Round 1)",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
1568,
128
],
"parameters": {
"text": "=Analyze this webpage for a research report on: \"{{ $json.topic }}\"\n\nSOURCE URL: {{ $json.url }}\n\nPAGE CONTENT:\n{{ $json.content }}\n\nINSTRUCTIONS:\n- If this page is a CAPTCHA challenge, login wall, access denied page, or has fewer than 150 words of real content, respond with EXACTLY: RETRY_NEEDED\n- Otherwise respond with ONLY this JSON (no markdown wrapper):\n{\"status\":\"ok\",\"title\":\"page title\",\"summary\":\"2-3 sentence summary\",\"keyPoints\":[\"point1\",\"point2\",\"point3\"],\"dataPoints\":[\"stat or fact\"],\"relevance\":\"high|medium|low\"}",
"batching": {},
"promptType": "define"
},
"typeVersion": 1.9
},
{
"id": "p8a",
"name": "Claude Extractor",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"position": [
1568,
304
],
"parameters": {
"model": {
"__rl": true,
"mode": "id",
"value": "claude-sonnet-4-5"
},
"options": {
"temperature": 0.1,
"maxTokensToSample": 1024
}
},
"typeVersion": 1.3
},
{
"id": "pCA1",
"name": "Combine Analysis R1",
"type": "n8n-nodes-base.code",
"position": [
1856,
128
],
"parameters": {
"jsCode": "const text = $input.first().json.text;\nconst orig = $('Normalize Jina Response').first().json;\nreturn [{json:{...orig,text}}];"
},
"typeVersion": 2
},
{
"id": "p9",
"name": "Retry Needed? (IF)",
"type": "n8n-nodes-base.if",
"position": [
2000,
128
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "retry-check",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ ($json.text || '').trim() }}",
"rightValue": "RETRY_NEEDED"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "p16",
"name": "Merge Page Results",
"type": "n8n-nodes-base.merge",
"position": [
2000,
352
],
"parameters": {
"mode": "append"
},
"typeVersion": 3.2
},
{
"id": "p17",
"name": "Enrich & Forward",
"type": "n8n-nodes-base.code",
"position": [
2224,
352
],
"parameters": {
"jsCode": "const r = $input.first().json;\nreturn [{json:{text:r.text||'{\"status\":\"error\",\"summary\":\"Analysis unavailable\",\"keyPoints\":[],\"dataPoints\":[],\"relevance\":\"none\"}',url:r.url||'',urlIndex:r.urlIndex||0,title:r.title||'',snippet:r.snippet||'',topic:r.topic||'',recipientEmail:r.recipientEmail||'',runId:r.runId||'',scrapeMethod:r.scrapeMethod||'unknown'}}];"
},
"typeVersion": 2
},
{
"id": "p10",
"name": "Wait Before Retry",
"type": "n8n-nodes-base.wait",
"position": [
2480,
128
],
"parameters": {
"amount": 3
},
"typeVersion": 1.1
},
{
"id": "p11",
"name": "Firecrawl (Fallback)",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
2704,
128
],
"parameters": {
"url": "https://api.firecrawl.dev/v1/scrape",
"method": "POST",
"options": {
"timeout": 45000
},
"sendBody": true,
"sendHeaders": true,
"bodyParameters": {
"parameters": [
{
"name": "url",
"value": "={{ $json.url }}"
},
{
"name": "formats",
"value": "=[\"markdown\"]"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer YOUR_TOKEN_HERE"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.4
},
{
"id": "p12",
"name": "Normalize Firecrawl",
"type": "n8n-nodes-base.code",
"position": [
2928,
128
],
"parameters": {
"jsCode": "const item = $input.first().json;\nconst orig = $('Combine Analysis R1').first().json;\nconst md = (item.data && item.data.markdown) || item.markdown || '';\nreturn [{json:{...orig,content:md.substring(0,14000),scrapeMethod:'firecrawl',scrapeOk:md.length>300&&!item.error}}];"
},
"typeVersion": 2
},
{
"id": "p13",
"name": "Page Analyzer (Round 2)",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
3152,
128
],
"parameters": {
"text": "=Analyze this webpage for a research report on: \"{{ $json.topic }}\"\n\nSOURCE URL: {{ $json.url }}\n\nPAGE CONTENT (fallback scrape):\n{{ $json.content }}\n\nINSTRUCTIONS:\n- If this page is a CAPTCHA challenge, login wall, access denied page, or has fewer than 150 words of real content, respond with EXACTLY: RETRY_NEEDED\n- Otherwise respond with ONLY this JSON (no markdown wrapper):\n{\"status\":\"ok\",\"title\":\"page title\",\"summary\":\"2-3 sentence summary\",\"keyPoints\":[\"point1\",\"point2\",\"point3\"],\"dataPoints\":[\"stat or fact\"],\"relevance\":\"high|medium|low\"}",
"batching": {},
"promptType": "define"
},
"typeVersion": 1.9
},
{
"id": "p13a",
"name": "Claude Re-Analyzer",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"position": [
3152,
304
],
"parameters": {
"model": {
"__rl": true,
"mode": "id",
"value": "claude-sonnet-4-5"
},
"options": {
"temperature": 0.1,
"maxTokensToSample": 1024
}
},
"typeVersion": 1.3
},
{
"id": "pCA2",
"name": "Combine Analysis R2",
"type": "n8n-nodes-base.code",
"position": [
3440,
128
],
"parameters": {
"jsCode": "const text = $input.first().json.text;\nconst orig = $('Normalize Firecrawl').first().json;\nreturn [{json:{...orig,text}}];"
},
"typeVersion": 2
},
{
"id": "p14",
"name": "Still Blocked? (IF)",
"type": "n8n-nodes-base.if",
"position": [
3584,
128
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "still-blocked-check",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ ($json.text || '').trim() }}",
"rightValue": "RETRY_NEEDED"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "p15",
"name": "Mark as Failed",
"type": "n8n-nodes-base.set",
"position": [
3584,
352
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "fail-text",
"name": "text",
"type": "string",
"value": "{\"status\":\"unavailable\",\"summary\":\"Source could not be retrieved after 2 attempts.\",\"keyPoints\":[],\"dataPoints\":[],\"relevance\":\"none\"}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "p18",
"name": "Aggregate Summaries",
"type": "n8n-nodes-base.aggregate",
"position": [
3920,
128
],
"parameters": {
"include": "allFields",
"options": {},
"aggregate": "aggregateAllItemData",
"destinationFieldName": "pageSummaries"
},
"typeVersion": 1
},
{
"id": "p19",
"name": "Build Synthesis Prompt",
"type": "n8n-nodes-base.code",
"position": [
4144,
128
],
"parameters": {
"jsCode": "const agg = $input.first().json;\nconst summaries = agg.pageSummaries || [];\nconst topic = (summaries[0] || {}).topic || 'Unknown Topic';\nconst recipientEmail = (summaries[0] || {}).recipientEmail || '';\nconst runId = (summaries[0] || {}).runId || '';\nconst parsed = summaries.map(s => { try { return JSON.parse(s.text); } catch(e) { return {status:'parse_error',summary:String(s.text)}; } });\nconst ok = parsed.filter(p => p.status === 'ok').length;\nconst evidence = parsed.map((p, i) => {\n const src = summaries[i];\n if (p.status !== 'ok') return 'SOURCE ' + (i+1) + ': ' + src.url + '\\nSTATUS: Unavailable';\n return 'SOURCE ' + (i+1) + ': ' + src.url + '\\nTITLE: ' + (p.title||'') + '\\nSUMMARY: ' + p.summary + '\\nKEY POINTS: ' + (p.keyPoints||[]).join(' | ') + '\\nDATA: ' + (p.dataPoints||[]).join(' | ') + '\\nRELEVANCE: ' + p.relevance;\n}).join('\\n\\n---\\n\\n');\nconst prompt = 'You are a senior research analyst.\\n\\nRESEARCH TOPIC: ' + topic + '\\nSOURCES: ' + summaries.length + ' analyzed, ' + ok + ' retrieved\\nDATE: ' + new Date().toLocaleDateString(\"en-US\",{year:\"numeric\",month:\"long\",day:\"numeric\"}) + '\\n\\nEVIDENCE:\\n' + evidence + '\\n\\nWrite a professional executive research report in Markdown with these sections:\\n# Executive Report: ' + topic + '\\n## Executive Summary\\n## Key Findings\\n## Detailed Analysis\\n## Data & Evidence\\n## Conclusions & Recommendations\\n## Sources\\n\\nRULES: Only include facts from the evidence. Do not invent statistics. Cite sources by number.';\nreturn [{json:{synthesisPrompt:prompt,topic,recipientEmail,runId,sourceCount:summaries.length,successCount:ok}}];"
},
"typeVersion": 2
},
{
"id": "p20",
"name": "Synthesize Report",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
4368,
128
],
"parameters": {
"text": "={{ $json.synthesisPrompt }}",
"batching": {},
"promptType": "define"
},
"typeVersion": 1.9
},
{
"id": "p20a",
"name": "Claude Synthesizer",
"type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
"position": [
4368,
304
],
"parameters": {
"model": {
"__rl": true,
"mode": "id",
"value": "claude-sonnet-4-5"
},
"options": {
"temperature": 0.3,
"maxTokensToSample": 4096
}
},
"typeVersion": 1.3
},
{
"id": "p21",
"name": "Build HTML Report",
"type": "n8n-nodes-base.code",
"position": [
4656,
128
],
"parameters": {
"jsCode": "const data = $input.first().json;\nconst synth = $('Build Synthesis Prompt').first().json;\nconst md = data.text || '';\nconst topic = synth.topic || 'Research Report';\nconst runId = synth.runId || '';\nconst date = new Date().toLocaleDateString('en-US',{year:'numeric',month:'long',day:'numeric'});\n\nconst toHtml = s => {\n const lines = s.split('\\n');\n const out = [];\n let i = 0;\n let inList = false;\n while (i < lines.length) {\n const line = lines[i];\n if (i + 1 < lines.length && /^\\|/.test(line) && /^\\|[\\s\\-|:]+\\|/.test(lines[i+1])) {\n if (inList) { out.push('</ul>'); inList = false; }\n const headers = line.split('|').slice(1,-1).map(h => '<th>' + h.trim() + '</th>').join('');\n out.push('<table><thead><tr>' + headers + '</tr></thead><tbody>');\n i += 2;\n while (i < lines.length && /^\\|/.test(lines[i])) {\n const cells = lines[i].split('|').slice(1,-1).map(c => '<td>' + c.trim().replace(/\\*\\*(.+?)\\*\\*/g,'<strong>$1</strong>') + '</td>').join('');\n out.push('<tr>' + cells + '</tr>');\n i++;\n }\n out.push('</tbody></table>');\n continue;\n }\n if (/^### /.test(line)) { if (inList) { out.push('</ul>'); inList = false; } out.push('<h3>' + line.slice(4) + '</h3>'); }\n else if (/^## /.test(line)) { if (inList) { out.push('</ul>'); inList = false; } out.push('<h2>' + line.slice(3) + '</h2>'); }\n else if (/^# /.test(line)) { if (inList) { out.push('</ul>'); inList = false; } out.push('<h1>' + line.slice(2) + '</h1>'); }\n else if (/^[-*] /.test(line) || /^\\d+\\. /.test(line)) {\n if (!inList) { out.push('<ul>'); inList = true; }\n const content = line.replace(/^[-*] /,'').replace(/^\\d+\\. /,'').replace(/\\*\\*(.+?)\\*\\*/g,'<strong>$1</strong>').replace(/`(.+?)`/g,'<code>$1</code>');\n out.push('<li>' + content + '</li>');\n } else if (/^---+$/.test(line.trim())) { if (inList) { out.push('</ul>'); inList = false; } out.push('<hr>'); }\n else if (line.trim() === '') { if (inList) { out.push('</ul>'); inList = false; } }\n else { if (inList) { out.push('</ul>'); inList = false; } const content = line.replace(/\\*\\*(.+?)\\*\\*/g,'<strong>$1</strong>').replace(/`(.+?)`/g,'<code>$1</code>').replace(/^> /,''); out.push('<p>' + content + '</p>'); }\n i++;\n }\n if (inList) out.push('</ul>');\n return out.join('\\n');\n};\n\nconst body = toHtml(md);\nconst html = `<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><title>${topic}</title><style>*{box-sizing:border-box;margin:0;padding:0}body{font-family:Georgia,serif;color:#1a1a2e;padding:40px;max-width:900px;margin:0 auto;font-size:14px}h1{font-size:24px;border-bottom:3px solid #0f3460;padding-bottom:10px;margin:0 0 20px}h2{font-size:18px;color:#0f3460;margin:24px 0 10px;border-left:4px solid #e94560;padding-left:10px}h3{font-size:15px;margin:16px 0 8px}p{line-height:1.7;margin-bottom:10px}ul{margin:10px 0 14px 20px;list-style:disc}li{line-height:1.7;margin-bottom:6px}ol{margin:10px 0 14px 20px}hr{border:none;border-top:1px solid #dee2e6;margin:20px 0}table{width:100%;border-collapse:collapse;margin:16px 0;font-size:13px}th{background:#0f3460;color:#fff;padding:8px 12px;text-align:left;font-weight:600}td{padding:7px 12px;border-bottom:1px solid #dee2e6}tr:nth-child(even) td{background:#f8f9fa}code{background:#f0f0f0;padding:1px 5px;border-radius:3px;font-size:12px}strong{font-weight:700}.meta{background:#f8f9fa;border:1px solid #dee2e6;border-radius:6px;padding:12px 18px;margin-bottom:24px;font-size:12px;color:#666}.footer{margin-top:40px;padding-top:14px;border-top:1px solid #dee2e6;font-size:11px;color:#999;text-align:center}</style></head><body><div class=\"meta\">Date: ${date} | Topic: ${topic} | Run: ${runId} | Sources: ${synth.sourceCount||'?'} (${synth.successCount||'?'} retrieved)</div>${body}<div class=\"footer\">Generated by Self-Healing Research Agent | n8n Workflow</div></body></html>`;\nreturn [{json:{html,topic,recipientEmail:synth.recipientEmail,runId,sourceCount:synth.sourceCount,successCount:synth.successCount}}];"
},
"typeVersion": 2
},
{
"id": "p23",
"name": "Send Gmail",
"type": "n8n-nodes-base.gmail",
"position": [
4800,
128
],
"parameters": {
"sendTo": "={{ $json.recipientEmail }}",
"message": "={{ $json.html }}",
"options": {},
"subject": "=Research Report: {{ $json.topic }} \u2014 {{ $now.toFormat('MMMM d, yyyy') }}",
"resource": "message",
"emailType": "html",
"operation": "send"
},
"typeVersion": 2.2
},
{
"id": "p24",
"name": "Error Trigger",
"type": "n8n-nodes-base.errorTrigger",
"position": [
-336,
672
],
"parameters": {},
"typeVersion": 1
},
{
"id": "p25",
"name": "Format Error",
"type": "n8n-nodes-base.set",
"position": [
-80,
672
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "e1",
"name": "error_message",
"type": "string",
"value": "={{ $json.execution.error.message }}"
},
{
"id": "e2",
"name": "failed_node",
"type": "string",
"value": "={{ $json.execution.error.node.name }}"
},
{
"id": "e3",
"name": "workflow_name",
"type": "string",
"value": "={{ $json.workflow.name }}"
},
{
"id": "e4",
"name": "execution_url",
"type": "string",
"value": "={{ $json.execution.url }}"
}
]
}
},
"typeVersion": 3.4
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"connections": {
"Set Config": {
"main": [
[
{
"node": "SerpApi Search",
"type": "main",
"index": 0
}
]
]
},
"Error Trigger": {
"main": [
[
{
"node": "Format Error",
"type": "main",
"index": 0
}
]
]
},
"Research Form": {
"main": [
[
{
"node": "Set Config",
"type": "main",
"index": 0
}
]
]
},
"Loop Over URLs": {
"main": [
[
{
"node": "Aggregate Summaries",
"type": "main",
"index": 0
}
],
[
{
"node": "Jina Reader (Primary)",
"type": "main",
"index": 0
}
]
]
},
"Mark as Failed": {
"main": [
[
{
"node": "Merge Page Results",
"type": "main",
"index": 0
}
]
]
},
"SerpApi Search": {
"main": [
[
{
"node": "Parse & Filter URLs",
"type": "main",
"index": 0
}
]
]
},
"Claude Extractor": {
"ai_languageModel": [
[
{
"node": "Page Analyzer (Round 1)",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Enrich & Forward": {
"main": [
[
{
"node": "Loop Over URLs",
"type": "main",
"index": 0
}
]
]
},
"Build HTML Report": {
"main": [
[
{
"node": "Send Gmail",
"type": "main",
"index": 0
}
]
]
},
"Synthesize Report": {
"main": [
[
{
"node": "Build HTML Report",
"type": "main",
"index": 0
}
]
]
},
"Wait Before Retry": {
"main": [
[
{
"node": "Firecrawl (Fallback)",
"type": "main",
"index": 0
}
]
]
},
"Claude Re-Analyzer": {
"ai_languageModel": [
[
{
"node": "Page Analyzer (Round 2)",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Claude Synthesizer": {
"ai_languageModel": [
[
{
"node": "Synthesize Report",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Merge Page Results": {
"main": [
[
{
"node": "Enrich & Forward",
"type": "main",
"index": 0
}
]
]
},
"Retry Needed? (IF)": {
"main": [
[
{
"node": "Wait Before Retry",
"type": "main",
"index": 0
}
],
[
{
"node": "Merge Page Results",
"type": "main",
"index": 0
}
]
]
},
"Aggregate Summaries": {
"main": [
[
{
"node": "Build Synthesis Prompt",
"type": "main",
"index": 0
}
]
]
},
"Combine Analysis R1": {
"main": [
[
{
"node": "Retry Needed? (IF)",
"type": "main",
"index": 0
}
]
]
},
"Combine Analysis R2": {
"main": [
[
{
"node": "Still Blocked? (IF)",
"type": "main",
"index": 0
}
]
]
},
"Normalize Firecrawl": {
"main": [
[
{
"node": "Page Analyzer (Round 2)",
"type": "main",
"index": 0
}
]
]
},
"Parse & Filter URLs": {
"main": [
[
{
"node": "Loop Over URLs",
"type": "main",
"index": 0
}
]
]
},
"Still Blocked? (IF)": {
"main": [
[
{
"node": "Mark as Failed",
"type": "main",
"index": 0
}
],
[
{
"node": "Merge Page Results",
"type": "main",
"index": 0
}
]
]
},
"Firecrawl (Fallback)": {
"main": [
[
{
"node": "Normalize Firecrawl",
"type": "main",
"index": 0
}
]
]
},
"Jina Reader (Primary)": {
"main": [
[
{
"node": "Normalize Jina Response",
"type": "main",
"index": 0
}
]
]
},
"Build Synthesis Prompt": {
"main": [
[
{
"node": "Synthesize Report",
"type": "main",
"index": 0
}
]
]
},
"Normalize Jina Response": {
"main": [
[
{
"node": "Page Analyzer (Round 1)",
"type": "main",
"index": 0
}
]
]
},
"Page Analyzer (Round 1)": {
"main": [
[
{
"node": "Combine Analysis R1",
"type": "main",
"index": 0
}
]
]
},
"Page Analyzer (Round 2)": {
"main": [
[
{
"node": "Combine Analysis R2",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Submit a research topic through a form and receive a professionally styled executive report in your inbox — fully automated, with built-in scraping resilience.
Source: https://n8n.io/workflows/13608/ — 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.
This workflow automates Invoice & Payment Tracking (with Approvals) across Notion and Slack. Ingest — You drop invoices/receipts (PDF/IMG/JSON) into the flow. Extract — OCR + parsing pulls out key fie
Content - Newsletter Agent. Uses formTrigger, chainLlm, outputParserStructured, httpRequest. Event-driven trigger; 87 nodes.
My workflow 53. Uses formTrigger, httpRequest, lmChatOpenAi, form. Event-driven trigger; 74 nodes.
Episode 23: UGC with nanobanana. Uses lmChatOpenAi, lmChatOllama, lmChatDeepSeek, lmChatOpenRouter. Event-driven trigger; 74 nodes.
Transform a hand-drawn character sketch into a fully animated, narrated video story — automatically. This 3-part pipeline uses Claude AI, image generation, and video synthesis to go from a simple draw