AutomationFlowsAI & RAG › Analyze Alertmanager Incidents with AI and Post to Mattermost

Analyze Alertmanager Incidents with AI and Post to Mattermost

Original n8n title: Analyze Alertmanager Incidents and Post Diagnostic Reports to Mattermost

BySergei Byvshev @javdet on n8n.io

This workflow helps automatically analyze alerts occurring in the infrastructure and suggest solutions even before the on-duty engineer sees the alert. Workflow receives alert from Alertmanager via Webhook. The variables required for operation are set Preparing a prompt for the…

Webhook trigger★★★★☆ complexityAI-powered23 nodesAgentOpenAI ChatQdrant Vector StoreGoogle Gemini EmbeddingsMcp Client ToolHTTP RequestMattermost
AI & RAG Trigger: Webhook Nodes: 23 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #14347 — we link there as the canonical source.

This workflow follows the Agent → Google Gemini Embeddings 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 →

Download .json
{
  "id": "iaQBJNGp3ERioXWn",
  "name": "AlertAssistant",
  "tags": [
    {
      "id": "hyB5cI3OJX7DXB43",
      "name": "public",
      "createdAt": "2026-04-05T04:05:10.508Z",
      "updatedAt": "2026-04-05T04:05:10.508Z"
    }
  ],
  "nodes": [
    {
      "id": "26b0cac2-157a-4bac-b77e-26d3ab644adc",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1008,
        448
      ],
      "parameters": {
        "options": {
          "maxIterations": 20,
          "systemMessage": "=You are an senior SRE assistant for a game studio infrastructure. Your main goal is to assist in the investigation of the incident indicated by the Alert.\n\n## Kubernetes Tools\nUse these to inspect cluster state: pods, deployments, ingress, services, logs, events, etc\n- Read container logs for error investigation\n- Use pods_log for the same pod no more than twice!\n- List resources across namespaces\n- Main workload is in namespace: {{ $('SetVars').first().json.mainNS }}\n\n\n## Grafana Tools  \nUse these to query metrics, logs, dashboards:\n- **Prometheus**: query_prometheus for PromQL queries (CPU, memory, request rates, error rates). Datasource uid: {{ $('SetVars').first().json.prometheus_uid }}\n- **Loki**: query_loki_logs for LogQL log searches. Datasource uid: {{ $('SetVars').first().json.loki_uid }}\n- **Dashboards**: search_dashboards, get_dashboard_summary to find relevant dashboards\n\n## Vector store tools\n- Read infromation about infratructure, service commuication, trafic balancing, useful tags and labels. Naming convention\n\n## Digitalocean tools:\n- Use if you need information about App Platform, Droplets, Kubernetes(DOKS), Networking\n\n## Github tools\n- Use this to find out if releases have been executed.\n- Search only within the organization {{ $('SetVars').first().json.GITHUB_ORG_NAME }}.\n\n## Critical Rules for Tool Usage\n1. **Never retry a failed tool call more than once.** If a Kubernetes resource (pod, deployment, node) is not found on the first attempt, it likely no longer exists. Do NOT retry the same query.\n2. **If any tool returns an error or empty result**, acknowledge it and move on.\n3.  Don't make any changes to anything through mcp.\n4.  Avoid queries that return all elements; filter and grep.\n\n## Important rules\n- Don't ask anything, analyze it yourself\n\n## Investigation flow recommendations\n- Pay attention to the alert labels. They will help you understand what the problem is and where it is.\n- Study the alert description and labels.\n- Determine the subject area of \u200b\u200bthe message. What is it related to, for example, a database, a message queue, a pod with a backend, or errors on an ingress controller.\n- If you need details about the infrastructure organization, endpoints, component names, and how they are related, use Qdrant vectore store \n- Try executing the request that triggered the alert.\n- Check the status of the service affected by the alert.\n- Check the resource consumption of this service.\n- Find out if releases have been executed\n- Examine the service logs.\n\n## Output format\n### What happened\nDescription of what happened and what happened to what\n\n### Event timeline\nDescription of events preceding the alert for more than 10 minutes\n\n### Root cause\nNo more than two root cause suggestions\n\n### Troubleshooting tips\nStep-by-step description of actions for each root cause"
        }
      },
      "typeVersion": 3.1
    },
    {
      "id": "0ca3947b-27d1-4981-be0c-65624e74fa04",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        896,
        592
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5.3-codex",
          "cachedResultName": "gpt-5.3-codex"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "db712c7f-f0e9-48ad-80ed-b76d4f3cfd38",
      "name": "Qdrant Vector Store",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant",
      "position": [
        1312,
        944
      ],
      "parameters": {
        "mode": "retrieve-as-tool",
        "options": {},
        "toolDescription": "Use this tool to fetch knowledge from the database. ",
        "qdrantCollection": {
          "__rl": true,
          "mode": "list",
          "value": "<your-qdrant-collection-name>",
          "cachedResultName": "<your-qdrant-collection-name>"
        }
      },
      "credentials": {
        "qdrantApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "d1d8a2f3-1fbc-47c3-bd78-97306e1dc595",
      "name": "Embeddings Google Gemini",
      "type": "@n8n/n8n-nodes-langchain.embeddingsGoogleGemini",
      "position": [
        1312,
        1152
      ],
      "parameters": {
        "modelName": "models/gemini-embedding-2-preview"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b75b9e64-b259-40fd-b5d8-c4219bc74100",
      "name": "K8S mcp",
      "type": "@n8n/n8n-nodes-langchain.mcpClientTool",
      "position": [
        1040,
        944
      ],
      "parameters": {
        "include": "selected",
        "options": {},
        "endpointUrl": "http://mcp-kubernetes:8089/mcp",
        "includeTools": [
          "configuration_view",
          "events_list",
          "namespaces_list",
          "nodes_log",
          "nodes_stats_summary",
          "nodes_top",
          "pods_get",
          "pods_list",
          "pods_list_in_namespace",
          "pods_log",
          "pods_top",
          "resources_get",
          "resources_list"
        ]
      },
      "typeVersion": 1.2
    },
    {
      "id": "3b1d8a04-1ac0-4546-9721-89057b694f1f",
      "name": "Grafana mcp",
      "type": "@n8n/n8n-nodes-langchain.mcpClientTool",
      "position": [
        1184,
        944
      ],
      "parameters": {
        "include": "selected",
        "options": {
          "timeout": 60000
        },
        "endpointUrl": "http://mcp-grafana:8000/mcp",
        "includeTools": [
          "generate_deeplink",
          "get_alert_rule_by_uid",
          "get_annotations",
          "get_dashboard_by_uid",
          "get_dashboard_panel_queries",
          "get_dashboard_property",
          "get_dashboard_summary",
          "get_datasource_by_name",
          "get_datasource_by_uid",
          "get_panel_image",
          "get_sift_analysis",
          "get_sift_investigation",
          "list_alert_rules",
          "list_loki_label_names",
          "list_loki_label_values",
          "list_prometheus_label_names",
          "list_prometheus_label_values",
          "list_prometheus_metric_metadata",
          "list_prometheus_metric_names",
          "query_loki_logs",
          "query_loki_patterns",
          "query_loki_stats",
          "query_prometheus",
          "query_prometheus_histogram",
          "search_dashboards"
        ]
      },
      "typeVersion": 1.2
    },
    {
      "id": "cdaf5a8a-7d73-4eb5-a1bf-38c2c0edf4c0",
      "name": "Digitalocean MCP",
      "type": "@n8n/n8n-nodes-langchain.mcpClientTool",
      "position": [
        896,
        944
      ],
      "parameters": {
        "include": "selected",
        "options": {
          "timeout": 60000
        },
        "endpointUrl": "http://mcp-digitalocean:8090/mcp",
        "includeTools": [
          "apps-get-deployment-status",
          "apps-get-info",
          "apps-get-logs",
          "apps-list",
          "byoip-prefix-get",
          "byoip-prefix-list",
          "byoip-prefix-resources-get",
          "certificate-get",
          "certificate-list",
          "doks-get-cluster",
          "doks-get-cluster-upgrades",
          "doks-get-nodepool",
          "doks-list-options",
          "doks-list-nodepools",
          "doks-list-clusters",
          "domain-get",
          "domain-list",
          "domain-record-list",
          "domain-record-get",
          "droplet-get",
          "droplet-list",
          "firewall-get",
          "firewall-list",
          "image-action-get",
          "image-get",
          "image-list",
          "lb-get",
          "lb-list",
          "region-list",
          "reserved-ip-list",
          "reserved-ip-get",
          "size-list",
          "vpc-list",
          "vpc-get",
          "vpc-list-members",
          "vpc-peering-get",
          "vpc-peering-list"
        ]
      },
      "typeVersion": 1.2
    },
    {
      "id": "9cdbd9bf-fc42-4f48-bcbb-7eaea24aba31",
      "name": "Github MCP",
      "type": "@n8n/n8n-nodes-langchain.mcpClientTool",
      "position": [
        768,
        944
      ],
      "parameters": {
        "include": "selected",
        "options": {},
        "endpointUrl": "=http://mcp-github:8091/mcp",
        "includeTools": [
          "search_repositories",
          "get_file_contents",
          "list_commits",
          "list_issues",
          "search_issues",
          "get_issue",
          "get_pull_request",
          "list_pull_requests",
          "get_pull_request_files",
          "get_pull_request_status",
          "get_pull_request_comments",
          "get_pull_request_reviews"
        ]
      },
      "typeVersion": 1.2
    },
    {
      "id": "f3671b7e-e797-44c3-a22b-386dea7c881f",
      "name": "Receive alerts",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -320,
        448
      ],
      "parameters": {
        "path": "<your-webhook-path>",
        "options": {},
        "httpMethod": "POST",
        "authentication": "basicAuth"
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "e46d4de0-8e99-49fc-ba66-740f84e30464",
      "name": "GetAlertMessages",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1472,
        448
      ],
      "parameters": {
        "url": "=https://{{ $('SetVars').first().json.MATTERMOST_HOST }}/api/v4/channels/{{ $('SetVars').first().json.MATTERMOST_CHANNEL_ID }}/posts",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "per_page",
              "value": "10"
            }
          ]
        },
        "nodeCredentialType": "mattermostApi"
      },
      "credentials": {
        "mattermostApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "bb6003d5-94c0-4983-be51-226aa077f699",
      "name": "Post in thread",
      "type": "n8n-nodes-base.mattermost",
      "position": [
        1824,
        448
      ],
      "parameters": {
        "message": "={{ $('AI Agent').item }}",
        "channelId": "={{ $('SetVars').first().json.MATTERMOST_CHANNEL_ID }}",
        "attachments": [],
        "otherOptions": {
          "root_id": "={{ $json.thread_root_id }}"
        }
      },
      "credentials": {
        "mattermostApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "34a40436-a431-4659-8d53-29ec618f2e94",
      "name": "PreProcessAlerts",
      "type": "n8n-nodes-base.code",
      "position": [
        16,
        448
      ],
      "parameters": {
        "jsCode": "const webhookData = $input.first().json.body || $input.first().json;\n\nconst SKIP_LABELS = new Set([\n  \"alertname\", \"endpoint\", \"instance\", \"job\",\n  \"metrics_path\", \"prometheus\", \"project\", \"env\",\n]);\n\nconst LABEL_RENAME = {\n  \"grafana_board\": \"Grafana Dashboard\",\n  \"persistentvolumeclaim\": \"PVC\",\n};\n\nconst alerts = webhookData.alerts || [];\nconst results = [];\n\nfor (const alert of alerts) {\n  const status = alert.status || \"unknown\";\n  const labels = alert.labels || {};\n  const annotations = alert.annotations || {};\n  const alertname = labels.alertname || \"UnknownAlert\";\n  const fingerprint = alert.fingerprint || \"\";\n  const startsAt = alert.startsAt || \"\";\n  const generatorURL = alert.generatorURL || \"\";\n\n  const lines = [\n    `Analyze this ${status.toUpperCase()} alert.`,\n    `Alertname: ${alertname}`,\n    `Severity: ${labels.severity || \"unknown\"}`,\n  ];\n\n  for (const key of Object.keys(labels).sort()) {\n    if (SKIP_LABELS.has(key) || key === \"severity\") continue;\n    const displayKey = LABEL_RENAME[key] || key;\n    lines.push(`${displayKey}: ${labels[key]}`);\n  }\n\n  if (startsAt) lines.push(`Started At: ${startsAt}`);\n  if (generatorURL) lines.push(`Alert Source: ${generatorURL}`);\n\n  for (const key of Object.keys(annotations).sort()) {\n    const displayKey = key.replace(/_/g, \" \").replace(/\\b\\w/g, c => c.toUpperCase());\n    lines.push(`${displayKey}: ${annotations[key]}`);\n  }\n\n  const chatInput = lines.join(\"\\n\");\n  const sessionId = fingerprint\n    ? `alert-${fingerprint}`\n    : `alert-${alertname}-${labels.namespace || \"\"}-${labels.service || \"\"}`;\n\n  results.push({\n    json: {\n      action: \"sendMessage\",\n      chatInput,\n      sessionId,\n      alert_id: fingerprint,\n      alertname,\n    },\n  });\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "2f51979a-16e3-475b-9cfb-58638745abbf",
      "name": "FindAlert",
      "type": "n8n-nodes-base.code",
      "position": [
        1648,
        448
      ],
      "parameters": {
        "jsCode": "let agentOutput = \"\";\nlet chatInput = \"\";\ntry {\n  const agentData = $('AI Agent').first().json;\n  agentOutput = agentData.output || \"\";\n  chatInput = agentData.chatInput || \"\";\n} catch (e) {\n  // AI Agent node not executed in this run\n}\n\n// Get Mattermost posts from GetAlertMessages (direct input)\nconst postsData = $input.first().json;\nconst order = postsData.order || [];\nconst posts = postsData.posts || {};\n\n// Extract alertname from chatInput\nlet alertname = \"\";\nfor (const line of chatInput.split(\"\\n\")) {\n  if (line.startsWith(\"Alertname:\")) {\n    alertname = line.split(\":\").slice(1).join(\":\").trim();\n    break;\n  }\n}\n\n// Search for existing Alertmanager post with this alertname\nlet thread_root_id = \"\";\n\nfor (const postId of order) {\n  const post = posts[postId] || {};\n  const props = post.props || {};\n  const attachments = props.attachments || [];\n\n  for (const att of attachments) {\n    const title = att.title || \"\";\n    // Match alertname in attachment title, e.g. \"[FIRING:1] KubeJobFailed\"\n    if (alertname && title.includes(alertname)) {\n      thread_root_id = post.root_id || postId;\n      break;\n    }\n  }\n  if (thread_root_id) break;\n}\n\nreturn [{\n  json: {\n    thread_root_id,\n    message: agentOutput,\n    alertname,\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "d57d5093-9007-40b8-ba7a-e3eba33d3ffe",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -368,
        352
      ],
      "parameters": {
        "width": 740,
        "height": 352,
        "content": "# Input chain\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nAdd your Mattermost server address and channel id into SetVars"
      },
      "typeVersion": 1
    },
    {
      "id": "4c05e834-8ee9-4536-bc1b-370f22678fbd",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1408,
        352
      ],
      "parameters": {
        "width": 640,
        "height": 352,
        "content": "# Output chain"
      },
      "typeVersion": 1
    },
    {
      "id": "5a8df1b8-57f6-46d1-806a-4f063cf00bc1",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        848,
        352
      ],
      "parameters": {
        "color": 6,
        "width": 528,
        "height": 352,
        "content": "# Alert analysis"
      },
      "typeVersion": 1
    },
    {
      "id": "1929829e-b398-4462-8da0-5e0303879ef9",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        736,
        880
      ],
      "parameters": {
        "color": 4,
        "width": 848,
        "height": 448,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n# MCP servers\nAdd correct URLs for remote MCPs\nUse following mcp:\n* [grafana-mcp](https://github.com/grafana/mcp-grafana)\n* [kubernetes-mcp-server](https://github.com/containers/kubernetes-mcp-server)\n* [digitalocean-mcp](https://github.com/digitalocean/digitalocean-mcp)\n* [github-mcp](https://github.com/github/github-mcp-server)"
      },
      "typeVersion": 1
    },
    {
      "id": "58c1322a-dfbb-420e-a022-3177799ef081",
      "name": "SetVars",
      "type": "n8n-nodes-base.set",
      "notes": "To get channel id\ncurl --request GET \\\n  --url \"https://<MM HOST>/api/v4/teams/<teamd_id>/channels/name/<channel-name> \\\n  --header 'Accept: application/json' \\\n  --header 'Authorization: Bearer '",
      "position": [
        -144,
        448
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "b5fe345b-04b2-4eef-a4a0-100ed63dc9de",
              "name": "MATTERMOST_HOST",
              "type": "string",
              "value": "mattermost.example.com"
            },
            {
              "id": "7b6f0211-00dc-4e0a-a6af-108c55c521de",
              "name": "MATTERMOST_CHANNEL_ID",
              "type": "string",
              "value": "dr87mpsdmbfrbxeag7i11acuyw"
            },
            {
              "id": "f8c9da79-3e04-4e9c-b5ad-28260a1cd27f",
              "name": "prometheus_uid",
              "type": "string",
              "value": "234543ijpo34ij"
            },
            {
              "id": "88c7c127-5219-4b12-8f5c-5c951896218c",
              "name": "loki_uid",
              "type": "string",
              "value": "r235jr24u5ohgke"
            },
            {
              "id": "cbed6664-a919-4f03-b726-c2891b165c0d",
              "name": "mainNS",
              "type": "string",
              "value": "myns"
            },
            {
              "id": "8eccc026-05c0-4972-8215-7b2214a6b058",
              "name": "PROMETHEUS_URL",
              "type": "string",
              "value": "https://prometheus-host"
            },
            {
              "id": "b14a6741-856b-4ce8-97ce-1d1762155a58",
              "name": "GITHUB_ORG_NAME",
              "type": "string",
              "value": "yourorg"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "b142abb3-e2df-431a-be2a-bc42a313b59b",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -368,
        752
      ],
      "parameters": {
        "color": 5,
        "width": 1072,
        "height": 752,
        "content": "# Overview\nWorkflow receives alert from Alertmanager, analize it and send report to Mattermost\n## Requirements:\n1. OpenAI  or Anthropic API key\n2. Mattermost API key\n3. Google Gemini API key\n4. Webhook receiver in Alertmanager\n5. Webhook token\n6. Qdrant with token\n7. Github token\n8. Digitalocean token\n## How it work\n1. Workflow receives alert from Alertmanager via Webhook.\n1. The variables required for operation are set\n1. Preparing a prompt for the agent containing only the data necessary for analysis\n1. Optional step to deduplicating duplicate alerts\n1. Getting the trigger condition\n1. The agent performs diagnostics as described in the system prompt. During operation, it can access various systems via MCP to obtain additional information.\n1. Search for a message in a Mattermost channel corresponding to a processed alert\n1. Send report to Mattermost thread.\n## How to use\n1. Upload to Vector store your infrastructure description\n1. Generate webhook credentials and use it in Alertmanager\n1. Add Alert fingerprint into Slack message template\n1. Set variables it SetVars node\n1. Add your own Rules and recomendations to system prompt\n1. Run mcp servers\n1. Choose Mattermost channel with alerts"
      },
      "typeVersion": 1
    },
    {
      "id": "05a2b15c-47f7-421a-8cff-849e01d2cb92",
      "name": "DeduplicateAlerts",
      "type": "n8n-nodes-base.code",
      "position": [
        192,
        448
      ],
      "parameters": {
        "jsCode": "const DEDUP_WINDOW_MS = 48 * 60 * 60 * 1000; // 48 hours\nconst now = Date.now();\n\nconst staticData = $getWorkflowStaticData('global');\n\nif (!staticData.alertDedup) {\n  staticData.alertDedup = {};\n}\n\n// Cleanup entries older than dedup window\nfor (const key of Object.keys(staticData.alertDedup)) {\n  if (now - staticData.alertDedup[key] > DEDUP_WINDOW_MS) {\n    delete staticData.alertDedup[key];\n  }\n}\n\n// Build dedup key from alert labels\nconst chatInput = $input.first().json.chatInput || \"\";\n\nconst extractLabel = (label) => {\n  const re = new RegExp(`(?:^|\\\\n)${label}:\\\\s*(.+)`, \"i\");\n  const m = chatInput.match(re);\n  return m ? m[1].trim() : \"\";\n};\n\nconst dedupKey = [\n  extractLabel(\"Alertname\"),\n  extractLabel(\"namespace\"),\n  extractLabel(\"service\"),\n  extractLabel(\"severity\"),\n  extractLabel(\"container\"),\n].join(\"|\").toLowerCase();\n\n// Check if already seen\nif (staticData.alertDedup[dedupKey]) {\n  const minutesAgo = Math.round((now - staticData.alertDedup[dedupKey]) / 60000);\n  console.log(`[Dedup] SKIP: \"${dedupKey}\" seen ${minutesAgo}m ago`);\n  return [];\n}\n\n// New alert \u2014 register and pass through\nstaticData.alertDedup[dedupKey] = now;\nconsole.log(`[Dedup] PASS: \"${dedupKey}\" \u2014 store size: ${Object.keys(staticData.alertDedup).length}`);\n\nreturn [$input.first()];"
      },
      "typeVersion": 2
    },
    {
      "id": "dfe76fd9-1977-4b17-995e-59628a2a2969",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        352
      ],
      "parameters": {
        "color": 2,
        "width": 416,
        "height": 352,
        "content": "## Collect data"
      },
      "typeVersion": 1
    },
    {
      "id": "1477dea9-dc56-41a5-bbd0-0868d21661db",
      "name": "GetAlertRule",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        464,
        448
      ],
      "parameters": {
        "url": "={{ $('SetVars').first().json.PROMETHEUS_URL }}/api/v1/rules",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "rule_name[]",
              "value": "={{ $json.alertname }}"
            },
            {
              "name": "type",
              "value": "alert"
            }
          ]
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "bae33d42-5c16-45ac-bd24-e5aec1d38740",
      "name": "ExtractRuleQuery",
      "type": "n8n-nodes-base.code",
      "position": [
        656,
        448
      ],
      "parameters": {
        "jsCode": "const rulesResponse = $input.first().json;\n\n// Get original alert data preserved from DeduplicateAlerts\nconst alertData = $('DeduplicateAlerts').first().json;\nconst alertname = alertData.alertname || \"\";\n\nlet triggerQuery = \"\";\nlet triggerDuration = \"\";\n\ntry {\n  const groups = rulesResponse?.data?.groups || [];\n  for (const group of groups) {\n    const rules = group.rules || [];\n    for (const rule of rules) {\n      // Match by name (should already be filtered by rule_name[] param, but double-check)\n      if (rule.name === alertname || rule.name === alertData.alertname) {\n        triggerQuery = rule.query || \"\";\n        // Duration in seconds (the 'for' clause)\n        if (rule.duration) {\n          triggerDuration = `${rule.duration}s`;\n        }\n        break;\n      }\n    }\n    if (triggerQuery) break;\n  }\n} catch (e) {\n  console.log(`[ExtractRuleQuery] Error parsing rules response: ${e.message}`);\n}\n\n// Build the enriched chatInput with trigger condition\nlet chatInput = alertData.chatInput || \"\";\n\nif (triggerQuery) {\n  chatInput += `\\nTrigger Query (PromQL): ${triggerQuery}`;\n  if (triggerDuration) {\n    chatInput += `\\nTrigger Duration (for): ${triggerDuration}`;\n  }\n} else {\n  console.log(`[ExtractRuleQuery] No rule found for alertname: \"${alertname}\"`);\n}\n\nreturn [{\n  json: {\n    ...alertData,\n    chatInput,\n    triggerQuery,\n    triggerDuration,\n  }\n}];"
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "d1a35bbd-1c9f-4d3d-a37e-cefbe6983b15",
  "connections": {
    "K8S mcp": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "SetVars": {
      "main": [
        [
          {
            "node": "PreProcessAlerts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "GetAlertMessages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "FindAlert": {
      "main": [
        [
          {
            "node": "Post in thread",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Github MCP": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Grafana mcp": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "GetAlertRule": {
      "main": [
        [
          {
            "node": "ExtractRuleQuery",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Receive alerts": {
      "main": [
        [
          {
            "node": "SetVars",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Digitalocean MCP": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "ExtractRuleQuery": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GetAlertMessages": {
      "main": [
        [
          {
            "node": "FindAlert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "PreProcessAlerts": {
      "main": [
        [
          {
            "node": "DeduplicateAlerts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DeduplicateAlerts": {
      "main": [
        [
          {
            "node": "GetAlertRule",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Qdrant Vector Store": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings Google Gemini": {
      "ai_embedding": [
        [
          {
            "node": "Qdrant Vector Store",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow helps automatically analyze alerts occurring in the infrastructure and suggest solutions even before the on-duty engineer sees the alert. Workflow receives alert from Alertmanager via Webhook. The variables required for operation are set Preparing a prompt for the…

Source: https://n8n.io/workflows/14347/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This workflow helps automatically analyze alerts occurring in the infrastructure and suggest solutions even before the on-duty engineer sees the alert.

Agent, OpenAI Chat, Mcp Client Tool +3
AI & RAG

HeyDinastia. Uses executeCommand, httpRequest, youTube, postgres. Webhook trigger; 66 nodes.

Execute Command, HTTP Request, YouTube +15
AI & RAG

This Workflow simulates an AI-powered phone agent with RetellAI with two main functions: 📅 Appointment Booking – It can schedule appointments directly into Google Calendar. 🧠 RAG-based Information Ret

OpenAI Chat, Output Parser Structured, Qdrant Vector Store +10
AI & RAG

AI Phone Agent with RetellAI. Uses lmChatOpenAi, outputParserStructured, vectorStoreQdrant, embeddingsOpenAi. Webhook trigger; 36 nodes.

OpenAI Chat, Output Parser Structured, Qdrant Vector Store +10
AI & RAG

Build a Chatbot, Voice Agent and Phone Agent with Voiceflow, Google Calendar and RAG. Uses googleCalendar, lmChatOpenAi, chainLlm, vectorStoreQdrant. Webhook trigger; 34 nodes.

Google Calendar, OpenAI Chat, Chain Llm +9