{ "name": "77 Log summary (answer)", "nodes": [ { "name": "Summary webhook", "type": "n8n-nodes-base.webhook", "typeVersion": 2, "parameters": { "httpMethod": "POST", "path": "my-log-summary", "responseMode": "responseNode", "options": {} }, "position": [ 0, 300 ] }, { "name": "Get report", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "parameters": { "method": "POST", "url": "http://localhost:5678/webhook/my-log-report", "sendBody": true, "specifyBody": "json", "jsonBody": "={{ JSON.stringify({ from: $json.body.from ?? '', to: $json.body.to ?? '', tag: $json.body.tag ?? '', source: $json.body.source ?? 'all' }) }}", "options": { "timeout": 30000 } }, "position": [ 220, 300 ] }, { "name": "Write summary", "type": "@n8n/n8n-nodes-langchain.agent", "typeVersion": 3.1, "parameters": { "promptType": "define", "text": "={{ JSON.stringify({ total: $json.total, errors: $json.errors, error_rate: $json.error_rate, failures: $json.failures, unanswered_topics: $json.unanswered_topics, anomalies: $json.anomalies }) }}", "options": { "systemMessage": "You write a short Korean operations summary for an IT help desk team from the statistics JSON given. Write exactly 3 sentences in 합니다체. Use only numbers that appear in the statistics (you may write a rate like 0.0588 as 5.88%). Sentence 1: the biggest unanswered topic and its count. Sentence 2: the most common failure (node, message, count). Sentence 3: the worst hour from anomalies, written like 10월 26일 09시, with its errors and total. Do not guess causes that are not in the data. Do not add any other numbers.", "maxIterations": 1 } }, "position": [ 440, 300 ] }, { "name": "Summary model", "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", "typeVersion": 1.2, "parameters": { "model": { "__rl": true, "mode": "id", "value": "gpt-4.1-mini" }, "options": { "temperature": 0 } }, "position": [ 440, 520 ], "credentials": { "openAiApi": { "id": "openAiCourse0001", "name": "OpenAI (.env)" } } }, { "name": "Check numbers", "type": "n8n-nodes-base.code", "typeVersion": 2, "parameters": { "jsCode": "const stats = $('Get report').first().json;\nconst summary = String($json.output ?? '').trim();\nconst allowed = new Set();\nconst addNum = (v) => { allowed.add(String(v)); for (const k of [100, 10, 1]) allowed.add(String(Math.round(v * 100 * k) / k)); };\nconst walk = (v) => {\n if (Array.isArray(v)) v.forEach(walk);\n else if (v && typeof v === 'object') Object.entries(v).forEach(([k, x]) => { (String(k).match(/\\d+(\\.\\d+)?/g) ?? []).forEach((n) => allowed.add(String(Number(n)))); walk(x); });\n else if (typeof v === 'string') (v.match(/\\d+(\\.\\d+)?/g) ?? []).forEach((n) => allowed.add(String(Number(n))));\n else if (typeof v === 'number') addNum(v);\n};\nwalk(stats);\nconst found = (summary.match(/\\d+(\\.\\d+)?/g) ?? []).map((n) => String(Number(n)));\nconst unknown = [...new Set(found.filter((n) => !allowed.has(n)))];\nconst worst = [...(stats.anomalies ?? [])].sort((a, b) => b.error_rate - a.error_rate)[0];\nreturn [{ json: { summary, numbers_ok: unknown.length === 0, unknown_numbers: unknown,\n top_topic: stats.unanswered_topics?.[0]?.topic ?? null, worst_hour: worst?.hour ?? null } }];" }, "position": [ 760, 300 ] }, { "name": "Send summary", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.1, "parameters": { "respondWith": "json", "responseBody": "={{ $json }}", "options": {} }, "position": [ 980, 300 ] } ], "connections": { "Summary webhook": { "main": [ [ { "node": "Get report", "type": "main", "index": 0 } ] ] }, "Get report": { "main": [ [ { "node": "Write summary", "type": "main", "index": 0 } ] ] }, "Write summary": { "main": [ [ { "node": "Check numbers", "type": "main", "index": 0 } ] ] }, "Check numbers": { "main": [ [ { "node": "Send summary", "type": "main", "index": 0 } ] ] }, "Summary model": { "ai_languageModel": [ [ { "node": "Write summary", "type": "ai_languageModel", "index": 0 } ] ] } }, "settings": { "executionOrder": "v1" } }