AutomationFlowsAI & RAG › Auto-Create Update SOP Docs from Google Drive

Auto-Create Update SOP Docs from Google Drive

Original n8n title: Sop Document Creator & Updater

SOP Document Creator & Updater. Uses googleDriveTrigger, googleDrive, n8n-nodes-pdfvector, googleSheets. Event-driven trigger; 8 nodes.

Event trigger★★★★☆ complexity8 nodesGoogle Drive TriggerGoogle DriveN8N Nodes PdfvectorGoogle SheetsSlack
AI & RAG Trigger: Event Nodes: 8 Complexity: ★★★★☆ Added:

This workflow follows the Google Drive → Google Drive Trigger recipe pattern — see all workflows that pair these two integrations.

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": "SOP Document Creator & Updater",
  "nodes": [
    {
      "parameters": {
        "content": "## \ud83d\udccb SOP Document Processor\n\n### What this workflow does\n1. Watches Google Drive for new SOP documents\n2. Downloads and extracts SOP information\n3. Parses procedures, safety items, checkpoints\n4. Generates quick checklist from procedures\n5. Logs SOP details to Google Sheets\n6. Sends summary to Slack with checklist\n\n### Setup steps\n1. Get PDF Vector API key from pdfvector.com/api-keys\n2. Create Google Drive folder for SOP documents\n3. Create Google Sheet with columns:\n   SOP Number, Title, Version, Department, Effective Date, Author, Approver, Procedure Steps, Safety Items, Quality Checkpoints, Document Link, Last Updated\n4. Update folder ID and spreadsheet ID in nodes\n5. Connect Slack for notifications\n\n### Perfect for\n- Operations managers\n- Quality assurance teams\n- Compliance officers\n- Training departments",
        "height": 560,
        "width": 380,
        "color": 5
      },
      "id": "sticky-main",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -120,
        40
      ]
    },
    {
      "parameters": {
        "content": "## \u2705 SOP Elements Extracted\n\n- Purpose/Scope\n- Responsibilities\n- Step-by-step procedures\n- Safety warnings\n- Required equipment\n- Quality checkpoints\n- Revision history",
        "height": 220,
        "width": 220
      },
      "id": "sticky-elements",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1080,
        40
      ]
    },
    {
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "specificFolder",
        "folderToWatch": {
          "__rl": true,
          "value": "YOUR_SOP_FOLDER_ID",
          "mode": "list",
          "cachedResultName": "SOP Documents"
        },
        "event": "fileCreated",
        "options": {}
      },
      "id": "gdrive-trigger",
      "name": "New SOP Document",
      "type": "n8n-nodes-base.googleDriveTrigger",
      "typeVersion": 1,
      "position": [
        300,
        300
      ]
    },
    {
      "parameters": {
        "operation": "download",
        "fileId": {
          "__rl": true,
          "value": "={{ $json.id }}",
          "mode": "id"
        },
        "options": {}
      },
      "id": "gdrive-download",
      "name": "Download SOP",
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        500,
        300
      ]
    },
    {
      "parameters": {
        "operation": "extract",
        "inputType": "file",
        "prompt": "Extract SOP (Standard Operating Procedure) as flat fields. title, sopNumber, version, effectiveDate (YYYY-MM-DD), author, approver, department, purpose, scope, responsibilitiesList (semicolon-separated formatted as: role: duties), equipmentList (semicolon-separated required equipment/materials), safetyPrecautionsList (semicolon-separated safety warnings), proceduresList (semicolon-separated steps formatted as: stepNumber. action - details), qualityCheckpointsList (semicolon-separated formatted as: checkpoint: criteria), revisionHistory (semicolon-separated formatted as: version date changes), procedureCount (number), safetyCount (number), checkpointCount (number).",
        "schema": "{\"type\": \"object\", \"properties\": {\"title\": {\"type\": \"string\"}, \"sopNumber\": {\"type\": \"string\"}, \"version\": {\"type\": \"string\"}, \"effectiveDate\": {\"type\": \"string\"}, \"author\": {\"type\": \"string\"}, \"approver\": {\"type\": \"string\"}, \"department\": {\"type\": \"string\"}, \"purpose\": {\"type\": \"string\"}, \"scope\": {\"type\": \"string\"}, \"responsibilitiesList\": {\"type\": \"string\"}, \"equipmentList\": {\"type\": \"string\"}, \"safetyPrecautionsList\": {\"type\": \"string\"}, \"proceduresList\": {\"type\": \"string\"}, \"qualityCheckpointsList\": {\"type\": \"string\"}, \"revisionHistory\": {\"type\": \"string\"}, \"procedureCount\": {\"type\": \"number\"}, \"safetyCount\": {\"type\": \"number\"}, \"checkpointCount\": {\"type\": \"number\"}}, \"additionalProperties\": false}"
      },
      "id": "pdfvector-extract",
      "name": "PDF Vector Extract",
      "type": "n8n-nodes-pdfvector.pdfVector",
      "typeVersion": 2,
      "position": [
        700,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "const data = ($input.first().json?.data || $input.first().json) || {};\nconst fileName = $('New SOP Document').item.json.name;\nconst fileId   = $('New SOP Document').item.json.id;\n\nconst procedures = (data.proceduresList || '').split(';').filter(p => p.trim());\nconst safety     = (data.safetyPrecautionsList || '').split(';').filter(s => s.trim());\nconst checkpoints= (data.qualityCheckpointsList || '').split(';').filter(c => c.trim());\n\nconst checklistItems = procedures.map(p => `\u2610 ${p.trim()}`).join('\\n') || 'No procedures found';\nconst safetyList     = safety.map(s => `\u26a0\ufe0f ${s.trim()}`).join('\\n')     || 'None specified';\nconst checkpointList = checkpoints.map(c => `\u2713 ${c.trim()}`).join('\\n') || 'None specified';\n\nreturn [{ json: {\n  title:           data.title          || 'Untitled SOP',\n  sopNumber:       data.sopNumber      || 'N/A',\n  version:         data.version        || '1.0',\n  effectiveDate:   data.effectiveDate  || 'N/A',\n  author:          data.author         || 'N/A',\n  approver:        data.approver       || 'N/A',\n  department:      data.department     || 'N/A',\n  purpose:         data.purpose        || 'N/A',\n  scope:           data.scope          || 'N/A',\n  checklistItems, safetyList, checkpointList,\n  procedureCount:  parseInt(data.procedureCount)  || procedures.length,\n  safetyCount:     parseInt(data.safetyCount)     || safety.length,\n  checkpointCount: parseInt(data.checkpointCount) || checkpoints.length,\n  fileName, fileId,\n  processedAt: new Date().toISOString()\n}}];"
      },
      "id": "process-sop",
      "name": "Process SOP",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        900,
        300
      ]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "list",
          "cachedResultName": "SOP Library"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "SOPs"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "SOP Number": "={{ $json.sopNumber }}",
            "Title": "={{ $json.title }}",
            "Version": "={{ $json.version }}",
            "Department": "={{ $json.department }}",
            "Effective Date": "={{ $json.effectiveDate }}",
            "Author": "={{ $json.author }}",
            "Approver": "={{ $json.approver }}",
            "Procedure Steps": "={{ $json.procedureCount }}",
            "Safety Items": "={{ $json.safetyCount }}",
            "Quality Checkpoints": "={{ $json.checkpointCount }}",
            "Document Link": "=https://drive.google.com/file/d/{{ $json.fileId }}/view",
            "Last Updated": "={{ $json.processedAt.split('T')[0] }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "SOP Number",
              "displayName": "SOP Number",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Title",
              "displayName": "Title",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Version",
              "displayName": "Version",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Department",
              "displayName": "Department",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Effective Date",
              "displayName": "Effective Date",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Author",
              "displayName": "Author",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Approver",
              "displayName": "Approver",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Procedure Steps",
              "displayName": "Procedure Steps",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Safety Items",
              "displayName": "Safety Items",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Quality Checkpoints",
              "displayName": "Quality Checkpoints",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Document Link",
              "displayName": "Document Link",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Last Updated",
              "displayName": "Last Updated",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ]
        },
        "options": {}
      },
      "id": "sheets-log",
      "name": "Log to SOP Library",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        1100,
        300
      ]
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": {
          "__rl": true,
          "value": "YOUR_SLACK_CHANNEL_ID",
          "mode": "list",
          "cachedResultName": "ops-team"
        },
        "text": "=\ud83d\udccb *SOP Document Processed*\n\n*Title:* {{ $('Process SOP').item.json.title }}\n*SOP #:* {{ $('Process SOP').item.json.sopNumber }}\n*Version:* {{ $('Process SOP').item.json.version }}\n*Department:* {{ $('Process SOP').item.json.department }}\n\n\ud83d\udcca *Summary:*\n\u2022 Procedure Steps: {{ $('Process SOP').item.json.procedureCount }}\n\u2022 Safety Items: {{ $('Process SOP').item.json.safetyCount }}\n\u2022 Quality Checkpoints: {{ $('Process SOP').item.json.checkpointCount }}\n\n\ud83d\udcdd *Quick Checklist:*\n{{ $('Process SOP').item.json.checklistItems }}\n\n\ud83d\udd17 <https://drive.google.com/file/d/{{ $('Process SOP').item.json.fileId }}/view|View Full SOP>",
        "options": {}
      },
      "id": "slack-notify",
      "name": "Send to Slack",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [
        1300,
        300
      ]
    }
  ],
  "connections": {
    "New SOP Document": {
      "main": [
        [
          {
            "node": "Download SOP",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download SOP": {
      "main": [
        [
          {
            "node": "PDF Vector Extract",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "PDF Vector Extract": {
      "main": [
        [
          {
            "node": "Process SOP",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process SOP": {
      "main": [
        [
          {
            "node": "Log to SOP Library",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log to SOP Library": {
      "main": [
        [
          {
            "node": "Send to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": []
}
Pro

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

About this workflow

SOP Document Creator & Updater. Uses googleDriveTrigger, googleDrive, n8n-nodes-pdfvector, googleSheets. Event-driven trigger; 8 nodes.

Source: https://github.com/khanhduyvt0101/workflows/blob/0153ee2efc0f692c931b9bb4c2a04abf11756822/n8n-workflows/sop-document-processor.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

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

AI & RAG

Lease Agreement Analyzer for Renters. Uses googleDriveTrigger, googleDrive, n8n-nodes-pdfvector, googleSheets. Event-driven trigger; 12 nodes.

Google Drive Trigger, Google Drive, N8N Nodes Pdfvector +2
AI & RAG

Expense Report Processor with AI Categorization. Uses googleDriveTrigger, googleDrive, n8n-nodes-pdfvector, googleSheets. Event-driven trigger; 12 nodes.

Google Drive Trigger, Google Drive, N8N Nodes Pdfvector +2
AI & RAG

Financial Report Analyzer (10-K, 10-Q). Uses googleDriveTrigger, googleDrive, n8n-nodes-pdfvector, googleSheets. Event-driven trigger; 11 nodes.

Google Drive Trigger, Google Drive, N8N Nodes Pdfvector +2
AI & RAG

AI Contract Review & Risk Analysis. Uses googleDriveTrigger, googleDrive, n8n-nodes-pdfvector, googleSheets. Event-driven trigger; 10 nodes.

Google Drive Trigger, Google Drive, N8N Nodes Pdfvector +2
AI & RAG

Patient Intake Form Processor for Healthcare. Uses googleDriveTrigger, googleDrive, n8n-nodes-pdfvector, googleSheets. Event-driven trigger; 10 nodes.

Google Drive Trigger, Google Drive, N8N Nodes Pdfvector +2