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: get_tasks",
"nodes": [
{
"parameters": {},
"id": "c2a0b002-0001-4000-8000-000000000001",
"name": "Execute Workflow Trigger",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"typeVersion": 1.1,
"position": [
200,
400
]
},
{
"parameters": {
"mode": "raw",
"jsonOutput": "={\n \"status\": \"{{ $json.status || 'all' }}\",\n \"category\": \"{{ $json.category || '' }}\",\n \"priority_max\": {{ $json.priority_max || 4 }},\n \"search\": \"{{ $json.search || '' }}\",\n \"time_budget_minutes\": {{ $json.time_budget_minutes || 0 }},\n \"query_timestamp\": \"{{ new Date().toISOString() }}\"\n}",
"options": {}
},
"id": "c2a0b002-0001-4000-8000-000000000002",
"name": "Parse Parameters",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
420,
400
]
},
{
"parameters": {
"operation": "read",
"tableId": "DATA_TABLE_ID_TASKS",
"returnAll": true,
"options": {}
},
"id": "c2a0b002-0001-4000-8000-000000000003",
"name": "Data Table: Read All Tasks",
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1,
"position": [
640,
400
]
},
{
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "// ============================================================\n// EISENHOWER REAL-TIME PRIORITY ENGINE\n// Recomputes urgency_score as f(time) for every task on each query.\n// Priority is DERIVED, never stored statically.\n// ============================================================\n\nconst MAX_HORIZON_HOURS = 336; // 2-week planning horizon\nconst now = new Date();\n\n// Retrieve filter params from first item in previous Set node\nconst params = $('Parse Parameters').first().json;\nconst statusFilter = params.status || 'all';\nconst categoryFilter = params.category || '';\nconst priorityMax = parseInt(params.priority_max) || 4;\nconst searchQuery = (params.search || '').toLowerCase().trim();\nconst timeBudget = parseInt(params.time_budget_minutes) || 0;\n\n// ---- PHASE 1: Recompute urgency for all tasks ----\nlet tasks = $input.all().map(item => {\n const t = { ...item.json };\n\n // Dynamic urgency: f(deadline, now)\n if (t.deadline && t.deadline !== 'null' && t.deadline !== '') {\n const deadline = new Date(t.deadline);\n const hoursRemaining = (deadline - now) / (1000 * 60 * 60);\n t.urgency_score = Math.max(0, Math.min(1, 1 - (hoursRemaining / MAX_HORIZON_HOURS)));\n t.is_overdue = hoursRemaining < 0;\n t.hours_remaining = Math.round(hoursRemaining * 10) / 10;\n } else {\n t.urgency_score = 0.3; // default medium-low for no-deadline tasks\n t.is_overdue = false;\n t.hours_remaining = null;\n }\n\n // Eisenhower matrix computation\n const u = parseFloat(t.urgency_score) || 0.3;\n const imp = parseFloat(t.importance_score) || 0.5;\n\n if (u >= 0.6 && imp >= 0.6) {\n t.eisenhower_quadrant = 'Q1_do_first';\n t.priority = 1;\n } else if (u < 0.6 && imp >= 0.6) {\n t.eisenhower_quadrant = 'Q2_schedule';\n t.priority = 2;\n } else if (u >= 0.6 && imp < 0.6) {\n t.eisenhower_quadrant = 'Q3_delegate';\n t.priority = 3;\n } else {\n t.eisenhower_quadrant = 'Q4_eliminate';\n t.priority = 4;\n }\n\n // Dependency status\n if (t.depends_on && t.depends_on !== '') {\n const depIds = t.depends_on.split(',').map(d => d.trim());\n const allTasks = $input.all().map(i => i.json);\n const blockedBy = depIds.filter(depId => {\n const dep = allTasks.find(task => String(task.id) === String(depId));\n return dep && dep.status !== 'done';\n });\n t.is_blocked = blockedBy.length > 0;\n t.blocked_by = blockedBy;\n } else {\n t.is_blocked = false;\n t.blocked_by = [];\n }\n\n return t;\n});\n\n// ---- PHASE 2: Apply filters ----\nif (statusFilter !== 'all') {\n tasks = tasks.filter(t => t.status === statusFilter);\n}\nif (categoryFilter) {\n tasks = tasks.filter(t => t.category === categoryFilter);\n}\ntasks = tasks.filter(t => t.priority <= priorityMax);\n\nif (searchQuery) {\n tasks = tasks.filter(t => {\n const title = (t.title || '').toLowerCase();\n const tags = (t.tags || '').toLowerCase();\n const desc = (t.description || '').toLowerCase();\n return title.includes(searchQuery) || tags.includes(searchQuery) || desc.includes(searchQuery);\n });\n}\n\nif (timeBudget > 0) {\n tasks = tasks.filter(t => {\n const est = parseInt(t.estimated_minutes) || 999;\n return est <= timeBudget;\n });\n}\n\n// ---- PHASE 3: Sort (overdue first \u2192 priority ASC \u2192 deadline ASC) ----\ntasks.sort((a, b) => {\n // Overdue tasks always first\n if (a.is_overdue && !b.is_overdue) return -1;\n if (!a.is_overdue && b.is_overdue) return 1;\n // Then by priority (1 = highest)\n if (a.priority !== b.priority) return a.priority - b.priority;\n // Then by deadline (earliest first)\n const dA = a.deadline || '9999-12-31';\n const dB = b.deadline || '9999-12-31';\n return dA.localeCompare(dB);\n});\n\n// ---- PHASE 4: Compute analytics ----\nconst analytics = {\n total: tasks.length,\n overdue: tasks.filter(t => t.is_overdue).length,\n blocked: tasks.filter(t => t.is_blocked).length,\n by_quadrant: {\n Q1_do_first: tasks.filter(t => t.priority === 1).length,\n Q2_schedule: tasks.filter(t => t.priority === 2).length,\n Q3_delegate: tasks.filter(t => t.priority === 3).length,\n Q4_eliminate: tasks.filter(t => t.priority === 4).length\n },\n total_estimated_minutes: tasks.reduce((sum, t) => sum + (parseInt(t.estimated_minutes) || 0), 0),\n query_timestamp: now.toISOString()\n};\n\n// ---- PHASE 5: Build structured response ----\nconst response = {\n success: true,\n analytics: analytics,\n tasks: tasks.map(t => ({\n id: t.id,\n title: t.title,\n status: t.status,\n priority: t.priority,\n eisenhower_quadrant: t.eisenhower_quadrant,\n urgency_score: Math.round(t.urgency_score * 100) / 100,\n importance_score: parseFloat(t.importance_score) || 0.5,\n category: t.category,\n deadline: t.deadline,\n is_overdue: t.is_overdue,\n hours_remaining: t.hours_remaining,\n is_blocked: t.is_blocked,\n blocked_by: t.blocked_by,\n estimated_minutes: t.estimated_minutes,\n context: t.context,\n tags: t.tags,\n created_at: t.created_at,\n depends_on: t.depends_on,\n recurrence_rule: t.recurrence_rule\n }))\n};\n\nreturn [{ json: response }];"
},
"id": "c2a0b002-0001-4000-8000-000000000004",
"name": "Eisenhower Priority Engine",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
860,
400
]
}
],
"connections": {
"Execute Workflow Trigger": {
"main": [
[
{
"node": "Parse Parameters",
"type": "main",
"index": 0
}
]
]
},
"Parse Parameters": {
"main": [
[
{
"node": "Data Table: Read All Tasks",
"type": "main",
"index": 0
}
]
]
},
"Data Table: Read All Tasks": {
"main": [
[
{
"node": "Eisenhower Priority Engine",
"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: get_tasks. Uses executeWorkflowTrigger, dataTable. Event-driven trigger; 4 nodes.
Source: https://github.com/neuron7xLab/ai-automation-portfolio/blob/main/agent-patterns/task-manager/wf2-tool-get-tasks.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.