{
  "id": "hf4Yn01ENv2SmX62",
  "meta": {
    "instanceId": "8443f10082278c46aa5cf3acf8ff0f70061a2c58bce76efac814b16290845177",
    "templateCredsSetupCompleted": true
  },
  "name": "Generate Structured Summary & Q&A from Documents Automatically",
  "tags": [],
  "nodes": [
    {
      "id": "5d658a79-3f5b-478f-960c-a4b232ece3aa",
      "name": "Receive Document Upload via Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -1040,
        -16
      ],
      "webhookId": "65df1798-c390-404d-827c-be1bf6fbe411",
      "parameters": {
        "path": "65df1798-c390-404d-827c-be1bf6fbe411",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "a3ebc454-23a1-4075-9520-cdc3ec9fdaa8",
      "name": "Check If Uploaded File Is PDF",
      "type": "n8n-nodes-base.if",
      "position": [
        -736,
        -176
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cc971d34-a0e4-4825-977b-18566d0e3e35",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $binary.file.fileExtension }}",
              "rightValue": "pdf"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "297fe3c7-75ff-4ad0-ad07-7ed98b1ecc68",
      "name": "Extract Text from PDF File",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -416,
        -192
      ],
      "parameters": {
        "options": {},
        "operation": "pdf",
        "binaryPropertyName": "file"
      },
      "typeVersion": 1.1
    },
    {
      "id": "5b978677-f37c-4851-bc10-557c16eafb7d",
      "name": "Check If Uploaded File Is TXT",
      "type": "n8n-nodes-base.if",
      "position": [
        -736,
        160
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cc971d34-a0e4-4825-977b-18566d0e3e35",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $binary.file.fileExtension }}",
              "rightValue": "txt"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "44d6706f-2686-4382-90c1-3d7adcde402e",
      "name": "Extract Text from TXT File",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -432,
        144
      ],
      "parameters": {
        "options": {},
        "operation": "text",
        "binaryPropertyName": "file"
      },
      "typeVersion": 1.1
    },
    {
      "id": "7011a911-73fa-422b-8969-f724c497c5bd",
      "name": "Generate Summary & Q&A Using AI",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -16,
        -16
      ],
      "parameters": {
        "text": "=Read the following document text and generate:\n\n1. A clear summary (150–200 words)\n2. 5 important questions about the document\n3. Answers for each question\n\nDocument Text:\n{{ $json[\"text\"] }}{{ $json.data }}\n\nReturn the output STRICTLY in this JSON format (no additional text):\n\n{\n  \"summary\": \"...\",\n  \"qa\": [\n    { \"q\": \"Question 1\", \"a\": \"Answer 1\" },\n    { \"q\": \"Question 2\", \"a\": \"Answer 2\" },\n    { \"q\": \"Question 3\", \"a\": \"Answer 3\" },\n    { \"q\": \"Question 4\", \"a\": \"Answer 4\" },\n    { \"q\": \"Question 5\", \"a\": \"Answer 5\" }\n  ]\n}\n",
        "options": {
          "systemMessage": "=You are an expert AI document analyst. \nYour job is to read long documents and produce a clean summary and structured Q&A.\n\nRules:\n- Be accurate.\n- Be concise.\n- Do NOT add any content that is not inside the document.\n- Always return the result in JSON format.\n"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.1
    },
    {
      "id": "5b501e1e-2457-4433-9552-81edb9864bfe",
      "name": "Parse AI Summary and Q&A into Structured JSON",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        224,
        352
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"summary\": \"Write a 150–200 word summary here.\",\n  \"qa\": [\n    {\n      \"q\": \"Question text here\",\n      \"a\": \"Answer text here\"\n    }\n  ]\n}\n"
      },
      "typeVersion": 1.3
    },
    {
      "id": "a8fccfc3-c609-4428-a3f3-e18a3f5fe186",
      "name": "Provide LLM Engine for Document Analysis",
      "type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
      "position": [
        -144,
        352
      ],
      "parameters": {
        "model": "gpt-4o",
        "options": {}
      },
      "credentials": {
        "azureOpenAiApi": {
          "id": "credential-id",
          "name": "azureOpenAiApi Credential"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7923ca09-5890-44ae-984e-6867a76407f3",
      "name": "Store AI Memory for Document Analysis Session",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        48,
        304
      ],
      "parameters": {
        "sessionKey": "\"json_review\"",
        "sessionIdType": "customKey",
        "contextWindowLength": 7
      },
      "typeVersion": 1.3
    },
    {
      "id": "6bd1bde6-bcb6-4587-ad27-6933e1042743",
      "name": "Validate AI Output Before Processing",
      "type": "n8n-nodes-base.if",
      "position": [
        512,
        -16
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "e2adb005-2b3c-4d1e-8445-442df1fe925a",
              "operator": {
                "type": "object",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.output }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "36161fd6-81f1-4662-ad1a-2f077b8382e8",
      "name": "Log Invalid AI Output to Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        672,
        336
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "error_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "error_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "error",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "error",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "error_id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1338537721,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Uldk_4BxWbdZTDZxFUeohIfeBmGHHqVEl9Ogb0l6R8Y/edit#gid=1338537721",
          "cachedResultName": "error log sheet"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1Uldk_4BxWbdZTDZxFUeohIfeBmGHHqVEl9Ogb0l6R8Y",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Uldk_4BxWbdZTDZxFUeohIfeBmGHHqVEl9Ogb0l6R8Y/edit?usp=drivesdk",
          "cachedResultName": "Interviewer Brief Pack "
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "credential-id",
          "name": "googleSheetsOAuth2Api Credential"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "c5abdf85-b1e2-42ef-8c81-87f81bceb9b8",
      "name": "Unwrap AI Output Object",
      "type": "n8n-nodes-base.code",
      "position": [
        800,
        -16
      ],
      "parameters": {
        "jsCode": "let out = $json.output;\n\n// If array → unwrap\nif (Array.isArray(out)) {\n  out = out[0];\n}\n\nreturn out;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "f3219fd7-3506-4592-9fab-b341210f0e93",
      "name": "Prepare Final Response Payload",
      "type": "n8n-nodes-base.code",
      "position": [
        1072,
        -16
      ],
      "parameters": {
        "jsCode": "// Extract the input item\nlet item = $input.item;\n\n// If array, unwrap the first object\nif (Array.isArray(item)) {\n  item = item[0];\n}\n\n// Return the item inside an array so n8n does NOT re-wrap it\nreturn [\n  item\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "c210cce4-5337-44e7-ad71-8a2321475d71",
      "name": "Send Final Summary & Q&A Response to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1440,
        -16
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.4
    },
    {
      "id": "60aab1ba-9cc7-418b-a3f6-57bdbfd97d09",
      "name": "Send Summary Preview to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        1328,
        -352
      ],
      "webhookId": "ddaa7632-9e35-4bd3-82d6-572d5cae84cc",
      "parameters": {
        "text": "=Short Summary:\n{{ $json.summary.substring(0, 300) }}...",
        "user": {
          "__rl": true,
          "mode": "list",
          "value": "U09HMPVD466",
          "cachedResultName": "newscctv22"
        },
        "select": "user",
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "id": "credential-id",
          "name": "slackApi Credential"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "44c5b8d8-0712-4fe2-833b-89656e54acee",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2032,
        -784
      ],
      "parameters": {
        "width": 704,
        "height": 416,
        "content": "## 📄Generate Structured Summary & Q&A from Documents Automatically\nThis workflow takes uploaded documents (PDF or TXT) and automatically extracts text,\ngenerates a clean summary, produces 5 structured Q&As, validates AI output, and delivers\nthe final result back to the requester via webhook. A quick preview is also sent to Slack\nfor internal visibility.\n\nIt intelligently handles:\n• Multi-format document intake (PDF + TXT)  \n• Text extraction from uploaded binary files  \n• AI-generated document summary (150–200 words)  \n• AI-generated 5-question Q&A with accurate answers  \n• Strict JSON parsing + validation to avoid broken responses  \n• Error logging into Google Sheets for debugging  \n• Slack preview messages for rapid review  \n\nThis workflow fully automates document understanding and delivers clean, structured,\nhuman-readable insights instantly.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "6ec5c2c3-9d4a-42bf-8c0f-b80bfdea217e",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1088,
        -512
      ],
      "parameters": {
        "color": 7,
        "width": 544,
        "height": 896,
        "content": "## 📥 Document Intake & File Type Validation\nReceives uploaded documents and determines whether the file is PDF or TXT.\n\n• Receive Document Upload via Webhook  \n  Captures uploaded binary files and forwards to file-type validation.\n\n• Check If Uploaded File Is PDF  \n  Validates extension and routes PDF files for text extraction.\n\n• Check If Uploaded File Is TXT  \n  Validates extension and routes TXT files for text extraction.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "2256db54-18d5-4027-b4e8-8666c4dd7a08",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -512,
        -512
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 880,
        "content": "## 📝 File Text Extraction\nExtracts readable text from uploaded documents.\n\n• Extract Text from PDF File  \n  Converts PDF binary → plain text for AI processing.\n\n• Extract Text from TXT File  \n  Reads raw text content directly from TXT files.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "2e650cf7-e842-468d-a5c3-19ccc676d884",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -192,
        -560
      ],
      "parameters": {
        "color": 7,
        "width": 608,
        "height": 1136,
        "content": "## 🤖 AI Summary + Q&A Generation\nProduces structured JSON with summary + 5 question-answer pairs.\n\n• Provide LLM Engine for Document Analysis  \n  Supplies GPT-4o model for summarization and Q&A.\n\n• Store AI Memory for Document Analysis Session  \n  Helps the AI maintain short-term context across retries.\n\n• Generate Summary & Q&A Using AI  \n  Creates:  \n  – 150–200 word summary  \n  – 5 questions + answers  \n  Returns output in strict JSON format.\n\n• Parse AI Summary and Q&A into Structured JSON  \n  Converts the LLM output into a strongly typed JSON object.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "39f13805-6f36-4c28-ae53-3f53bbfb4a14",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        464,
        -320
      ],
      "parameters": {
        "color": 7,
        "width": 544,
        "height": 848,
        "content": "## ⚠️ AI Output Validation & Error Logging\nEnsures the AI returned valid structured JSON before sending to the user.\n\n• Validate AI Output Before Processing  \n  Confirms the \"output\" object is not empty.\n\n• Log Invalid AI Output to Google Sheet  \n  Stores malformed or empty outputs for debugging.\n\n• Unwrap AI Output Object  \n  Cleans the JSON output so downstream nodes receive a single, clean object.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "506f55cb-4b3a-4c79-8128-07ac38d10b3d",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1024,
        -624
      ],
      "parameters": {
        "color": 7,
        "width": 576,
        "height": 896,
        "content": "## 📤 Final Response Delivery & Slack Preview\nPrepares the final JSON output and sends it to the requester + Slack.\n\n• Prepare Final Response Payload  \n  Ensures response is a clean JSON object without nested arrays.\n\n• Send Final Summary & Q&A Response to Webhook  \n  Sends the formatted JSON back to the calling system.\n\n• Send Summary Preview to Slack  \n  Sends a short preview snippet (first 300 chars) to Slack for visibility.\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "45103417-92c4-4a53-a585-3090d4028ad8",
  "connections": {
    "Unwrap AI Output Object": {
      "main": [
        [
          {
            "node": "Prepare Final Response Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Text from PDF File": {
      "main": [
        [
          {
            "node": "Generate Summary & Q&A Using AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Text from TXT File": {
      "main": [
        [
          {
            "node": "Generate Summary & Q&A Using AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check If Uploaded File Is PDF": {
      "main": [
        [
          {
            "node": "Extract Text from PDF File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check If Uploaded File Is TXT": {
      "main": [
        [
          {
            "node": "Extract Text from TXT File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Final Response Payload": {
      "main": [
        [
          {
            "node": "Send Final Summary & Q&A Response to Webhook",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send Summary Preview to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Summary & Q&A Using AI": {
      "main": [
        [
          {
            "node": "Validate AI Output Before Processing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Receive Document Upload via Webhook": {
      "main": [
        [
          {
            "node": "Check If Uploaded File Is PDF",
            "type": "main",
            "index": 0
          },
          {
            "node": "Check If Uploaded File Is TXT",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate AI Output Before Processing": {
      "main": [
        [
          {
            "node": "Unwrap AI Output Object",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log Invalid AI Output to Google Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Provide LLM Engine for Document Analysis": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Summary & Q&A Using AI",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Summary and Q&A into Structured JSON": {
      "ai_outputParser": [
        [
          {
            "node": "Generate Summary & Q&A Using AI",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Store AI Memory for Document Analysis Session": {
      "ai_memory": [
        [
          {
            "node": "Generate Summary & Q&A Using AI",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    }
  }
}