{
  "id": "pFgRdFBDYCSDSR9Z",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "News Based Risk Alert",
  "tags": [],
  "nodes": [
    {
      "id": "7f343272-a8a8-4eb3-a76a-c48f16f23eb1",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2112,
        -1792
      ],
      "parameters": {
        "width": 784,
        "height": 752,
        "content": "## Summary (News Based Risk Alerts)\n\nThe workflow functions as a proactive monitoring system that separates \"market noise\" from \"market risk.\" Instead of flooding your inbox with every news mention, it uses Llama 3 (via Groq) to act as a virtual risk analyst, categorizing news as Low, Medium or High risk and only alerting you when the risk is significant (Medium or High).\n\n## How It Works\n\n* **1. Grabs Keywords:** It reads a list of companies or topics you want to track from a Google Sheet.\n* **2. Scans the News:** It searches Google News to find the newest articles about those specific topics.\n* **3. AI Analyzes Risk:** It has an AI read the headlines to decide if the news is a \"Low\", \"Medium\" or \"High\" risk.\n* **4. Emails the Important Stuff:** It ignores the \"Low\" risk news, gathers up the \"Medium\" and \"High\" risk alerts and sends them straight to your email.\n\n## Set Up Steps\nTo get this workflow operational, follow these steps:\n\n- Spreadsheet Preparation\nCreate a Google Sheet named Risk Keywords.\nIn the first column (Sheet1), add a header named Keyword. List the companies, tickers or industry terms you want to monitor (e.g., \"Tesla\", \"Nvidia\", \"Inflation Rate\").\n\n- API & Credentials Configuration\nn8n Credentials: Ensure your n8n instance has valid credentials for Google Sheets and Gmail.\nGroq API: Obtain an API key from Groq. In the \"Llama 3 (via Groq)\" node, enter your API key to enable the AI analysis.\n\n- Node Adjustments\nFetch Risk Keywords: Open this node and select your specific \"Risk Keywords\" spreadsheet from the dropdown.\nGmail Alert Dispatcher: Replace RECIPIENT_EMAIL_HERE with the email address where you want to receive the alerts."
      },
      "typeVersion": 1
    },
    {
      "id": "03f6703f-64ed-435f-847f-a4c31d78a060",
      "name": "Start",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -1280,
        -1424
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "9fc70e3e-df54-4151-8b65-073d3cc85c96",
      "name": "Fetch Risk Keywords",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1040,
        -1424
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1BqW8icG1q1Dj0-Gge4KhMqcGVrkOHtVNUE_HhgJSWEs/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1BqW8icG1q1Dj0-Gge4KhMqcGVrkOHtVNUE_HhgJSWEs",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1BqW8icG1q1Dj0-Gge4KhMqcGVrkOHtVNUE_HhgJSWEs/edit?usp=drivesdk",
          "cachedResultName": "Risk Keywords"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "a6448c0a-a7c1-4c18-819b-259e10e43b36",
      "name": "Keyword Iterator",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -864,
        -1424
      ],
      "parameters": {
        "options": {
          "reset": false
        }
      },
      "typeVersion": 3
    },
    {
      "id": "36cd4cae-14cd-47ef-9884-fb1a7611034b",
      "name": "Google News Scraper",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        -608,
        -1424
      ],
      "parameters": {
        "url": "=https://news.google.com/rss/search?q={{ $json.Keyword }}",
        "options": {}
      },
      "executeOnce": false,
      "retryOnFail": false,
      "typeVersion": 1.2,
      "alwaysOutputData": false
    },
    {
      "id": "e7152caf-db5b-4c31-b820-a5ca82aad3e0",
      "name": "Top 4 Articles Filter",
      "type": "n8n-nodes-base.limit",
      "position": [
        -384,
        -1424
      ],
      "parameters": {
        "keep": "lastItems",
        "maxItems": 4
      },
      "typeVersion": 1
    },
    {
      "id": "e2712910-57c7-41ed-b2e9-7f9b828ba56f",
      "name": "API Rate-Limit Delay",
      "type": "n8n-nodes-base.wait",
      "position": [
        -176,
        -1424
      ],
      "parameters": {
        "amount": 2
      },
      "typeVersion": 1.1
    },
    {
      "id": "c4726c7f-154e-47a3-99c8-c9f221ab283c",
      "name": "Risk Analysis Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -608,
        -1184
      ],
      "parameters": {
        "text": "=Title: {{ $json.title }} | Summary: {{ $json.contentSnippet || $json.content || $json.description }}",
        "options": {
          "systemMessage": "You are a risk intelligence analyst. Review the provided news article headline and snippet. Determine the risk level this news poses to the company. You MUST return your answer strictly as a JSON object with exactly two keys: \"Risk_Level\" (must be exactly \"Low\", \"Medium\" or \"High\") and \"Reason\" (a 1-sentence explanation of why)."
        },
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "21eeca9a-cb33-4ec9-9517-b17f3f1dd4b4",
      "name": "Llama 3 (via Groq)",
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "position": [
        -640,
        -944
      ],
      "parameters": {
        "model": "openai/gpt-oss-120b",
        "options": {}
      },
      "credentials": {
        "groqApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "cd4b57f1-f642-45f5-9395-4bd389493ce6",
      "name": "Filter High/Medium Risk",
      "type": "n8n-nodes-base.if",
      "position": [
        -224,
        -992
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "3b550bb7-2b40-494c-90dd-1097b18e11e0",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.output }}",
              "rightValue": "High"
            },
            {
              "id": "66988e53-948c-465c-918c-efb82d96f4da",
              "operator": {
                "type": "string",
                "operation": "contains"
              },
              "leftValue": "={{ $json.output }}",
              "rightValue": "Medium"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "1dfdb5c7-177c-42d5-8b27-ab311b562b44",
      "name": "Batch Article Results",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        16,
        -1008
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "37d284f5-d6fb-4327-b814-cd7a55a3294b",
      "name": "Format Alert Email",
      "type": "n8n-nodes-base.code",
      "position": [
        128,
        -1408
      ],
      "parameters": {
        "jsCode": "// Grab the bundled data array from the incoming item\nlet articles = $input.first().json.data; \n\n// Start building our clean email/message text\nlet alertMessage = \"Business Risk Alert \\n\\n\";\n\n// Loop through each bundled article\nfor (let item of articles) {\n    try {\n        // Unpack the text string back into a real JSON object\n        let aiData = JSON.parse(item.output);\n        \n        // Extract our specific pieces of information\n        let riskLevel = aiData.Risk_Level;\n        let riskAnalysis = aiData.Reason;\n        \n        // Add them neatly to our final message\n        alertMessage += `Risk Level: ${riskLevel}\\n`;\n        alertMessage += `Risk Analysis: ${riskAnalysis}\\n`;\n        alertMessage += `-----------------------------------\\n\\n`;\n        \n    } catch (error) {\n        // Just in case the AI ever formats the text weirdly and it can't be parsed\n        alertMessage += `Error reading AI output for one article.\\n\\n`;\n    }\n}\n\n// Output the final, beautifully formatted text message\nreturn [{ \n    json: { \n        formatted_message: alertMessage \n    } \n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "862fab0c-eb11-4408-8c0f-8249de324238",
      "name": "Gmail Alert Dispatcher",
      "type": "n8n-nodes-base.gmail",
      "position": [
        416,
        -1152
      ],
      "parameters": {
        "sendTo": "RECIPIENT_EMAIL_HERE",
        "message": "={{ $json.formatted_message }}",
        "options": {},
        "subject": " High Risk Alert Triggered",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "021764a3-b099-4eee-a41a-fbd65fbba545",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -656,
        -1616
      ],
      "parameters": {
        "color": 7,
        "width": 608,
        "height": 352,
        "content": "## News Scraping & Rate Limiting\nScans Google News RSS feeds for real-time updates. A Limit node ensures we only analyze the most relevant recent news, while a Wait node protects the AI API from being overwhelmed by too many simultaneous requests."
      },
      "typeVersion": 1
    },
    {
      "id": "03d82013-0c62-4c1c-b01d-aca2c045d81e",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1088,
        -1616
      ],
      "parameters": {
        "color": 7,
        "width": 384,
        "height": 368,
        "content": "## Fetch & Loop Keywords\n\nThis section connects to a Google Sheet (Risk Keywords) to retrieve the list of companies or topics to monitor. It uses a Split-in-Batches approach to ensure every keyword is processed individually."
      },
      "typeVersion": 1
    },
    {
      "id": "c4fdf2d1-fff5-46d4-851d-1c20e35c543f",
      "name": "Prepare Alert Message",
      "type": "n8n-nodes-base.set",
      "position": [
        304,
        -1408
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "85d64fe1-0e80-40fd-953b-1b5d107bf6f8",
              "name": "formatted_message",
              "type": "string",
              "value": "={{ $json.formatted_message }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "65d398f7-8c95-4e3c-b044-6e1fb4a18dda",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        64,
        -1616
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 368,
        "content": "## Final Formatting & Data Prep\n- Uses a JavaScript snippet to loop through the gathered articles and parse the AI's JSON response. It extracts the Risk_Level and Reason to build a clean, bulleted text summary for the final message.\n- Acts as a final staging area to define the formatted_message variable before sending."
      },
      "typeVersion": 1
    },
    {
      "id": "b33d686a-33e3-4753-a2d1-e34eb7c92fa9",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -320,
        -1184
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 336,
        "content": "## Filer high/medium risk\n- This node is responsible to check whether the risk is high/ medium.\n- If it is low then it doesn't forward it goes to false state.\n- Next node make the bundle which batch the article results"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "12302408-5cf9-4ca3-99b9-940d6558b160",
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Fetch Risk Keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Keyword Iterator": {
      "main": [
        [],
        [
          {
            "node": "Google News Scraper",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Alert Email": {
      "main": [
        [
          {
            "node": "Prepare Alert Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Llama 3 (via Groq)": {
      "ai_languageModel": [
        [
          {
            "node": "Risk Analysis Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Risk Keywords": {
      "main": [
        [
          {
            "node": "Keyword Iterator",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google News Scraper": {
      "main": [
        [
          {
            "node": "Top 4 Articles Filter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Risk Analysis Agent": {
      "main": [
        [
          {
            "node": "Keyword Iterator",
            "type": "main",
            "index": 0
          },
          {
            "node": "Filter High/Medium Risk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "API Rate-Limit Delay": {
      "main": [
        [
          {
            "node": "Risk Analysis Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Batch Article Results": {
      "main": [
        [
          {
            "node": "Format Alert Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Alert Message": {
      "main": [
        [
          {
            "node": "Gmail Alert Dispatcher",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Top 4 Articles Filter": {
      "main": [
        [
          {
            "node": "API Rate-Limit Delay",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter High/Medium Risk": {
      "main": [
        [
          {
            "node": "Batch Article Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}