Analyse des prêts à souscrire

Avancé

Ceci est unDocument Extraction, AI Summarizationworkflow d'automatisation du domainecontenant 17 nœuds.Utilise principalement des nœuds comme Code, MistralAi, ManualTrigger, SplitInBatches, Agent. Utiliser Mistral OCR et GPT pour automatiser l'analyse des documents de prêt pour les décisions d'assurance

Prérequis
  • Clé API OpenAI
Aperçu du workflow
Visualisation des connexions entre les nœuds, avec support du zoom et du déplacement
Exporter le workflow
Copiez la configuration JSON suivante dans n8n pour importer et utiliser ce workflow
{
  "id": "rVKBWXqaa79EfTVA",
  "meta": {
    "instanceId": "db1715da5f21adba44ce4ea3b08abb06cd1771e876f5ad2751fcafd78c5eb9dc",
    "templateCredsSetupCompleted": true
  },
  "name": "UnderwritingLoanAnalysis",
  "tags": [],
  "nodes": [
    {
      "id": "0d40759f-812a-4972-ba74-e42c8d5aa258",
      "name": "Rechercher un dossier",
      "type": "n8n-nodes-base.microsoftOneDrive",
      "position": [
        624,
        0
      ],
      "parameters": {
        "query": "<Your Folder Name>",
        "resource": "folder",
        "operation": "search"
      },
      "credentials": {
        "microsoftOneDriveOAuth2Api": {
          "id": "<Your One Drive API Key>",
          "name": "Microsoft Drive account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "65de0a29-5e09-41ae-b14c-e83a10eb1be5",
      "name": "Obtenir les éléments d'un dossier",
      "type": "n8n-nodes-base.microsoftOneDrive",
      "position": [
        832,
        0
      ],
      "parameters": {
        "folderId": "={{ $json.id }}",
        "resource": "folder"
      },
      "credentials": {
        "microsoftOneDriveOAuth2Api": {
          "id": "<Your One Drive API Key>",
          "name": "Microsoft Drive account"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "bdfdb814-df76-42ff-8b07-926c7e7d48c2",
      "name": "Télécharger un fichier",
      "type": "n8n-nodes-base.microsoftOneDrive",
      "position": [
        1216,
        80
      ],
      "parameters": {
        "fileId": "={{ $('Get items in a folder').item.json.id }}",
        "operation": "download"
      },
      "credentials": {
        "microsoftOneDriveOAuth2Api": {
          "id": "<Your One Drive API Key>",
          "name": "Microsoft Drive account"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "bcd0718c-df22-41e1-9754-a2298877ae43",
      "name": "Extraire le texte",
      "type": "n8n-nodes-base.mistralAi",
      "position": [
        1376,
        80
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "mistralCloudApi": {
          "id": "<Your OCR API Key>",
          "name": "Mistral Cloud account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "6eaee806-a5e6-4c5d-b89a-500bd70cc03d",
      "name": "Classer le fichier",
      "type": "n8n-nodes-base.code",
      "position": [
        1584,
        80
      ],
      "parameters": {
        "jsCode": "// get filename from Download node\nconst fileName = ($('Download a file').first().json.name || '').toLowerCase();\n\n// get extracted text from OCR node\nconst text = ($input.first().json.extractedText || '').toLowerCase();\n\nlet type = \"Unknown\";\n\n// --- Rule-based classification ---\n\n// Priority 1: File name clues\nif (fileName.includes(\"passport\")) type = \"Passport\";\nelse if (fileName.includes(\"license\") || fileName.includes(\"dl\")) type = \"Driving License\";\nelse if (fileName.includes(\"mortgage\")) type = \"Mortgage Application\";\nelse if (fileName.includes(\"proof\") && fileName.includes(\"fund\")) type = \"Proof of Funds Letter\";\nelse if (fileName.includes(\"pay\") || fileName.includes(\"paystub\")) type = \"Employee Pay Statement\";\nelse if (fileName.includes(\"t4\")) type = \"T4 Statement\";\nelse if (fileName.includes(\"electric\") || fileName.includes(\"hydro\")) type = \"Electricity Bill\";\nelse if (fileName.includes(\"internet\") || fileName.includes(\"shaw\")) type = \"Internet Bill\";\nelse if (fileName.includes(\"statement\") && fileName.includes(\"account\")) type = \"Account Statement\";\nelse if (fileName.includes(\"bank\")) type = \"Bank Statement\";\n\n// Priority 2: Text-based fallback\nelse if (text.includes(\"gross pay\") || text.includes(\"net pay\")) type = \"Employee Pay Statement\";\nelse if (text.includes(\"bank of montreal\") || text.includes(\"scotiabank\") || text.includes(\"royal bank\")) type = \"Bank Statement\";\nelse if (text.includes(\"proof of funds\")) type = \"Proof of Funds Letter\";\nelse if (text.includes(\"mortgage application\")) type = \"Mortgage Application\";\nelse if (text.includes(\"driver\") && text.includes(\"licence\")) type = \"Driving License\";\nelse if (text.includes(\"internet\") && text.includes(\"usage\")) type = \"Internet Bill\";\nelse if (text.includes(\"hydro\") || text.includes(\"electricity\")) type = \"Electricity Bill\";\nelse if (text.includes(\"t4\") && text.includes(\"income\")) type = \"T4 Statement\";\n\nreturn [{\n  json: {\n    FileName: $('Download a file').first().json.name,\n    DocumentType: type,\n    ExtractedText: $input.first().json.extractedText\n  }\n}];\n"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "15d653cd-af01-43a1-ac1d-1497774745dd",
      "name": "Combiner les données",
      "type": "n8n-nodes-base.code",
      "position": [
        1248,
        -256
      ],
      "parameters": {
        "jsCode": "// Gather all items coming from the \"Done\" output of the Loop Over Items node\nconst docs = $input.all().map(item => ({\n  FileName: item.json.FileName || null,\n  DocumentType: item.json.DocumentType || \"Unknown\",\n  ExtractedText: item.json.ExtractedText || \"\"\n}));\n\nreturn [{\n  json: {\n    BorrowerName: \"Kenneth Smith\", // replace with dynamic value if available\n    Documents: docs\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "fa0b2bc5-2038-4b94-8650-5908298c64dc",
      "name": "Agent IA",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1392,
        -256
      ],
      "parameters": {
        "text": "=You will receive an array of documents belonging to a single mortgage applicant.\n\nEach document object includes:\n- FileName  \n- DocumentType  \n- ExtractedText (the OCR text from the original file)\n\nAnalyze the full dataset, identify document types, extract key financial information, and produce an underwriting summary and decision as described in the system prompt.\n\nBorrower Documents:\n{{ JSON.stringify($json.Documents, null, 2) }}\n",
        "options": {
          "systemMessage": "=You are a senior mortgage underwriter at a Canadian financial institution.\n\nYou will analyze a borrower’s full document set to determine mortgage eligibility, loan feasibility, and documentation completeness.\n\nYour analysis must include:\n\n### 1. Identity Verification\nConfirm borrower identity, address, and citizenship using ID documents (Passport, Driver’s License, Utility Bills).\n\n### 2. Employment & Income Verification\nValidate employment details, employer name, job title, tenure, and consistency of pay across pay statements, T4s, and tax filings.\n\n### 3. Asset & Liability Review\nSummarize checking, savings, and investment balances.  \nIdentify recurring debts or monthly obligations (utilities, rent, phone, insurance, etc.).  \nCalculate Debt-to-Income (DTI) ratio.\n\n### 4. Property & Loan Analysis\nIf a mortgage application or loan-related document is present, extract:\n- Lender name and officer\n- Loan amount and term\n- Interest rate type (fixed / variable)\n- Loan purpose (purchase / refinance)\n- Down payment and percentage\n- Property value and address\n- Property type and use (primary, investment, secondary)\n- Amortization structure\n- Derived Loan-to-Value (LTV = loan amount ÷ property value)\nThen evaluate:\n- Whether the borrower’s verified assets can support the required down payment.\n- Whether DTI and LTV fall within standard underwriting thresholds.\n- Any property or loan risks (e.g., old property, low down payment, non-owner-occupied use).\n\n### 5. Document Consistency\nIdentify missing, inconsistent, or outdated documents (expired IDs, missing pay stubs, missing credit report).\n\n### 6. Decision\nProvide a professional underwriter-style decision with justification:\n- **Decision:** Approve / Approve with conditions / Decline / Escalate\n- **Rationale:** Clear bullet points explaining the reasoning.\n- **Next Steps:** Requested documents or verifications before final approval.\n\n### Output Format\nReturn your analysis as Markdown:\n\n#### Step 1: Identity Verification\n#### Step 2: Employment & Income\n#### Step 3: Assets & Liabilities\n#### Step 4: Property & Loan Analysis\n#### Step 5: Document Consistency\n#### Step 6: Final Decision\n#### Decision Summary (bullet points)\n"
        },
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "1be14652-9fa5-473b-afc8-901a0ec4ed07",
      "name": "Modèle de Chat OpenAI",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1392,
        -112
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "<Your LLM Model Name>"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "<Your LLM Model API Key>",
          "name": "OpenAi account 2"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "e5fe5cff-e538-4032-8df5-1246099618d1",
      "name": "Lors du clic sur 'Exécuter le workflow'",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        432,
        0
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "30b481ed-670c-4303-a0da-7362e94fa2d4",
      "name": "Note adhésive",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -480,
        176
      ],
      "parameters": {
        "color": 4,
        "width": 816,
        "content": "**Solution: \n\ntrigger the run, grab files from a known OneDrive folder, loop in batches, OCR each file, classify it with simple filename+text rules, aggregate into a borrower payload, then have the LLM return JSON first and a brief Markdown decision. Add filters/retries, bucket unknown/unreadable docs, log counts/costs, and keep PII out of logs.**"
      },
      "typeVersion": 1
    },
    {
      "id": "9ea5459a-21f6-4e75-830b-b4b38400f089",
      "name": "Note adhésive1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -480,
        -224
      ],
      "parameters": {
        "color": 4,
        "width": 816,
        "content": "**Problem Statement**\n\nUnderwriters receive borrower documents in mixed formats and naming conventions (IDs, paystubs, bank statements, utility bills, tax forms). Manually opening, reading, and sorting these files is slow and error-prone. Two big pain points: 1) reliably extracting text from scans, and 2) consistently identifying document types to assemble a complete borrower picture. This leads to missed docs, inconsistent decisions, weak audit trails, and high turnaround time—especially when multiple borrowers are involved."
      },
      "typeVersion": 1
    },
    {
      "id": "4d426895-0b7f-4ea1-a38f-5188801f586a",
      "name": "Note adhésive2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -480,
        -32
      ],
      "parameters": {
        "color": 4,
        "width": 816,
        "height": 176,
        "content": "***Constraints***\n\nFiles live in OneDrive folders with variable naming.\nQuality of scans varies; OCR can fail or return partial text.\nDocument classification needs to be understandable and easily adjustable.\nPII must not leak through logs or exports.\nCosts (OCR + LLM tokens) rise with folder size and page counts.\nYou need a deterministic path when AI isn’t confident (fallbacks, flags)."
      },
      "typeVersion": 1
    },
    {
      "id": "844083c1-ce99-4ab3-98b7-7a6523d88109",
      "name": "Boucler sur les éléments",
      "type": "n8n-nodes-base.splitInBatches",
      "disabled": true,
      "position": [
        1040,
        0
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "40f0d23a-aae0-4450-959e-3b98032659c2",
      "name": "Note adhésive3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        368,
        -144
      ],
      "parameters": {
        "width": 208,
        "height": 112,
        "content": "Entry trigger used for local testing and manual runs; it simply starts the pipeline and hands off to the OneDrive folder search."
      },
      "typeVersion": 1
    },
    {
      "id": "781728d1-9f06-4e95-adfc-ae2095771027",
      "name": "Note adhésive4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        624,
        -144
      ],
      "parameters": {
        "width": 320,
        "height": 112,
        "content": "Finds the target borrower documents container in OneDrive and outputs the folder id that downstream nodes use, Takes the found folder id and lists the files inside so the loop can process each item"
      },
      "typeVersion": 1
    },
    {
      "id": "8425b303-96cc-4ff9-ba20-a386a300519d",
      "name": "Note adhésive5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        992,
        288
      ],
      "parameters": {
        "width": 768,
        "height": 256,
        "content": "**Loop Over** : Drives per-file processing: for each listed file it routes to download/OCR/classify, and when the last item is done it forwards the collected results to the combiner. \n\n**Download a file (OneDrive)**: Fetches the actual file binary (plus metadata) for the current item so OCR can read its contents.\n\n**Extract text (Mistral AI)**: Runs OCR on the downloaded file and emits the extracted text that classification and later analysis depend on.\n\n**Classify the File (Code)**: Uses filename clues and OCR text to assign a document type (e.g., Passport, Paystub, Bank Statement, Utility Bill, T4, Proof of Funds, Mortgage Application, or Unknown) and forwards a compact record per file."
      },
      "typeVersion": 1
    },
    {
      "id": "f55f83eb-f7b7-4982-99c1-ec21f573793c",
      "name": "Note adhésive6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1200,
        -432
      ],
      "parameters": {
        "width": 560,
        "content": "**Combine the Data (Code)**: Aggregates all per-file records into a single borrower payload with BorrowerName and a Documents[] array ready for underwriting analysis. \n**AI Agent (@n8n/n8n-nodes-langchain.agent)**: Consumes the consolidated Documents[], applies an underwriting-oriented system prompt, and produces the decision-focused analysis for the borrower. Provides the language model (gpt-4.1-mini) that the AI Agent uses to generate the underwriting summary and decision.\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "b3d81169-9b6f-4530-b765-1ab386b90e4a",
  "connections": {
    "bcd0718c-df22-41e1-9754-a2298877ae43": {
      "main": [
        [
          {
            "node": "6eaee806-a5e6-4c5d-b89a-500bd70cc03d",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "bdfdb814-df76-42ff-8b07-926c7e7d48c2": {
      "main": [
        [
          {
            "node": "bcd0718c-df22-41e1-9754-a2298877ae43",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "844083c1-ce99-4ab3-98b7-7a6523d88109": {
      "main": [
        [
          {
            "node": "15d653cd-af01-43a1-ac1d-1497774745dd",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "bdfdb814-df76-42ff-8b07-926c7e7d48c2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "0d40759f-812a-4972-ba74-e42c8d5aa258": {
      "main": [
        [
          {
            "node": "65de0a29-5e09-41ae-b14c-e83a10eb1be5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "15d653cd-af01-43a1-ac1d-1497774745dd": {
      "main": [
        [
          {
            "node": "fa0b2bc5-2038-4b94-8650-5908298c64dc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6eaee806-a5e6-4c5d-b89a-500bd70cc03d": {
      "main": [
        [
          {
            "node": "844083c1-ce99-4ab3-98b7-7a6523d88109",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1be14652-9fa5-473b-afc8-901a0ec4ed07": {
      "ai_languageModel": [
        [
          {
            "node": "fa0b2bc5-2038-4b94-8650-5908298c64dc",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "65de0a29-5e09-41ae-b14c-e83a10eb1be5": {
      "main": [
        [
          {
            "node": "844083c1-ce99-4ab3-98b7-7a6523d88109",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e5fe5cff-e538-4032-8df5-1246099618d1": {
      "main": [
        [
          {
            "node": "0d40759f-812a-4972-ba74-e42c8d5aa258",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Foire aux questions

Comment utiliser ce workflow ?

Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.

Dans quelles scénarios ce workflow est-il adapté ?

Avancé - Extraction de documents, Résumé IA

Est-ce payant ?

Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.

Informations sur le workflow
Niveau de difficulté
Avancé
Nombre de nœuds17
Catégorie2
Types de nœuds8
Description de la difficulté

Adapté aux utilisateurs avancés, avec des workflows complexes contenant 16+ nœuds

Liens externes
Voir sur n8n.io

Partager ce workflow

Catégories

Catégories: 34