This workflow follows the Chainllm → Execute Workflow Trigger 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 →
{
"updatedAt": "2025-12-24T09:32:10.732Z",
"createdAt": "2025-12-23T09:30:18.636Z",
"id": "Gu9mVRTwvJCq0Fpf",
"name": "Capture_Projection",
"description": null,
"active": false,
"isArchived": false,
"nodes": [
{
"parameters": {
"inputSource": "passthrough"
},
"type": "n8n-nodes-base.executeWorkflowTrigger",
"typeVersion": 1.1,
"position": [
-1600,
704
],
"id": "trigger-capture-projection",
"name": "ExecuteWorkflowTrigger"
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Determine emoji based on projection type and prepare for routing\nconst ctx = $json.ctx;\nconst projectionType = ctx.projection?.type || 'note';\n\nconst emojiMap = {\n 'activity': '\ud83d\udd18',\n 'note': '\ud83d\udcdd',\n 'todo': '\u2705'\n};\n\nconst emoji = emojiMap[projectionType] || '\ud83d\udcdd';\n\nreturn {\n json: {\n ctx: ctx,\n projection_type: projectionType,\n emoji: emoji,\n inference_start: Date.now()\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-1376,
704
],
"id": "prepare-routing",
"name": "PrepareRouting"
},
{
"parameters": {
"method": "DELETE",
"url": "=https://discord.com/api/v10/channels/{{ $json.ctx.event.channel_id }}/messages/{{ $json.ctx.event.message_id }}/reactions/\ud83d\udd35/@me",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "discordBotApi",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-1152,
912
],
"id": "remove-blue-reaction",
"name": "Remove\ud83d\udd35Reaction",
"retryOnFail": true,
"maxTries": 3,
"waitBetweenTries": 1000,
"credentials": {
"discordBotApi": {
"name": "<your credential>"
}
},
"onError": "continueRegularOutput"
},
{
"parameters": {
"method": "PUT",
"url": "=https://discord.com/api/v10/channels/{{ $json.ctx.event.channel_id }}/messages/{{ $json.ctx.event.message_id }}/reactions/{{ encodeURIComponent($json.emoji) }}/@me",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "discordBotApi",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-1152,
496
],
"id": "add-type-reaction",
"name": "AddTypeReaction",
"retryOnFail": true,
"maxTries": 3,
"waitBetweenTries": 1000,
"credentials": {
"discordBotApi": {
"name": "<your credential>"
}
},
"onError": "continueRegularOutput"
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 1
},
"conditions": [
{
"id": "is-activity",
"leftValue": "={{ $json.projection_type }}",
"rightValue": "activity",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "activity"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 1
},
"conditions": [
{
"id": "is-note",
"leftValue": "={{ $json.projection_type }}",
"rightValue": "note",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "note"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 1
},
"conditions": [
{
"id": "is-todo",
"leftValue": "={{ $json.projection_type }}",
"rightValue": "todo",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "todo"
}
]
},
"options": {
"fallbackOutput": "extra"
}
},
"id": "route-by-type",
"name": "RouteByType",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [
-1152,
688
]
},
{
"parameters": {
"promptType": "define",
"text": "=You are an activity classifier for a life-tracking system.\n\nAssign probability scores (0-100) to each category. Scores must add up to exactly 100.\n\n## Categories\n\nwork \u2192 Productive, focused effort on projects, coding, building, debugging, refining systems, testing, or task-oriented development.\nleisure \u2192 Relaxed, non-productive enjoyment: scrolling, watching videos, browsing, casual reading, coffee breaks.\nstudy \u2192 Intentional learning or skill-building not directly tied to immediate project work.\nhealth \u2192 Physical or mental self-care: exercise, eating meals, hygiene, mindfulness.\nsleep \u2192 Going to bed, waking up, napping, or sleep transitions.\nrelationships \u2192 Social interaction: chatting with friends/family/partners, or personal/social AI conversations.\nadmin \u2192 Organizational/maintenance tasks: planning schedules, managing todos, fixing tools/setup, meta work on tracking system.\n\n## Key Guidelines\n- Heavily favor the most dominant theme.\n- Sleep-related messages \u2192 give sleep the highest score.\n- Project-related AI chats \u2192 work.\n- Eating/drinking \u2192 health (split with leisure if combined).\n- Meta work on tracking system \u2192 admin (or work if core building).\n- Omit any category with score \u22645 (treat as 0).\n\nOutput ONLY lines for categories with score >5, in any order:\ncategory_name|X\n\n(Printed scores must sum to exactly 100, integers only)\n\n## Examples\nworking on the router agent implementation\nwork|98\nadmin|2\n\nsipping coffee while scrolling social media\nleisure|88\nhealth|12\n\ngoing to bed after a long day\nsleep|93\nhealth|7\n\nhaving lunch\nhealth|92\nleisure|8\n\n## Message to classify:\n{{ $json.ctx.event.clean_text }}",
"needsFallback": true,
"batching": {}
},
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.7,
"position": [
-928,
496
],
"id": "activity-classifier",
"name": "ActivityClassifier"
},
{
"parameters": {
"promptType": "define",
"text": "=You are a note classifier for a life-tracking system.\n\nClassify notes into exactly 2 categories. Assign probability scores (0-100) that add up to exactly 100.\n\n# Categories\n\nfact \u2192 External, objective, declarative knowledge about the world or people (birthdays, preferences, allergies, likes/dislikes, factual statements about others).\n\nreflection \u2192 Internal, subjective knowledge (insights, decisions, observations, realizations, thoughts, self-analysis, patterns, emotional states, personal commitments).\n\n# The Core Distinction\n- fact = \"Things about the world/others\" (external reality)\n- reflection = \"Things about me/my mind\" (internal experience)\n\n# Key Guidelines\n- Declarative statements about others \u2192 fact (\"John loves coffee\", \"Sarah is allergic to nuts\")\n- Dates, birthdays, preferences of others \u2192 fact\n- Personal insights, realizations \u2192 reflection (\"I work better in mornings\")\n- Decisions, commitments \u2192 reflection (\"decided to switch to async\")\n- Self-observations \u2192 reflection (\"I've been more focused lately\")\n- When in doubt: Is it about THEM or about ME? \u2192 fact vs reflection\n\nOutput format (only lines with score >5):\ncategory_name|score\n\n(Scores must sum to exactly 100, integers only)\n\n# Examples\n\nJohn loves dark roast coffee\nfact|95\nreflection|5\n\nMom's birthday is June 12\nfact|98\nreflection|2\n\nnoticed an interesting pattern in my productivity\nreflection|94\nfact|6\n\nI work better in the mornings\nreflection|88\nfact|12\n\n## Message to classify:\n{{ $json.ctx.event.clean_text }}",
"needsFallback": true,
"batching": {}
},
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.7,
"position": [
-928,
704
],
"id": "note-classifier",
"name": "NoteClassifier"
},
{
"parameters": {
"promptType": "define",
"text": "=You are a todo priority classifier for a life-tracking system.\n\nAssign probability scores (0-100) to each priority level. Scores must add up to exactly 100.\n\n# Priority Levels\n\nhigh \u2192 Urgent, time-sensitive, blocking other work, or has significant consequences if delayed.\nmedium \u2192 Important but not urgent, should be done soon, normal priority.\nlow \u2192 Nice to have, can be deferred, no immediate impact if delayed.\n\n# Key Guidelines\n- Explicit urgency words (\"ASAP\", \"urgent\", \"today\", \"now\") \u2192 high\n- Deadlines mentioned \u2192 high if soon, medium if later\n- \"Should\", \"need to\", \"have to\" without urgency \u2192 medium\n- \"Maybe\", \"sometime\", \"eventually\", \"would be nice\" \u2192 low\n- Bug fixes, blockers \u2192 high\n- Regular tasks, maintenance \u2192 medium\n- Ideas, improvements, \"someday\" items \u2192 low\n\nOutput format (only lines with score >5):\npriority_name|score\n\n(Scores must sum to exactly 100, integers only)\n\n# Examples\n\nneed to fix the auth bug before demo tomorrow\nhigh|92\nmedium|8\n\nshould update the documentation\nmedium|85\nlow|15\n\nmaybe add dark mode someday\nlow|88\nmedium|12\n\nurgent: server is down\nhigh|98\nmedium|2\n\n## Message to classify:\n{{ $json.ctx.event.clean_text }}",
"needsFallback": true,
"batching": {}
},
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.7,
"position": [
-928,
896
],
"id": "todo-classifier",
"name": "TodoClassifier"
},
{
"parameters": {
"model": "xiaomi/mimo-v2-flash:free",
"options": {
"timeout": 10000
}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
"typeVersion": 1,
"position": [
-928,
1296
],
"id": "mimo-v2-flash",
"name": "MimoV2Flash",
"credentials": {
"openRouterApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"model": "nvidia/nemotron-nano-9b-v2:free",
"options": {
"timeout": 10000
}
},
"type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
"typeVersion": 1,
"position": [
-784,
1232
],
"id": "nemotron-nano-9b",
"name": "NemotronNano9b",
"credentials": {
"openRouterApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"mode": "append",
"numberInputs": 2
},
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [
-576,
688
],
"id": "merge-classifiers",
"name": "MergeClassifiers"
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Parse LLM classification output and build query for Execute_Queries\nconst llmText = $json.text?.trim() || '';\nconst routingItem = $('PrepareRouting').first().json;\nconst ctx = routingItem.ctx;\nconst projectionType = routingItem.projection_type;\nconst inferenceStart = routingItem.inference_start;\nconst durationMs = Date.now() - inferenceStart;\n\n// Format trace_chain for PostgreSQL uuid[] type\nconst traceChain = ctx.event.trace_chain || [];\nconst traceChainPg = '{' + traceChain.join(',') + '}';\n\n// Get voided projection IDs from correction context (if this is a correction)\nconst voidedProjectionIds = ctx.correction?.voided_projection_ids || [];\nconst voidedProjectionIdsPg = voidedProjectionIds.length > 0 \n ? '{' + voidedProjectionIds.join(',') + '}' \n : null;\n\n// Default categories/priorities per type\nconst defaults = {\n activity: 'work',\n note: 'reflection',\n todo: 'medium'\n};\n\n// Parse scores from LLM output\nconst scores = {};\nlet topResult = null;\nlet topScore = 0;\n\ntry {\n const lines = llmText.split('\\n').filter(line => line.includes('|'));\n lines.forEach(line => {\n const [key, scoreStr] = line.split('|').map(s => s.trim());\n const score = parseInt(scoreStr);\n if (!isNaN(score)) {\n scores[key] = score;\n if (score > topScore) {\n topScore = score;\n topResult = key;\n }\n }\n });\n} catch (e) {\n // Use default on parse error\n}\n\nif (!topResult) {\n topResult = defaults[projectionType];\n topScore = 50;\n}\n\n// Build projection data based on type\nlet projectionData;\nif (projectionType === 'activity') {\n projectionData = {\n timestamp: new Date().toISOString(),\n category: topResult,\n description: ctx.event.clean_text,\n message_url: ctx.event.message_url,\n confidence: topScore / 100,\n all_scores: scores\n };\n} else if (projectionType === 'note') {\n projectionData = {\n timestamp: new Date().toISOString(),\n category: topResult,\n text: ctx.event.clean_text,\n message_url: ctx.event.message_url,\n confidence: topScore / 100,\n all_scores: scores\n };\n} else if (projectionType === 'todo') {\n projectionData = {\n timestamp: new Date().toISOString(),\n priority: topResult,\n description: ctx.event.clean_text,\n message_url: ctx.event.message_url,\n confidence: topScore / 100,\n all_scores: scores,\n status: 'pending'\n };\n}\n\nreturn {\n json: {\n ctx: {\n ...ctx,\n llm: {\n result: topResult,\n confidence: topScore / 100,\n all_scores: scores,\n completion_text: llmText,\n duration_ms: durationMs\n },\n db_queries: [{\n key: 'projection',\n sql: `WITH new_trace AS (\n INSERT INTO traces (event_id, step_name, data, trace_chain)\n VALUES (\n $1::uuid,\n $2 || '_classification',\n jsonb_build_object(\n 'input', jsonb_build_object('text', $3),\n 'completion', $4,\n 'result', jsonb_build_object(\n 'value', $5,\n 'confidence', $6::numeric,\n 'all_scores', $7::jsonb\n ),\n 'model', 'xiaomi/mimo-v2-flash:free',\n 'duration_ms', $8::integer\n ),\n $9::uuid[]\n )\n RETURNING id, event_id\n),\nnew_projection AS (\n INSERT INTO projections (\n trace_id,\n event_id,\n trace_chain,\n projection_type,\n data,\n status,\n timezone,\n supersedes_projection_id\n )\n SELECT\n new_trace.id,\n new_trace.event_id,\n $9::uuid[] || new_trace.id,\n $2,\n $10::jsonb,\n 'auto_confirmed',\n $11,\n CASE WHEN $12::uuid[] IS NOT NULL AND array_length($12::uuid[], 1) > 0 THEN ($12::uuid[])[1] ELSE NULL END\n FROM new_trace\n RETURNING *\n),\nupdate_voided AS (\n UPDATE projections\n SET superseded_by_projection_id = (SELECT id FROM new_projection)\n WHERE id = ANY($12::uuid[])\n RETURNING id\n)\nSELECT np.*, COALESCE((SELECT array_agg(id) FROM update_voided), ARRAY[]::uuid[]) as linked_voided_ids\nFROM new_projection np;`,\n params: [\n ctx.event.event_id,\n projectionType,\n ctx.event.clean_text,\n llmText,\n topResult,\n topScore / 100,\n JSON.stringify(scores),\n durationMs,\n traceChainPg,\n JSON.stringify(projectionData),\n ctx.event.timezone,\n voidedProjectionIdsPg\n ]\n }]\n },\n projection_type: projectionType,\n projection_data: projectionData\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-352,
704
],
"id": "parse-classification",
"name": "ParseClassification"
},
{
"parameters": {
"workflowId": {
"__rl": true,
"value": "CgUAxK0i4YhrZ2Wp",
"mode": "list",
"cachedResultName": "Execute_Queries",
"cachedResultUrl": "/workflow/CgUAxK0i4YhrZ2Wp"
},
"workflowInputs": {
"mappingMode": "defineBelow",
"value": {
"ctx": "={{ $json.ctx }}"
}
},
"options": {
"waitForSubWorkflow": true
}
},
"type": "n8n-nodes-base.executeWorkflow",
"typeVersion": 1.3,
"position": [
-128,
704
],
"id": "store-projection",
"name": "StoreProjection"
},
{
"parameters": {
"resource": "message",
"guildId": {
"__rl": true,
"value": "={{ $('ParseClassification').item.json.ctx.event.guild_id }}",
"mode": "id"
},
"channelId": {
"__rl": true,
"value": "={{ $env.DISCORD_CHANNEL_KAIRON_LOGS }}",
"mode": "id"
},
"content": "=**[{{ $('ParseClassification').item.json.projection_type.charAt(0).toUpperCase() + $('ParseClassification').item.json.projection_type.slice(1) }} Classification]**\n**Message:** {{ $('ParseClassification').item.json.ctx.event.clean_text }}\n**Result:** {{ $('ParseClassification').item.json.ctx.llm.result }}\n**Confidence:** [ {{ Object.entries($('ParseClassification').item.json.ctx.llm.all_scores || {}).sort((a, b) => b[1] - a[1]).map(([k, v]) => `${k}:${v}%`).join(' | ') }} ]",
"options": {}
},
"type": "n8n-nodes-base.discord",
"typeVersion": 2,
"position": [
96,
704
],
"id": "log-to-kairon-logs",
"name": "LogToKaironLogs",
"retryOnFail": true,
"maxTries": 3,
"waitBetweenTries": 1000,
"credentials": {
"discordBotApi": {
"name": "<your credential>"
}
},
"onError": "continueRegularOutput"
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Extract text for embedding from projection data\n// Activity uses 'description', Note/Todo use 'text'\nconst ctx = $json.ctx;\nconst projection = ctx.db?.projection?.row || {};\nconst data = projection.data || {};\nconst embeddingText = data.description || data.text || '';\n\nreturn {\n json: {\n projection_id: projection.id,\n embedding_text: embeddingText\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
96,
496
],
"id": "prepare-embedding-text",
"name": "PrepareEmbeddingText"
},
{
"parameters": {
"method": "POST",
"url": "={{ $env.EMBEDDING_SERVICE_URL }}/embed",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"texts\": [{{ JSON.stringify($json.embedding_text || '') }}]\n}",
"options": {
"timeout": 10000
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
320,
496
],
"id": "embed-projection-text",
"name": "EmbedProjectionText",
"continueOnFail": true
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Build embedding insert query for Execute_Queries\nconst prepareData = $('PrepareEmbeddingText').first().json;\nconst embeddings = $json.embeddings;\n\n// Check if we have a valid embedding\nif (!embeddings || !embeddings[0]) {\n return {}; // Skip if no embedding\n}\n\nconst embeddingVector = '[' + embeddings[0].join(',') + ']';\n\nreturn {\n json: {\n ctx: {\n db_queries: [{\n key: 'embedding',\n sql: `-- Insert embedding for the projection (fire-and-forget)\nINSERT INTO embeddings (projection_id, model, embedding_data, embedded_text, embedding)\nSELECT \n $1::uuid,\n 'all-MiniLM-L6-v2',\n '{}',\n $2,\n $3::vector\nWHERE $3 IS NOT NULL\nON CONFLICT DO NOTHING;`,\n params: [\n prepareData.projection_id,\n prepareData.embedding_text,\n embeddingVector\n ]\n }]\n }\n }\n};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
544,
496
],
"id": "build-embedding-query",
"name": "BuildEmbeddingQuery"
},
{
"parameters": {
"workflowId": {
"__rl": true,
"value": "CgUAxK0i4YhrZ2Wp",
"mode": "list",
"cachedResultName": "Execute_Queries",
"cachedResultUrl": "/workflow/CgUAxK0i4YhrZ2Wp"
},
"workflowInputs": {
"mappingMode": "defineBelow",
"value": {
"ctx": "={{ $json.ctx }}"
}
},
"options": {
"waitForSubWorkflow": true
}
},
"type": "n8n-nodes-base.executeWorkflow",
"typeVersion": 1.3,
"position": [
768,
496
],
"id": "insert-embedding",
"name": "InsertEmbedding",
"continueOnFail": true
}
],
"connections": {
"ExecuteWorkflowTrigger": {
"main": [
[
{
"node": "PrepareRouting",
"type": "main",
"index": 0
}
]
]
},
"PrepareRouting": {
"main": [
[
{
"node": "RouteByType",
"type": "main",
"index": 0
},
{
"node": "AddTypeReaction",
"type": "main",
"index": 0
},
{
"node": "Remove\ud83d\udd35Reaction",
"type": "main",
"index": 0
}
]
]
},
"RouteByType": {
"main": [
[
{
"node": "ActivityClassifier",
"type": "main",
"index": 0
}
],
[
{
"node": "NoteClassifier",
"type": "main",
"index": 0
}
],
[
{
"node": "TodoClassifier",
"type": "main",
"index": 0
}
],
[
{
"node": "NoteClassifier",
"type": "main",
"index": 0
}
]
]
},
"ActivityClassifier": {
"main": [
[
{
"node": "MergeClassifiers",
"type": "main",
"index": 0
}
]
]
},
"NoteClassifier": {
"main": [
[
{
"node": "MergeClassifiers",
"type": "main",
"index": 1
}
]
]
},
"TodoClassifier": {
"main": [
[
{
"node": "MergeClassifiers",
"type": "main",
"index": 2
}
]
]
},
"MergeClassifiers": {
"main": [
[
{
"node": "ParseClassification",
"type": "main",
"index": 0
}
]
]
},
"ParseClassification": {
"main": [
[
{
"node": "StoreProjection",
"type": "main",
"index": 0
}
]
]
},
"StoreProjection": {
"main": [
[
{
"node": "PrepareEmbeddingText",
"type": "main",
"index": 0
},
{
"node": "LogToKaironLogs",
"type": "main",
"index": 0
}
]
]
},
"PrepareEmbeddingText": {
"main": [
[
{
"node": "EmbedProjectionText",
"type": "main",
"index": 0
}
]
]
},
"EmbedProjectionText": {
"main": [
[
{
"node": "BuildEmbeddingQuery",
"type": "main",
"index": 0
}
]
]
},
"BuildEmbeddingQuery": {
"main": [
[
{
"node": "InsertEmbedding",
"type": "main",
"index": 0
}
]
]
},
"MimoV2Flash": {
"ai_languageModel": [
[
{
"node": "ActivityClassifier",
"type": "ai_languageModel",
"index": 0
}
],
[
{
"node": "NoteClassifier",
"type": "ai_languageModel",
"index": 0
}
],
[
{
"node": "TodoClassifier",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"NemotronNano9b": {
"ai_languageModel": [
[
{
"node": "ActivityClassifier",
"type": "ai_languageModel",
"index": 1
}
],
[
{
"node": "NoteClassifier",
"type": "ai_languageModel",
"index": 1
}
],
[
{
"node": "TodoClassifier",
"type": "ai_languageModel",
"index": 1
}
]
]
}
},
"settings": {
"callerPolicy": "workflowsFromSameOwner",
"errorWorkflow": "NOJ7FqVhVLqw0n8D",
"availableInMCP": false,
"executionOrder": "v1"
},
"staticData": null,
"meta": null,
"versionId": "ff0e1285-46be-426e-a39f-c5d22bde9ec3",
"activeVersionId": null,
"versionCounter": 187,
"triggerCount": 0,
"shared": [
{
"updatedAt": "2025-12-23T09:30:18.636Z",
"createdAt": "2025-12-23T09:30:18.636Z",
"role": "workflow:owner",
"workflowId": "Gu9mVRTwvJCq0Fpf",
"projectId": "erM3nntdLL53noWi",
"project": {
"updatedAt": "2025-12-23T09:23:39.658Z",
"createdAt": "2025-12-23T09:16:56.460Z",
"id": "erM3nntdLL53noWi",
"name": "Chris Irineo <chriskevini@gmail.com>",
"type": "personal",
"icon": null,
"description": null,
"projectRelations": [
{
"updatedAt": "2025-12-23T09:16:56.460Z",
"createdAt": "2025-12-23T09:16:56.460Z",
"userId": "2a851a2d-b7e5-4b3c-aefb-6eaaa79e0659",
"projectId": "erM3nntdLL53noWi",
"user": {
"updatedAt": "2025-12-24T08:40:46.063Z",
"createdAt": "2025-12-23T09:16:54.881Z",
"id": "2a851a2d-b7e5-4b3c-aefb-6eaaa79e0659",
"email": "chriskevini@gmail.com",
"firstName": "Chris",
"lastName": "Irineo",
"personalizationAnswers": {
"version": "v4",
"personalization_survey_submitted_at": "2025-12-23T09:23:43.723Z",
"personalization_survey_n8n_version": "1.123.5"
},
"settings": {
"userActivated": true,
"firstSuccessfulWorkflowId": "CgUAxK0i4YhrZ2Wp",
"userActivatedAt": 1766487000077,
"easyAIWorkflowOnboarded": true
},
"disabled": false,
"mfaEnabled": false,
"lastActiveAt": "2025-12-24",
"isPending": false
}
}
]
}
}
],
"tags": [],
"activeVersion": null
}
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.
discordBotApiopenRouterApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Capture_Projection. Uses executeWorkflowTrigger, httpRequest, chainLlm, lmChatOpenRouter. Event-driven trigger; 18 nodes.
Source: https://github.com/chriskevini/kairon/blob/ab924f228ceb22522b9a4dfa1ab4589eb86273ad/n8n-workflows/Capture_Projection.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Capture_Thread. Uses executeWorkflowTrigger, chainLlm, httpRequest, discord. Event-driven trigger; 26 nodes.
Continue_Thread. Uses executeWorkflowTrigger, chainLlm, lmChatOpenRouter, discord. Event-driven trigger; 14 nodes.
This workflow is designed for n8n users who manage multiple production workflows and want to: Receive intelligent, actionable error alerts instead of raw stack traces Understand root causes without ma
End-to-End Video Creation from user idea or transcript AI-Powered Scriptwriting using LLMs (e.g., DeepSeek via OpenRouter) Voiceover Generation with customizable TTS voices Image Scene Generation usin
This comprehensive N8N automation template revolutionizes content creation by delivering a complete end-to-end solution for AI-powered blog generation. Transform simple ideas into fully SEO-optimized,