{
  "name": "Company Sector Classification - Ollama AI",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "classify-company",
        "responseMode": "responseNode",
        "options": {
          "rawBody": true
        }
      },
      "id": "70efe005-7bd9-40f4-a795-dcda79b978f3",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -1440,
        336
      ],
      "webhookId": "ea6c3c6a-8fa0-4940-bb55-a4580c37f350"
    },
    {
      "parameters": {
        "jsCode": "// Validate URL(s) - handles both single URL and array of URLs\nconst item = $input.first();\nconst urlInput = item.json.body?.url || item.json.url || item.json.body?.urls || item.json.urls || '';\n\n// Normalize to array\nlet urls = [];\nif (Array.isArray(urlInput)) {\n  urls = urlInput;\n} else if (typeof urlInput === 'string') {\n  // Check if it's a JSON string array\n  try {\n    const parsed = JSON.parse(urlInput);\n    if (Array.isArray(parsed)) {\n      urls = parsed;\n    } else {\n      urls = [urlInput];\n    }\n  } catch(e) {\n    urls = [urlInput];\n  }\n} else {\n  urls = [String(urlInput || '')];\n}\n\n// Validate each URL and create output items\nconst outputItems = [];\nfor (let i = 0; i < urls.length; i++) {\n  const urlString = typeof urls[i] === 'string' ? urls[i].trim() : String(urls[i] || '').trim();\n  if (!urlString) continue;\n  \n  if (!/^https?:\\/\\//i.test(urlString)) {\n    throw new Error(`Invalid URL at index ${i}: \"${urlString}\". Must start with http:// or https://`);\n  }\n  \n  outputItems.push({ json: { url: urlString, urlIndex: i, totalUrls: urls.length } });\n}\n\nif (outputItems.length === 0) {\n  throw new Error('No valid URLs provided');\n}\n\nreturn outputItems;"
      },
      "id": "0c0f4f65-4ee5-4cf3-9875-a9926505cafb",
      "name": "Validate URL",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1200,
        336
      ]
    },
    {
      "parameters": {
        "url": "={{ $json.url }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "User-Agent",
              "value": "Mozilla/5.0"
            }
          ]
        },
        "options": {
          "redirect": {
            "redirect": {
              "maxRedirects": 3
            }
          },
          "response": {
            "response": {
              "neverError": true,
              "responseFormat": "text"
            }
          },
          "timeout": 30000
        }
      },
      "id": "db0051b3-d4e5-48c0-88ed-91266bd17be5",
      "name": "Fetch Homepage",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -960,
        224
      ]
    },
    {
      "parameters": {
        "jsCode": "// Ensure body is always string and preserve metadata - process ALL items\nconst items = $input.all();\nconst outputItems = [];\n\nfor (const item of items) {\n  let htmlString = '';\n  if (typeof item.json === 'string') htmlString = item.json;\n  else if (item.json && typeof item.json.body === 'string') htmlString = item.json.body;\n  else htmlString = JSON.stringify(item.json || '');\n  \n  // Preserve URL and metadata\n  const output = { body: String(htmlString), url: String(item.json.url || '') };\n  if (item.json.urlIndex !== undefined) output.urlIndex = item.json.urlIndex;\n  if (item.json.totalUrls !== undefined) output.totalUrls = item.json.totalUrls;\n  \n  outputItems.push({ json: output });\n}\n\nreturn outputItems;"
      },
      "id": "e381d8e7-1497-44d9-afb7-171d6d832541",
      "name": "Prepare HTML",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -784,
        224
      ]
    },
    {
      "parameters": {
        "operation": "extractHtmlContent",
        "dataPropertyName": "body",
        "extractionValues": {
          "values": [
            {
              "key": "pageTitle",
              "cssSelector": "title"
            },
            {
              "key": "metaDescription",
              "cssSelector": "meta[name='description']",
              "returnValue": "attribute"
            },
            {
              "key": "mainContent",
              "cssSelector": "main, article, .content, #content, body"
            }
          ]
        },
        "options": {
          "trimValues": true,
          "cleanUpText": true
        }
      },
      "id": "66045587-fdbd-4eec-953b-1d328e72168f",
      "name": "Extract Text",
      "type": "n8n-nodes-base.html",
      "typeVersion": 1.2,
      "position": [
        -592,
        224
      ]
    },
    {
      "parameters": {
        "jsCode": "// Preserve metadata after HTML extraction - process ALL items\nconst items = $input.all();\nconst outputItems = [];\n\nfor (const item of items) {\n  const output = { ...item.json };\n  \n  // Ensure URL and metadata are preserved\n  if (item.json.url) output.url = item.json.url;\n  if (item.json.urlIndex !== undefined) output.urlIndex = item.json.urlIndex;\n  if (item.json.totalUrls !== undefined) output.totalUrls = item.json.totalUrls;\n  \n  outputItems.push({ json: output });\n}\n\nreturn outputItems;"
      },
      "id": "6f8b6234-d046-4844-97bd-e7b51c2a8055",
      "name": "Preserve Metadata",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -432,
        224
      ]
    },
    {
      "parameters": {
        "jsCode": "// Build LLM prompt with full glossary - process ALL items\nconst items = $input.all();\nconst outputItems = [];\n\n// Full glossary (defined once, reused for all items)\nconst glossary = `SECTOR CLASSIFICATION GLOSSARY:\\n\\n1. Fintech & Insurtech\\n   - Insurtech - Use of technology, digital solutions, and data analytics to disrupt and innovate the traditional insurance industry\\n   - Lending & Financing - Providing financial assistance through loans or credit via traditional institutions or fintech platforms\\n   - Money Transfer & Management - Online banking, secure movement of funds between parties, digital payment methods\\n   - Trading & Investing - Buying, selling, or holding financial assets like stocks, bonds, cryptocurrencies, or commodities\\n   - Personal Finance Management - Managing individual's financial resources, budgeting, expense tracking, financial goals\\n\\n2. Retail Platforms\\n   - Digital Products - Intangible items sold digitally (software, e-books, online courses, music, digital art)\\n   - Services - Intangible activities provided in exchange for payment (consulting, coaching, freelance skills, SaaS subscriptions)\\n   - Goods - Physical items sold through retail platforms (electronics, clothing, home items, beauty products, food)\\n\\n3. Business Software - IT, R&D, & Data Solutions\\n   - IT & Network Management - Software for administration and management of IT resources and network infrastructure\\n   - Data Architecture - Tools for designing and defining data structures, databases, and data models\\n   - Data Analysis & Decision Support - Software for analyzing data to provide insights and support decision-making\\n   - Project Management & Collaboration - Platforms for planning, executing, and monitoring project work\\n   - Product Management Tools - Software for planning, developing, and launching products\\n   - Software Development Tools - Tools assisting in software development processes\\n\\n4. Business Software - Operations Solutions\\n   - Human Resources Management - Systems for managing employee information, recruitment, onboarding, performance, payroll\\n   - Legal and Compliance Solutions - Software ensuring compliance with legal requirements\\n   - Financial Operations Software - Tools for accounting, budgeting, invoicing, payroll, financial planning, risk management\\n\\n5. Business Software - Sales & Marketing Solutions\\n   - Advertising Platforms - Software for refining and improving online advertising campaigns\\n   - eCommerce Tools - Specialized software for online business transactions, storefronts, shopping carts, payment gateways\\n\\n6. Life Sciences & HealthTech - Digital Healthcare\\n   - Medical Decision Support - Companies helping physicians make accurate, personalized, data-driven decisions\\n   - Patient Remote Monitoring - Technological tools that continually monitor and collect patient data remotely\\n   - Digital Accessibility Solutions - Devices or software aiding consumers by improving quality of life\\n   - Digital Therapeutics - Digital tools empowering consumers to track, treat and manage medical conditions\\n   - Digital Medical Diagnostics - Digital data analytics tools providing automatic, fast, affordable medical diagnostics\\n   - Patient Engagement - Technologies increasing patient adherence and compliance with healthcare guidelines\\n   - Clinical Workflow - Solutions digitalizing healthcare administrative workflow\\n\\n7. Life Sciences & HealthTech - Medical Devices\\n   - Medical Treatment & Therapeutics - Products aimed at remediation of health problems\\n   - Assistive Devices - Products helping maintain or improve individual's functioning\\n   - Medical Monitors - Remote patient monitoring devices\\n   - Diagnostics Devices - Equipment for discovering what is wrong with people who are ill\\n   - Aesthetic Devices - Instruments providing desired change in visual appearance\\n   - Life Support - Medical procedures keeping patients alive until body functions recover\\n\\n8. Pharma & Medical Biotechnology\\n   - Medical Cannabis - Cannabis and cannabinoids prescribed by physicians\\n   - Drug Delivery - Approaches for transporting pharmaceutical compounds to target sites\\n   - Cosmetic Materials - Constituted mixtures of chemical compounds from natural or synthetic sources\\n   - Drugs Discovery & Development - Process of identifying and developing new pharmaceutical drugs\\n   - Test Diagnostics & Screening - Tests for early detection of disease or risk factors\\n   - Biomaterials & Tissue Engineering - Man-made materials for medical treatments and methods to produce living functional tissue\\n\\n9. Agriculture & Food Technologies - AgriTech\\n   - Agriculture Genetics & Inputs - Genetic improvement of crops, genetic engineering, biotechnology, seed breeding\\n   - Farm Equipment & Treatment - Equipment used on farms, treatment processes for crops, soil, and livestock\\n   - Precision Agriculture - Approach utilizing technology, data, and analytics to optimize agricultural production\\n\\n10. Agriculture & Food Technologies - FoodTech\\n    - Produce Preservation - Technologies for preserving and packaging agricultural and food products\\n    - Novel Food & Ingredients - Alternative sources-based foods, cultivated foods, fermentation\\n    - Food Processing - Update, enrichment, and preparation of existing food with robotics and equipment\\n    - Food Trade & Services - Food delivery platforms, meal kit services, restaurant management systems\\n\\n11. Industrial Technologies\\n    - Product Fabrication Technologies - Methods and machinery for manufacturing goods (3D printing, CNC machining)\\n    - Material Innovations & Applications - Development of new materials or novel application of existing materials\\n    - Process Automation & Intelligence Systems - Technologies automating and controlling industrial processes\\n    - Operational Optimization Solutions - Software solutions enhancing efficiency and productivity of industrial operations\\n    - Microelectronics and Photonics Solutions - Electronic components, semiconductor devices, optical systems, MEMS, quantum computing\\n\\n12. Automotive & Mobility Technologies\\n    - Autonomous and Connected Technology - Self-operating vehicles with AI, sensors, V2V, V2I, V2X communication\\n    - Electric Mobility & Alternative Fuels - Electric vehicles, charging infrastructure, batteries, hydrogen fuel cells, biofuels\\n    - Urban Mobility - Public transit, micro mobility (bikes, scooters), ride-hailing services\\n    - Logistics & Transportation Management - Technology optimizing movement of goods, fleet management, route optimization\\n\\n13. Energy Tech\\n    - Energy Production & Sources - Technologies for generating energy from fossil fuels, renewable sources, nuclear power\\n    - Energy Management & Grid Integration - Infrastructure for distributing energy, smart grids, energy storage\\n    - Energy Consumption & Efficiency - Technologies improving energy use in transportation, industry, buildings\\n\\n14. Aerospace, Defense & HLS\\n    - Defense & HLS Solutions - Defense tech for navy, air, ground forces; Homeland Security measures\\n    - Unmanned Systems - UAVs, UGVs, USVs, robotics with AI and communication modules\\n    - Aircrafts & Avionics - Aircraft technologies, aerostructures, sensor integration, targeting\\n    - C4I - Command, Control, Communications, Computers, and Intelligence solutions\\n    - Defense Electronics - Cybersecurity, communications security, encryption, sensors, signal processing\\n    - Space Tech - Space Exploration, Space Components and Infrastructure, Communication & Navigation, Earth Observation\\n\\n15. Cybersecurity\\n    - Cloud Security - Securing cloud computing platforms, services, and data\\n    - Security Operations - Combining information security and IT operations practices\\n    - Data Security - Protecting sensitive data from unauthorized access\\n    - Application & Website Security - Securing software applications and web systems\\n    - Security Intelligence - Gathering, analysis, and utilization of security threat information\\n    - Network & Infrastructure Security - Securing computer networks, firewalls, intrusion detection\\n    - GRC & Vulnerability - Governance, Risk Management, Compliance, and security vulnerability management\\n    - Industrial Security - Protection of critical infrastructure and industrial control systems\\n    - Identity Security - Managing user identities, authentication, and access control\\n    - Endpoint Security - Securing endpoints like laptops, desktops, mobile devices\\n\\n16. Media & Entertainment Technologies\\n    - Digital Content Production - Technologies facilitating content production (audio, video, graphic design, web design)\\n    - Digital Content Distribution - Platforms for content distribution, CMS, DAM, CDNs, social media platforms\\n    - Digital Content Engagement & Entertainment - Streaming services, broadcasting, gaming, AR/VR, gadgets\\n\\n17. Education & Knowledge Technologies\\n    - Learning/Self Learning Applications - Tools for individual and corporate training, language learning, MOOCs\\n    - Teaching & Instruction Tools - Technologies assisting educators in content creation and course management\\n    - Assessment & Verification - Tools for evaluating educational programs, automated grading, performance analytics\\n`;\n\nfor (const item of items) {\n  let text = item.json.mainContent || '';\n  const url = item.json.url || '';\n  \n  // Clean the text - extract actual content if it's wrapped in JSON\n  if (typeof text === 'string' && text.trim().startsWith('{\"data\":')) {\n    try {\n      const parsed = JSON.parse(text);\n      text = parsed.data || parsed.text || String(text);\n    } catch (e) {\n      const match = text.match(/\\{\"data\":\"([\\s\\S]*?)\"\\}/);\n      if (match && match[1]) {\n        text = match[1].replace(/\\\\n/g, '\\n').replace(/\\\\\"/g, '\"');\n      }\n    }\n  }\n  \n  // Ensure text is a clean string\n  if (typeof text !== 'string') {\n    text = String(text || '');\n  }\n  \n  // Limit text length to avoid token limits\n  const maxLength = 8000;\n  if (text.length > maxLength) {\n    text = text.substring(0, maxLength) + '...';\n  }\n  \n  const prompt = `You are an expert company-sector analyst.\\n\\nGiven the following homepage text, classify the company into a business sector and subsector.\\n\\n${glossary}\\n\\nReturn strictly JSON with fields:\\n{\\n  \\\"sector\\\": \\\"...\\\",\\n  \\\"subsector\\\": \\\"...\\\",\\n  \\\"confidence\\\": 0-100,\\n  \\\"reason\\\": \\\"short explanation\\\"\\n}\\n\\nHomepage text:\\n${text}\\n\\nRespond with ONLY valid JSON, no additional text. Select the most appropriate sector and subsector from the list above.`;\n  \n  // Preserve URL and metadata\n  const output = { llmPrompt: prompt, url: url };\n  if (item.json.urlIndex !== undefined) output.urlIndex = item.json.urlIndex;\n  if (item.json.totalUrls !== undefined) output.totalUrls = item.json.totalUrls;\n  \n  outputItems.push({ json: output });\n}\n\nreturn outputItems;"
      },
      "id": "5279e6c8-5f7a-4e56-8a20-8c0416fe6cbb",
      "name": "AI Prompt Builder",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -256,
        224
      ]
    },
    {
      "parameters": {
        "jsCode": "// Prepare JSON body for Ollama API with proper escaping - process ALL items\nconst items = $input.all();\nconst outputItems = [];\n\nfor (const item of items) {\n  const prompt = item.json.llmPrompt || '';\n  \n  // Create the request body object - n8n will serialize this properly\n  const requestBody = {\n    model: 'qwen3:latest',\n    prompt: String(prompt), // Ensure it's a string\n    stream: false,\n    format: 'json'\n  };\n  \n  // Preserve URL and metadata\n  const output = { requestBody: requestBody, url: item.json.url || '' };\n  if (item.json.urlIndex !== undefined) output.urlIndex = item.json.urlIndex;\n  if (item.json.totalUrls !== undefined) output.totalUrls = item.json.totalUrls;\n  \n  outputItems.push({ json: output });\n}\n\nreturn outputItems;"
      },
      "id": "dfc8d12d-f0ba-4695-9dda-3d2e7a138775",
      "name": "Prepare JSON Body",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -80,
        224
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://host.docker.internal:11434/api/generate",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ $json.requestBody }}",
        "options": {
          "response": {
            "response": {
              "neverError": true,
              "responseFormat": "json"
            }
          },
          "timeout": 120000
        }
      },
      "id": "f11e4f95-1a43-4c65-942d-af5b88933974",
      "name": "AI Call Ollama",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        128,
        224
      ]
    },
    {
      "parameters": {
        "jsCode": "// Parse AI Response - process ALL items\nconst items = $input.all();\nconst outputItems = [];\n\nfor (const item of items) {\n  let responseText = item.json.response || item.json.body?.response || item.json.body || '';\n  \n  // Handle Ollama response format - response might be in different fields\n  if (typeof responseText === 'object') {\n    responseText = responseText.response || responseText.text || JSON.stringify(responseText);\n  }\n  \n  responseText = String(responseText).replace(/```json/g,'').replace(/```/g,'').trim();\n  \n  let parsed;\n  try { \n    parsed = JSON.parse(responseText); \n  } catch(e) { \n    parsed = { sector:'Unknown', subsector:'Unspecified', confidence:0, reason:'Parse error: ' + e.message };\n  }\n  \n  // Get URL and metadata from current item (passed through workflow)\n  const url = item.json.url || '';\n  const urlIndex = item.json.urlIndex;\n  const totalUrls = item.json.totalUrls;\n  \n  // Extract company name from URL\n  let companyName = '';\n  if (url) {\n    try {\n      const urlObj = new URL(url);\n      let hostname = urlObj.hostname;\n      // Remove www. prefix\n      hostname = hostname.replace(/^www\\./i, '');\n      // Extract main domain (e.g., 'stripe.com' -> 'stripe')\n      const domainParts = hostname.split('.');\n      if (domainParts.length >= 2) {\n        // Take the second-to-last part (usually the company name)\n        companyName = domainParts[domainParts.length - 2];\n      } else {\n        companyName = hostname;\n      }\n      // Capitalize first letter\n      companyName = companyName.charAt(0).toUpperCase() + companyName.slice(1);\n    } catch(e) {\n      // If URL parsing fails, try to extract from string\n      const match = url.match(/(?:https?:\\/\\/)?(?:www\\.)?([^.]+)\\./i);\n      if (match && match[1]) {\n        companyName = match[1].charAt(0).toUpperCase() + match[1].slice(1);\n      }\n    }\n  }\n  \n  // Add URL and company name to response\n  if (url) parsed.url = url;\n  if (companyName) parsed['company name'] = companyName;\n  \n  // Preserve ordering metadata\n  if (urlIndex !== undefined) parsed.urlIndex = urlIndex;\n  if (totalUrls !== undefined) parsed.totalUrls = totalUrls;\n  \n  outputItems.push({ json: parsed });\n}\n\nreturn outputItems;"
      },
      "id": "f49d4bdc-f640-424e-8fa1-f1a1c532948c",
      "name": "Parse AI Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        320,
        224
      ]
    },
    {
      "parameters": {
        "jsCode": "// Aggregate results - collect all classification results\n// This node receives all items from Parse AI Response\nconst allItems = $input.all();\n\nif (allItems.length === 0) {\n  return [{ json: { error: 'No results to aggregate' } }];\n}\n\n// Extract json from each item - items should be in standard n8n format { json: {...} }\nconst results = [];\nfor (let index = 0; index < allItems.length; index++) {\n  const item = allItems[index];\n  \n  // Validate item structure\n  if (!item || typeof item !== 'object' || Array.isArray(item)) {\n    continue; // Skip invalid items\n  }\n  \n  // Get the json property - must be an object\n  if (item.json === undefined) {\n    continue; // Skip items without json property\n  }\n  \n  // json must be a plain object (not array, not null)\n  if (typeof item.json !== 'object' || item.json === null || Array.isArray(item.json)) {\n    continue; // Skip items where json is not a plain object\n  }\n  \n  // Valid item - add it to results\n  results.push(item.json);\n}\n\nif (results.length === 0) {\n  return [{ json: { error: 'No valid results to aggregate', receivedItems: allItems.length, debug: JSON.stringify(allItems[0]) } }];\n}\n\n// Sort by urlIndex if available to maintain order\nif (results.length > 1 && results[0] && results[0].urlIndex !== undefined) {\n  results.sort((a, b) => (a.urlIndex || 0) - (b.urlIndex || 0));\n}\n\n// Remove metadata fields from final output\nconst cleanResults = results.map(result => {\n  if (result && typeof result === 'object' && !Array.isArray(result)) {\n    const { urlIndex, totalUrls, ...cleanResult } = result;\n    return cleanResult;\n  }\n  return result;\n});\n\n// Return results - n8n requires json to be an object, not an array\n// For single result: return the object directly\n// For multiple results: wrap in an object with 'results' property\nlet response;\nif (cleanResults.length === 1) {\n  response = cleanResults[0];\n} else {\n  // Multiple results - wrap array in object since n8n doesn't allow arrays directly in json\n  response = { results: cleanResults };\n}\n\n// Ensure we return in correct n8n format: [{ json: {...} }]\n\nreturn [{ json: response }];"
      },
      "id": "5197637e-5953-468a-a15b-03e0c4723ced",
      "name": "Aggregate Results",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        496,
        224
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ $json.results || $json }}",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "application/json"
              }
            ]
          }
        }
      },
      "id": "6cf179f3-f0e6-4601-b8bf-7ce7a1aac1cd",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        720,
        224
      ]
    },
    {
      "parameters": {},
      "id": "260a7a7c-2b20-4aa6-b419-b7ee3810e794",
      "name": "When clicking ‘Test workflow’",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -1376,
        80
      ]
    }
  ],
  "pinData": {},
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Validate URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate URL": {
      "main": [
        [
          {
            "node": "Fetch Homepage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Homepage": {
      "main": [
        [
          {
            "node": "Prepare HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare HTML": {
      "main": [
        [
          {
            "node": "Extract Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Text": {
      "main": [
        [
          {
            "node": "Preserve Metadata",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Preserve Metadata": {
      "main": [
        [
          {
            "node": "AI Prompt Builder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Prompt Builder": {
      "main": [
        [
          {
            "node": "Prepare JSON Body",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare JSON Body": {
      "main": [
        [
          {
            "node": "AI Call Ollama",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Call Ollama": {
      "main": [
        [
          {
            "node": "Parse AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Response": {
      "main": [
        [
          {
            "node": "Aggregate Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Results": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking ‘Test workflow’": {
      "main": [
        []
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "a3ce6e2c-3af8-486f-9c67-11d19c675da1",
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "e09d1f0f8b9f78e80ac70b6dc8726dd263b0b6ffc4300b0eee3b58f6da316f29"
  },
  "id": "OORMfVBOjUWwQRzq",
  "tags": []
}