Automatisation de la diligence raisonnable sur les fournisseurs avec Gemini et Jina AI
Ceci est unDocument Extraction, AI Summarizationworkflow d'automatisation du domainecontenant 27 nœuds.Utilise principalement des nœuds comme If, Set, Code, Form, Wait. Automatiser l'enquête de diligence raisonnable des fournisseurs avec Gemini et Jina AI
- •Peut nécessiter les informations d'identification d'authentification de l'API cible
- •Informations d'identification Google Sheets API
- •Clé API Google Gemini
Nœuds utilisés (27)
Catégorie
{
"meta": {
"instanceId": "558d88703fb65b2d0e44613bc35916258b0f0bf983c5d4730c00c424b77ca36a",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "0d639cb7-a8f0-4242-b209-e688ce8347d5",
"name": "Note adhésive1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-120,
-3740
],
"parameters": {
"color": 5,
"width": 480,
"height": 260,
"content": "## | Step 2: Vendor Risk Research"
},
"typeVersion": 1
},
{
"id": "777a4b84-b328-4c01-b43a-bef29b1ef8e8",
"name": "Note adhésive",
"type": "n8n-nodes-base.stickyNote",
"position": [
-740,
-3740
],
"parameters": {
"color": 3,
"width": 580,
"height": 260,
"content": "## | Step 1: Vendor Background & Classification"
},
"typeVersion": 1
},
{
"id": "a267e7b6-9ddb-454b-aba0-15c8828fd46b",
"name": "Analyseur de sortie structurée",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
1240,
-3460
],
"parameters": {
"jsonSchemaExample": "{\n\t\"url\": \"the url\",\n \"page_title\": \"title of the page\",\n\t\"topic\": \"one line summary of the page text\",\n \"summary\": \"150 word page summary or 'invalid data' if the content is not related to legal or cybersecurity\"\n}"
},
"typeVersion": 1.3
},
{
"id": "594d0c74-1ae2-4831-8c39-cc39e90312d9",
"name": "Note adhésive2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1320,
-3740
],
"parameters": {
"width": 540,
"height": 260,
"content": "## | INPUT: Intake Form"
},
"typeVersion": 1
},
{
"id": "725b0646-af7b-4aae-9fd5-4494af2b5a72",
"name": "Note adhésive3",
"type": "n8n-nodes-base.stickyNote",
"position": [
400,
-3740
],
"parameters": {
"color": 4,
"width": 980,
"height": 800,
"content": "## | Step 3: Vendor Linls Review & Summary\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## 🚀 Setup Requirements\n\nTo get started with this workflow, follow these steps:\n\n1. **🔑 Configure Credentials**: Set up your API credentials for Gemini and Jina AI\n2. **📊 Connect Google Sheets**: Authenticate your Google Sheets account\n3. Download the Google Sheet template for outputs from here: https://docs.google.com/spreadsheets/d/1PCpZ9wMPFvm4vubiPBqw021Lz8JiHUnr-EWl1cdIKYY/edit?usp=sharing \n4. **⚙️ (Optional) Customize Prompts**: Adjust the prompts within the workflow to better suit your specific needs\n5. **🎯 (Optional) Align Risk Framework**: Modify the risk questions to align with your organization's internal vendor risk framework\n\n**Important Note:** The accuracy and detail of the final risk assessment report are directly influenced by the quality of the information provided in the initial intake form."
},
"typeVersion": 1
},
{
"id": "29f06597-5afa-4b89-a45a-4afe1c911f02",
"name": "Répondre aux questions de risque",
"type": "n8n-nodes-base.httpRequest",
"position": [
180,
-3660
],
"parameters": {
"url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent",
"method": "POST",
"options": {},
"jsonBody": "={\n \"system_instruction\": {\n \"parts\": [\n {\n \"text\": {{ $('Build Research Prompts').item.json.system_prompt.toJsonString() }}\n }\n ]\n },\n \"contents\": [\n {\n \"parts\": [\n {\n \"text\": {{ $('Build Research Prompts').item.json.all_q.toJsonString() }}\n }\n ]\n }\n ],\n \"tools\": [\n {\n \"google_search\": {}\n }\n ]\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googlePalmApi"
},
"credentials": {
"googlePalmApi": {
"id": "8ugdViiQrStHA45M",
"name": "Google Gemini(PaLM) Api account CB"
}
},
"retryOnFail": true,
"typeVersion": 4.2
},
{
"id": "e3f6ac89-fda7-4f0c-a073-ee8c7578e041",
"name": "Formulaire de prise de contact",
"type": "n8n-nodes-base.formTrigger",
"position": [
-1240,
-3660
],
"webhookId": "37edf358-a260-4c7b-9021-8d4bd1aa6a09",
"parameters": {
"options": {
"respondWithOptions": {
"values": {
"formSubmittedText": "The vendor assessment will be added to the vendor's sheet once completed."
}
}
},
"formTitle": "Vendor Intake Form",
"formFields": {
"values": [
{
"fieldLabel": "What is the vendor's company name?",
"placeholder": "Linkedin",
"requiredField": true
},
{
"fieldLabel": "In which domain does the vendor operate?",
"placeholder": "FinTech"
},
{
"fieldLabel": "What service will the vendor provide for your organization?",
"placeholder": "Cloud based CRM",
"requiredField": true
},
{
"fieldLabel": "What type of data will the vendor process or store?",
"placeholder": "confidential company data, employees pii",
"requiredField": true
}
]
},
"formDescription": "Please fill in the vendor details and the business use case as accurately as possible to determine the risk level."
},
"typeVersion": 2.2
},
{
"id": "22421d1c-4436-4de5-85da-57c7d7f94f9b",
"name": "Délai1 : 1 seconde",
"type": "n8n-nodes-base.wait",
"position": [
-520,
-3660
],
"webhookId": "e09ddeee-8d1e-4748-bf98-0108069ec37f",
"parameters": {
"amount": 1
},
"typeVersion": 1.1
},
{
"id": "df5a13bc-e717-4bb1-9cc5-eadc9ad5f42f",
"name": "Délai2 : 1 seconde",
"type": "n8n-nodes-base.wait",
"position": [
-40,
-3660
],
"webhookId": "7dbd2515-20c9-4af5-adf0-1eebf0fc90fb",
"parameters": {
"amount": 1
},
"typeVersion": 1.1
},
{
"id": "25ace280-8fe4-405c-a547-ca36d4baf886",
"name": "Note adhésive4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1320,
-3420
],
"parameters": {
"color": 5,
"width": 960,
"height": 480,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## | Step 4: Vendor Risk Assessment"
},
"typeVersion": 1
},
{
"id": "690c94ee-3ab2-48be-a913-8f72168cc801",
"name": "Note adhésive5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-320,
-3420
],
"parameters": {
"color": 6,
"width": 680,
"height": 480,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## | Step 5 - Export Results"
},
"typeVersion": 1
},
{
"id": "fc9c0965-1012-4e7d-b682-bae874c3ee27",
"name": "Construire les invites de recherche",
"type": "n8n-nodes-base.set",
"position": [
-980,
-3660
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "ad076d87-748a-4c12-8f6b-dcb404b69756",
"name": "system_prompt",
"type": "string",
"value": "=You are an AI research analyst conducting due diligence on SaaS companies. Your role is to deliver precise, evidence-based answers using grounded information from recent and reliable sources on the public internet, including company websites, security reports, regulatory filings, press coverage, customer reviews, and trust portals.\n\nSupport informed decision-making by producing concise, actionable due diligence insights on {{ $json[\"What is the vendor's company name?\"] }} (Domain: {{ $json[\"In which domain does the vendor operate?\"] }}), focusing on security, compliance, AI risks, financial health, and trustworthiness.\n- Business use case: {{ $json[\"What service will the vendor provide for your organization?\"] }}\n- Data exposure: {{ $json[\"What type of data will the vendor process or store?\"] }}\n\nGuidelines:\n- Use real-time internet search to support your response. Prioritize sources from the last 3–5 years.\n- All answers must be specific, factual, and verifiable. Do not speculate or generalize.\n- If no reliable information is available, clearly state that (e.g., “No official SOC 2 audit found. You may request it directly from the vendor or check their trust center.”)\n- Do not hallucinate. Maintain an objective, professional, and analytical tone.\n- Write in plain text, as a single paragraph with no new line characters.\n- Structure responses professionally for inclusion in a business due diligence report.\n\nOutput Format:\n1. risk: One of critical, high, medium, or low\n2. rationale: A single-paragraph explanation based on your research\n\nRESEARCH\n"
},
{
"id": "3dbb5603-90dd-4eca-9a1e-39c64d0d9d72",
"name": "risk_classifier",
"type": "string",
"value": "=You are an expert Information Security Risk Analyst. Your task is to review vendor details and assign a risk tier classification based on the definitions below and relevant research findings.\n\nVendor Details:\n- Application or Service: {{ $json[\"What is the vendor's company name?\"] }}\n- Company Domain: {{ $json[\"In which domain does the vendor operate?\"] }}\n- Business Use Case: {{ $json[\"What service will the vendor provide for your organization?\"] }}, with access to {{ $json[\"What type of data will the vendor process or store?\"] }}\n\nRisk Tier Definitions:\n\n🟥 Critical Risk\n- Vendor plays a foundational role in operational infrastructure of production environment\n- May have full or privileged access to production environments or sensitive systems\n- Their unavailability could cause significant disruption to business operations or service delivery\n\n🟧 High Risk\n- Vendor provides infrastructure of corporate environment\n- Vendor has access to sensitive or confidential data (e.g., customer PII, financial records, source code)\n- May integrate with mission-critical systems or support core business processes\n\n🟨 Medium Risk\n- Vendor has limited access to sensitive data\n- Supports key functions within a department or team\n- May include end-user applications with potential exposure over the Internet\n\n🟩 Low Risk\n- Vendor does not access sensitive or confidential data\n- Provides standalone tools or services with minimal business impact\n- Typically limited to individual user workstations or internal utilities\n\nInstructions:\n- Classify the vendor into one of the four risk tiers: critical, high, medium, or low\n- Your classification must be grounded in verifiable research and based on how the vendor interacts with your business environment\n- Provide your response as a plain text paragraph (no new lines) in a professional, neutral tone suitable for an InfoSec report\n\nOutput Format:\n1. risk: One of critical, high, medium, low\n2. rationale: A single-paragraph explanation based on research and the tier definitions above\n\nVENDOR DETAILS\n"
},
{
"id": "62c6e6fb-e258-4f1c-88bd-ba852adcdd7b",
"name": "background_q",
"type": "string",
"value": "- What is the legal name, founding year, and headquarters of the company?\n- What SaaS products does the company offer, and who are its target customers?\n- Who are the key executives at the company (e.g., CEO, CTO, CISO)?\n- How many employees does the company have, and where are their offices located?\n- Who are the company’s primary competitors and what is its market position?\n- Has the company made any significant acquisitions or strategic changes in the past 3 years?"
},
{
"id": "98251647-59a3-49c7-98b6-bd233d68195c",
"name": "all_q",
"type": "string",
"value": "=Financial Risk\n- What are the recent revenue trends and funding history of the company?\n- Who are the key investors or majority shareholders of the company?\n- Does the company carry significant debt, or face any financial risk indicators?\n- Has the company been involved in any lawsuits, bankruptcies, or financial scandals?\n\nCybersecurity Risk\n- What security certifications does the company hold (e.g., SOC 2, ISO 27001, NIST)?\n- What are the company’s data encryption and access control practices?\n- Has the company experienced any cybersecurity incidents or breaches in the past 5 years?\n- Does the company maintain a public trust center or transparency report?\n- What are the vendor's trust center, privacy policy, or security compliance related links?\n\nLegal Risk\n- Which data privacy or industry-specific regulations apply to the company (e.g., GDPR, HIPAA, CCPA)?\n- Does the company undergo third-party audits or assessments for regulatory compliance?\n- Has the company faced any legal actions, regulatory fines, or compliance violations?\n\nSLA Risk\n- What uptime SLA does the company offer, and has it had major outages in the last 3 years?\n- What do customers report about the company’s support response times and reliability?\n- Does the company include penalty clauses or credits in its SLA for service failures?\n\nBCP Risk\n- Does the company have a documented business continuity and disaster recovery plan?\n- How does the company handle major service disruptions like cyberattacks or cloud outages?\n- Who are the company’s key third-party dependencies, and how are vendor risks managed?\n- What data export or service exit options does the company provide to customers?\n\nAI Risk\n- How does the company use AI in its products or internal operations?\n- What frameworks or providers does the company rely on for AI (e.g., OpenAI, AWS SageMaker)?\n- How does the company mitigate AI security risks such as model poisoning or adversarial attacks?\n- Does the company publish documentation or disclosures on AI model transparency and fairness?\n- Does the company comply with AI-related regulations (e.g., EU AI Act, NIST AI RMF)?\n- Has the company been involved in any controversies regarding AI ethics, bias, or misuse?\n- Does the company maintain governance policies for responsible AI development and deployment?\n\nReputation Risk\n- What are common customer reviews and ratings of the company on G2, Trustpilot, and Capterra?\n- Are there any recurring complaints or concerns about the company from users?\n- Has the company faced any major PR incidents, social media backlash, or reputational damage?"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "8e210a6c-120b-4912-a164-db4a9a6ec4e4",
"name": "Rechercher le contexte de l'entreprise",
"type": "n8n-nodes-base.httpRequest",
"position": [
-700,
-3660
],
"parameters": {
"url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent",
"method": "POST",
"options": {},
"jsonBody": "={\n \"system_instruction\": {\n \"parts\": [\n {\n \"text\": {{ $json.system_prompt.toJsonString() }}\n }\n ]\n },\n \"contents\": [\n {\n \"parts\": [\n { \"text\" : {{ $json.background_q.toJsonString() }}\n } \n]\n }\n ],\n \"tools\": [\n {\n \"google_search\": {}\n }\n ]\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googlePalmApi"
},
"credentials": {
"googlePalmApi": {
"id": "8ugdViiQrStHA45M",
"name": "Google Gemini(PaLM) Api account CB"
}
},
"retryOnFail": true,
"typeVersion": 4.2
},
{
"id": "aafd0eb9-5a1c-4261-9831-3950eda71cbd",
"name": "Gemini - Évaluation des risques",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
-560,
-3120
],
"parameters": {
"options": {},
"modelName": "models/gemini-2.5-flash-preview-04-17-thinking"
},
"credentials": {
"googlePalmApi": {
"id": "8ugdViiQrStHA45M",
"name": "Google Gemini(PaLM) Api account CB"
}
},
"typeVersion": 1
},
{
"id": "9c70972b-958e-435d-b2a6-97394131b907",
"name": "Gemini - Résumeur de liens",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
1040,
-3460
],
"parameters": {
"options": {},
"modelName": "models/gemini-2.5-flash-preview-05-20"
},
"credentials": {
"googlePalmApi": {
"id": "8ugdViiQrStHA45M",
"name": "Google Gemini(PaLM) Api account CB"
}
},
"typeVersion": 1
},
{
"id": "e7eefa82-940f-4603-91b6-d013ed4dbe5b",
"name": "Extraire les URL de référence",
"type": "n8n-nodes-base.code",
"position": [
480,
-3660
],
"parameters": {
"language": "python",
"pythonCode": "import re\nimport json\n\ndef extract_urls_from_nested_json(data):\n \"\"\"Recursively extract text from nested JSON structure\"\"\"\n urls = []\n \n def extract_text_recursive(obj):\n if isinstance(obj, dict):\n for key, value in obj.items():\n if key == 'text' and isinstance(value, str):\n return value\n elif isinstance(value, (dict, list)):\n result = extract_text_recursive(value)\n if result:\n return result\n elif isinstance(obj, list):\n for item in obj:\n result = extract_text_recursive(item)\n if result:\n return result\n return None\n \n return extract_text_recursive(data)\n\n# Get input from previous node\ninput_data = items[0]['json']\n\n# Try multiple paths to extract text\ntext_to_search = \"\"\npossible_paths = [\n # Primary path\n lambda x: x.get(\"candidates\", [{}])[0].get(\"content\", {}).get(\"parts\", [{}])[0].get(\"text\", \"\"),\n # Alternative paths\n lambda x: x.get(\"text\", \"\"),\n lambda x: x.get(\"content\", \"\"),\n # Recursive search\n lambda x: extract_urls_from_nested_json(x)\n]\n\nfor path_func in possible_paths:\n try:\n result = path_func(input_data)\n if result and isinstance(result, str) and len(result.strip()) > 0:\n text_to_search = result\n break\n except (KeyError, TypeError, IndexError, AttributeError):\n continue\n\n# Enhanced URL regex patterns\nurl_patterns = [\n # Standard HTTP/HTTPS URLs\n r'https?://[^\\s<>\"{}|\\\\^`\\[\\]]+',\n # URLs without protocol\n r'(?:www\\.)?[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\\.[a-zA-Z]{2,}(?:/[^\\s<>\"{}|\\\\^`\\[\\]]*)?',\n # Domain-only patterns\n r'[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\\.[a-zA-Z]{2,}(?:/[^\\s<>\"{}|\\\\^`\\[\\]]*)?'\n]\n\nall_urls = []\nfor pattern in url_patterns:\n urls = re.findall(pattern, text_to_search, re.IGNORECASE)\n all_urls.extend(urls)\n\n# Remove duplicates and filter valid URLs\nunique_urls = []\nseen = set()\nfor url in all_urls:\n # Clean up URL\n url = url.strip().rstrip('.,;:!?)')\n \n # Skip if already seen\n if url in seen:\n continue\n seen.add(url)\n \n # Add protocol if missing\n if not url.startswith(('http://', 'https://')):\n # Check if it looks like a valid domain\n if '.' in url and not url.startswith('www.'):\n url = 'https://' + url\n elif url.startswith('www.'):\n url = 'https://' + url\n else:\n continue\n \n # Basic validation\n if len(url) > 10 and '.' in url:\n unique_urls.append(url)\n\n# Log extraction results\nprint(f\"Extracted text length: {len(text_to_search)}\")\nprint(f\"Found {len(unique_urls)} unique URLs\")\n\n# Return results\nif unique_urls:\n # Return each URL as a separate item for iteration\n return [{'json': {'url': url, 'extraction_success': True}} for url in unique_urls]\nelse:\n # Return a single item indicating no URLs found\n return [{'json': {'url': '', 'extraction_success': False, 'message': 'No URLs found in text'}}]"
},
"executeOnce": false,
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "737c24ce-0618-41ac-bf8f-f9e96581631a",
"name": "Récupérer le contenu web",
"type": "n8n-nodes-base.jinaAi",
"onError": "continueRegularOutput",
"position": [
880,
-3680
],
"parameters": {
"url": "={{ $json.url }}",
"options": {},
"requestOptions": {
"batching": {
"batch": {
"batchSize": 1
}
}
}
},
"credentials": {
"jinaAiApi": {
"id": "pjDC9JmP3DK7s0xt",
"name": "Jina AI account"
}
},
"retryOnFail": true,
"typeVersion": 1,
"waitBetweenTries": 5000
},
{
"id": "a7482557-743c-4779-8e7e-bc58c57bf1d4",
"name": "Résumer le contenu web",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1040,
-3680
],
"parameters": {
"text": "=You are performing vendor due diligence. Analyze the following page content to determine whether it provides relevant information for evaluating the vendor's legal structure, cybersecurity practices, data handling, compliance, or corporate governance.\n\nInstructions:\n- If the content is unrelated (e.g., broken link, marketing fluff, product promotion, irrelevant blog, or non-cyber/legal topic), return `\"invalid data\"` in the `summary` field.\n- If the content is relevant, return a JSON object with:\n - `url`: the source URL\n - `page_title`: the title of the page\n - `topic`: a one-line summary of what the page is about\n - `summary`: a neutral, professional, ~150-word summary of the content for inclusion in a vendor due diligence report\n\nOutput only valid JSON. Do not include explanations or extra text.\n\nInput:\nPage title: {{ $json.title }}\nPage description: {{ $json.description }}\nPage URL: {{ $json.url }}\nPage content:\n{{ $json.content }}\n",
"options": {
"batching": {
"batchSize": 1,
"delayBetweenBatches": 1
}
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 2
},
{
"id": "fb637cbe-1d9f-4212-ac36-dd84d9b32975",
"name": "Valider l'extraction d'URL",
"type": "n8n-nodes-base.if",
"position": [
660,
-3660
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "ecde2c4c-c2b8-4584-a966-710f7e0a7989",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.url && $json.url.length > 0 }}",
"rightValue": ""
}
]
},
"looseTypeValidation": true
},
"typeVersion": 2.2
},
{
"id": "611a9e07-427e-4174-9397-32f4b70f3f66",
"name": "Déterminer la classification du fournisseur",
"type": "n8n-nodes-base.httpRequest",
"position": [
-300,
-3660
],
"parameters": {
"url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent",
"method": "POST",
"options": {},
"jsonBody": "={\n \"system_instruction\": {\n \"parts\": [\n {\n \"text\": {{ $('Build Research Prompts').item.json.risk_classifier.toJsonString() }}\n }\n ]\n },\n \"contents\": [\n {\n \"parts\": [\n {\n \"text\": {{ $('Research Company Background').item.json.candidates[0].content.parts[0].text.toJsonString() }}\n }\n ]\n }\n ],\n \"tools\": [\n {\n \"google_search\": {}\n }\n ]\n}",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googlePalmApi"
},
"credentials": {
"googlePalmApi": {
"id": "8ugdViiQrStHA45M",
"name": "Google Gemini(PaLM) Api account CB"
}
},
"retryOnFail": true,
"typeVersion": 4.2
},
{
"id": "574056af-a3e1-4773-9269-70ca49d8aa34",
"name": "Calculer le score de risque",
"type": "@n8n/n8n-nodes-langchain.informationExtractor",
"position": [
-660,
-3340
],
"parameters": {
"text": "=You are an expert Information Security Risk Analyst specializing in third-party vendor due diligence.\n\n## OBJECTIVE\nAnalyze the research data below to assess and classify the vendor’s risk across multiple categories. Your tasks are:\n\n1. Summarize the vendor’s risk posture in each category (financial, cybersecurity, regulatory, SLA, BCP, AI, reputation).\n2. Assign a risk level (low, medium, high) to each category and provide a clear, evidence-based rationale.\n3. Determine the overall vendor risk level (low, medium, high, critical).\n4. Provide a concise overall summary and relevant recommendations:\n - Only give recommendations for vendors classified as **critical** and **high**.\n - For **medium-risk vendors**, only recommend: *Collect vendor compliance documentation annually.*\n - Use `-` bullets for recommendations.\n5. Include relevant URLs from the research only if they support your summary.\n6. Format all text responses in **Markdown** for readability (use `###` for headings, `-` for bullets, emojis like 🔐📉⚠️ for clarity, but no extra whitespace).\n\n## OUTPUT FORMAT\nReturn your response as a **valid JSON object** matching the schema provided below. Do not add any explanations or non-JSON content.\n\n---\n\n## INPUTS\n\n### 🔍 Company Background \n{{ $('Research Company Background').item.json.candidates[0].content.parts[0].text }}\n\n### 🧾 Business Use Case \n- Service: {{ $('Intake form').item.json['What service will the vendor provide for your organization?'] }} \n- Data Access: {{ $('Intake form').item.json['What type of data will the vendor process or store?'] }}\n\n### 🏷️ Vendor Classification \n{{ $('Determine Vendor Classification').item.json.candidates[0].content.parts[0].text }}\n\n### 🔎 Risk Research \n{{ $('Answer risk questions').item.json.candidates[0].content.parts[0].text }}\n\n### 🔗 Vendor URLs \n{{ $json.data.toJsonString() }}",
"options": {},
"schemaType": "manual",
"inputSchema": "{\n \"type\": \"object\",\n \"properties\": {\n \"vendor\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": { \"type\": \"string\" },\n \"business_use_case\": { \"type\": \"string\" },\n \"classification\": { \"type\": \"string\", \"enum\": [\"low\", \"medium\", \"high\", \"critical\"] }\n }\n },\n \"financial_risk\": {\n \"type\": \"object\",\n \"properties\": {\n \"summary\": { \"type\": \"string\" },\n \"risk_level\": { \"type\": \"string\", \"enum\": [\"low\", \"medium\", \"high\"] },\n \"risk_rationale\": { \"type\": \"string\" }\n }\n },\n \"cybersecurity_risk\": {\n \"type\": \"object\",\n \"properties\": {\n \"summary\": { \"type\": \"string\" },\n \"risk_level\": { \"type\": \"string\", \"enum\": [\"low\", \"medium\", \"high\"] },\n \"risk_rationale\": { \"type\": \"string\" }\n }\n },\n \"regulatory_risk\": {\n \"type\": \"object\",\n \"properties\": {\n \"summary\": { \"type\": \"string\" },\n \"risk_level\": { \"type\": \"string\", \"enum\": [\"low\", \"medium\", \"high\"] },\n \"risk_rationale\": { \"type\": \"string\" }\n }\n },\n \"sla_risk\": {\n \"type\": \"object\",\n \"properties\": {\n \"summary\": { \"type\": \"string\" },\n \"risk_level\": { \"type\": \"string\", \"enum\": [\"low\", \"medium\", \"high\"] },\n \"risk_rationale\": { \"type\": \"string\" }\n }\n },\n \"bcp_risk\": {\n \"type\": \"object\",\n \"properties\": {\n \"summary\": { \"type\": \"string\" },\n \"risk_level\": { \"type\": \"string\", \"enum\": [\"low\", \"medium\", \"high\"] },\n \"risk_rationale\": { \"type\": \"string\" }\n }\n },\n \"ai_risk\": {\n \"type\": \"object\",\n \"properties\": {\n \"summary\": { \"type\": \"string\" },\n \"risk_level\": { \"type\": \"string\", \"enum\": [\"low\", \"medium\", \"high\"] },\n \"risk_rationale\": { \"type\": \"string\" }\n }\n },\n \"reputation_risk\": {\n \"type\": \"object\",\n \"properties\": {\n \"summary\": { \"type\": \"string\" },\n \"risk_level\": { \"type\": \"string\", \"enum\": [\"low\", \"medium\", \"high\"] },\n \"risk_rationale\": { \"type\": \"string\" }\n }\n },\n \"overall_risk\": {\n \"type\": \"object\",\n \"properties\": {\n \"summary\": { \"type\": \"string\" },\n \"risk_level\": { \"type\": \"string\", \"enum\": [\"low\", \"medium\", \"high\", \"critical\"] },\n \"risk_rationale\": { \"type\": \"string\" },\n \"recommendations\": { \"type\": \"string\" }\n }\n }\n }\n}"
},
"retryOnFail": true,
"typeVersion": 1.2
},
{
"id": "2df5075b-3821-4664-84f1-953ac823e105",
"name": "Gérer l'absence d'URL trouvées",
"type": "n8n-nodes-base.set",
"position": [
-1240,
-3340
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "c76bd8f6-e31d-4253-9801-5c36884f17b2",
"name": "url",
"type": "string",
"value": "no urls"
},
{
"id": "3f299be0-fe82-411f-8dfd-60a7c5ab2f65",
"name": "extraction_success",
"type": "boolean",
"value": false
},
{
"id": "ea79a42f-fa14-412f-bcab-7607c609fdfe",
"name": "summary",
"type": "string",
"value": "invalid data"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "605f7937-2ff2-4d96-9519-0f42ef40a9a5",
"name": "Fusionner les données de contenu",
"type": "n8n-nodes-base.aggregate",
"position": [
-1040,
-3340
],
"parameters": {
"options": {},
"aggregate": "aggregateAllItemData"
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "76249732-c833-4c4b-a104-181407c7d0a5",
"name": "Assainir les données d'URL",
"type": "n8n-nodes-base.code",
"position": [
-840,
-3340
],
"parameters": {
"language": "python",
"pythonCode": "# Filter out items with \"invalid data\" summary\ninput_items = items if items else []\n\n# Filter the data array to remove items with \"invalid data\" summary\nfiltered_data = []\nfor item in input_items:\n data_array = item.get('json', {}).get('data', [])\n filtered_array = []\n \n for data_item in data_array:\n output = data_item.get('output', {})\n if output.get('summary') != \"invalid data\":\n filtered_array.append(data_item)\n \n # Create new item with filtered data\n filtered_item = {\n 'json': {\n 'data': filtered_array\n }\n }\n if 'pairedItem' in item:\n filtered_item['pairedItem'] = item['pairedItem']\n \n filtered_data.append(filtered_item)\n\nreturn filtered_data"
},
"typeVersion": 2
},
{
"id": "375c9dbd-e3d9-43f9-b0a5-e4d8da4c7f91",
"name": "Formater les résultats de l'évaluation",
"type": "n8n-nodes-base.code",
"position": [
-260,
-3340
],
"parameters": {
"language": "python",
"pythonCode": "result = {}\n\n# Loop through all incoming items\nfor item in items:\n item_json = item.get('json', {})\n output = item_json.get('output', {})\n\n # Add vendor name and business use case\n result['company_name'] = output.get('vendor', '').get('name', '')\n result['business_use_case'] = output.get('vendor', '').get('business_use_case', '')\n result['classification'] = output.get('vendor', '').get('classification', '')\n\n # Handle risk categories\n for key, value in output.items():\n result[f\"{key}.summary\"] = value.get('summary')\n result[f\"{key}.risk_level\"] = value.get('risk_level')\n result[f\"{key}.risk_rationale\"] = value.get('risk_rationale')\n\n # Add recommendations only for overall risk\n if key == \"overall_risk\":\n result[f\"{key}.recommendations\"] = value.get('recommendations')\n\n# Return one item with the full result\nreturn [{ \"json\": result }]\n"
},
"typeVersion": 2
},
{
"id": "41c49d8c-8389-471b-bff2-58d79e6f203b",
"name": "Exporter vers la feuille Google",
"type": "n8n-nodes-base.googleSheets",
"position": [
-60,
-3340
],
"parameters": {
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "",
"cachedResultUrl": "",
"cachedResultName": ""
},
"documentId": {
"__rl": true,
"mode": "url",
"value": "",
"__regex": "https:\\/\\/(?:drive|docs)\\.google\\.com(?:\\/.*|)\\/d\\/([0-9a-zA-Z\\-_]+)(?:\\/.*|)"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "1OGq7nctjDrcRtbR",
"name": "Google Sheets account"
}
},
"typeVersion": 4.6
},
{
"id": "e05334ad-f22a-4557-be74-dcb44c785bb5",
"name": "Afficher le résumé de l'évaluation",
"type": "n8n-nodes-base.form",
"position": [
140,
-3340
],
"webhookId": "7bb2048c-a817-4472-99a9-60976434d322",
"parameters": {
"options": {},
"operation": "completion",
"completionTitle": "The results",
"completionMessage": "=Vendor name: {{ $json.company_name }}\nBusiness use case: {{ $json.business_use_case }}\nVendor classification: {{ $json.classification }}\nRisk rationale: {{ $json['overall_risk.risk_rationale'] }}\nRecommendations:\n{{ $json['overall_risk.recommendations'] }}"
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"e3f6ac89-fda7-4f0c-a073-ee8c7578e041": {
"main": [
[
{
"node": "fc9c0965-1012-4e7d-b682-bae874c3ee27",
"type": "main",
"index": 0
}
]
]
},
"22421d1c-4436-4de5-85da-57c7d7f94f9b": {
"main": [
[
{
"node": "611a9e07-427e-4174-9397-32f4b70f3f66",
"type": "main",
"index": 0
}
]
]
},
"df5a13bc-e717-4bb1-9cc5-eadc9ad5f42f": {
"main": [
[
{
"node": "29f06597-5afa-4b89-a45a-4afe1c911f02",
"type": "main",
"index": 0
}
]
]
},
"737c24ce-0618-41ac-bf8f-f9e96581631a": {
"main": [
[
{
"node": "a7482557-743c-4779-8e7e-bc58c57bf1d4",
"type": "main",
"index": 0
}
]
]
},
"76249732-c833-4c4b-a104-181407c7d0a5": {
"main": [
[
{
"node": "574056af-a3e1-4773-9269-70ca49d8aa34",
"type": "main",
"index": 0
}
]
]
},
"605f7937-2ff2-4d96-9519-0f42ef40a9a5": {
"main": [
[
{
"node": "76249732-c833-4c4b-a104-181407c7d0a5",
"type": "main",
"index": 0
}
]
]
},
"574056af-a3e1-4773-9269-70ca49d8aa34": {
"main": [
[
{
"node": "375c9dbd-e3d9-43f9-b0a5-e4d8da4c7f91",
"type": "main",
"index": 0
}
]
]
},
"2df5075b-3821-4664-84f1-953ac823e105": {
"main": [
[
{
"node": "605f7937-2ff2-4d96-9519-0f42ef40a9a5",
"type": "main",
"index": 0
}
]
]
},
"29f06597-5afa-4b89-a45a-4afe1c911f02": {
"main": [
[
{
"node": "e7eefa82-940f-4603-91b6-d013ed4dbe5b",
"type": "main",
"index": 0
}
]
]
},
"a7482557-743c-4779-8e7e-bc58c57bf1d4": {
"main": [
[
{
"node": "605f7937-2ff2-4d96-9519-0f42ef40a9a5",
"type": "main",
"index": 0
}
]
]
},
"fc9c0965-1012-4e7d-b682-bae874c3ee27": {
"main": [
[
{
"node": "8e210a6c-120b-4912-a164-db4a9a6ec4e4",
"type": "main",
"index": 0
}
]
]
},
"41c49d8c-8389-471b-bff2-58d79e6f203b": {
"main": [
[
{
"node": "e05334ad-f22a-4557-be74-dcb44c785bb5",
"type": "main",
"index": 0
}
]
]
},
"e7eefa82-940f-4603-91b6-d013ed4dbe5b": {
"main": [
[
{
"node": "fb637cbe-1d9f-4212-ac36-dd84d9b32975",
"type": "main",
"index": 0
}
]
]
},
"fb637cbe-1d9f-4212-ac36-dd84d9b32975": {
"main": [
[
{
"node": "737c24ce-0618-41ac-bf8f-f9e96581631a",
"type": "main",
"index": 0
}
],
[
{
"node": "2df5075b-3821-4664-84f1-953ac823e105",
"type": "main",
"index": 0
}
]
]
},
"9c70972b-958e-435d-b2a6-97394131b907": {
"ai_languageModel": [
[
{
"node": "a7482557-743c-4779-8e7e-bc58c57bf1d4",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"aafd0eb9-5a1c-4261-9831-3950eda71cbd": {
"ai_languageModel": [
[
{
"node": "574056af-a3e1-4773-9269-70ca49d8aa34",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"a267e7b6-9ddb-454b-aba0-15c8828fd46b": {
"ai_outputParser": [
[
{
"node": "a7482557-743c-4779-8e7e-bc58c57bf1d4",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"375c9dbd-e3d9-43f9-b0a5-e4d8da4c7f91": {
"main": [
[
{
"node": "41c49d8c-8389-471b-bff2-58d79e6f203b",
"type": "main",
"index": 0
}
]
]
},
"8e210a6c-120b-4912-a164-db4a9a6ec4e4": {
"main": [
[
{
"node": "22421d1c-4436-4de5-85da-57c7d7f94f9b",
"type": "main",
"index": 0
}
]
]
},
"611a9e07-427e-4174-9397-32f4b70f3f66": {
"main": [
[
{
"node": "df5a13bc-e717-4bb1-9cc5-eadc9ad5f42f",
"type": "main",
"index": 0
}
]
]
}
}
}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.
Workflows recommandés
Partager ce workflow