AutomationFlowsGeneral › Taskmanager Tool: Complete_task

Taskmanager Tool: Complete_task

TaskManager Tool: complete_task. Uses executeWorkflowTrigger, dataTable. Event-driven trigger; 8 nodes.

Event trigger★★★★☆ complexity8 nodesExecute Workflow TriggerData Table
General Trigger: Event Nodes: 8 Complexity: ★★★★☆ Added:

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 →

Download .json
{
  "name": "TaskManager Tool: complete_task",
  "nodes": [
    {
      "parameters": {},
      "id": "c4a0b004-0001-4000-8000-000000000001",
      "name": "Execute Workflow Trigger",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "typeVersion": 1.1,
      "position": [
        200,
        400
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "// ============================================================\n// INPUT VALIDATION \u2014 Verify task_id is valid integer\n// ============================================================\n\nconst input = $input.first().json;\nconst taskId = parseInt(input.task_id);\n\nif (isNaN(taskId) || taskId <= 0) {\n  return [{\n    json: {\n      success: false,\n      error: 'INVARIANT_VIOLATION: task_id must be a positive integer, got: ' + input.task_id,\n      timestamp: new Date().toISOString()\n    }\n  }];\n}\n\nreturn [{ json: { task_id: taskId, validated: true } }];"
      },
      "id": "c4a0b004-0001-4000-8000-000000000002",
      "name": "Validate Input",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        420,
        400
      ]
    },
    {
      "parameters": {
        "operation": "read",
        "tableId": "DATA_TABLE_ID_TASKS",
        "returnAll": true,
        "options": {}
      },
      "id": "c4a0b004-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// TASK LOOKUP + STATUS CHECK\n// Find target task, verify it exists and isn't already done.\n// ============================================================\n\nconst taskId = $('Validate Input').first().json.task_id;\nconst allTasks = $input.all().map(item => item.json);\n\n// Find target task\nconst targetTask = allTasks.find(t => parseInt(t.id) === taskId);\n\nif (!targetTask) {\n  return [{\n    json: {\n      success: false,\n      error: 'NOT_FOUND: Task #' + taskId + ' does not exist in the database.',\n      available_tasks: allTasks\n        .filter(t => t.status !== 'done')\n        .map(t => ({ id: t.id, title: t.title, status: t.status }))\n        .slice(0, 10),\n      timestamp: new Date().toISOString()\n    }\n  }];\n}\n\nif (targetTask.status === 'done') {\n  return [{\n    json: {\n      success: false,\n      error: 'IDEMPOTENCY_CHECK: Task #' + taskId + ' (\"' + targetTask.title + '\") is already marked as done (completed at ' + targetTask.completed_at + '). No action taken.',\n      task: targetTask,\n      timestamp: new Date().toISOString()\n    }\n  }];\n}\n\n// Task is valid and not yet complete\nreturn [{\n  json: {\n    success: true,\n    target_task: targetTask,\n    all_tasks: allTasks,\n    proceed: true\n  }\n}];"
      },
      "id": "c4a0b004-0001-4000-8000-000000000004",
      "name": "Lookup & Status Check",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        860,
        400
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "proceed-check",
              "leftValue": "={{ $json.proceed }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "c4a0b004-0001-4000-8000-000000000005",
      "name": "Proceed Gate",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1080,
        400
      ]
    },
    {
      "parameters": {
        "mode": "raw",
        "jsonOutput": "={\n  \"id\": {{ $json.target_task.id }},\n  \"status\": \"done\",\n  \"completed_at\": \"{{ new Date().toISOString() }}\"\n}",
        "options": {}
      },
      "id": "c4a0b004-0001-4000-8000-000000000006",
      "name": "Prepare Update",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1300,
        300
      ]
    },
    {
      "parameters": {
        "operation": "update",
        "tableId": "DATA_TABLE_ID_TASKS",
        "columns": {
          "mappingMode": "autoMapInputData"
        },
        "options": {}
      },
      "id": "c4a0b004-0001-4000-8000-000000000007",
      "name": "Data Table: Mark Done",
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1,
      "position": [
        1520,
        300
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "// ============================================================\n// DAG TRAVERSAL ENGINE\n// After completing a task, traverse the dependency graph\n// to find tasks that are now unblocked.\n// ============================================================\n\nconst lookupData = $('Lookup & Status Check').first().json;\nconst completedTask = lookupData.target_task;\nconst completedId = String(completedTask.id);\nconst allTasks = lookupData.all_tasks;\nconst now = new Date();\n\n// --- Find newly unblocked tasks ---\nconst unblockedTasks = [];\n\nfor (const task of allTasks) {\n  if (task.status === 'done' || task.status === 'cancelled') continue;\n  if (!task.depends_on || task.depends_on === '') continue;\n\n  const depIds = task.depends_on.split(',').map(d => d.trim());\n  \n  // Only check tasks that depend on the completed task\n  if (!depIds.includes(completedId)) continue;\n\n  // Check if ALL dependencies are now satisfied\n  const allDepsSatisfied = depIds.every(depId => {\n    if (depId === completedId) return true; // just completed\n    const depTask = allTasks.find(t => String(t.id) === depId);\n    return depTask && depTask.status === 'done';\n  });\n\n  if (allDepsSatisfied) {\n    unblockedTasks.push({\n      id: task.id,\n      title: task.title,\n      priority: task.priority,\n      category: task.category\n    });\n  }\n}\n\n// --- Compute completion metrics ---\nconst createdAt = new Date(completedTask.created_at);\nconst completedAt = now;\nconst elapsedMs = completedAt - createdAt;\nconst elapsedHours = Math.round(elapsedMs / (1000 * 60 * 60) * 10) / 10;\nconst elapsedDays = Math.round(elapsedMs / (1000 * 60 * 60 * 24) * 10) / 10;\n\nlet elapsedHuman;\nif (elapsedDays >= 1) {\n  elapsedHuman = elapsedDays + ' days';\n} else {\n  elapsedHuman = elapsedHours + ' hours';\n}\n\n// --- Count completed tasks for productivity metric ---\nconst doneTasks = allTasks.filter(t => t.status === 'done').length + 1; // +1 for this one\nconst totalTasks = allTasks.length;\n\n// --- Check recurrence ---\nlet recurrenceNote = null;\nif (completedTask.recurrence_rule && completedTask.recurrence_rule !== 'none') {\n  recurrenceNote = 'This is a recurring task (' + completedTask.recurrence_rule + '). A new instance should be created.';\n}\n\n// --- Build response ---\nconst response = {\n  success: true,\n  operation: 'task_completed',\n  completed_task: {\n    id: completedTask.id,\n    title: completedTask.title,\n    category: completedTask.category,\n    priority_was: completedTask.priority,\n    eisenhower_was: completedTask.eisenhower_quadrant,\n    created_at: completedTask.created_at,\n    completed_at: completedAt.toISOString()\n  },\n  metrics: {\n    elapsed_human: elapsedHuman,\n    elapsed_hours: elapsedHours,\n    tasks_done_total: doneTasks,\n    tasks_remaining: totalTasks - doneTasks,\n    completion_rate: Math.round((doneTasks / totalTasks) * 100) + '%'\n  },\n  dependency_graph: {\n    unblocked_tasks: unblockedTasks,\n    unblocked_count: unblockedTasks.length\n  },\n  recurrence: recurrenceNote,\n  timestamp: completedAt.toISOString()\n};\n\nreturn [{ json: response }];"
      },
      "id": "c4a0b004-0001-4000-8000-000000000008",
      "name": "DAG Traversal & Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1740,
        300
      ]
    }
  ],
  "connections": {
    "Execute Workflow Trigger": {
      "main": [
        [
          {
            "node": "Validate Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Input": {
      "main": [
        [
          {
            "node": "Data Table: Read All Tasks",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Data Table: Read All Tasks": {
      "main": [
        [
          {
            "node": "Lookup & Status Check",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lookup & Status Check": {
      "main": [
        [
          {
            "node": "Proceed Gate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Proceed Gate": {
      "main": [
        [
          {
            "node": "Prepare Update",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Prepare Update": {
      "main": [
        [
          {
            "node": "Data Table: Mark Done",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Data Table: Mark Done": {
      "main": [
        [
          {
            "node": "DAG Traversal & Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [
    {
      "name": "Tool",
      "id": "4"
    },
    {
      "name": "Task Manager",
      "id": "2"
    }
  ]
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

TaskManager Tool: complete_task. Uses executeWorkflowTrigger, dataTable. Event-driven trigger; 8 nodes.

Source: https://github.com/neuron7xLab/ai-automation-portfolio/blob/main/agent-patterns/task-manager/wf4-tool-complete-task.json — original creator credit. Request a take-down →

More General workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

General

Reagendamiento. Uses executeWorkflowTrigger, redis, n8n-nodes-evolution-api, dataTable. Event-driven trigger; 73 nodes.

Execute Workflow Trigger, Redis, N8N Nodes Evolution Api +2
General

Agendamiento. Uses n8n-nodes-evolution-api, redis, dataTable, executeWorkflowTrigger. Event-driven trigger; 60 nodes.

N8N Nodes Evolution Api, Redis, Data Table +2
General

This workflow provides a reusable error handling, audit logging, and observability pattern for n8n workflows using two n8n custom Data Tables: and .

Error Trigger, Data Table, Execute Workflow Trigger
General

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!

Execute Workflow Trigger, Data Table, Stop And Error
General

TaskManager Tool: add_task. Uses executeWorkflowTrigger, dataTable. Event-driven trigger; 6 nodes.

Execute Workflow Trigger, Data Table