Created
July 11, 2026 18:28
-
-
Save iamvaar-dev/a1ef7e2704a78f6e3da80ea28d196550 to your computer and use it in GitHub Desktop.
AI Contract Analyser | Personalised
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "nodes": [ | |
| { | |
| "parameters": { | |
| "operation": "pdf", | |
| "options": {} | |
| }, | |
| "type": "n8n-nodes-base.extractFromFile", | |
| "typeVersion": 1, | |
| "position": [ | |
| -2368, | |
| -224 | |
| ], | |
| "id": "424d5ea0-04e8-4367-add2-380e338b9b4c", | |
| "name": "Extract Contract Text" | |
| }, | |
| { | |
| "parameters": { | |
| "assignments": { | |
| "assignments": [ | |
| { | |
| "id": "clause1", | |
| "name": "masterClauses", | |
| "type": "string", | |
| "value": "STRICT DEALBREAKERS AND TURNOFFS:\n1. Payment Terms: Net-30 maximum. No Net-60 or Net-90 terms accepted under any circumstances. Late fees must not exceed 1.5% monthly.\n2. Liability Cap: Liability must be strictly capped at the total amount paid under the contract. Absolute NO to unlimited liability or indirect/consequential damages.\n3. IP Ownership: I retain all rights to my pre-existing IP. Work product ownership transfers ONLY upon full and final payment.\n4. Auto-Renewal: Strictly NO evergreen/auto-renewal clauses. All renewals require explicit, mutual written agreement.\n5. Termination: Mutual right to terminate for convenience with no more than 15-30 days written notice. No aggressive lock-in periods.\n6. Indemnification: Indemnification must be mutual. I will not accept one-sided indemnification protecting only the client." | |
| } | |
| ] | |
| }, | |
| "options": {} | |
| }, | |
| "type": "n8n-nodes-base.set", | |
| "typeVersion": 3.4, | |
| "position": [ | |
| -2144, | |
| -224 | |
| ], | |
| "id": "a411cd60-fa36-43ab-875a-2b2a02d96c91", | |
| "name": "Define Master Clauses" | |
| }, | |
| { | |
| "parameters": { | |
| "method": "POST", | |
| "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-lite:generateContent", | |
| "authentication": "predefinedCredentialType", | |
| "nodeCredentialType": "googlePalmApi", | |
| "sendBody": true, | |
| "specifyBody": "json", | |
| "jsonBody": "={{ {\n \"contents\": [\n {\n \"parts\": [\n {\n \"text\": `You are a sharp, highly-protective personal contract negotiator representing me. Forget robotic, generalized legal auditing. Compare the EXTRACTED CONTRACT below against my STRICT PERSONAL TURNOFFS. Do not flag random standard boilerplate clauses just because they are phrased differently. ONLY flag direct, dangerous violations of my non-negotiable boundaries. Score the risk from 0 (perfectly aligned with my boundaries) to 100 (contains severe dealbreakers). Give a blunt, straight-to-the-point summary of why I should or shouldn't sign this. Respond with ONLY valid JSON, no markdown, in this exact shape: {\"risk_score\": number, \"unapproved_indemnity_clauses\": [string], \"other_flagged_clauses\": [string], \"summary\": string}.\\n\\nEXTRACTED CONTRACT:\\n${$('Extract Contract Text').item.json.text}\\n\\nMY STRICT PERSONAL TURNOFFS:\\n${JSON.stringify($json.masterClauses)}`\n }\n ]\n }\n ],\n \"generationConfig\": {\n \"responseMimeType\": \"application/json\",\n \"temperature\": 0.2\n }\n} }}", | |
| "options": {} | |
| }, | |
| "type": "n8n-nodes-base.httpRequest", | |
| "typeVersion": 4.4, | |
| "position": [ | |
| -1920, | |
| -224 | |
| ], | |
| "id": "cb9cbd0f-2438-444f-82e6-ae1cf0390e01", | |
| "name": "Score Deviations (Gemini 3.1 Flash Lite)", | |
| "credentials": { | |
| "googlePalmApi": { | |
| "id": "x2sCC1GX3iizemFd", | |
| "name": "vaar@blankarray" | |
| } | |
| } | |
| }, | |
| { | |
| "parameters": { | |
| "assignments": { | |
| "assignments": [ | |
| { | |
| "id": "a1", | |
| "name": "riskScore", | |
| "type": "number", | |
| "value": "={{ $json.risk_score }}" | |
| }, | |
| { | |
| "id": "a2", | |
| "name": "unapprovedIndemnityClauses", | |
| "type": "array", | |
| "value": "={{ $json.unapproved_indemnity_clauses }}" | |
| }, | |
| { | |
| "id": "a3", | |
| "name": "otherFlaggedClauses", | |
| "type": "array", | |
| "value": "={{ $json.other_flagged_clauses }}" | |
| }, | |
| { | |
| "id": "a4", | |
| "name": "summary", | |
| "type": "string", | |
| "value": "={{ $json.summary }}" | |
| }, | |
| { | |
| "id": "a5", | |
| "name": "driveFileLink", | |
| "type": "string", | |
| "value": "={{ $('Upload Contract to Drive').item.json.webViewLink }}" | |
| } | |
| ] | |
| }, | |
| "options": {} | |
| }, | |
| "type": "n8n-nodes-base.set", | |
| "typeVersion": 3.4, | |
| "position": [ | |
| -1472, | |
| -224 | |
| ], | |
| "id": "d77a0380-5f6c-454d-9d1e-f670cf1ac478", | |
| "name": "Parse Risk Analysis" | |
| }, | |
| { | |
| "parameters": { | |
| "conditions": { | |
| "options": { | |
| "caseSensitive": true, | |
| "leftValue": "", | |
| "typeValidation": "strict", | |
| "version": 2 | |
| }, | |
| "conditions": [ | |
| { | |
| "id": "c1", | |
| "leftValue": "={{ $json.riskScore }}", | |
| "rightValue": 70, | |
| "operator": { | |
| "type": "number", | |
| "operation": "gte" | |
| } | |
| } | |
| ], | |
| "combinator": "and" | |
| }, | |
| "options": {} | |
| }, | |
| "type": "n8n-nodes-base.if", | |
| "typeVersion": 2.2, | |
| "position": [ | |
| -1248, | |
| -224 | |
| ], | |
| "id": "14c46e83-8e10-4535-a4ce-7866e88bcf2f", | |
| "name": "High Risk?" | |
| }, | |
| { | |
| "parameters": { | |
| "operation": "move", | |
| "fileId": { | |
| "__rl": true, | |
| "value": "={{ $('Upload Contract to Drive').item.json.id }}", | |
| "mode": "id" | |
| }, | |
| "driveId": { | |
| "__rl": true, | |
| "mode": "list", | |
| "value": "My Drive" | |
| }, | |
| "folderId": { | |
| "__rl": true, | |
| "value": "1ylu0OgN-fvFGZ_Zd3uQ_2v2tTrwrJ9od", | |
| "mode": "list", | |
| "cachedResultName": "Processed", | |
| "cachedResultUrl": "https://drive.google.com/drive/folders/1ylu0OgN-fvFGZ_Zd3uQ_2v2tTrwrJ9od" | |
| } | |
| }, | |
| "type": "n8n-nodes-base.googleDrive", | |
| "typeVersion": 3, | |
| "position": [ | |
| -1024, | |
| -128 | |
| ], | |
| "id": "a3f605fe-8ea8-4c05-932c-f0e10111bbd9", | |
| "name": "Archive Low-Risk Contract", | |
| "credentials": { | |
| "googleDriveOAuth2Api": { | |
| "id": "P67Tj3JDLHD8zgPh", | |
| "name": "vaar primary drive acc" | |
| } | |
| } | |
| }, | |
| { | |
| "parameters": { | |
| "formTitle": "Contract Submission", | |
| "formDescription": "Submit your contract right here", | |
| "formFields": { | |
| "values": [ | |
| { | |
| "fieldLabel": "Contract in PDF", | |
| "fieldType": "file", | |
| "fieldName": "data", | |
| "acceptFileTypes": "pdf", | |
| "requiredField": true | |
| } | |
| ] | |
| }, | |
| "options": { | |
| "appendAttribution": false, | |
| "path": "contracts", | |
| "customCss": ":root {\n\t/* Fonts: Swapped to something punchy and structural */\n\t--font-family: 'Space Grotesk', 'Helvetica Neue', sans-serif;\n\t--font-weight-normal: 500; /* Beefed up base weight for presence */\n\t--font-weight-bold: 700;\n\n\t/* Font Sizes: Scaled up slightly for a bolder layout */\n\t--font-size-body: 14px;\n\t--font-size-label: 14px;\n\t--font-size-test-notice: 12px;\n\t--font-size-input: 14px;\n\t--font-size-header: 24px;\n\t--font-size-paragraph: 14px;\n\t--font-size-link: 14px;\n\t--font-size-error: 12px;\n\t--font-size-html-h1: 32px;\n\t--font-size-html-h2: 24px;\n\t--font-size-html-h3: 18px;\n\t--font-size-html-h4: 16px;\n\t--font-size-html-h5: 14px;\n\t--font-size-html-h6: 12px;\n\t--font-size-subheader: 16px;\n\n\t/* Colors: High Contrast Monochrome with striking accents */\n\t--color-background: #e0e0e0; /* Concrete Grey */\n\t--color-test-notice-text: #000000;\n\t--color-test-notice-bg: #ccff00; /* Volt Green Accent */\n\t--color-test-notice-border: #000000;\n\t\n\t--color-card-bg: #ffffff;\n\t--color-card-border: #000000; /* Thick black borders */\n\t--color-card-shadow: #000000; /* Solid black for harsh shadows */\n\t\n\t--color-header: #000000;\n\t--color-header-subtext: #444444;\n\t--color-label: #000000;\n\t--color-html-text: #000000;\n\n\t--color-input-border: #000000;\n\t--color-input-text: #000000;\n\t--color-focus-border: #0000ff; /* Pure Blue Focus */\n\t\n\t--color-link: #0000ff;\n\t--color-html-link: #0000ff;\n\t\n\t--color-submit-btn-bg: #0000ff; /* Pure Blue Button */\n\t--color-submit-btn-text: #ffffff;\n\t\n\t--color-error: #ff0000; /* Pure Red */\n\t--color-required: #ff0000;\n\t--color-clear-button-bg: #000000;\n\n\t/* Border Radii: Zeroed out for sharp, blocky edges */\n\t--border-radius-card: 0px;\n\t--card-border-radius: 0px;\n\t--border-radius-input: 0px;\n\t--border-radius-clear-btn: 0px;\n\n\t/* Spacing: Increased for breathing room against heavy borders */\n\t--padding-container-top: 32px;\n\t--padding-card: 32px;\n\t--card-padding: 32px;\n\t--padding-test-notice-vertical: 16px;\n\t--padding-test-notice-horizontal: 24px;\n\t--margin-bottom-card: 24px;\n\t--card-margin-bottom: 24px;\n\t--padding-form-input: 16px;\n\t\n\t/* Dimensions: Slightly chunkier */\n\t--container-width: 480px;\n\t--submit-btn-height: 54px;\n\t--checkbox-size: 20px;\n\n\t/* Others: The signature solid brutalist drop shadow */\n\t--box-shadow-card: 6px 6px 0px 0px var(--color-card-shadow);\n\t--opacity-placeholder: 1; /* Solid placeholders */\n}" | |
| } | |
| }, | |
| "type": "n8n-nodes-base.formTrigger", | |
| "typeVersion": 2.6, | |
| "position": [ | |
| -3040, | |
| -224 | |
| ], | |
| "id": "81622a4b-2f4e-4a91-b722-036d8dde7815", | |
| "name": "On form submission", | |
| "webhookId": "c27e8cc0-ac20-4cce-a047-295ec860dc97" | |
| }, | |
| { | |
| "parameters": { | |
| "jsCode": "// Get the JSON data of the first input item\nconst item = $input.first().json;\n\n// Extract the text content from the Gemini API response\nlet rawText = item.candidates[0].content.parts[0].text;\n\n// Clean the text by removing potential markdown code blocks (e.g., ```json ... ```)\nrawText = rawText.replace(/^```json\\s*/i, '').replace(/\\s*```$/i, '').trim();\n\ntry {\n // Parse the cleaned text into a JSON object\n const parsedData = JSON.parse(rawText);\n \n // Return the parsed data so each key becomes a separate field in n8n\n return [{ json: parsedData }];\n \n} catch (error) {\n // Throw a descriptive error if parsing fails\n throw new Error(\"Failed to parse Gemini response as JSON: \" + error.message);\n}" | |
| }, | |
| "type": "n8n-nodes-base.code", | |
| "typeVersion": 2, | |
| "position": [ | |
| -1696, | |
| -224 | |
| ], | |
| "id": "cd11094b-ceaa-4128-83a5-dd29487be60d", | |
| "name": "Code in JavaScript1" | |
| }, | |
| { | |
| "parameters": { | |
| "select": "channel", | |
| "channelId": { | |
| "__rl": true, | |
| "value": "C0B8VH1M5PX", | |
| "mode": "list", | |
| "cachedResultName": "general" | |
| }, | |
| "text": "=Risk Score: {{ $json.riskScore }}/100\n\nUnapproved Indemnity Clauses:\n{{ $json.unapprovedIndemnityClauses.join('\\n- ') }}\n\nOther Flagged Clauses:\n{{ $json.otherFlaggedClauses.join('\\n- ') }}\n\nSummary:\n{{ $json.summary }}\n\nContract Document: {{ $json.driveFileLink }}", | |
| "otherOptions": {} | |
| }, | |
| "type": "n8n-nodes-base.slack", | |
| "typeVersion": 2.5, | |
| "position": [ | |
| -1024, | |
| -320 | |
| ], | |
| "id": "fbac066e-fc08-4301-8054-2df65c3e0c38", | |
| "name": "Send a message", | |
| "webhookId": "c50ffc32-eae9-4bda-8ead-59281e1616a2", | |
| "credentials": { | |
| "slackApi": { | |
| "id": "uBs2LjzTiloElvwT", | |
| "name": "Slack account 2" | |
| } | |
| } | |
| }, | |
| { | |
| "parameters": { | |
| "name": "={{ $json.data[0].filename }} - {{ $json.email }}", | |
| "driveId": { | |
| "__rl": true, | |
| "mode": "list", | |
| "value": "My Drive" | |
| }, | |
| "folderId": { | |
| "__rl": true, | |
| "value": "1p2gViUN_yqD9MeSjigPyj0fwx-uUj34T", | |
| "mode": "list", | |
| "cachedResultName": "Contracts_july", | |
| "cachedResultUrl": "https://drive.google.com/drive/folders/1p2gViUN_yqD9MeSjigPyj0fwx-uUj34T" | |
| }, | |
| "options": {} | |
| }, | |
| "type": "n8n-nodes-base.googleDrive", | |
| "typeVersion": 3, | |
| "position": [ | |
| -2816, | |
| -224 | |
| ], | |
| "id": "db3c1c65-1e7c-4358-84e7-00624cbab2bb", | |
| "name": "Upload Contract to Drive", | |
| "credentials": { | |
| "googleDriveOAuth2Api": { | |
| "id": "P67Tj3JDLHD8zgPh", | |
| "name": "vaar primary drive acc" | |
| } | |
| } | |
| }, | |
| { | |
| "parameters": { | |
| "select": "channel", | |
| "channelId": { | |
| "__rl": true, | |
| "value": "C0B8VH1M5PX", | |
| "mode": "list", | |
| "cachedResultName": "general" | |
| }, | |
| "text": "=Risk Score: {{ $('High Risk?').item.json.riskScore }}/100\n\nUnapproved Indemnity Clauses:\n{{ $('High Risk?').item.json.unapprovedIndemnityClauses }}\n\nOther Flagged Clauses:\n{{ $('High Risk?').item.json.otherFlaggedClauses }}\n\nSummary:\n{{ $('High Risk?').item.json.summary }}\n\n Contract Document: {{ $('High Risk?').item.json.driveFileLink }}", | |
| "otherOptions": {} | |
| }, | |
| "type": "n8n-nodes-base.slack", | |
| "typeVersion": 2.5, | |
| "position": [ | |
| -784, | |
| -128 | |
| ], | |
| "id": "acad2835-ebd1-409c-b0a6-f957dbaaa293", | |
| "name": "Send a message1", | |
| "webhookId": "c50ffc32-eae9-4bda-8ead-59281e1616a2", | |
| "credentials": { | |
| "slackApi": { | |
| "id": "uBs2LjzTiloElvwT", | |
| "name": "Slack account 2" | |
| } | |
| } | |
| }, | |
| { | |
| "parameters": { | |
| "jsCode": "// 1. Get the items output by the specific Form node\nconst formItems = $('On form submission').all();\n\n// 2. Get the current items (output from the Google Drive node)\nconst currentItems = $input.all();\n\n// 3. Loop through current items and merge the binary data from the form\nfor (let i = 0; i < currentItems.length; i++) {\n \n // Check if the form item exists and has the binary field named 'data'\n if (formItems[i] && formItems[i].binary && formItems[i].binary.data) {\n \n // Grab the binary context from the form node\n const formBinaryContext = formItems[i].binary.data;\n \n // Re-attach the binary object to the current item \n // so subsequent nodes can use the file again if needed\n currentItems[i].binary = {\n data: formBinaryContext\n };\n \n // Example: Extracting metadata into the JSON payload for easy access\n currentItems[i].json.fileContext = {\n originalName: formBinaryContext.fileName,\n mimeType: formBinaryContext.mimeType,\n fileSize: formBinaryContext.fileSize\n };\n }\n}\n\n// Return the modified items containing both the Drive output (JSON) and Form output (Binary)\nreturn currentItems;" | |
| }, | |
| "type": "n8n-nodes-base.code", | |
| "typeVersion": 2, | |
| "position": [ | |
| -2592, | |
| -224 | |
| ], | |
| "id": "64aa94b3-48cd-4c08-a65c-20918b3fea08", | |
| "name": "Code in JavaScript" | |
| } | |
| ], | |
| "connections": { | |
| "Extract Contract Text": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Define Master Clauses", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Define Master Clauses": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Score Deviations (Gemini 3.1 Flash Lite)", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Score Deviations (Gemini 3.1 Flash Lite)": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Code in JavaScript1", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Parse Risk Analysis": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "High Risk?", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "High Risk?": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Send a message", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ], | |
| [ | |
| { | |
| "node": "Archive Low-Risk Contract", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Archive Low-Risk Contract": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Send a message1", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "On form submission": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Upload Contract to Drive", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Code in JavaScript1": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Parse Risk Analysis", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Upload Contract to Drive": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Code in JavaScript", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| }, | |
| "Code in JavaScript": { | |
| "main": [ | |
| [ | |
| { | |
| "node": "Extract Contract Text", | |
| "type": "main", | |
| "index": 0 | |
| } | |
| ] | |
| ] | |
| } | |
| }, | |
| "pinData": {}, | |
| "meta": { | |
| "templateCredsSetupCompleted": true, | |
| "instanceId": "93f396852104089b8670e7494b0f3668b420464668ae4a8c1d6b4b5799f8e3ef" | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment