{
  "id": "BRLb2C4pBght9DIL",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "RFP Automation Workflow (Groq AI Agent)",
  "tags": [
    {
      "id": "uyNFmHe7fqRdqtCp",
      "name": "RFP Automation",
      "createdAt": "2026-04-14T07:00:09.108Z",
      "updatedAt": "2026-04-14T07:00:09.108Z"
    }
  ],
  "nodes": [
    {
      "id": "bdbc130b-1f49-4461-85c7-dd3635ab6b3d",
      "name": "Watch RFP Upload Folder",
      "type": "n8n-nodes-base.googleDriveTrigger",
      "notes": "Configure: Replace YOUR_GOOGLE_DRIVE_FOLDER_ID with your actual RFP intake folder ID from the Drive URL.",
      "position": [
        -6048,
        -288
      ],
      "parameters": {
        "event": "fileCreated",
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "specificFolder",
        "folderToWatch": {
          "__rl": true,
          "mode": "list",
          "value": "1odaBEvPyuzyRwGktzYeefyoOFnV554HM",
          "cachedResultUrl": "https://drive.google.com/drive/folders/1odaBEvPyuzyRwGktzYeefyoOFnV554HM",
          "cachedResultName": "Contract"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c9b31957-8577-4dea-a9f3-027655f6d3ce",
      "name": "Download RFP Document",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -5872,
        -288
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {},
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "4ae1f284-d940-46c4-9d7b-9e32158fbfb5",
      "name": "Extract Text from RFP",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -5696,
        -288
      ],
      "parameters": {
        "options": {},
        "operation": "pdf"
      },
      "typeVersion": 1
    },
    {
      "id": "6d6de114-938e-49bb-b849-aea14a99ef4b",
      "name": "Prepare RFP Metadata",
      "type": "n8n-nodes-base.set",
      "position": [
        -5488,
        -288
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "assign-filename",
              "name": "fileName",
              "type": "string",
              "value": "={{ $('Watch RFP Upload Folder').item.json.name }}\n\n"
            },
            {
              "id": "assign-fileid",
              "name": "fileId",
              "type": "string",
              "value": "={{ $('Watch RFP Upload Folder').item.json.id }}"
            },
            {
              "id": "assign-fileurl",
              "name": "fileUrl",
              "type": "string",
              "value": "={{ $('Watch RFP Upload Folder').item.json.webViewLink }}"
            },
            {
              "id": "assign-text",
              "name": "rawText",
              "type": "string",
              "value": "={{ $json.text }}"
            },
            {
              "id": "assign-timestamp",
              "name": "receivedAt",
              "type": "string",
              "value": "={{ $now.toISO() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "6141abda-c15c-4d7d-baba-7b385df5c02f",
      "name": "AI Extract RFP Requirements",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "notes": "AI Agent using Groq. The Groq Chat Model sub-node must be connected to the 'Model' input of this node.",
      "position": [
        -5152,
        -288
      ],
      "parameters": {
        "text": "=You are an expert RFP analyst. Extract structured requirements from the RFP document below and return ONLY a valid raw JSON object \u2014 no markdown, no code fences, no explanation.\n\nReturn exactly this JSON structure:\n{\n  \"client_name\": \"Company or organization name\",\n  \"project_title\": \"Title of the project or RFP\",\n  \"project_scope\": \"2-3 sentence summary of what is needed\",\n  \"budget_range\": \"Exact budget text from document or Not specified\",\n  \"submission_deadline\": \"ISO date string YYYY-MM-DD or Not specified\",\n  \"project_start_date\": \"ISO date string YYYY-MM-DD or Not specified\",\n  \"contract_duration\": \"Duration string e.g. 12 months or Not specified\",\n  \"evaluation_criteria\": [\"criterion 1\", \"criterion 2\"],\n  \"required_sections\": [\"section 1\", \"section 2\"],\n  \"technical_requirements\": [\"requirement 1\", \"requirement 2\"],\n  \"key_contacts\": [{\"name\": \"name\", \"email\": \"email\", \"role\": \"role\"}],\n  \"industry\": \"Industry sector e.g. Healthcare Finance Government\",\n  \"project_type\": \"e.g. Software Development Consulting Infrastructure\",\n  \"complexity\": \"Low or Medium or High\",\n  \"estimated_value\": 0\n}\n\nFILE NAME: {{ $json.fileName }}\n\nDOCUMENT TEXT:\n{{ $json.rawText.substring(0, 12000) }}",
        "agent": "conversationalAgent",
        "options": {
          "systemMessage": "You are an expert RFP analyst. You extract structured data from procurement documents. Always respond with raw valid JSON only \u2014 never use markdown, code fences or any explanation text before or after the JSON."
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "faad274e-24cd-46f1-a7a0-bf13ab86c916",
      "name": "AI Model \u2013 Requirement Extraction",
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "notes": "llama-3.3-70b-versatile \u2014 fast and accurate for structured extraction. Alternatives: mixtral-8x7b-32768, llama3-70b-8192.",
      "position": [
        -5152,
        -144
      ],
      "parameters": {
        "model": "llama-3.3-70b-versatile",
        "options": {
          "temperature": 0.1
        }
      },
      "credentials": {
        "groqApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "910fd3de-dc75-4297-8b79-a958c89d0773",
      "name": "Clean & Parse AI Output",
      "type": "n8n-nodes-base.code",
      "notes": "Reads $json.output from the AI Agent node (not .message.content like the old OpenAI node). Strips any stray markdown fences and parses JSON safely.",
      "position": [
        -4864,
        -288
      ],
      "parameters": {
        "jsCode": "// Safely extract the agent output regardless of where n8n puts it\nconst agentJson = $input.item.json;\n\nlet raw;\nif (typeof agentJson.output === 'string') {\n  raw = agentJson.output;\n} else if (typeof agentJson.output === 'object' && agentJson.output !== null) {\n  raw = JSON.stringify(agentJson.output);\n} else if (typeof agentJson.text === 'string') {\n  raw = agentJson.text;\n} else if (typeof agentJson.response === 'string') {\n  raw = agentJson.response;\n} else {\n  raw = JSON.stringify(agentJson);\n}\n\n// Strip markdown fences if present\nlet cleaned = raw.trim();\nif (cleaned.startsWith('```json')) cleaned = cleaned.slice(7);\nelse if (cleaned.startsWith('```')) cleaned = cleaned.slice(3);\nif (cleaned.endsWith('```')) cleaned = cleaned.slice(0, -3);\ncleaned = cleaned.trim();\n\n// Find the outermost JSON object even if there is surrounding text\nconst jsonStart = cleaned.indexOf('{');\nconst jsonEnd = cleaned.lastIndexOf('}');\nif (jsonStart !== -1 && jsonEnd !== -1) {\n  cleaned = cleaned.slice(jsonStart, jsonEnd + 1);\n}\n\nlet requirements;\ntry {\n  requirements = JSON.parse(cleaned);\n} catch(e) {\n  requirements = {\n    client_name: 'Parse Error - Check Logs',\n    project_title: $('Prepare RFP Metadata').item.json.fileName,\n    project_scope: 'Could not parse requirements - review raw AI output',\n    budget_range: 'Not specified',\n    submission_deadline: 'Not specified',\n    project_start_date: 'Not specified',\n    contract_duration: 'Not specified',\n    evaluation_criteria: [],\n    required_sections: [],\n    technical_requirements: [],\n    key_contacts: [],\n    industry: 'Unknown',\n    project_type: 'Unknown',\n    complexity: 'Medium',\n    estimated_value: 0\n  };\n}\n\nreturn {\n  ...requirements,\n  fileName: $('Prepare RFP Metadata').item.json.fileName,\n  fileId: $('Prepare RFP Metadata').item.json.fileId,\n  fileUrl: $('Prepare RFP Metadata').item.json.fileUrl,\n  rawText: $('Prepare RFP Metadata').item.json.rawText,\n  receivedAt: $('Prepare RFP Metadata').item.json.receivedAt\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "5c5deb25-7790-4cb6-b4c4-2d365f983ab7",
      "name": "Fetch Past Proposals (KB",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "Configure: Replace YOUR_PAST_PROPOSALS_FOLDER_ID in the q parameter value with your actual folder ID. Uses Drive API v3 directly \u2014 avoids the broken search operation bug in n8n Google Drive node.",
      "position": [
        -4400,
        -288
      ],
      "parameters": {
        "url": "",
        "options": {},
        "sendQuery": true,
        "authentication": "predefinedCredentialType",
        "queryParameters": {
          "parameters": [
            {
              "name": "q",
              "value": "'1odaBEvPyuzyRwGktzYeefyoOFnV554HM' in parents and mimeType != 'application/vnd.google-apps.folder' and trashed = false"
            }
          ]
        },
        "nodeCredentialType": "googleDriveOAuth2Api"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "0de0fa6d-1473-4b8a-ab0d-c19c1ecb6ecc",
      "name": "Combine Requirements + KB",
      "type": "n8n-nodes-base.code",
      "position": [
        -4240,
        -288
      ],
      "parameters": {
        "jsCode": "const requirements = $('Clean & Parse AI Output').item.json;\n// HTTP Request node returns the Drive API response directly as $json\n// files are under $json.files array\nconst responseJson = $input.item.json;\nconst kbFiles = Array.isArray(responseJson.files) ? responseJson.files : [];\n\nconst kbSummary = kbFiles.length > 0\n  ? kbFiles.map((f, i) => `${i+1}. \"${f.name}\" - ${f.webViewLink || 'no link'}`).join('\\n')\n  : 'No past proposals found in knowledge base.';\n\nreturn {\n  requirements,\n  kbSummary,\n  kbFileCount: kbFiles.length\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "f2d9f915-eb2b-4a5d-9251-8c4abe3a1558",
      "name": "AI Generate Proposal Draft",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "notes": "AI Agent using Groq for proposal writing. The Groq Chat Model sub-node must be connected to the 'Model' input of this node. Update the company background in the prompt text.",
      "position": [
        -3888,
        -288
      ],
      "parameters": {
        "text": "=Write a complete, professional RFP proposal response in Markdown format.\n\nCOMPANY BACKGROUND (customize this):\n- Company Name: Acme Solutions Pvt Ltd\n- Core Services: Software development, IT consulting, digital transformation\n- Founded: 2015 | Team: 120+ professionals\n- Strengths: Agile delivery, enterprise integrations, cloud expertise\n\nEXTRACTED RFP REQUIREMENTS:\nClient: {{ $json.requirements.client_name }}\nProject: {{ $json.requirements.project_title }}\nScope: {{ $json.requirements.project_scope }}\nBudget: {{ $json.requirements.budget_range }}\nSubmission Deadline: {{ $json.requirements.submission_deadline }}\nDuration: {{ $json.requirements.contract_duration }}\nIndustry: {{ $json.requirements.industry }}\nType: {{ $json.requirements.project_type }}\nComplexity: {{ $json.requirements.complexity }}\nEvaluation Criteria: {{ $json.requirements.evaluation_criteria.join(', ') }}\nRequired Sections: {{ $json.requirements.required_sections.join(', ') }}\nTechnical Requirements: {{ $json.requirements.technical_requirements.join(', ') }}\n\nREFERENCE PAST PROPOSALS (use for style and content patterns):\n{{ $json.kbSummary }}\n\nWrite the full proposal now with these exact sections:\n# 1. Executive Summary\n# 2. Understanding of Requirements\n# 3. Proposed Solution & Methodology\n# 4. Project Timeline & Milestones\n# 5. Team Composition\n# 6. Relevant Experience\n# 7. Pricing & Investment\n# 8. Why Choose Us\n# 9. Next Steps\n\nBe specific, compelling and tailor every section to the requirements above.",
        "agent": "conversationalAgent",
        "options": {
          "systemMessage": "You are a senior proposal writer at a professional services company. You write detailed, persuasive RFP responses that win contracts. Write in clear professional Markdown. Never add preamble or meta-commentary \u2014 start directly with the Executive Summary heading."
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "1718d827-d493-4e4b-ac95-30200cd6aac0",
      "name": "AI Model \u2013 Proposal Writing",
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "notes": "Higher temperature (0.7) for more creative, natural-sounding proposal writing. Uses llama-3.3-70b-versatile.",
      "position": [
        -3888,
        -144
      ],
      "parameters": {
        "model": "llama-3.3-70b-versatile",
        "options": {
          "temperature": 0.7
        }
      },
      "credentials": {
        "groqApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7915fd02-3f88-4e27-a233-f45c658140a4",
      "name": "Prepare Final Output Data",
      "type": "n8n-nodes-base.code",
      "notes": "Reads $json.output from the Agent node. Prepares clean objects for Salesforce and Google Docs.",
      "position": [
        -3424,
        -288
      ],
      "parameters": {
        "jsCode": "const req = $('Clean & Parse AI Output').item.json;\nconst agentJson = $input.item.json;\n\n// Safely read draft content from wherever the agent puts it\nlet draftContent;\nif (typeof agentJson.output === 'string') {\n  draftContent = agentJson.output;\n} else if (typeof agentJson.output === 'object' && agentJson.output !== null) {\n  draftContent = JSON.stringify(agentJson.output);\n} else if (typeof agentJson.text === 'string') {\n  draftContent = agentJson.text;\n} else if (typeof agentJson.response === 'string') {\n  draftContent = agentJson.response;\n} else {\n  draftContent = JSON.stringify(agentJson);\n}\n\nconst deadlineDate = req.submission_deadline && req.submission_deadline !== 'Not specified'\n  ? req.submission_deadline\n  : new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];\n\nconst estimatedValue = req.estimated_value && req.estimated_value > 0\n  ? req.estimated_value\n  : null;\n\nreturn {\n  req,\n  draftContent,\n  deadlineDate,\n  estimatedValue,\n  opportunityName: `RFP - ${req.client_name} - ${req.project_title}`.substring(0, 120)\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "01548234-f6e0-4ebd-a490-cb6c62d39c63",
      "name": "Create Salesforce Opportunity",
      "type": "n8n-nodes-base.salesforce",
      "notes": "Configure: Remove Industry__c if that custom field doesn't exist in your org or create it first in Salesforce Setup.",
      "position": [
        -3120,
        -384
      ],
      "parameters": {
        "name": "={{ $json.req.client_name }}",
        "resource": "opportunity",
        "closeDate": "={{ $json.deadlineDate }}",
        "stageName": "={{ $json.req.client_name }}",
        "additionalFields": {
          "customFieldsUi": {
            "customFieldsValues": [
              {
                "value": "={{ $json.opportunityName }}",
                "fieldId": "=Name"
              },
              {
                "value": "RFP Received",
                "fieldId": "=StageName"
              },
              {
                "value": "={{ $json.deadlineDate }}",
                "fieldId": "=CloseDate"
              },
              {
                "value": "={{ $json.estimatedValue }}",
                "fieldId": "=Amount"
              },
              {
                "value": "={{ $json.req.project_scope }}",
                "fieldId": "=Description"
              },
              {
                "value": "RFP",
                "fieldId": "=LeadSource"
              }
            ]
          }
        }
      },
      "credentials": {
        "salesforceOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a718397b-f010-4674-a7b6-089aa947054a",
      "name": "Save Proposal to Google Docs",
      "type": "n8n-nodes-base.googleDocs",
      "position": [
        -3120,
        -192
      ],
      "parameters": {
        "title": "=RFP Draft - {{ $json.req.client_name }} - {{ $('Clean & Parse AI Output').item.json.project_title }}",
        "folderId": "1xYBz_fgUXtkUMnD54bvXAo99av3oXQKK"
      },
      "credentials": {
        "googleDocsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "d9a297ef-68b7-4954-a108-4fab7b76c510",
      "name": "Merge Docs + Salesforce Results",
      "type": "n8n-nodes-base.merge",
      "position": [
        -2800,
        -288
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "863f4eae-ca95-4abd-846c-ca745ee9dd48",
      "name": "Combine Final Output Links",
      "type": "n8n-nodes-base.code",
      "position": [
        -2576,
        -288
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\n\nconst sfResult = items.find(i => i.json.id)?.json || {};\nconst docsResult = items.find(i => i.json.documentId)?.json || {};\n\nconst req = $('Clean & Parse AI Output').item.json;\n\nconst sfId = sfResult.id || 'SF_ID_UNAVAILABLE';\n\nconst docUrl = docsResult.documentId\n  ? `https://docs.google.com/document/d/${docsResult.documentId}/edit`\n  : 'DOC_URL_UNAVAILABLE';\n\nreturn {\n  salesforceOpportunityId: sfId,\n  googleDocUrl: docUrl,\n  googleDocId: docsResult.documentId,\n  clientName: req.client_name,\n  projectTitle: req.project_title,\n  submissionDeadline: req.submission_deadline,\n  complexity: req.complexity,\n  rfpFileUrl: req.fileUrl,\n  rfpFileName: req.fileName\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "478ac518-f86e-49df-858c-3a837af96b42",
      "name": "Create Review Task in Salesforce",
      "type": "n8n-nodes-base.salesforce",
      "position": [
        -2400,
        -288
      ],
      "parameters": {
        "status": "Not Started",
        "resource": "task",
        "additionalFields": {
          "customFieldsUi": {
            "customFieldsValues": [
              {
                "value": "=Review RFP Draft - {{ $json.clientName }} ({{ $json.complexity }} complexity)",
                "fieldId": "Subject"
              },
              {
                "value": "={{ $json.salesforceOpportunityId }}",
                "fieldId": "WhatId"
              },
              {
                "value": "High",
                "fieldId": "Priority"
              },
              {
                "value": "Not Started",
                "fieldId": "Status"
              },
              {
                "value": "=RFP response draft auto-generated by AI Agent (Groq / Llama 3.3).\n\nClient: {{ $json.clientName }}\nProject: {{ $json.projectTitle }}\nDeadline: {{ $json.submissionDeadline }}\nIndustry: {{ $json.industry }}\n\nDraft Proposal (review and edit):\n{{ $json.googleDocUrl }}\n\nOriginal RFP File:\n{{ $json.rfpFileUrl }}\n\nAction required:\n1. Review and customise the AI-generated draft\n2. Validate pricing and timeline sections\n3. Get sign-off from legal/finance if needed\n4. Submit before the deadline",
                "fieldId": "Description"
              }
            ]
          }
        }
      },
      "credentials": {
        "salesforceOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b537e816-e650-4364-916e-6df60a0c3e24",
      "name": "Notify Team via Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        -2208,
        -288
      ],
      "parameters": {
        "text": "=RFP Task Created for *{{ $('Combine Final Output Links').item.json.clientName }}*  \nTitle : {{ $('Combine Final Output Links').item.json.projectTitle }} \nRFP:  {{ $('Combine Final Output Links').item.json.rfpFileUrl }} \nPlease review & proceed.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "name",
          "value": "#general"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "c7181a58-8bc2-4919-8683-be201a88987a",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -6144,
        -528
      ],
      "parameters": {
        "color": 7,
        "width": 832,
        "height": 416,
        "content": "## RFP INGESTION MODULE\n\nPurpose:\nAutomatically detects and processes new RFP documents.                                            \nKey Config:\n\u2714 Replace Google Drive folder ID\n\u2714 Ensure PDF format compatibility\n\nOutput:\nRaw text + metadata ready for AI processing"
      },
      "typeVersion": 1
    },
    {
      "id": "ef24b9af-a191-4fb8-8e0b-ce1ed5b916f7",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -5200,
        -688
      ],
      "parameters": {
        "color": 7,
        "width": 576,
        "height": 672,
        "content": "## AI REQUIREMENT EXTRACTION\n\nPurpose:\nConvert unstructured RFP text into structured JSON.\n\nWhat AI Extracts:\n- Client name\n- Project scope\n- Budget & deadlines\n- Technical requirements\n- Evaluation criteria\n\nImportant:\n\u2714 Always returns clean JSON\n\u2714 Handles malformed AI responses safely\n\nOutput:\nStructured RFP data for downstream automation"
      },
      "typeVersion": 1
    },
    {
      "id": "9c6946a0-925c-4001-ad7c-bb28aa71dab1",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4480,
        -544
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 432,
        "content": "## KNOWLEDGE BASE ENRICHMENT\n\nPurpose:\nEnhance proposal quality using past proposals.\n\nBenefit:\n\u2714 Improves consistency\n\u2714 Reuses winning proposal patterns\n\nOutput:\nRequirements + reference context"
      },
      "typeVersion": 1
    },
    {
      "id": "25d804f9-8d9d-49b3-8c5f-07e95f7ef269",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3936,
        -640
      ],
      "parameters": {
        "color": 7,
        "width": 352,
        "height": 624,
        "content": "## AI PROPOSAL GENERATION\n\nPurpose:\nAutomatically generate a full RFP response.\n\nCustomization:\n\u2714 Update company profile in prompt\n\u2714 Adjust tone via temperature\n\nAI Behavior:\n- Tailored to extracted requirements\n- Uses knowledge base references\n\nOutput:\nComplete proposal draft (Markdown)"
      },
      "typeVersion": 1
    },
    {
      "id": "cfe17985-8784-4c55-90ed-03b222c6acc8",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3472,
        -624
      ],
      "parameters": {
        "color": 7,
        "width": 496,
        "height": 608,
        "content": "## OUTPUT STORAGE & CRM INTEGRATION\n\nPurpose:\nStore and track generated proposals.\n\nActions:\n- Saves proposal in Google Docs\n- Creates Salesforce Opportunity\n- Adds key RFP details (deadline, value, scope)\n\nOutput:\nDocument link + Salesforce record"
      },
      "typeVersion": 1
    },
    {
      "id": "3ed96ded-1c48-468b-b672-ed087767ba28",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2880,
        -544
      ],
      "parameters": {
        "color": 7,
        "width": 800,
        "height": 432,
        "content": "## REVIEW & NOTIFICATION SYSTEM\n\nPurpose:\nEnsure human review before submission.\n\nActions:\n- Creates Salesforce task\n- Attaches proposal + RFP link\n- Sends Slack notification to team\n"
      },
      "typeVersion": 1
    },
    {
      "id": "af4686b5-268f-467a-8c07-cc72aafd43ed",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -6896,
        -1104
      ],
      "parameters": {
        "width": 688,
        "height": 992,
        "content": "##  RFP AUTOMATION WORKFLOW (AI-POWERED)\n\n### WHAT THIS WORKFLOW DOES:\nThis workflow fully automates the RFP (Request for Proposal) lifecycle:\n1. Detects new RFP files uploaded to Google Drive\n2. Extracts and understands requirements using AI (Groq + LLaMA)\n3. Generates a complete proposal draft automatically\n4. Stores outputs (Google Docs + Salesforce)\n5. Assigns review tasks and notifies team via Slack\n\n### SETUP REQUIREMENTS:\n- Google Drive (Trigger folder + Knowledge Base folder)\n- Groq API (for AI processing)\n- Salesforce account (Opportunity + Task creation)\n- Google Docs account (to save proposals)\n- Slack integration (for notifications)\n\n###  WORKFLOW STEPS:\n1. Trigger \u2192 New RFP uploaded\n2. Extract \u2192 Read PDF content\n3. AI Analysis \u2192 Convert text to structured JSON\n4. Knowledge Base \u2192 Fetch past proposals\n5. AI Writing \u2192 Generate proposal draft\n6. Storage \u2192 Save to Google Docs + Salesforce\n7. Task Creation \u2192 Assign review task\n8. Notification \u2192 Alert team on Slack\n\n### BENEFITS:\n- Saves 90% manual effort in proposal writing\n- Faster turnaround time for RFP submissions\n- Standardized, high-quality proposals\n- Centralized tracking via Salesforce\n- Reduces human errors in requirement extraction\n\n### IDEAL USE CASE:\nConsulting firms, IT services companies, agencies handling frequent RFP submissions.\n\n### IMPORTANT NOTES:\n- Update folder IDs before running\n- Customize company profile in proposal generator\n- Validate AI output before final submission"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "8a8dd413-67ef-48fa-aeff-e47533714ce2",
  "connections": {
    "Prepare RFP Metadata": {
      "main": [
        [
          {
            "node": "AI Extract RFP Requirements",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download RFP Document": {
      "main": [
        [
          {
            "node": "Extract Text from RFP",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Text from RFP": {
      "main": [
        [
          {
            "node": "Prepare RFP Metadata",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clean & Parse AI Output": {
      "main": [
        [
          {
            "node": "Fetch Past Proposals (KB",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Watch RFP Upload Folder": {
      "main": [
        [
          {
            "node": "Download RFP Document",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Past Proposals (KB": {
      "main": [
        [
          {
            "node": "Combine Requirements + KB",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine Requirements + KB": {
      "main": [
        [
          {
            "node": "AI Generate Proposal Draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Final Output Data": {
      "main": [
        [
          {
            "node": "Create Salesforce Opportunity",
            "type": "main",
            "index": 0
          },
          {
            "node": "Save Proposal to Google Docs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Generate Proposal Draft": {
      "main": [
        [
          {
            "node": "Prepare Final Output Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine Final Output Links": {
      "main": [
        [
          {
            "node": "Create Review Task in Salesforce",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Extract RFP Requirements": {
      "main": [
        [
          {
            "node": "Clean & Parse AI Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Proposal to Google Docs": {
      "main": [
        [
          {
            "node": "Merge Docs + Salesforce Results",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "AI Model \u2013 Proposal Writing": {
      "ai_languageModel": [
        [
          {
            "node": "AI Generate Proposal Draft",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Create Salesforce Opportunity": {
      "main": [
        [
          {
            "node": "Merge Docs + Salesforce Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Docs + Salesforce Results": {
      "main": [
        [
          {
            "node": "Combine Final Output Links",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Review Task in Salesforce": {
      "main": [
        [
          {
            "node": "Notify Team via Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Model \u2013 Requirement Extraction": {
      "ai_languageModel": [
        [
          {
            "node": "AI Extract RFP Requirements",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}