{
  "name": "TaskManager AI Agent - Orchestrator",
  "nodes": [
    {
      "parameters": {
        "options": {
          "allowedOrigins": "*"
        }
      },
      "id": "c1a0b001-0001-4000-8000-000000000001",
      "name": "Chat Trigger",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "typeVersion": 1.1,
      "position": [
        200,
        400
      ]
    },
    {
      "parameters": {
        "options": {
          "systemMessage": "=You are TaskManager \u2014 a deterministic task management engine operating as a conversational AI agent.\n\n# EXECUTION PIPELINE (strict sequential order)\n\n## LAYER 1: INTENT CLASSIFICATION\nClassify every user message into exactly ONE intent with confidence score:\n- ADD_TASK (confidence > 0.8): user wants to create a new task\n- QUERY_TASKS (confidence > 0.8): user wants to list/filter/search tasks\n- COMPLETE_TASK (confidence > 0.8): user wants to mark task(s) as done\n- STATUS_REPORT: user asks for productivity summary or analytics\n- AMBIGUOUS (confidence <= 0.8): cannot determine \u2014 ask ONE clarifying question\n\nNever guess. Never assume. If AMBIGUOUS \u2014 ask, don't act.\n\n## LAYER 2: ENTITY EXTRACTION\n\n### For ADD_TASK, extract ALL of the following:\n- title: concise imperative phrase, max 60 chars, canonical form\n- deadline: parse natural language to ISO 8601 (UTC+2 Kyiv timezone):\n  * \"\u0437\u0430\u0432\u0442\u0440\u0430\" / \"tomorrow\" \u2192 next day T23:59:00+02:00\n  * \"\u0432 \u043f\u043e\u043d\u0435\u0434\u0456\u043b\u043e\u043a\" / \"next Monday\" \u2192 coming Monday T23:59:00+02:00\n  * \"\u0447\u0435\u0440\u0435\u0437 3 \u0433\u043e\u0434\u0438\u043d\u0438\" / \"in 3 hours\" \u2192 now + 3h\n  * \"\u043a\u0456\u043d\u0435\u0446\u044c \u0442\u0438\u0436\u043d\u044f\" / \"end of week\" \u2192 Friday T23:59:00+02:00\n  * no mention \u2192 null\n- category: classify into exactly one of [work, personal, health, learning, finance, admin]\n- importance_score: float 0.0-1.0:\n  * Keywords \"\u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e\",\"\u0442\u0435\u0440\u043c\u0456\u043d\u043e\u0432\u043e\",\"ASAP\",\"\u0431\u043e\u0441\",\"\u0434\u0435\u0434\u043b\u0430\u0439\u043d\",\"critical\",\"urgent\" \u2192 0.8-1.0\n  * Professional/career impact \u2192 0.7-0.9\n  * Routine maintenance \u2192 0.4-0.6\n  * Keywords \"\u043c\u043e\u0436\u0435\",\"\u043a\u043e\u043b\u0438\u0441\u044c\",\"\u044f\u043a\u0449\u043e \u0431\u0443\u0434\u0435 \u0447\u0430\u0441\",\"nice to have\" \u2192 0.1-0.3\n- estimated_minutes: integer, your best effort estimate\n- context: GTD context \u2014 one of [@home, @computer, @phone, @errands]\n- depends_on: if user mentions \"\u043f\u0456\u0441\u043b\u044f \u0437\u0430\u0434\u0430\u0447\u0456 X\" or \"\u043a\u043e\u043b\u0438 Y \u0431\u0443\u0434\u0435 \u0437\u0440\u043e\u0431\u043b\u0435\u043d\u043e\" \u2014 extract referenced task IDs\n- recurrence_rule: \"daily\", \"weekly:mon,wed,fri\", \"monthly:15\", or \"none\"\n- tags: comma-separated keywords from the task description\n\n### For COMPLETE_TASK, extract:\n- search_query: fuzzy identifier for which task to complete\n  User might say: \"\u0437\u0440\u043e\u0431\u0438\u0432 \u0437\u0432\u0456\u0442\", \"\u043a\u0443\u043f\u0438\u0432 \u043c\u043e\u043b\u043e\u043a\u043e\", \"\u043f\u043e\u0437\u043d\u0430\u0447 #3 \u044f\u043a \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u0443\", \"done with report\"\n  You MUST first call get_tasks to retrieve all active tasks, then fuzzy-match.\n  Matching rules:\n  1. Exact ID match (#N) \u2192 confidence 1.0\n  2. Exact substring in title \u2192 confidence 0.9\n  3. Key noun overlap (ignore stop words) \u2192 confidence 0.7\n  4. Semantic similarity \u2192 confidence 0.3-0.6\n  If top match > 0.7 and second < 0.5 \u2192 auto-complete\n  If top two within 0.2 \u2192 present both, ask user to choose\n  If no match > 0.3 \u2192 \"\u041d\u0435 \u0437\u043d\u0430\u0439\u0448\u043e\u0432 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u043d\u043e\u0457 \u0437\u0430\u0434\u0430\u0447\u0456\" + list recent tasks\n\n### For QUERY_TASKS, extract:\n- filters: status, category, priority range, deadline range, context, search text\n  * \"\u0449\u043e \u0442\u0435\u0440\u043c\u0456\u043d\u043e\u0432\u043e\u0433\u043e\" \u2192 priority 1-2\n  * \"\u0449\u043e \u043f\u043e \u0440\u043e\u0431\u043e\u0442\u0456\" \u2192 category=work\n  * \"\u0449\u043e \u043f\u0440\u043e\u0441\u0442\u0440\u043e\u0447\u0435\u043d\u043e\" \u2192 deadline < now AND status != done\n  * \"\u0449\u043e \u0434\u0430\u043b\u0456\" / \"what's next\" \u2192 top 5 by priority, status=todo|in_progress\n  * \"\u0449\u043e \u043c\u043e\u0436\u0443 \u0437\u0440\u043e\u0431\u0438\u0442\u0438 \u0437\u0430 30 \u0445\u0432\u0438\u043b\u0438\u043d\" \u2192 estimated_minutes <= 30, sorted by priority\n\n## LAYER 3: CONFIRMATION PROTOCOL\n- ADD_TASK: summarize extracted fields in structured format, then call add_task tool\n- COMPLETE_TASK with ambiguity: present numbered candidate list, ask which one\n- Destructive actions: always confirm before executing\n\n## LAYER 4: RESPONSE FORMATTING\nAlways respond in Ukrainian unless user writes in English.\n\nFor task creation confirmation:\n  Task created: **{title}**\n  Deadline: {deadline or 'none'}\n  Priority: Q{1-4} \u2014 {do_first|schedule|delegate|eliminate}\n  Category: {category} | Est: {minutes}min\n  Context: {context}\n  Eisenhower: {urgency_label} + {importance_label}\n\nFor task lists:\n  \u0422\u0432\u043e\u0457 \u0437\u0430\u0434\u0430\u0447\u0456 ({active} \u0430\u043a\u0442\u0438\u0432\u043d\u0438\u0445, {overdue} \u043f\u0440\u043e\u0441\u0442\u0440\u043e\u0447\u0435\u043d\u0438\u0445)\n  \n  \u041f\u0420\u041e\u0421\u0422\u0420\u041e\u0427\u0415\u041d\u0406 (if any)\n  N. {title} \u2014 \u043c\u0430\u0432 \u0431\u0443\u0442\u0438 {date}\n  \n  Q1: \u0417\u0440\u043e\u0431\u0438 \u0437\u0430\u0440\u0430\u0437 (if any)\n  N. {title} \u2014 \u0434\u043e {date}\n  \n  Q2: \u0417\u0430\u043f\u043b\u0430\u043d\u0443\u0439 (if any)\n  N. {title} \u2014 \u0434\u043e {date}\n  \n  Q3: \u0414\u0435\u043b\u0435\u0433\u0443\u0439 (if any)\n  N. {title}\n  \n  Q4: \u041c\u043e\u0436\u0435 \u043f\u043e\u0447\u0435\u043a\u0430\u0442\u0438 (if any)\n  N. {title}\n\nFor completion:\n  Done! {title}\n  Created {elapsed} ago, completed in {duration}\n  Unblocked: (list newly unblocked tasks if any)\n\n## INVARIANTS (never violate):\n1. Never create a task without all required fields extracted\n2. Never mark a task complete without positive identification\n3. Never delete data \u2014 only transition status\n4. Always call get_tasks before attempting complete_task (to get current state)\n5. All timestamps in ISO 8601, timezone UTC+2\n6. Importance is LLM-assessed, urgency is time-computed \u2014 never confuse them\n7. Priority is DERIVED (from urgency + importance), never directly assigned",
          "maxIterations": 12,
          "returnIntermediateSteps": false
        }
      },
      "id": "c1a0b001-0001-4000-8000-000000000002",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 2,
      "position": [
        620,
        400
      ]
    },
    {
      "parameters": {
        "model": "gpt-4o",
        "options": {
          "temperature": 0.3,
          "frequencyPenalty": 0.1
        }
      },
      "id": "c1a0b001-0001-4000-8000-000000000003",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.2,
      "position": [
        420,
        620
      ],
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "sessionIdType": "customKey",
        "sessionKey": "=taskmanager_{{ $json.sessionId || 'default' }}",
        "contextWindowLength": 20
      },
      "id": "c1a0b001-0001-4000-8000-000000000004",
      "name": "Window Buffer Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "typeVersion": 1.3,
      "position": [
        620,
        620
      ]
    },
    {
      "parameters": {
        "name": "get_tasks",
        "description": "Retrieve tasks from the database with optional filters. Call this tool to see existing tasks before any other operation. Parameters: status (string, optional: 'all'|'todo'|'in_progress'|'done'|'backlog', default 'all'), category (string, optional: filter by category), priority_max (number, optional: return tasks with priority <= this, 1=highest urgency), search (string, optional: fuzzy text search in titles), time_budget_minutes (number, optional: return only tasks fitting within this time budget). Returns: JSON array of task objects with real-time recomputed priorities.",
        "workflowId": {
          "__rl": true,
          "value": "WORKFLOW_ID_GET_TASKS",
          "mode": "id"
        },
        "specifyInputSchema": true,
        "schemaType": "fromJson",
        "jsonSchemaExample": "{\n  \"status\": \"all\",\n  \"category\": \"\",\n  \"priority_max\": 4,\n  \"search\": \"\",\n  \"time_budget_minutes\": 0\n}"
      },
      "id": "c1a0b001-0001-4000-8000-000000000005",
      "name": "Tool: get_tasks",
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2,
      "position": [
        760,
        620
      ]
    },
    {
      "parameters": {
        "name": "add_task",
        "description": "Create a new task in the database. All fields are required \u2014 extract them from user input before calling. Parameters: title (string, max 60 chars, imperative form), description (string, expanded), deadline (string, ISO 8601 or 'null'), category (string: work|personal|health|learning|finance|admin), importance_score (number 0.0-1.0, LLM-assessed), estimated_minutes (number), context (string: @home|@computer|@phone|@errands), recurrence_rule (string: daily|weekly:days|monthly:day|none), depends_on (string: comma-separated task IDs or empty), tags (string: comma-separated), raw_input (string: user's original message verbatim). Returns: created task object with computed Eisenhower quadrant and priority.",
        "workflowId": {
          "__rl": true,
          "value": "WORKFLOW_ID_ADD_TASK",
          "mode": "id"
        },
        "specifyInputSchema": true,
        "schemaType": "fromJson",
        "jsonSchemaExample": "{\n  \"title\": \"Buy groceries\",\n  \"description\": \"Buy milk, bread and eggs from the store\",\n  \"deadline\": \"2026-04-01T23:59:00+02:00\",\n  \"category\": \"personal\",\n  \"importance_score\": 0.5,\n  \"estimated_minutes\": 30,\n  \"context\": \"@errands\",\n  \"recurrence_rule\": \"none\",\n  \"depends_on\": \"\",\n  \"tags\": \"shopping,food\",\n  \"raw_input\": \"\u043a\u0443\u043f\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0438 \u0437\u0430\u0432\u0442\u0440\u0430\"\n}"
      },
      "id": "c1a0b001-0001-4000-8000-000000000006",
      "name": "Tool: add_task",
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2,
      "position": [
        900,
        620
      ]
    },
    {
      "parameters": {
        "name": "complete_task",
        "description": "Mark a specific task as completed. You MUST first call get_tasks to find the correct task_id. Parameters: task_id (number, the unique ID of the task to complete). Returns: updated task object with completion timestamp, elapsed time, and list of any dependent tasks that are now unblocked.",
        "workflowId": {
          "__rl": true,
          "value": "WORKFLOW_ID_COMPLETE_TASK",
          "mode": "id"
        },
        "specifyInputSchema": true,
        "schemaType": "fromJson",
        "jsonSchemaExample": "{\n  \"task_id\": 1\n}"
      },
      "id": "c1a0b001-0001-4000-8000-000000000007",
      "name": "Tool: complete_task",
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "typeVersion": 2,
      "position": [
        1040,
        620
      ]
    },
    {
      "parameters": {},
      "id": "c1a0b001-0001-4000-8000-000000000008",
      "name": "Think",
      "type": "@n8n/n8n-nodes-langchain.toolThink",
      "typeVersion": 1,
      "position": [
        1180,
        620
      ]
    }
  ],
  "connections": {
    "Chat Trigger": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Window Buffer Memory": {
      "ai_memory": [
        [
          {
            "node": "AI Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Tool: get_tasks": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Tool: add_task": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Tool: complete_task": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Think": {
      "ai_tool": [
        [
          {
            "node": "AI Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [
    {
      "name": "AI Agent",
      "id": "1"
    },
    {
      "name": "Task Manager",
      "id": "2"
    },
    {
      "name": "GoIT HW5",
      "id": "3"
    }
  ]
}