{
  "updatedAt": "2026-08-09T08:30:15.065Z",
  "createdAt": "2026-08-09T08:02:28.548Z",
  "id": "xeOvOsePmdCQlAtI",
  "name": "TA v0.2",
  "active": false,
  "isArchived": false,
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "10e4c630-6bce-4038-8777-916fba8bdc28",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -656,
        272
      ],
      "id": "13fb30a0-aab7-49e7-b4a2-cc6a00413c0d",
      "name": "Webhook"
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.body.type }}",
                    "rightValue": "attacker-session",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "id": "5eee27fb-395e-4528-a930-dc591aa335de"
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "Attacker Session"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "69852c71-48a5-41c9-8622-41667f97cef1",
                    "leftValue": "={{ $json.body.type }}",
                    "rightValue": "attacker-behavior",
                    "operator": {
                      "type": "string",
                      "operation": "equals",
                      "name": "filter.operator.equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "Attacker Behavior"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.3,
      "position": [
        -448,
        272
      ],
      "id": "5040a630-fbe1-42a3-abbf-92aa442dfeca",
      "name": "Switch"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.body }}",
        "hasOutputParser": true,
        "options": {
          "systemMessage": "=# Attacker Session Analyzer - System Prompt\n\n## Role\nYou are the *Attacker Session Security Analyst AI*, tasked with analyzing attacker sessions captured by the Cowrie honeypot. Your job is to interpret attacker behavior, determine their intent, identify dangerous actions, and produce a structured threat assessment.\n\n## Input Format\nYou will receive JSON with structure:\n\n```\n{\n  \"type\": \"attacker-session\",\n  \"ip\": \"172.x.x.x\",\n  \"session_id\": \"string\",\n  \"start_time\": \"ISO timestamp\",\n  \"end_time\": \"ISO timestamp\",\n  \"command_count\": number,\n  \"commands\": [\n      {\n        \"timestamp\": \"...\",\n        \"eventid\": \"cowrie.command.input\",\n        \"input\": \"string\",\n        ...\n      }\n  ]\n}\n```\n\n## Objectives\n1. **Analyze attacker intent**  \n   Example categories:\n   - reconnaissance  \n   - destructive actions  \n   - privilege escalation  \n   - persistence  \n   - malware installation  \n   - exfiltration  \n   - command probing / trial & error  \n   - automated scanner behavior\n\n2. **Describe attacker behavior clearly**, including:\n   - what they tried to do  \n   - why they executed certain commands  \n   - whether the sequence suggests manual or automated actions\n\n3. **Identify dangerous commands**, for example:\n   - `rm -rf /` or `rm -rf boot` \u2192 destructive  \n   - `wget` / `curl` external links \u2192 potential malware download  \n   - `chmod +x` \u2192 preparing executable  \n   - `useradd`, `passwd` \u2192 persistence  \n   - `uname -a`, `ls`, `cat /etc/*` \u2192 reconnaissance\n\n4. **Assess threat level**, using this scale:\n\n### Threat Levels\n| Level | Description |\n|-------|-------------|\n| **Informational** | Harmless inspection like `ls`, `pwd`, simple exploration |\n| **Low** | Reconnaissance without dangerous actions |\n| **Medium** | Suspicious patterns, directory probing, partial system manipulation |\n| **High** | Dangerous commands, attempts to modify system state, download files |\n| **Critical** | Active destruction, malware deployment, privilege escalation, persistence creation |\n\n5. **Produce human-readable reasoning**, not only listing logs.\n\n6. **Produce a final structured JSON output.**\n\n## Output Format\nYou must reply using **this exact structured JSON**:\n\n```\n{\n  \"session_summary\": \"Narrative explanation of what attacker attempted to do.\",\n\n  \"attacker_intent\": \"One of: reconnaissance | destructive | malware installation | persistence | privilege escalation | exfiltration | mixed | unknown\",\n\n  \"suspicious_commands\": [\n      {\"cmd\": \"rm -rf /\", \"reason\": \"Destructive filesystem wipe\"},\n      {\"cmd\": \"wget http://malicious\", \"reason\": \"Possible malware download\"}\n  ],\n\n  \"behavior_analysis\": \"Explain whether attacker looks skilled, automated, random, or targeted.\",\n\n  \"threat_level\": \"Informational | Low | Medium | High | Critical\",\n\n  \"timeline\": [\n      {\"timestamp\": \"...\", \"action\": \"Attacker logged in\"},\n      {\"timestamp\": \"...\", \"action\": \"Executed ls\"},\n      {\"timestamp\": \"...\", \"action\": \"Executed rm -rf /\"}\n  ],\n\n  \"recommendations\": [\n      \"Block IP address\",\n      \"Analyze downloaded artifacts if any\",\n      \"Add stricter SSH rate limits\",\n      \"Apply additional honeypot deception techniques\"\n  ]\n}\n```\n\n## Additional Notes\n- Provide deep analysis, not surface-level summary.\n- Evaluate intent even if commands fail (because Cowrie is a honeypot).\n- Be precise with threat classification.\n\n## MITRE ATT&CK TTP Extraction (mandatory)\nMap every class of detected action to the exact MITRE ATT&CK technique ID (parent ID only, e.g. T1059 not T1059.004). Include them in the `ttps` field of your structured JSON output. Common examples: T1110 Brute Force, T1078 Valid Accounts, T1021 Lateral Movement, T1082 System Information Discovery, T1033 System Owner/User Discovery, T1083 File and Directory Discovery, T1016 System Network Configuration Discovery, T1105 Ingress Tool Transfer, T1059 Command and Scripting Interpreter, T1562 Impair Defenses, T1496 Resource Hijacking.\nFormat `\"ttps\"`: [{\"technique_id\": \"T1059\", \"tactic\": \"Execution\", \"technique_name\": \"Command and Scripting Interpreter\", \"procedure\": \"attacker executed shell commands\"}]"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3,
      "position": [
        0,
        0
      ],
      "id": "0cf3ffe4-4a5c-44f6-ab72-5aee73317333",
      "name": "AI Agent"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        -128,
        208
      ],
      "id": "3acae345-926c-4e75-a52e-bed93a7163ce",
      "name": "Google Gemini Chat Model",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $json.body.session_id }}"
      },
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "typeVersion": 1.3,
      "position": [
        32,
        208
      ],
      "id": "b843f902-1b96-4423-b4dd-d4188612cda4",
      "name": "Simple Memory"
    },
    {
      "parameters": {
        "authentication": "webhook",
        "content": "={{ $json.content }}{{ $json.message }}",
        "options": {}
      },
      "type": "n8n-nodes-base.discord",
      "typeVersion": 2,
      "position": [
        656,
        192
      ],
      "id": "266827df-dcdc-46ad-b3dc-7c5bca2597a7",
      "name": "Discord",
      "credentials": {
        "discordWebhookApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsonSchemaExample": "{\n  \"session_id\": \"string\",\n  \"ip\": \"string\",\n  \"start_time\": \"HH:MM:SS\",\n  \"end_time\": \"HH:MM:SS\",\n  \"session_summary\": \"string\",\n  \"attacker_intent\": \"string\",\n  \"suspicious_commands\": [\n    {\n      \"cmd\": \"string\",\n      \"reason\": \"string\"\n    }\n  ],\n  \"behavior_analysis\": \"string\",\n  \"threat_level\": \"Informational | Low | Medium | High | Critical\",\n  \"timeline\": [\n    {\n      \"time\": \"HH:MM:SS\",\n      \"action\": \"string\"\n    }\n  ],\n  \"recommendations\": [\n    \"string\",\n    \"string\"\n  ],\n  \"ttps\": [\n    {\n      \"technique_id\": \"T1xxx\",\n      \"tactic\": \"string\",\n      \"technique_name\": \"string\",\n      \"procedure\": \"string\"\n    }\n  ]\n}"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        176,
        208
      ],
      "id": "c8941610-68fb-461f-84fd-90bac10558f6",
      "name": "Structured Output Parser"
    },
    {
      "parameters": {
        "jsCode": "const data = $input.first().json.output;\n\n// Safeguard\nconst safe = v => (v === undefined || v === null ? \"unknown\" : v);\n\n// Format time to HH:MM:SS\nconst fixTime = (t) => {\n  if (!t) return \"unknown\";\n  if (t.length === 8) return t;\n  const d = new Date(t);\n  if (isNaN(d)) return t;\n  return d.toISOString().substring(11,19);\n};\n\n// List formatter\nconst list = (arr, fmt) => {\n  if (!arr || arr.length === 0) return \"(none)\";\n  return arr.map(fmt).join(\"\\n\");\n};\n\n// MITRE ATT&CK TTP formatter\nconst ttpsList = (arr) => {\n  if (!arr || !Array.isArray(arr) || arr.length === 0) return \"(none)\";\n  return arr.map((t, i) => {\n    const id = t.technique_id || t.id || t.technique || \"unknown\";\n    const tactic = t.tactic ? ` (${t.tactic})` : \"\";\n    return `**${i + 1}.** \\`${id}\\`${tactic} \u2014 ${t.technique_name || t.procedure || \"\"}`;\n  }).join(\"\\n\");\n};\n\n// Build final report text (NO EMBED)\nconst reportText =\n`\ud83d\udea8 **Honeypot Attacker Session Report**\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n**\ud83c\udd94 Session ID:** \\`${safe(data.session_id)}\\`\n**\ud83c\udf10 IP:** \\`${safe(data.ip)}\\`\n**\u23f3 Duration:** ${fixTime(data.start_time)} \u279d ${fixTime(data.end_time)}\n**\ud83d\udca5 Threat Level:** ${safe(data.threat_level)}\n\n### \ud83d\udcdd Session Summary\n${safe(data.session_summary)}\n\n### \ud83c\udfaf Attacker Intent\n**${safe(data.attacker_intent)}**\n\n### \u26a0\ufe0f Suspicious Commands\n${list(data.suspicious_commands, (c, i) => `**${i+1}.** \\`${c.cmd}\\` \u2014 ${c.reason}`)}\n\n### \ud83d\udc40 Behavior Analysis\n${safe(data.behavior_analysis)}\n\n### \ud83e\udde9 MITRE ATT&CK TTPs\n${ttpsList(data.ttps)}\n\n### \ud83d\udd52 Timeline\n${list(data.timeline, (t, i) => `**${i+1}.** \\`${fixTime(t.time)}\\`\n\u27a1\ufe0f ${t.action}`)}\n\n### \ud83d\udee1\ufe0f Recommendations\n${list(data.recommendations, (r, i) => `**${i+1}.** ${r}`)}`;\n\nconst reportSizeBytes = Buffer.byteLength(reportText, 'utf8');\nconst receivedAt = new Date().toISOString();\n\n// ========== DISCORD HARD LIMIT FIX ==========\nconst MAX = 1800;\nlet chunks = [];\nlet message = reportText;\n\nwhile (message.length > MAX) {\n  chunks.push(message.slice(0, MAX));\n  message = message.slice(MAX);\n}\nchunks.push(message);\n\nreturn chunks.map(c => ({\n  json: {\n    content: c,\n    report_size_bytes: reportSizeBytes,\n    report_received_at: receivedAt,\n    session_id: safe(data.session_id),\n    threat_level: safe(data.threat_level),\n    ttps: Array.isArray(data.ttps) ? data.ttps : []\n  }\n}));\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        352,
        0
      ],
      "id": "b9e51e3a-c0e7-40d8-aa0a-bb91dda05d84",
      "name": "Code in JavaScript"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{ $json.body }}",
        "hasOutputParser": true,
        "options": {
          "systemMessage": "=# Attacker Behavior Analyzer \u2014 System Prompt (Final v1)\n\n## ROLE\nYou are the **Attacker Behavior Security Analyst AI**, responsible for analyzing malicious activities *before* an attacker successfully logs into the Cowrie honeypot. This includes:  \n- brute\u2011force attempts  \n- credential\u2011stuffing  \n- dictionary attacks  \n- botnet SSH scanning  \n- high\u2011frequency failed logins  \n- DDoS\u2011like connection storms  \n- reconnaissance attempts  \n\nYour job is to analyze the attacker's behavior, classify the attack type, identify patterns, and assess the threat level.\n\n---\n\n## INPUT FORMAT (Always Provided)\n\n```\n{\n  \"type\": \"attacker-behavior\",\n  \"ip\": \"string\",\n  \"behavior_window_start\": \"ISO timestamp\",\n  \"behavior_window_end\": \"ISO timestamp\",\n  \"attempt_count\": number,\n  \"unique_usernames\": [\"root\", \"admin\", ...],\n  \"unique_passwords\": [\"123456\", ...],\n  \"events\": [\n    {\n      \"timestamp\": \"ISO timestamp\",\n      \"eventid\": \"cowrie.login.failed | cowrie.login.attempt | cowrie.connection.failed | cowrie.client.version\",\n      \"username\": \"string\",\n      \"password\": \"string\",\n      \"message\": \"string\"\n    }\n  ]\n}\n```\n\n---\n\n## OBJECTIVES\n\nYou must determine:\n\n### 1. **Attack Type**\nChoose the most appropriate classification:\n- bruteforce  \n- dictionary  \n- credential stuffing  \n- botnet  \n- scanning  \n- ddos  \n- mixed  \n- unknown  \n\n### 2. **Behavior Summary**\nClear explanation of what the attacker is attempting, based on patterns such as:\n- rapid login failures  \n- repeated username/password cycling  \n- botnet signatures  \n- predictable dictionary use  \n- slow/fast attack pace  \n\n### 3. **Attacker Profile**\nIdentify:\n- automation level (manual / automated / botnet / unknown)  \n- attack speed (slow / moderate / fast / extreme)  \n- username & password patterns  \n\n### 4. **Threat Level**\nUse the following classification:\n\n| Level | Description |\n|-------|-------------|\n| **Informational** | harmless noise, accidental hits, scanners |\n| **Low** | low-volume bruteforce or random botnet probing |\n| **Medium** | consistent bruteforce or dictionary attack |\n| **High** | credential stuffing or targeted attack |\n| **Critical** | aggressive bruteforce, DDoS pattern, botnet propagation |\n\n### 5. **Timeline**\nSummaries of key behavior converted into `HH:MM:SS` format.\n\n### 6. **Indicators**\nImportant flags for detection, e.g.:\n- repeated password cycling  \n- botnet login signature  \n- extreme connection rate  \n- failure storm pattern  \n\n### 7. **Recommendations**\nActionable security actions.\n\n---\n\n## OUTPUT FORMAT (REQUIRED)\n\nYou must return **valid JSON** in the following format:\n\n```\n{\n  \"ip\": \"string\",\n\n  \"attack_type\": \"bruteforce | dictionary | credential stuffing | ddos | scanning | botnet | mixed | unknown\",\n\n  \"behavior_summary\": \"Detailed explanation of observed attack behavior.\",\n\n  \"attacker_profile\": {\n    \"automation\": \"manual | automated | botnet | unknown\",\n    \"speed\": \"slow | moderate | fast | extreme\",\n    \"username_pattern\": \"string\",\n    \"password_pattern\": \"string\"\n  },\n\n  \"threat_level\": \"Informational | Low | Medium | High | Critical\",\n\n  \"timeline\": [\n    {\n      \"time\": \"HH:MM:SS\",\n      \"event\": \"string\"\n    }\n  ],\n\n  \"indicators\": [\n    \"string\",\n    \"string\"\n  ],\n\n  \"recommendations\": [\n    \"string\",\n    \"string\"\n  ]\n}\n```\n\n---\n\n## RULES\n\n- **Convert all timestamps into `HH:MM:SS`.**\n- **Never return undefined, null, or empty fields.**\n- If a field is missing \u2192 use `\"unknown\"`.\n- Provide deep behavior analysis, not surface summary.\n- Extract attacker intent and automation patterns from timing, username variety, password variety, and frequency.\n- Do NOT describe Cowrie internals \u2014 focus only on attacker behavior.\n\n---\n\n## MITRE ATT&CK TTP Extraction (mandatory)\nMap every class of detected action to the exact MITRE ATT&CK technique ID (parent ID only, e.g. T1059 not T1059.004). Include them in the `ttps` field of your structured JSON output. Common examples: T1110 Brute Force, T1078 Valid Accounts, T1021 Lateral Movement, T1082 System Information Discovery, T1033 System Owner/User Discovery, T1083 File and Directory Discovery, T1016 System Network Configuration Discovery, T1105 Ingress Tool Transfer, T1059 Command and Scripting Interpreter, T1562 Impair Defenses, T1496 Resource Hijacking.\nFormat `\"ttps\"`: [{\"technique_id\": \"T1059\", \"tactic\": \"Execution\", \"technique_name\": \"Command and Scripting Interpreter\", \"procedure\": \"attacker executed shell commands\"}]"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3,
      "position": [
        0,
        352
      ],
      "id": "5c1e5629-956f-4e8b-955d-3bd7a263c0a4",
      "name": "AI Agent1"
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        -128,
        576
      ],
      "id": "d4bdce63-70c7-47d8-9bc2-e5f82e54243e",
      "name": "Google Gemini Chat Model1",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "={{ $json.body.logs[0].session }}"
      },
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "typeVersion": 1.3,
      "position": [
        16,
        576
      ],
      "id": "f9396b96-b695-416b-a88d-04ab322b9fd2",
      "name": "Simple Memory1"
    },
    {
      "parameters": {
        "jsonSchemaExample": "{\n  \"ip\": \"string\",\n  \"attack_type\": \"bruteforce | dictionary | credential stuffing | ddos | scanning | botnet | mixed | unknown\",\n  \"behavior_summary\": \"Detailed explanation of observed attack behavior.\",\n  \"attacker_profile\": {\n    \"automation\": \"manual | automated | botnet | unknown\",\n    \"speed\": \"slow | moderate | fast | extreme\",\n    \"username_pattern\": \"string\",\n    \"password_pattern\": \"string\"\n  },\n  \"threat_level\": \"Informational | Low | Medium | High | Critical\",\n  \"timeline\": [\n    {\n      \"time\": \"HH:MM:SS\",\n      \"event\": \"string\"\n    }\n  ],\n  \"indicators\": [\n    \"string\",\n    \"string\"\n  ],\n  \"recommendations\": [\n    \"string\",\n    \"string\"\n  ],\n  \"ttps\": [\n    {\n      \"technique_id\": \"T1xxx\",\n      \"tactic\": \"string\",\n      \"technique_name\": \"string\",\n      \"procedure\": \"string\"\n    }\n  ]\n}"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        176,
        576
      ],
      "id": "78588fbd-f2a3-447a-97fa-3283a11f78fb",
      "name": "Structured Output Parser1"
    },
    {
      "parameters": {
        "jsCode": "const data = $input.first().json.output;\nconst payload = ($(\"Switch\").first().json.body || $(\"Switch\").first().json || {});\n\n// Helper untuk value aman\nfunction clean(v, fallback = \"(unknown)\") {\n    if (v === undefined || v === null) return fallback;\n    if (typeof v === \"string\" && v.trim() === \"-\") return fallback;\n    if (typeof v === \"string\" && v.trim() === \"\") return fallback;\n    return v;\n}\n\n// Format list\nfunction formatList(arr) {\n    if (!Array.isArray(arr)) return \"-\";\n    return arr.map((x, i) => `**${i + 1}.** ${x}`).join(\"\\n\");\n}\n\n// Format timeline\nfunction formatTimeline(arr) {\n    if (!Array.isArray(arr)) return \"-\";\n    return arr\n        .map((x, i) => {\n            const t = clean(x.time, \"(no time)\");\n            const e = clean(x.event, \"(no event)\");\n            return `**${i + 1}.** \\`${t}\\`\\n\u27a1\ufe0f ${e}`;\n        })\n        .join(\"\\n\\n\");\n}\n\n// MITRE ATT&CK TTP formatter\nfunction formatTtps(arr) {\n    if (!Array.isArray(arr) || arr.length === 0) return \"-\";\n    return arr\n        .map((t, i) => {\n            const id = t.technique_id || t.id || t.technique || \"unknown\";\n            const tactic = t.tactic ? ` (${t.tactic})` : \"\";\n            return `**${i + 1}.** \\`${id}\\`${tactic} \u2014 ${t.technique_name || t.procedure || \"\"}`;\n        })\n        .join(\"\\n\");\n}\n\n// Extract attacker profile safely\nconst profile = data.attacker_profile || {};\n\nconst message =\n`\ud83d\udea8 **Attacker Behavior Analysis Report**\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n### \ud83c\udf10 IP Address\n\\`${clean(data.ip)}\\`\n\n### \ud83c\udfaf Attack Type\n**${clean(data.attack_type)}**\n\n### \ud83d\udca5 Threat Level\n**${clean(data.threat_level).toUpperCase()}**\n\n## \ud83e\udde0 Behavior Summary\n${clean(data.behavior_summary)}\n\n## \ud83e\uddec Attacker Profile\n- **Automation:** ${clean(profile.automation)}\n- **Speed:** ${clean(profile.speed)}\n- **Username Pattern:** ${clean(profile.username_pattern)}\n- **Password Pattern:** ${clean(profile.password_pattern)}\n\n## \ud83e\udde9 MITRE ATT&CK TTPs\n${formatTtps(data.ttps)}\n\n## \ud83d\udd52 Timeline\n${formatTimeline(data.timeline)}\n\n## \ud83d\udd0d Indicators\n${formatList(data.indicators)}\n\n## \ud83d\udee1\ufe0f Recommendations\n${formatList(data.recommendations)}`;\n\nconst reportSizeBytes = Buffer.byteLength(message, 'utf8');\n\nreturn [{\n  json: {\n    message: message,\n    session_id: payload.session_id || \"unknown\",\n    ip: clean(data.ip),\n    threat_level: clean(data.threat_level).toUpperCase(),\n    ttps: Array.isArray(data.ttps) ? data.ttps : [],\n    report_size_bytes: reportSizeBytes\n  }\n}];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        352,
        352
      ],
      "id": "9bfac2b5-4eca-4517-9d36-38f411f2688c",
      "name": "Code in JavaScript1"
    },
    {
      "parameters": {
        "jsCode": "const items = $input.all();\n\nreturn items.map(item => ({\n  json: {\n    session_id: item.json.session_id,\n    threat_level: item.json.threat_level,\n    ttps: Array.isArray(item.json.ttps) ? item.json.ttps : [],\n    report_size_bytes: item.json.report_size_bytes || 0\n  }\n}));\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        928,
        0
      ],
      "id": "d24f2fcc-84de-4dfe-910d-934c80cde69b",
      "name": "Metrics Response"
    },
    {
      "parameters": {
        "jsCode": "const items = $input.all();\n\nreturn items.map(item => ({\n  json: {\n    session_id: item.json.session_id,\n    threat_level: item.json.threat_level,\n    ttps: Array.isArray(item.json.ttps) ? item.json.ttps : [],\n    report_size_bytes: item.json.report_size_bytes || 0\n  }\n}));\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        928,
        352
      ],
      "id": "bc67fb21-ca66-4f91-8e4d-954326916e9b",
      "name": "Metrics Response1"
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Switch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "AI Agent1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Discord",
            "type": "main",
            "index": 0
          },
          {
            "node": "Metrics Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent1": {
      "main": [
        [
          {
            "node": "Code in JavaScript1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent1",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Simple Memory1": {
      "ai_memory": [
        [
          {
            "node": "AI Agent1",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser1": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent1",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript1": {
      "main": [
        [
          {
            "node": "Discord",
            "type": "main",
            "index": 0
          },
          {
            "node": "Metrics Response1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "availableInMCP": false
  },
  "staticData": null,
  "meta": null,
  "nodeGroups": [],
  "versionId": "eacbdcc3-ec2d-417d-85e1-455d30a46db2",
  "activeVersionId": null,
  "triggerCount": 0,
  "shared": [
    {
      "updatedAt": "2026-08-09T08:02:28.552Z",
      "createdAt": "2026-08-09T08:02:28.552Z",
      "role": "workflow:owner",
      "workflowId": "xeOvOsePmdCQlAtI",
      "projectId": "UoStXPqNC0kdV8zl"
    }
  ],
  "activeVersion": null,
  "tags": []
}