AutomationFlowsAI & RAG › Automated Document Compliance Validation with AI and Vector Database

Automated Document Compliance Validation with AI and Vector Database

ByThapani Sawaengsri @mango25 on n8n.io

This workflow automates compliance validation between a policy/procedure and a corresponding uploaded document. It leverages an AI agent to determine whether the content of the document aligns with the expectations outlined in the provided procedure or policy. Document Upload A…

Webhook trigger★★★★☆ complexityAI-powered22 nodesHTTP RequestOllama EmbeddingsQdrant Vector StoreDocument Default Data LoaderText Splitter Recursive Character Text SplitterAgentOllama ChatOutput Parser Structured
AI & RAG Trigger: Webhook Nodes: 22 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #7662 — we link there as the canonical source.

This workflow follows the Agent → Documentdefaultdataloader 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
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "22c5f212-aeca-46d1-a684-41147efc6547",
      "name": "Audit Document Upload",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -464,
        -272
      ],
      "parameters": {
        "path": "creatorhub/audit-document-upload",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "lastNode"
      },
      "typeVersion": 2
    },
    {
      "id": "bf8f5941-db69-4db3-b344-183e23b010ca",
      "name": "Procedure Submission",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -464,
        288
      ],
      "parameters": {
        "path": "creatorhub/procedure-validate",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "35b34dc7-27f0-446d-b052-1bf7eb990ce2",
      "name": "Fetch Document (Microsoft Graph)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -256,
        -272
      ],
      "parameters": {
        "url": "={{$env.GRAPH_BASE_URL || \"https://graph.microsoft.com\"}}/v1.0/drives/{{$json.body.spDriveId}}/items/{{$json.body.spDocumentId}}/content",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "a9520145-7f98-4f22-a477-cb24caa599b2",
      "name": "Delete Old Document Vectors",
      "type": "@n8n/n8n-nodes-langchain.code",
      "position": [
        0,
        -272
      ],
      "parameters": {
        "code": {
          "execute": {
            "code": "const { QdrantVectorStore } = require(\"@langchain/qdrant\");\nconst { OllamaEmbeddings } = require(\"@langchain/community/embeddings/ollama\");\n\nconst OLLAMA_BASE_URL = $env.OLLAMA_BASE_URL || \"http://localhost:11434\";\nconst QDRANT_BASE_URL = $env.QDRANT_BASE_URL || \"http://localhost:6333\";\nconst QDRANT_COLLECTION = $env.QDRANT_COLLECTION || \"audit-docs\";\nconst EMBED_MODEL = $env.OLLAMA_EMBED_MODEL || \"nomic-embed-text\";\n\nconst embeddings = new OllamaEmbeddings({ model: EMBED_MODEL, baseUrl: OLLAMA_BASE_URL });\nconst vectorStore = await QdrantVectorStore.fromExistingCollection(embeddings, { url: QDRANT_BASE_URL, collectionName: QDRANT_COLLECTION });\n\nconst items = this.getInputData();\nconst fileIdToDelete = items[0].json.body.spDocumentId;\n\nconst filter = { must: [ { key: \"metadata.file_id\", match: { value: fileIdToDelete } } ] };\n\ntry {\n  if (vectorStore?.client?.delete) {\n    await vectorStore.client.delete(QDRANT_COLLECTION, { filter });\n  }\n} catch (e) {\n  // Non-fatal: continue import/index even if delete fails\n  this.logger?.warn?.(`Qdrant delete skipped/failed: ${e?.message || e}`);\n}\n\nreturn items.map(item => ({ json: { ...item.json, file_id: fileIdToDelete }, binary: item.binary }));"
          }
        },
        "inputs": {
          "input": [
            {
              "type": "main",
              "required": true
            }
          ]
        },
        "outputs": {
          "output": [
            {
              "type": "main"
            }
          ]
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": false
    },
    {
      "id": "a0be08c7-54b0-41ad-9b8a-326601c0e6b8",
      "name": "Extract PDF Text",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        416,
        -272
      ],
      "parameters": {
        "options": {},
        "operation": "pdf",
        "binaryPropertyName": "=data"
      },
      "executeOnce": true,
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "c8a629c8-80d6-484f-ade6-e3a969c1a353",
      "name": "Generate Document Embeddings",
      "type": "@n8n/n8n-nodes-langchain.embeddingsOllama",
      "position": [
        560,
        -80
      ],
      "parameters": {
        "model": "={{ $env.OLLAMA_EMBED_MODEL || \"nomic-embed-text:latest\" }}"
      },
      "credentials": {
        "ollamaApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0e2b9829-03bf-4dfb-b557-94d79f13c5d7",
      "name": "Insert Vectors into Qdrant",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant",
      "position": [
        656,
        -272
      ],
      "parameters": {
        "mode": "insert",
        "options": {},
        "qdrantCollection": {
          "__rl": true,
          "mode": "list",
          "value": "={{ $env.QDRANT_COLLECTION || \"audit-docs\" }}",
          "cachedResultName": "audit-docs"
        }
      },
      "credentials": {
        "qdrantApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "250e006a-d815-475e-a0f6-daa88c0b2a71",
      "name": "Load Document Metadata",
      "type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
      "position": [
        768,
        -96
      ],
      "parameters": {
        "options": {
          "metadata": {
            "metadataValues": [
              {
                "name": "documentId",
                "value": "={{ $('Delete Old Document Vectors').item.json.body.spDocumentId }}"
              },
              {
                "name": "documentName",
                "value": "={{ $('Delete Old Document Vectors').item.json.body.fileName }}"
              }
            ]
          }
        },
        "textSplittingMode": "custom"
      },
      "typeVersion": 1.1
    },
    {
      "id": "53151c0a-7fbe-4a35-a9a9-9d082842f05f",
      "name": "Split Text into Chunks",
      "type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter",
      "position": [
        880,
        48
      ],
      "parameters": {
        "options": {},
        "chunkOverlap": 10
      },
      "typeVersion": 1
    },
    {
      "id": "1970eb10-01aa-4108-b686-47e6fa955cf8",
      "name": "Format Procedure Payload",
      "type": "n8n-nodes-base.code",
      "position": [
        -224,
        288
      ],
      "parameters": {
        "jsCode": "const {procedures, spDocumentId, description} = $input.first().json.body;\nconst result = procedures.map(procedure => ({ json: { spDocumentId, procedure, description } }));\nreturn result;"
      },
      "typeVersion": 2
    },
    {
      "id": "a9d11ff6-6cf0-4efa-a120-b7d86ecb48fa",
      "name": "AI Compliance Validator",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        112,
        288
      ],
      "parameters": {
        "text": "=# Role\nYou are an expert internal auditor with extensive experience in compliance analysis, document review, and gap identification. Your analytical skills, attention to detail, and ability to extract relevant information from complex documents are unmatched in the industry.\n\n# Inputs\n\n**Procedure**\n{{ $json.procedure }}\n \n**spDocumentId**\n{{ $json.spDocumentId }}\n \n**description**\n{{ $json.description }}\n\n# Task\nAnalyze the provided procedure and related documents by following these steps:\n\n1. Carefully review the procedure and description text to understand all requirements and compliance standards.\n2. With the spDocumentId passed in, generate effective search queries based on key requirements in the procedure.\n3. Use these queries to retrieve relevant text from the Qdrant datastore that relates to compliance requirements.\n4. Systematically analyze the retrieved documents to:\n   - Identify sections that meet the procedure's requirements\n   - Identify gaps where requirements are not met\n   - Document specific citations for both compliant and non-compliant findings\n5. Organize your findings into a structured JSON response with clear summaries and supporting evidence.\n6. Assign an appropriate confidence level to your analysis based on the quality and relevance of the evidence found.\n\n# Specifics\n- This compliance analysis is critically important to our organization's regulatory standing, and your thorough evaluation will directly impact our business operations.\n- When generating search queries, focus on specific requirements, standards, and action items mentioned in the procedure.\n- For each compliance or non-compliance finding, provide specific text citations including page numbers or section references.\n- Your expertise in identifying subtle compliance gaps is greatly valued and will help protect our organization from potential regulatory issues.\n- If certain requirements have no corresponding evidence in the documents, clearly indicate this as a gap in the non-compliance summary.\n- Ensure your confidence level accurately reflects the strength of evidence found in the documents.\n\n# Context\nYou are conducting an internal audit for a regulated organization that must demonstrate compliance with specific procedures. The Qdrant vector datastore contains the full text of all relevant documents that need to be evaluated against the procedure requirements. Your analysis will be used by compliance officers and management to address any gaps and prepare for potential external audits. The procedure document contains the standards against which all other documents must be measured, and your task is to determine whether these standards are being met based on the evidence in the documents.\n\n# Examples\n## Example 1\nQ:\n{\n  \"output\": {\n    \"procedure\": \"Analyze financial and operational highlights, identify key issues, and develop strategic recommendations.\",\n    \"spDocumentId\": \"SP123456\",\n    \"confidenceLevel\": 40,\n    \"summaryOfCompliance\": \"The meeting transcript provided detailed insights into Apollo's financial performance and operational strategies. The summary of compliance includes a thorough analysis of sales trends, pricing adjustments, R&D projects, cost-saving measures, marketing efforts, and legal considerations.\",\n    \"summaryOfNonCompliance\": \"There are no specific non-compliances noted in the provided transcript; however, potential risks such as market research gaps, cost-cutting strategies impacting innovation, and pending litigation pose challenges that need to be addressed.\",\n    \"supportingTextCitations\": \"Based on the meeting transcript, key financial highlights include decreased sales of premium shoes, increased product prices by approximately 10%, cessation of the Phoneshoe project, labor reallocation, reduced postage and phone expenses, Superbowl commercial costs increase, and pending litigation.\"\n  }\n}\n\n## Example 2\nQ:\n[\n  {\n    \"output\": {\n      \"procedure\": \"Implement all recommendations from Charter for Corporate Responsibility in Environmental Protection (CREP) related to cement plants.\",\n      \"spDocumentId\": \"SP-DOC-00123\",\n      \"confidenceLevel\": 40,\n      \"summaryOfCompliance\": \"All commitments made during the Public Hearing on July 18, 2012, will be satisfactorily implemented. A separate budget has been allocated for this purpose and progress reports will be submitted to the Ministry's Regional Office in Bangalore.\",\n      \"summaryOfNonCompliance\": \"None were found.\",\n      \"supportingTextCitations\": \"citation on page 3\"\n    }\n  }\n]\n\n# Notes\n- Return only a structured JSON response matching the required schema.\n- If any fields would be empty, provide \"No Additional Feedback\" as the value.\n- Place special emphasis on the accuracy of citations to ensure traceability of your findings.\n- Ensure your confidence level (0-100) accurately reflects the quality and completeness of evidence found.\n- Remember that both compliance and non-compliance findings are equally important for a comprehensive audit.",
        "options": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "executeOnce": false,
      "typeVersion": 2.1
    },
    {
      "id": "d2cef8a0-0e15-4e06-9c5c-3eae0aa2fc93",
      "name": "Language Model (AI Agent)",
      "type": "@n8n/n8n-nodes-langchain.lmChatOllama",
      "position": [
        16,
        496
      ],
      "parameters": {
        "model": "={{ $env.OLLAMA_CHAT_MODEL || \"qwen2.5:7b\" }}",
        "options": {
          "numCtx": 2048
        }
      },
      "credentials": {
        "ollamaApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "26ff7b08-8fd3-4ea6-baee-ca215382cffb",
      "name": "Retrieve Relevant Document Chunks",
      "type": "@n8n/n8n-nodes-langchain.vectorStoreQdrant",
      "position": [
        192,
        496
      ],
      "parameters": {
        "mode": "retrieve-as-tool",
        "topK": 8,
        "options": {
          "searchFilterJson": "={\n  \"should\": [\n    {\n      \"key\": \"metadata.documentId\",\n      \"match\": { \"value\": \"{{ $('Format Procedure Payload').first().json.spDocumentId }}\" }\n    }\n  ]\n}"
        },
        "toolDescription": "Query document text from uploaded documents.",
        "qdrantCollection": {
          "__rl": true,
          "mode": "list",
          "value": "={{ $env.QDRANT_COLLECTION || \"audit-docs\" }}",
          "cachedResultName": "audit-docs"
        }
      },
      "credentials": {
        "qdrantApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "b5f941e6-699f-4146-9ac5-98881a6e350c",
      "name": "Generate Query Embeddings",
      "type": "@n8n/n8n-nodes-langchain.embeddingsOllama",
      "position": [
        256,
        640
      ],
      "parameters": {
        "model": "={{ $env.OLLAMA_EMBED_MODEL || \"nomic-embed-text:latest\" }}"
      },
      "credentials": {
        "ollamaApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0f05420f-46ff-4388-9ac4-1873769b27fa",
      "name": "Language Model (Structured Output)",
      "type": "@n8n/n8n-nodes-langchain.lmChatOllama",
      "position": [
        560,
        640
      ],
      "parameters": {
        "model": "={{ $env.OLLAMA_CHAT_MODEL || \"qwen2.5:7b\" }}",
        "options": {}
      },
      "credentials": {
        "ollamaApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "cc4d8ab4-4fb6-43e1-bac2-608d7cde44b9",
      "name": "Parse AI Response",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        496,
        496
      ],
      "parameters": {
        "autoFix": true,
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"required\": [\"confidenceLevel\",\"summaryOfCompliance\",\"summaryOfNonCompliance\",\"supportingTextCitations\"],\n  \"properties\": {\n    \"procedure\": {\"type\": \"string\"},\n    \"spDocumentId\": {\"type\": \"string\"},\n    \"confidenceLevel\": {\"type\": \"integer\"},\n    \"summaryOfCompliance\": {\"type\": \"string\"},\n    \"summaryOfNonCompliance\": {\"type\": \"string\"},\n    \"supportingTextCitations\": {\"type\": \"string\"}\n  }\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "d67b5769-ef38-4e94-b0eb-9052c43dd113",
      "name": "Return Compliance Report",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        608,
        288
      ],
      "parameters": {
        "options": {},
        "respondWith": "allIncomingItems"
      },
      "typeVersion": 1.4
    },
    {
      "id": "a07e2a08-6304-4abf-81b0-d2ab0ae90c5d",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -464,
        -480
      ],
      "parameters": {
        "content": "### 1. Start: Upload Document\n* Via Webhook: Audit Document Upload\n* Accepts PDF/DOCX file\n* Optionally fetches from Microsoft Graph"
      },
      "typeVersion": 1
    },
    {
      "id": "5bfb1299-0b6b-4c45-abce-f2c725c22581",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -16,
        -480
      ],
      "parameters": {
        "content": "### 2. Document Preprocessing\n* Clear Old Vectors (remove previous embeddings for same file)\n* Extract PDF Text\n* Split into chunks for embedding\n* Generate embeddings \u2192 Insert into Qdrant"
      },
      "typeVersion": 1
    },
    {
      "id": "3b49fd17-f85d-4ad4-9ad3-e8274faf9fef",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -464,
        80
      ],
      "parameters": {
        "content": "### 3. Procedure Submission\n* Webhook: Procedure Submission\n* Accepts JSON payload (procedure, description, spDocumentId)\n* Payload formatted \u2192 passed to AI"
      },
      "typeVersion": 1
    },
    {
      "id": "cb5b5349-47d3-4c01-ac2a-ea7a9b596503",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        80
      ],
      "parameters": {
        "content": "### 4. AI Compliance Validation\n* Retrieve Relevant Document Chunks from Qdrant\n* AI Compliance Validator uses LLM + embeddings\n* Output parsed & structured into JSON"
      },
      "typeVersion": 1
    },
    {
      "id": "d6b8d7c6-d14d-4625-97de-ac6fdd792156",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        576,
        80
      ],
      "parameters": {
        "content": "### 5. Return Results\n* Structured compliance report returned to webhook caller"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Extract PDF Text": {
      "main": [
        [
          {
            "node": "Insert Vectors into Qdrant",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Response": {
      "ai_outputParser": [
        [
          {
            "node": "AI Compliance Validator",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Procedure Submission": {
      "main": [
        [
          {
            "node": "Format Procedure Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Audit Document Upload": {
      "main": [
        [
          {
            "node": "Fetch Document (Microsoft Graph)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load Document Metadata": {
      "ai_document": [
        [
          {
            "node": "Insert Vectors into Qdrant",
            "type": "ai_document",
            "index": 0
          }
        ]
      ]
    },
    "Split Text into Chunks": {
      "ai_textSplitter": [
        [
          {
            "node": "Load Document Metadata",
            "type": "ai_textSplitter",
            "index": 0
          }
        ]
      ]
    },
    "AI Compliance Validator": {
      "main": [
        [
          {
            "node": "Return Compliance Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Procedure Payload": {
      "main": [
        [
          {
            "node": "AI Compliance Validator",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Query Embeddings": {
      "ai_embedding": [
        [
          {
            "node": "Retrieve Relevant Document Chunks",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Language Model (AI Agent)": {
      "ai_languageModel": [
        [
          {
            "node": "AI Compliance Validator",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Delete Old Document Vectors": {
      "main": [
        [
          {
            "node": "Extract PDF Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Document Embeddings": {
      "ai_embedding": [
        [
          {
            "node": "Insert Vectors into Qdrant",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Document (Microsoft Graph)": {
      "main": [
        [
          {
            "node": "Delete Old Document Vectors",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Retrieve Relevant Document Chunks": {
      "ai_tool": [
        [
          {
            "node": "AI Compliance Validator",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Language Model (Structured Output)": {
      "ai_languageModel": [
        [
          {
            "node": "Parse AI Response",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

This workflow automates compliance validation between a policy/procedure and a corresponding uploaded document. It leverages an AI agent to determine whether the content of the document aligns with the expectations outlined in the provided procedure or policy. Document Upload A…

Source: https://n8n.io/workflows/7662/ — 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

⚡AI-Powered YouTube Playlist & Video Summarization and Analysis v2. Uses lmChatGoogleGemini, agent, splitOut, chainLlm. Chat trigger; 72 nodes.

Google Gemini Chat, Agent, Chain Llm +11
AI & RAG

This n8n workflow transforms entire YouTube playlists or single videos into interactive knowledge bases you can chat with. Ask questions and get summaries without needing to watch hours of content. 🔗

Google Gemini Chat, Agent, Chain Llm +11
AI & RAG

HeyDinastia. Uses executeCommand, httpRequest, youTube, postgres. Webhook trigger; 66 nodes.

Execute Command, HTTP Request, YouTube +15
AI & RAG

YouTube Agent. Uses supabase, agent, lmChatAnthropic, outputParserStructured. Webhook trigger; 56 nodes.

Supabase, Agent, Anthropic Chat +10
AI & RAG

This n8n template demonstrates how to automate comprehensive web research using multiple AI models to find, analyze, and extract insights from authoritative sources.

HTTP Request, Execute Workflow Trigger, Output Parser Structured +7