{
  "id": "OtwtSFJ7MgNL33lT",
  "meta": {
    "instanceId": "ca28f413fdb95be940f2c6f2dd73dbba56a53de00dbbaba04dcd5be83e1e7731",
    "templateCredsSetupCompleted": true
  },
  "name": "AGENTIC AI",
  "tags": [
    {
      "id": "oPwjXlckTdNT4rp6",
      "name": "template",
      "createdAt": "2025-11-17T08:27:25.890Z",
      "updatedAt": "2025-11-17T08:27:25.890Z"
    }
  ],
  "nodes": [
    {
      "id": "38e7d8a0-9378-4550-9baa-70c2feeeb909",
      "name": "Form Trigger",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -80,
        310
      ],
      "webhookId": "f7978098-4fb4-4419-9c92-a6fd5f8d33cd",
      "parameters": {
        "path": "f7978098-4fb4-4419-9c92-a6fd5f8d33cd",
        "options": {},
        "formTitle": "AI Research Team",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Research Topic",
              "requiredField": true
            },
            {
              "fieldType": "dropdown",
              "fieldLabel": "Research Depth",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Quick (5 min)"
                  },
                  {
                    "option": "Standard (10 min)"
                  },
                  {
                    "option": "Deep (15 min)"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldType": "dropdown",
              "fieldLabel": "Output Format",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Executive Summary"
                  },
                  {
                    "option": "Detailed Report"
                  },
                  {
                    "option": "Blog Article"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldType": "textarea",
              "fieldLabel": "Additional Context (Optional)"
            }
          ]
        },
        "responseMode": "responseNode",
        "formDescription": "Submit your research topic and let our AI agents work together"
      },
      "typeVersion": 2
    },
    {
      "id": "d71ffa02-9aa7-434f-b2e0-7c84f284a7f2",
      "name": "Parse Form Input",
      "type": "n8n-nodes-base.code",
      "position": [
        140,
        310
      ],
      "parameters": {
        "jsCode": "// Parse form data and prepare for agents\nconst formData = $input.item.json;\n\nreturn [{\n  json: {\n    query: formData['Research Topic'],\n    depth: formData['Research Depth'],\n    format: formData['Output Format'],\n    context: formData['Additional Context (Optional)'] || '',\n    timestamp: new Date().toISOString(),\n    sessionId: $workflow.id + '_' + Date.now()\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "2f8432e1-5e92-4c1f-8fd3-d9999bd75199",
      "name": "Research Agent - Plan",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        380,
        240
      ],
      "parameters": {
        "url": "https://api.groq.com/openai/v1/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"model\": \"llama-3.3-70b-versatile\",\n  \"messages\": [\n    {\n      \"role\": \"system\",\n      \"content\": \"You are a research specialist. Your task is to create a comprehensive research plan and identify key search queries for the topic. List 5-7 specific search queries that would gather the most relevant information. Format as JSON array of queries.\"\n    },\n    {\n      \"role\": \"user\",\n      \"content\": \"{{ $json.query }}{{ $json.context ? '\\\\n\\\\nAdditional context: ' + $json.context : '' }}\"\n    }\n  ],\n  \"temperature\": 0.7,\n  \"max_tokens\": 4096\n}\n",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "groqApi"
      },
      "credentials": {
        "groqApi": {
          "id": "credential-id",
          "name": "groqApi Credential"
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "3a5be3ee-bd09-4c33-b998-7ee956ba78f7",
      "name": "Extract Search Queries",
      "type": "n8n-nodes-base.code",
      "position": [
        640,
        220
      ],
      "parameters": {
        "jsCode": "// Extract search queries from research plan\nconst response = $input.item.json.choices[0].message.content;\nlet queries = [];\n\n// Try to parse JSON first\ntry {\n  queries = JSON.parse(response);\n} catch (e) {\n  // Fallback: extract queries from text\n  const lines = response.split('\\n');\n  queries = lines\n    .filter(line => line.trim().length > 10)\n    .map(line => line.replace(/^[\\d\\-\\.\\*]\\s*/, '').trim())\n    .filter(q => q.length > 0)\n    .slice(0, 5);\n}\n\n// Return array of queries for batch processing\nreturn queries.map(query => ({\n  json: {\n    searchQuery: query,\n    originalTopic: $input.item.json.query || $('Parse Form Input').item.json.query,\n    sessionId: $input.item.json.sessionId || $('Parse Form Input').item.json.sessionId\n  }\n}));"
      },
      "typeVersion": 2
    },
    {
      "id": "5fcb3f72-4b3b-4e6c-a99d-ab2021b31399",
      "name": "SERP Search",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        800,
        235
      ],
      "parameters": {
        "url": "https://serpapi.com/search.json",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "q",
              "value": "={{ $json.searchQuery }}"
            },
            {
              "name": "num",
              "value": "5"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "serpApi"
      },
      "credentials": {
        "serpApi": {
          "id": "credential-id",
          "name": "serpApi Credential"
        }
      },
      "typeVersion": 4.1
    },
    {
      "id": "906a3e0c-5c8d-4f23-8345-b13d6f1b5add",
      "name": "Merge Research",
      "type": "n8n-nodes-base.merge",
      "position": [
        1020,
        310
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combinationMode": "multiplex"
      },
      "typeVersion": 2.1
    },
    {
      "id": "da016204-312e-4192-9c75-f216e3e65ff2",
      "name": "Aggregate Research",
      "type": "n8n-nodes-base.code",
      "position": [
        1240,
        310
      ],
      "parameters": {
        "jsCode": "// Combine all search results\nconst allResults = $input.all();\nconst formData = $('Parse Form Input').first().json;\n\nlet researchData = {\n  topic: formData.query,\n  context: formData.context,\n  sources: []\n};\n\nallResults.forEach(item => {\n  if (item.json.organic) {\n    item.json.organic.forEach(result => {\n      researchData.sources.push({\n        title: result.title,\n        snippet: result.snippet,\n        link: result.link\n      });\n    });\n  }\n});\n\nreturn [{\n  json: {\n    ...formData,\n    research: researchData,\n    sourceCount: researchData.sources.length\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "5d8ee0ec-12db-4b0c-97c1-5d7d6c0a9a63",
      "name": "Merge All Agents",
      "type": "n8n-nodes-base.merge",
      "position": [
        2212,
        310
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combinationMode": "multiplex"
      },
      "typeVersion": 2.1
    },
    {
      "id": "6e00b2c3-5429-4832-b428-98de2942b253",
      "name": "Return Results",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        2808,
        310
      ],
      "parameters": {
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/html"
              }
            ]
          }
        },
        "respondWith": "allIncomingItems"
      },
      "typeVersion": 1.1
    },
    {
      "id": "82d17fe2-2ae2-4141-bc8a-ef1f4a5b8da9",
      "name": "Groq Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "position": [
        2320,
        520
      ],
      "parameters": {
        "model": "llama-3.3-70b-versatile",
        "options": {}
      },
      "credentials": {
        "groqApi": {
          "id": "credential-id",
          "name": "groqApi Credential"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4c7f292a-c0d3-4193-aee4-be3026be67e3",
      "name": "Fact-Checker Agent",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1840,
        240
      ],
      "parameters": {
        "text": "=Content to verify:\\n{{ $json.text }}\\n\\nSource material:\\n{{ $('Aggregate Research').item.json.research.sources.map((s, i) => (i+1) + '. ' + s.title + ': ' + s.snippet).join('\\n\\n') }}\\n\\nProvide fact-check report with any corrections needed.",
        "messages": {
          "messageValues": [
            {
              "message": "You are a fact-checker. Verify claims against source material and flag any inaccuracies or unsupported statements."
            }
          ]
        },
        "promptType": "define"
      },
      "typeVersion": 1.6
    },
    {
      "id": "15c0884b-e3d3-4e36-b286-8b7df8868d4a",
      "name": "Editor Agent",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1840,
        360
      ],
      "parameters": {
        "text": "=Edit this content:\\n{{ $json.text }}\\n\\nReturn improved version.",
        "messages": {
          "messageValues": [
            {
              "message": "You are an editor. Improve clarity, fix grammar, enhance readability, and ensure professional tone."
            }
          ]
        },
        "promptType": "define"
      },
      "typeVersion": 1.6
    },
    {
      "id": "0b7812ba-eb64-4a7f-8f0b-5f131c9e652d",
      "name": "PM Agent - Final Review1",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        2432,
        310
      ],
      "parameters": {
        "text": "=ORIGINAL TOPIC: {{ $('Aggregate Research').item.json.research.topic }}\\n\\nWRITTEN CONTENT:\\n{{ $('Writer Agent').item.json.text }}\\n\\nFACT-CHECK REPORT:\\n{{ $('Fact-Checker Agent').item.json.text }}\\n\\nEDITED VERSION:\\n{{ $('Editor Agent').item.json.text }}\\n\\nSOURCES:\\n{{ $('Aggregate Research').item.json.research.sources.map((s, i) => (i+1) + '. ' + s.title + ' - ' + s.link).join('\\\\n') }}\\n\\nCreate final consolidated output with citations.",
        "messages": {
          "messageValues": [
            {
              "message": "You are a Project Manager reviewing team outputs. Merge insights from all agents into one cohesive, accurate, well-written final deliverable. Include source citations."
            }
          ]
        },
        "promptType": "define"
      },
      "typeVersion": 1.6
    },
    {
      "id": "9807e86a-f35e-4a02-81b5-f36769bcf5e9",
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "position": [
        3028,
        310
      ],
      "parameters": {
        "jsCode": "// n8n Function node code\n// Input: items where items[i].json.text contains the markdown-ish string\n// Output: items with .json.html and .binary.data (base64 HTML) ready for HTML->PDF nodes\n\nconst sanitizeForHtml = (md) => {\n  if (!md) return '';\n  // Basic conversion: bold (**text**) -> <strong>text</strong>\n  // This is intentionally simple — for complex markdown use a markdown library.\n  let html = md.replace(/\\*\\*(.+?)\\*\\*/gs, '<strong>$1</strong>');\n  // Convert two or more newlines to paragraph separators\n  html = html.replace(/\\r\\n/g, '\\n');\n  html = html.split('\\n\\n').map(p => p.trim()).filter(p => p !== '').map(p => {\n    // inside a paragraph convert single newlines to <br>\n    const withBr = p.replace(/\\n/g, '<br>');\n    return `<p>${withBr}</p>`;\n  }).join('\\n');\n  return html;\n};\n\nconst wrapFullHtml = (bodyHtml, title = 'Report') => {\n  return `<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\"/>\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"/>\n  <title>${title}</title>\n  <style>\n    body { font-family: Arial, Helvetica, sans-serif; font-size: 12pt; line-height:1.4; padding: 28px; color: #222; }\n    h1 { font-size: 20pt; margin-bottom: 6px; }\n    p { margin: 8px 0; }\n    strong { font-weight: 700; }\n    .footer { margin-top: 24px; font-size: 9pt; color: #666; }\n    pre { white-space: pre-wrap; word-wrap: break-word; }\n  </style>\n</head>\n<body>\n  <h1>${title}</h1>\n  ${bodyHtml}\n  <div class=\"footer\">Generated by n8n • ${new Date().toLocaleString()}</div>\n</body>\n</html>`;\n};\n\n// process all items\nconst output = [];\n\nfor (let i = 0; i < items.length; i++) {\n  const item = items[i];\n  const rawText = item.json && (item.json.text || item.json.body || item.json.content) ? (item.json.text || item.json.body || item.json.content) : '';\n  const title = (item.json && item.json.title) ? item.json.title : 'Report';\n  const bodyHtml = sanitizeForHtml(rawText);\n  const fullHtml = wrapFullHtml(bodyHtml, title);\n\n  // place HTML in json for nodes that read html from json\n  const newItem = {\n    json: {\n      ...item.json,\n      html: fullHtml,\n      _generatedTitle: title,\n    },\n    binary: {}\n  };\n\n  // attach binary (base64) — many HTML->PDF nodes accept binary input\n  const buffer = Buffer.from(fullHtml, 'utf8');\n  newItem.binary.data = {\n    fileName: `${title.replace(/[^a-z0-9]+/gi, '_').toLowerCase() || 'report'}.html`,\n    mimeType: 'text/html',\n    fileExtension: 'html',\n    data: buffer.toString('base64'),\n  };\n\n  output.push(newItem);\n}\n\nreturn output;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "924fa486-8dda-48c5-b882-ed12567cf132",
      "name": "Writer Agent",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1460,
        310
      ],
      "parameters": {
        "text": "={{ $json.query }}\\n\\nResearch Sources:\\n{{ $json.research.sources.map((s, i) => (i+1) + '. ' + s.title + ': ' + s.snippet).join('\\\\n\\\\n') }}\\n\\nWrite comprehensive content covering all key findings.",
        "messages": {
          "messageValues": [
            {
              "message": "=You are a professional content writer. Create engaging, well-structured content based on research findings. Format: {{ $json.format }}"
            }
          ]
        },
        "promptType": "define"
      },
      "typeVersion": 1.6
    },
    {
      "id": "0a7774e0-c5f4-49df-b83c-0979f5cc6477",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1380,
        120
      ],
      "parameters": {
        "color": 3,
        "width": 1360,
        "height": 520,
        "content": "## AI AGENTS"
      },
      "typeVersion": 1
    },
    {
      "id": "39f31e11-6ec4-4af3-978f-9d1e139e140f",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        300,
        120
      ],
      "parameters": {
        "color": 3,
        "width": 300,
        "height": 520,
        "content": "## RESEARCH AGENT\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b64b2f2c-a687-4805-9488-5578a7c7fa02",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        620,
        120
      ],
      "parameters": {
        "color": 4,
        "width": 740,
        "height": 520,
        "content": "## FINALIZING RESEARCH"
      },
      "typeVersion": 1
    },
    {
      "id": "adf8837f-503f-4e4e-9f1d-5ca9af2cfcf2",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -100,
        120
      ],
      "parameters": {
        "color": 6,
        "width": 380,
        "height": 520,
        "content": "## INPUT"
      },
      "typeVersion": 1
    },
    {
      "id": "cebfb2b3-3697-493e-9c15-73f719803293",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2760,
        120
      ],
      "parameters": {
        "color": 6,
        "width": 400,
        "height": 520,
        "content": "## OUTPUT"
      },
      "typeVersion": 1
    },
    {
      "id": "c12bdca2-4610-4243-a680-55c1da2941aa",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -140,
        -40
      ],
      "parameters": {
        "color": 7,
        "width": 3400,
        "height": 780,
        "content": "# AGENTIC AI"
      },
      "typeVersion": 1
    },
    {
      "id": "78c1b410-1ea5-425a-98f3-62c69098cb6c",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -720,
        -260
      ],
      "parameters": {
        "width": 560,
        "height": 1380,
        "content": "# 🧠 Agentic AI Research System\n\n# 🎥 **Watch the Tutorial**  \n[![Watch on YouTube](https://img.youtube.com/vi/GUfUzls_9yI/hqdefault.jpg)](https://youtu.be/GUfUzls_9yI?si=XgjiMw9tysyNb6TQ)\n\n\nBuild a complete autonomous research engine inside n8n that behaves like a small AI research team.\nThis workflow uses Groq (Llama 3.3), LangChain Agents, and SerpAPI to collect information, analyze data, fact-check content, and generate a polished, citation-backed report.\n\n⚙️ How It Works\n\nA form collects the research topic, depth, and output format.\n\nA Research Agent generates targeted search queries.\n\nSerpAPI fetches real-time results from the web.\n\nAll findings are aggregated and structured for processing.\n\nA Writer Agent creates the first draft based on collected data.\n\nA Fact-Checker Agent verifies statements against the source material.\n\nAn Editor Agent improves tone, structure, and clarity.\n\nA PM Agent consolidates everything into a final research report.\n\n💼 Use Cases\n\nResearch automation for teams and freelancers\n\nLong-form content creation with verified sources\n\nKnowledge gathering for business, academic, and technical projects\n\nSetup takes less than 10 minutes. Add your Groq API key, SerpAPI key, and run your first research request directly from the form.\n\n🔗 Created by: Muhammad Shaheer\n💡 YouTube Channel: https://www.youtube.com/@ShaheerAutomation\n\n📧 For collaborations: shaheerawan001@gmail.com\n\n🔗 LinkedIn: www.linkedin.com/in/muhammad-shaheer-898513192"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "ae9f79cb-7558-4487-97fa-5fbef8907600",
  "connections": {
    "Code": {
      "main": [
        []
      ]
    },
    "SERP Search": {
      "main": [
        [
          {
            "node": "Merge Research",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Editor Agent": {
      "main": [
        [
          {
            "node": "Merge All Agents",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Form Trigger": {
      "main": [
        [
          {
            "node": "Parse Form Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Writer Agent": {
      "main": [
        [
          {
            "node": "Fact-Checker Agent",
            "type": "main",
            "index": 0
          },
          {
            "node": "Editor Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Research": {
      "main": [
        [
          {
            "node": "Aggregate Research",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Return Results": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Groq Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Fact-Checker Agent",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Editor Agent",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "PM Agent - Final Review1",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Writer Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Merge All Agents": {
      "main": [
        [
          {
            "node": "PM Agent - Final Review1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Form Input": {
      "main": [
        [
          {
            "node": "Merge Research",
            "type": "main",
            "index": 1
          },
          {
            "node": "Research Agent - Plan",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Research": {
      "main": [
        [
          {
            "node": "Writer Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fact-Checker Agent": {
      "main": [
        [
          {
            "node": "Merge All Agents",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Research Agent - Plan": {
      "main": [
        [
          {
            "node": "Extract Search Queries",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Search Queries": {
      "main": [
        [
          {
            "node": "SERP Search",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "PM Agent - Final Review1": {
      "main": [
        [
          {
            "node": "Return Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}