{ "name": "answer · 68 Lab 01 challenge (agent and missing input)", "nodes": [ { "name": "Assistant webhook", "type": "n8n-nodes-base.webhook", "typeVersion": 2, "position": [ 0, 300 ], "parameters": { "httpMethod": "POST", "path": "my-split", "responseMode": "responseNode", "options": {} } }, { "name": "Has message?", "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 200, 300 ], "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "c1", "leftValue": "={{ $json.body.message }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty", "singleValue": true } } ], "combinator": "and" }, "options": {} } }, { "name": "Reject empty", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.1, "position": [ 420, 520 ], "parameters": { "respondWith": "json", "responseBody": "{ \"error\": \"message is required\" }", "options": { "responseCode": 400 } } }, { "name": "Split tasks", "type": "@n8n/n8n-nodes-langchain.agent", "typeVersion": 3.1, "position": [ 420, 300 ], "parameters": { "promptType": "define", "text": "={{ $('Assistant webhook').first().json.body.message }}", "options": { "systemMessage": "You split one employee message into separate tasks. Task types: \"it\" = IT problems and IT request status (password, account, VPN, printer, mail, software, ticket ids like T-1002); \"meeting\" = organizing meeting notes or action items; \"other\" = anything else. One task per separate request. Keep each task text in Korean as the employee wrote it, and keep ticket ids. Return only JSON, no code fence: {\"tasks\": [{\"type\": \"it\", \"text\": \"...\"}]}", "maxIterations": 2 } } }, { "name": "OpenAI chat model", "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi", "typeVersion": 1.2, "position": [ 380, 520 ], "parameters": { "model": { "__rl": true, "mode": "id", "value": "gpt-4.1-mini" }, "options": { "temperature": 0 } }, "credentials": { "openAiApi": { "id": "openAiCourse0001", "name": "OpenAI (.env)" } } }, { "name": "Parse tasks", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 680, 300 ], "parameters": { "jsCode": "// Turn the agent text into a list of tasks, then decide in code who handles each task\n// and which input is missing (the LLM does not decide this).\nconst body = $('Assistant webhook').first().json.body;\nconst raw = String($json.output ?? '').trim().replace(/^```(json)?\\s*|```$/g, '');\nlet items = [];\ntry { const data = JSON.parse(raw); items = Array.isArray(data) ? data : (data.tasks ?? []); } catch (error) { items = []; }\nconst AGENT = { it: 'it-agent', meeting: 'meeting-agent', other: '담당자 연결' };\nconst tasks = items\n .map(item => ({ type: ['it', 'meeting', 'other'].includes(item?.type) ? item.type : 'other', text: String(item?.text ?? '').trim() }))\n .filter(task => task.text)\n .map(task => {\n const missing = [];\n if (task.type === 'meeting' && !String(body.notes ?? '').trim()) missing.push('notes');\n if (task.type === 'it' && !String(body.user ?? '').trim()) missing.push('user');\n return { ...task, agent: AGENT[task.type], missing };\n });\nreturn [{ json: { count: tasks.length, tasks } }];" } }, { "name": "Send result", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.1, "position": [ 900, 300 ], "parameters": { "respondWith": "json", "responseBody": "={{ $json }}", "options": {} } } ], "connections": { "Assistant webhook": { "main": [ [ { "node": "Has message?", "type": "main", "index": 0 } ] ] }, "Has message?": { "main": [ [ { "node": "Split tasks", "type": "main", "index": 0 } ], [ { "node": "Reject empty", "type": "main", "index": 0 } ] ] }, "OpenAI chat model": { "ai_languageModel": [ [ { "node": "Split tasks", "type": "ai_languageModel", "index": 0 } ] ] }, "Split tasks": { "main": [ [ { "node": "Parse tasks", "type": "main", "index": 0 } ] ] }, "Parse tasks": { "main": [ [ { "node": "Send result", "type": "main", "index": 0 } ] ] } }, "settings": { "executionOrder": "v1" } }