{
  "name": "Anomaly Detection Alert System",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 15
            }
          ]
        }
      },
      "id": "e5f6a7b8-5555-4000-8000-000000000001",
      "name": "Schedule - Every 15 Minutes",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT metric_name, metric_value, recorded_at, service_name, ROUND(AVG(metric_value) OVER (PARTITION BY metric_name ORDER BY recorded_at ROWS BETWEEN 96 PRECEDING AND 1 PRECEDING), 2) as rolling_avg, ROUND(STDDEV(metric_value) OVER (PARTITION BY metric_name ORDER BY recorded_at ROWS BETWEEN 96 PRECEDING AND 1 PRECEDING), 2) as rolling_stddev FROM system_metrics WHERE recorded_at >= NOW() - INTERVAL '24 hours' ORDER BY recorded_at DESC LIMIT 50",
        "options": {}
      },
      "id": "e5f6a7b8-5555-4000-8000-000000000002",
      "name": "PostgreSQL - Get Metrics",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        480,
        300
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const metrics = $input.all().map(item => item.json);\nconst metricsText = metrics.map(m => \n  `[${m.service_name}] ${m.metric_name}: current=${m.metric_value}, avg=${m.rolling_avg}, stddev=${m.rolling_stddev}, at=${m.recorded_at}`\n).join('\\n');\nreturn [{ json: { metricsText, metricCount: metrics.length, checkTime: new Date().toISOString() } }];"
      },
      "id": "e5f6a7b8-5555-4000-8000-000000000003",
      "name": "Code - Prepare Metrics",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        300
      ]
    },
    {
      "parameters": {
        "resource": "chat",
        "model": "gpt-4o",
        "messages": {
          "values": [
            {
              "content": "=You are a system monitoring expert specializing in anomaly detection. Analyze the following system metrics and identify any anomalies.\n\nFor each metric, consider:\n1. Values more than 2 standard deviations from the rolling average\n2. Sudden spikes or drops compared to recent trends\n3. Unusual patterns (e.g., metrics that should correlate but diverge)\n4. Service-specific thresholds (CPU > 85%, memory > 90%, error rate > 5%, latency > 2000ms)\n\nReturn JSON with:\n- anomalyDetected: boolean\n- anomalies: array of { service, metric, currentValue, expectedRange, severity (critical/warning/info), description }\n- summary: brief overall assessment\n- recommendedActions: array of strings\n\nMetrics Data:\n{{ $json.metricsText }}"
            }
          ]
        },
        "options": {
          "temperature": 0.2,
          "maxTokens": 2048,
          "responseFormat": "json_object"
        }
      },
      "id": "e5f6a7b8-5555-4000-8000-000000000004",
      "name": "OpenAI - Detect Anomalies",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.4,
      "position": [
        960,
        300
      ],
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const aiResponse = $input.first().json.message.content;\nlet analysis;\ntry {\n  analysis = JSON.parse(aiResponse);\n} catch (e) {\n  analysis = { anomalyDetected: false, anomalies: [], summary: 'Parse error', recommendedActions: [] };\n}\nconst checkTime = $('Code - Prepare Metrics').first().json.checkTime;\nreturn [{ json: { ...analysis, checkTime } }];"
      },
      "id": "e5f6a7b8-5555-4000-8000-000000000005",
      "name": "Code - Parse Analysis",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1200,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "condition-1",
              "leftValue": "={{ $json.anomalyDetected }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "e5f6a7b8-5555-4000-8000-000000000006",
      "name": "IF - Anomaly Found",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1440,
        300
      ]
    },
    {
      "parameters": {
        "channel": "#alerts-production",
        "text": "=:rotating_light: *ANOMALY DETECTED* :rotating_light:\n\n*Time:* {{ $('Code - Parse Analysis').first().json.checkTime }}\n*Summary:* {{ $('Code - Parse Analysis').first().json.summary }}\n\n*Anomalies:*\n{{ $('Code - Parse Analysis').first().json.anomalies.map(a => `\u2022 [${a.severity.toUpperCase()}] ${a.service} - ${a.metric}: ${a.currentValue} (expected: ${a.expectedRange})\\n  _${a.description}_`).join('\\n') }}\n\n*Recommended Actions:*\n{{ $('Code - Parse Analysis').first().json.recommendedActions.map((a, i) => `${i+1}. ${a}`).join('\\n') }}",
        "otherOptions": {}
      },
      "id": "e5f6a7b8-5555-4000-8000-000000000007",
      "name": "Slack - Alert Channel",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [
        1680,
        200
      ],
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "url": "https://events.pagerduty.com/v2/enqueue",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"routing_key\": \"YOUR_PAGERDUTY_INTEGRATION_KEY\",\n  \"event_action\": \"trigger\",\n  \"payload\": {\n    \"summary\": \"Anomaly Detected: {{ $('Code - Parse Analysis').first().json.summary }}\",\n    \"severity\": \"{{ $('Code - Parse Analysis').first().json.anomalies[0] ? $('Code - Parse Analysis').first().json.anomalies[0].severity : 'warning' }}\",\n    \"source\": \"n8n-anomaly-detection\",\n    \"component\": \"{{ $('Code - Parse Analysis').first().json.anomalies[0] ? $('Code - Parse Analysis').first().json.anomalies[0].service : 'unknown' }}\",\n    \"timestamp\": \"{{ $('Code - Parse Analysis').first().json.checkTime }}\"\n  }\n}",
        "options": {}
      },
      "id": "e5f6a7b8-5555-4000-8000-000000000008",
      "name": "PagerDuty - Trigger Incident",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1680,
        400
      ]
    }
  ],
  "connections": {
    "Schedule - Every 15 Minutes": {
      "main": [
        [
          {
            "node": "PostgreSQL - Get Metrics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "PostgreSQL - Get Metrics": {
      "main": [
        [
          {
            "node": "Code - Prepare Metrics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Prepare Metrics": {
      "main": [
        [
          {
            "node": "OpenAI - Detect Anomalies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI - Detect Anomalies": {
      "main": [
        [
          {
            "node": "Code - Parse Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Parse Analysis": {
      "main": [
        [
          {
            "node": "IF - Anomaly Found",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Anomaly Found": {
      "main": [
        [
          {
            "node": "Slack - Alert Channel",
            "type": "main",
            "index": 0
          },
          {
            "node": "PagerDuty - Trigger Incident",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [
    {
      "name": "ai-data"
    }
  ]
}