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 →
{
"name": "TaskManager Tool: add_task",
"nodes": [
{
"parameters": {},
"id": "c3a0b003-0001-4000-8000-000000000001",
"name": "Execute Workflow Trigger",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"typeVersion": 1.1,
"position": [
200,
400
]
},
{
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "// ============================================================\n// VALIDATION LAYER \u2014 Contract enforcement\n// Every field is validated before touching the database.\n// Returns structured error objects, never crashes.\n// ============================================================\n\nconst input = $input.first().json;\nconst errors = [];\nconst warnings = [];\n\n// --- Required field validation ---\nif (!input.title || input.title.trim().length === 0) {\n errors.push('INVARIANT_VIOLATION: title is required and cannot be empty');\n}\nif (input.title && input.title.trim().length > 120) {\n errors.push('CONSTRAINT: title must be <= 120 characters, got ' + input.title.length);\n}\n\n// --- Importance score: must be in [0.0, 1.0] ---\nconst importance = parseFloat(input.importance_score);\nif (isNaN(importance) || importance < 0 || importance > 1) {\n errors.push('RANGE_VIOLATION: importance_score must be float in [0.0, 1.0], got: ' + input.importance_score);\n}\n\n// --- Category: must be in allowed set ---\nconst VALID_CATEGORIES = ['work', 'personal', 'health', 'learning', 'finance', 'admin'];\nconst category = (input.category || '').toLowerCase().trim();\nif (!VALID_CATEGORIES.includes(category)) {\n warnings.push('Category \"' + input.category + '\" not in allowed set, defaulting to \"personal\"');\n}\n\n// --- Context: must be valid GTD context ---\nconst VALID_CONTEXTS = ['@home', '@computer', '@phone', '@errands'];\nconst context = (input.context || '').toLowerCase().trim();\nif (context && !VALID_CONTEXTS.includes(context)) {\n warnings.push('Context \"' + input.context + '\" not recognized, defaulting to \"@computer\"');\n}\n\n// --- Deadline: validate ISO 8601 if provided ---\nlet deadline = input.deadline;\nif (deadline && deadline !== 'null' && deadline !== '') {\n const d = new Date(deadline);\n if (isNaN(d.getTime())) {\n errors.push('FORMAT_VIOLATION: deadline must be valid ISO 8601, got: ' + deadline);\n }\n} else {\n deadline = null;\n}\n\n// --- Estimated minutes: must be positive integer ---\nconst estMinutes = parseInt(input.estimated_minutes);\nif (isNaN(estMinutes) || estMinutes < 0) {\n warnings.push('estimated_minutes invalid, defaulting to 15');\n}\n\n// --- Recurrence rule validation ---\nconst VALID_RECURRENCE_PREFIXES = ['daily', 'weekly', 'monthly', 'none'];\nconst recurrence = (input.recurrence_rule || 'none').toLowerCase().trim();\nconst recurrencePrefix = recurrence.split(':')[0];\nif (!VALID_RECURRENCE_PREFIXES.includes(recurrencePrefix)) {\n warnings.push('recurrence_rule \"' + recurrence + '\" not recognized, defaulting to \"none\"');\n}\n\n// --- Depends_on: validate format (comma-separated integers) ---\nconst dependsOn = (input.depends_on || '').trim();\nif (dependsOn && dependsOn !== '') {\n const depIds = dependsOn.split(',').map(d => d.trim());\n for (const depId of depIds) {\n if (isNaN(parseInt(depId))) {\n errors.push('REFERENCE_VIOLATION: depends_on contains non-integer: \"' + depId + '\"');\n }\n }\n}\n\n// --- If errors exist, return failure ---\nif (errors.length > 0) {\n return [{\n json: {\n success: false,\n errors: errors,\n warnings: warnings,\n validation_timestamp: new Date().toISOString()\n }\n }];\n}\n\n// --- Sanitize and normalize ---\nconst sanitized = {\n title: input.title.trim().charAt(0).toUpperCase() + input.title.trim().slice(1),\n description: (input.description || '').trim(),\n deadline: deadline,\n category: VALID_CATEGORIES.includes(category) ? category : 'personal',\n importance_score: importance,\n estimated_minutes: isNaN(estMinutes) || estMinutes < 0 ? 15 : estMinutes,\n context: VALID_CONTEXTS.includes(context) ? context : '@computer',\n recurrence_rule: VALID_RECURRENCE_PREFIXES.includes(recurrencePrefix) ? recurrence : 'none',\n depends_on: dependsOn,\n tags: (input.tags || '').trim(),\n raw_input: (input.raw_input || '').trim(),\n status: 'todo',\n created_at: new Date().toISOString(),\n completed_at: '',\n validation_passed: true,\n warnings: warnings\n};\n\nreturn [{ json: sanitized }];"
},
"id": "c3a0b003-0001-4000-8000-000000000002",
"name": "Validation Layer",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
420,
400
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "validation-check",
"leftValue": "={{ $json.validation_passed }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "c3a0b003-0001-4000-8000-000000000003",
"name": "Validation Gate",
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
640,
400
]
},
{
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "// ============================================================\n// EISENHOWER COMPUTATION ENGINE\n// Computes urgency from deadline, derives quadrant and priority.\n// This is the mathematical core of the system.\n// ============================================================\n\nconst MAX_HORIZON_HOURS = 336; // 2-week planning horizon\nconst now = new Date();\nconst task = $input.first().json;\n\n// --- Compute urgency_score as f(deadline, now) ---\nlet urgencyScore = 0.3; // default for no-deadline\nif (task.deadline && task.deadline !== 'null') {\n const deadline = new Date(task.deadline);\n const hoursRemaining = (deadline - now) / (1000 * 60 * 60);\n urgencyScore = Math.max(0, Math.min(1, 1 - (hoursRemaining / MAX_HORIZON_HOURS)));\n}\n\n// --- Eisenhower Matrix Derivation ---\nconst u = urgencyScore;\nconst imp = task.importance_score;\nlet quadrant, priority, actionLabel;\n\nif (u >= 0.6 && imp >= 0.6) {\n quadrant = 'Q1_do_first';\n priority = 1;\n actionLabel = 'Urgent + Important -> Act immediately';\n} else if (u < 0.6 && imp >= 0.6) {\n quadrant = 'Q2_schedule';\n priority = 2;\n actionLabel = 'Not Urgent + Important -> Schedule for focused time';\n} else if (u >= 0.6 && imp < 0.6) {\n quadrant = 'Q3_delegate';\n priority = 3;\n actionLabel = 'Urgent + Not Important -> Delegate or batch';\n} else {\n quadrant = 'Q4_eliminate';\n priority = 4;\n actionLabel = 'Not Urgent + Not Important -> Consider dropping';\n}\n\nconst enriched = {\n ...task,\n urgency_score: Math.round(urgencyScore * 100) / 100,\n eisenhower_quadrant: quadrant,\n priority: priority,\n action_label: actionLabel\n};\n\n// Remove internal fields before DB write\ndelete enriched.validation_passed;\ndelete enriched.warnings;\n\nreturn [{ json: enriched }];"
},
"id": "c3a0b003-0001-4000-8000-000000000004",
"name": "Eisenhower Compute",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
860,
300
]
},
{
"parameters": {
"operation": "create",
"tableId": "DATA_TABLE_ID_TASKS",
"columns": {
"mappingMode": "autoMapInputData"
},
"options": {}
},
"id": "c3a0b003-0001-4000-8000-000000000005",
"name": "Data Table: Insert Task",
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1,
"position": [
1080,
300
]
},
{
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "// ============================================================\n// RESPONSE BUILDER \u2014 Structured output for the agent\n// ============================================================\n\nconst task = $input.first().json;\n\nconst response = {\n success: true,\n operation: 'task_created',\n task: {\n id: task.id,\n title: task.title,\n description: task.description,\n status: task.status,\n priority: task.priority,\n eisenhower_quadrant: task.eisenhower_quadrant,\n urgency_score: task.urgency_score,\n importance_score: task.importance_score,\n category: task.category,\n deadline: task.deadline,\n estimated_minutes: task.estimated_minutes,\n context: task.context,\n recurrence_rule: task.recurrence_rule,\n depends_on: task.depends_on,\n tags: task.tags,\n created_at: task.created_at\n },\n metadata: {\n action_recommendation: task.action_label || 'No recommendation',\n is_recurring: task.recurrence_rule && task.recurrence_rule !== 'none',\n has_dependencies: task.depends_on && task.depends_on !== '',\n creation_timestamp: new Date().toISOString()\n }\n};\n\nreturn [{ json: response }];"
},
"id": "c3a0b003-0001-4000-8000-000000000006",
"name": "Build Response",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1300,
300
]
}
],
"connections": {
"Execute Workflow Trigger": {
"main": [
[
{
"node": "Validation Layer",
"type": "main",
"index": 0
}
]
]
},
"Validation Layer": {
"main": [
[
{
"node": "Validation Gate",
"type": "main",
"index": 0
}
]
]
},
"Validation Gate": {
"main": [
[
{
"node": "Eisenhower Compute",
"type": "main",
"index": 0
}
]
]
},
"Eisenhower Compute": {
"main": [
[
{
"node": "Data Table: Insert Task",
"type": "main",
"index": 0
}
]
]
},
"Data Table: Insert Task": {
"main": [
[
{
"node": "Build Response",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [
{
"name": "Tool",
"id": "4"
},
{
"name": "Task Manager",
"id": "2"
}
]
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
TaskManager Tool: add_task. Uses executeWorkflowTrigger, dataTable. Event-driven trigger; 6 nodes.
Source: https://github.com/neuron7xLab/ai-automation-portfolio/blob/main/agent-patterns/task-manager/wf3-tool-add-task.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.
Reagendamiento. Uses executeWorkflowTrigger, redis, n8n-nodes-evolution-api, dataTable. Event-driven trigger; 73 nodes.
Agendamiento. Uses n8n-nodes-evolution-api, redis, dataTable, executeWorkflowTrigger. Event-driven trigger; 60 nodes.
This workflow provides a reusable error handling, audit logging, and observability pattern for n8n workflows using two n8n custom Data Tables: and .
If you're in need of a quick and dirty cache that doesn't need anything other than the current version of N8N, boy do I have a dodgy script for you to try!
TaskManager Tool: complete_task. Uses executeWorkflowTrigger, dataTable. Event-driven trigger; 8 nodes.