AutomationFlows β€Ί AI & RAG β€Ί Ai-powered Autonomous B2b Supplier Price Negotiation Agent

Ai-powered Autonomous B2b Supplier Price Negotiation Agent

ByRahul Joshi @rahul08βœ“ on n8n.io

Automate your entire supplier negotiation process with this AI-driven workflow that intelligently drafts, refines, and sends negotiation emails πŸ“§. Using advanced LLM reasoning and multi-angle strategies πŸ€–, it generates high-converting negotiation messages tailored to each…

Event triggerβ˜…β˜…β˜…β˜…β˜† complexityAI-powered29 nodesGoogle Sheets TriggerGmailGoogle SheetsNotionSlackOpenAI ChatAgent
AI & RAG Trigger: Event Nodes: 29 Complexity: β˜…β˜…β˜…β˜…β˜† AI nodes: yes Added:

This workflow corresponds to n8n.io template #15686 β€” we link there as the canonical source.

This workflow follows the Agent β†’ Gmail recipe pattern β€” see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide β†’

Download .json
{
  "id": "wqP7nSudZJpKVk2t",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Autonomous B2B Supplier Price Negotiation Agent",
  "tags": [],
  "nodes": [
    {
      "id": "fcd461f2-9593-40e4-ac4d-725161d35884",
      "name": "\ud83d\udccb Trigger \u2014 New Supplier Row",
      "type": "n8n-nodes-base.googleSheetsTrigger",
      "position": [
        -2304,
        1120
      ],
      "parameters": {
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1AqoI7azDDBPYyV4cZmEAQkG7cL48bvvyIU5ti_Llebk/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1AqoI7azDDBPYyV4cZmEAQkG7cL48bvvyIU5ti_Llebk",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1AqoI7azDDBPYyV4cZmEAQkG7cL48bvvyIU5ti_Llebk/edit?usp=drivesdk",
          "cachedResultName": "Negotiation sheet"
        }
      },
      "credentials": {
        "googleSheetsTriggerOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "af86c8e6-71e8-4231-9919-75439114189f",
      "name": "\ud83d\udd0d Validate & Prepare Supplier Data",
      "type": "n8n-nodes-base.code",
      "position": [
        -2096,
        1120
      ],
      "parameters": {
        "jsCode": "const row = $input.first().json;\n\n// Helper to convert Excel serial date to ISO string\nfunction excelDateToISO(serial) {\n  if (!serial || isNaN(serial)) return '';\n  const date = new Date((serial - 25569) * 86400 * 1000);\n  return date.toISOString();\n}\n\n// Clean email \u2014 strip markdown link format [email](mailto:email)\nfunction cleanEmail(val) {\n  if (!val) return '';\n  const match = val.match(/\\[([^\\]]+)\\]\\(mailto:[^\\)]+\\)/);\n  return match ? match[1] : val;\n}\n\n// Validate required fields (using ACTUAL column names from your sheet)\nif (!row['Supplier URL'] || !row['Product / Item'] || !row['Quantity'] || !row['Our Budget ($)']) {\n  throw new Error('Missing required fields: Supplier URL, Product / Item, Quantity, or Our Budget ($)');\n}\n\nreturn [{\n  json: {\n    rowId:        row['Row ID'] || Date.now().toString(),\n    supplierName: row['Supplier Name'] || 'Unknown Supplier',\n    supplierUrl:  row['Supplier URL'],\n    supplierEmail: cleanEmail(row['Supplier Email']),\n    product:      row['Product / Item'],\n    quantity:     row['Quantity'],\n    budget:       row['Our Budget ($)'],\n    listedPrice:  row['Listed Price ($)'] || row['Our Budget ($)'],\n    requestDate:  excelDateToISO(row['Request Date']),\n    messageSentAt: excelDateToISO(row['Message Sent At']),\n    retrySentAt:  excelDateToISO(row['Retry Sent At']),\n    finalPrice:   row['Final Price ($)'] || null,\n    status:       row['Status'] || 'Pending',\n    angleTried:   row['Angle Tried'] || '',\n    timestamp:    new Date().toISOString()\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "b4fc23df-4ce3-47c2-9859-2acdbd4bc5d5",
      "name": "\ud83c\udfc6 Pick Best Draft",
      "type": "n8n-nodes-base.code",
      "position": [
        -1456,
        1120
      ],
      "parameters": {
        "jsCode": "const responseBody = $input.first().json;\nconst rawText = responseBody.content[0].text;\n\nlet drafts;\ntry {\n  drafts = JSON.parse(rawText);\n} catch (e) {\n  // Try to extract JSON from response if wrapped in text\n  const match = rawText.match(/\\[\\s*\\{[\\s\\S]*\\}\\s*\\]/);\n  if (match) {\n    drafts = JSON.parse(match[0]);\n  } else {\n    throw new Error('Could not parse MCTS drafts: ' + rawText);\n  }\n}\n\n// Sort by score descending\ndrafts.sort((a, b) => b.score - a.score);\n\nconst best = drafts[0];\nconst prevData = $('Prepare & Validate Data').first().json;\n\nreturn [{\n  json: {\n    ...prevData,\n    allDrafts: drafts,\n    bestDraft: best,\n    bestAngle: best.angle,\n    bestSubject: best.subject,\n    bestMessage: best.message,\n    bestScore: best.score\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "0df8a2b8-2f68-4125-a6c9-46b25618e463",
      "name": "\ud83d\udcdd Parse Final Critique Output",
      "type": "n8n-nodes-base.code",
      "position": [
        -848,
        1120
      ],
      "parameters": {
        "jsCode": "const responseBody = $input.first().json;\nconst rawText = responseBody.content[0].text;\n\nlet critique;\ntry {\n  critique = JSON.parse(rawText);\n} catch (e) {\n  const match = rawText.match(/\\{[\\s\\S]*\\}/);\n  if (match) {\n    critique = JSON.parse(match[0]);\n  } else {\n    throw new Error('Could not parse self-critique response: ' + rawText);\n  }\n}\n\nconst prevData = $('Pick Best Draft').first().json;\n\nreturn [{\n  json: {\n    ...prevData,\n    critique: critique.critique,\n    changesMade: critique.changes_made,\n    finalSubject: critique.final_subject,\n    finalMessage: critique.final_message\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "c9e8da44-f8fb-4503-9376-86bfcfd19a46",
      "name": "\ud83d\udce7 Send Negotiation Email to Supplier",
      "type": "n8n-nodes-base.gmail",
      "position": [
        -624,
        1120
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "={{ $json.finalMessage }}",
        "options": {
          "replyTo": "user@example.com"
        },
        "subject": "={{ $json.finalSubject }} [REF-{{ $json.rowId }}]",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "c16210b6-90c5-4724-8341-46a632fba559",
      "name": "\u2705 Mark Email Sent in Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -400,
        1120
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1085802152,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1AqoI7azDDBPYyV4cZmEAQkG7cL48bvvyIU5ti_Llebk/edit#gid=1085802152",
          "cachedResultName": "Sheet2"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1AqoI7azDDBPYyV4cZmEAQkG7cL48bvvyIU5ti_Llebk",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1AqoI7azDDBPYyV4cZmEAQkG7cL48bvvyIU5ti_Llebk/edit?usp=drivesdk",
          "cachedResultName": "Negotiation sheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "6abc72e0-21b1-42ce-8e90-9ffd3a03046e",
      "name": "\u23f3 Wait 24 Hours for Reply",
      "type": "n8n-nodes-base.wait",
      "position": [
        -176,
        1120
      ],
      "parameters": {
        "unit": "hours",
        "amount": 24
      },
      "typeVersion": 1.1
    },
    {
      "id": "35c62bd8-0b22-409c-9d04-efd7cfaeb74e",
      "name": "\ud83d\udcec Check Supplier Reply (Gmail)",
      "type": "n8n-nodes-base.gmail",
      "position": [
        32,
        1120
      ],
      "parameters": {
        "limit": 5,
        "filters": {
          "q": "=subject:[REF-{{ $('Parse Critique Result').first().json.rowId }}] in:inbox"
        },
        "operation": "getAll"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "846f02a0-fa0e-4f4b-a08d-ec986f651c2a",
      "name": "\u2753 Reply Received?",
      "type": "n8n-nodes-base.if",
      "position": [
        256,
        1120
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "check_reply_condition",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.messages ? $json.messages.length : 0 }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "31e9fbe2-49bb-4d33-ae61-be962abca7d1",
      "name": "\ud83d\udd04 Build DPO Retry Prompt",
      "type": "n8n-nodes-base.code",
      "position": [
        736,
        1280
      ],
      "parameters": {
        "jsCode": "const responseBody = $input.first().json;\nconst rawText = responseBody.content[0].text;\n\nlet retry;\ntry {\n  retry = JSON.parse(rawText);\n} catch (e) {\n  const match = rawText.match(/\\{[\\s\\S]*\\}/);\n  if (match) {\n    retry = JSON.parse(match[0]);\n  } else {\n    throw new Error('Could not parse DPO retry: ' + rawText);\n  }\n}\n\nconst prevData = $('Parse Critique Result').first().json;\n\nreturn [{\n  json: {\n    ...prevData,\n    retryAngle: retry.angle_used,\n    retrySubject: retry.subject,\n    retryMessage: retry.message,\n    retryReasoning: retry.strategy_reasoning\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "989ff4fc-a6e1-4835-ad49-85d408188f57",
      "name": "\ud83d\udce7 Send Follow-Up Retry Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        928,
        1280
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "={{ $json.retryMessage }}",
        "options": {
          "replyTo": "user@example.com"
        },
        "subject": "={{ $json.retrySubject }} [REF-{{ $json.rowId }}]",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "a16b18fc-173a-4aec-b2c6-819b832769fe",
      "name": "\u2705 Mark Retry Sent in Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1152,
        1280
      ],
      "parameters": {
        "columns": {
          "value": {
            "Status": "Retry Sent",
            "Angle Tried": "={{ $json.retryAngle }}",
            "Retry Sent At": "={{ new Date().toISOString() }}"
          },
          "mappingMode": "defineBelow"
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "8525f61d-221d-493b-a83f-9c7f8275174a",
      "name": "\u2699\ufe0f Process & Score Supplier Reply",
      "type": "n8n-nodes-base.code",
      "position": [
        480,
        976
      ],
      "parameters": {
        "jsCode": "// This node handles REPLY RECEIVED path\n// Parse the email reply and extract negotiated price if mentioned\nconst replyData = $input.first().json;\nconst prevData = $('Parse Critique Result').first().json;\n\nconst replySnippet = replyData.messages && replyData.messages[0] ? replyData.messages[0].snippet : 'Reply received';\n\nreturn [{\n  json: {\n    ...prevData,\n    outcome: 'Reply Received',\n    replySnippet: replySnippet,\n    finalStatus: 'Negotiated',\n    // Savings to be manually or AI-extracted \u2014 placeholder here\n    finalPrice: prevData.budget,\n    listedPrice: prevData.listedPrice,\n    savingsAmount: prevData.listedPrice - prevData.budget,\n    savingsPct: (((prevData.listedPrice - prevData.budget) / prevData.listedPrice) * 100).toFixed(2)\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "00e103aa-cc44-41b2-9791-de93f799e1b2",
      "name": "\ud83d\udcd2 Log Negotiation Result in Notion",
      "type": "n8n-nodes-base.notion",
      "position": [
        704,
        976
      ],
      "parameters": {
        "title": "=Negotiation \u2014 {{ $json.supplierName }} \u2014 {{ $json.product }} \u2014 {{ new Date().toLocaleDateString() }}",
        "pageId": {
          "__rl": true,
          "mode": "url",
          "value": "https://www.notion.so/Test-n8n-automation-350f839f118480fb9bddfb4278f2ae4e"
        },
        "blockUi": {
          "blockValues": [
            {
              "type": "heading_2",
              "textContent": "Negotiation Summary"
            },
            {
              "textContent": "=Supplier: {{ $json.supplierName }} | Product: {{ $json.product }} | Qty: {{ $json.quantity }}"
            },
            {
              "type": "heading_3",
              "textContent": "Messages Sent"
            },
            {
              "textContent": "=ANGLE 1 ({{ $json.bestAngle }} | Score: {{ $json.bestScore }})\n\nSubject: {{ $json.finalSubject }}\n\n{{ $json.finalMessage }}"
            },
            {
              "type": "heading_3",
              "textContent": "Self-Critique Notes"
            },
            {
              "textContent": "={{ $json.critique }}"
            }
          ]
        },
        "options": {}
      },
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "7fa2b483-db3d-43a0-84fd-31cc404098ad",
      "name": "\ud83d\udcca Final Update in Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        928,
        976
      ],
      "parameters": {
        "columns": {
          "value": {
            "Status": "={{ $('Process Reply Data').first().json.finalStatus || 'Completed' }}",
            "Savings %": "={{ $('Process Reply Data').first().json.savingsPct }}",
            "Final Price": "={{ $('Process Reply Data').first().json.finalPrice }}",
            "Notion Log URL": "={{ $json.url }}"
          },
          "mappingMode": "defineBelow"
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1AqoI7azDDBPYyV4cZmEAQkG7cL48bvvyIU5ti_Llebk",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1AqoI7azDDBPYyV4cZmEAQkG7cL48bvvyIU5ti_Llebk/edit?usp=drivesdk",
          "cachedResultName": "Negotiation sheet"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "15dd308f-5f51-4c94-ac03-47306b86fcfa",
      "name": "\ud83d\udd14 Slack \u2014 Alert Procurement Team",
      "type": "n8n-nodes-base.slack",
      "position": [
        1152,
        976
      ],
      "parameters": {
        "text": "=:white_check_mark: *Negotiation Complete*\n\n*Supplier:* {{ $('Process Reply Data').first().json.supplierName }}\n*Product:* {{ $('Process Reply Data').first().json.product }}\n*Quantity:* {{ $('Process Reply Data').first().json.quantity }} units\n\n:moneybag: *Listed Price:* ${{ $('Process Reply Data').first().json.listedPrice }}\n:chart_with_downwards_trend: *Final Price:* ${{ $('Process Reply Data').first().json.finalPrice }}\n:tada: *Savings:* {{ $('Process Reply Data').first().json.savingsPct }}%\n\n*Angle Used:* {{ $('Process Reply Data').first().json.bestAngle }}\n*Status:* {{ $('Process Reply Data').first().json.finalStatus }}\n\n:memo: Full audit log in Notion \u2192 {{ $('Notion \u2014 Log Negotiation').first().json.url }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "C0B0QTA3KG9"
        },
        "otherOptions": {},
        "authentication": "webhook"
      },
      "typeVersion": 2.2
    },
    {
      "id": "0f50708a-30cf-407d-afcb-f8380c3205dd",
      "name": "\ud83d\udd14 Slack \u2014 Retry Alert to Team",
      "type": "n8n-nodes-base.slack",
      "position": [
        1360,
        1280
      ],
      "parameters": {
        "text": "=:warning: *No Reply \u2014 Retry Sent*\n\n*Supplier:* {{ $json.supplierName }}\n*Product:* {{ $json.product }}\n*Original Angle:* {{ $json.bestAngle }}\n*Retry Angle:* {{ $json.retryAngle }}\n*Strategy:* {{ $json.retryReasoning }}\n\nRetry email sent. Monitor for response.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "C0B0QTA3KG9"
        },
        "otherOptions": {},
        "authentication": "webhook"
      },
      "typeVersion": 2.2
    },
    {
      "id": "3ae69061-db64-46b2-822d-590c1f84dee8",
      "name": "\u26a1 LLM \u2014 Draft Generator (GPT-4o)",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -2032,
        1328
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "a41b4843-380f-4208-b3a4-298f3e48837e",
      "name": "\ud83e\udde0 MCTS \u2014 Generate 3 Negotiation Drafts",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -1856,
        1120
      ],
      "parameters": {
        "text": "={{ JSON.stringify([{ role: 'user', content: `You are a professional B2B procurement negotiation expert. Generate exactly 3 negotiation email drafts for the following purchase request and score each one from 0\u201310.\n\nSupplier: ${$json.supplierName}\nProduct: ${$json.product}\nQuantity: ${$json.quantity} units\nOur Budget: $${$json.budget}\nListed Price: $${$json.listedPrice}\n\nGenerate 3 negotiation angles:\n1. BULK_DISCOUNT - Leverage quantity for a volume discount\n2. COMPETITOR_MATCH - Mention we are evaluating competitors and request price matching\n3. LOYALTY_OFFER - Offer long-term partnership/repeat business in exchange for better price\n\nFor each draft, write a professional, concise email (150\u2013200 words). Score each on: tone (0-3), specificity (0-3), persuasiveness (0-4).\n\nReturn ONLY valid JSON in this exact format, no markdown:\n[\n  {\n    \"angle\": \"BULK_DISCOUNT\",\n    \"subject\": \"email subject line\",\n    \"message\": \"full email body\",\n    \"score\": 8.5,\n    \"reasoning\": \"why this angle scores this way\"\n  },\n  {\n    \"angle\": \"COMPETITOR_MATCH\",\n    \"subject\": \"email subject line\",\n    \"message\": \"full email body\",\n    \"score\": 7.0,\n    \"reasoning\": \"why this angle scores this way\"\n  },\n  {\n    \"angle\": \"LOYALTY_OFFER\",\n    \"subject\": \"email subject line\",\n    \"message\": \"full email body\",\n    \"score\": 6.5,\n    \"reasoning\": \"why this angle scores this way\"\n  }\n]` }]) }}",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "f0c68df0-1611-4443-b314-8b033517fae0",
      "name": "\u26a1 LLM \u2014 Critique Model (GPT-4o)",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -1360,
        1344
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "6bd57383-5301-4668-bfd3-d5181068c9b5",
      "name": "\ud83d\udd01 Self-Critique Round 1 \u2014 Refine Draft",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -1232,
        1120
      ],
      "parameters": {
        "text": "={{ JSON.stringify([{ role: 'user', content: `You are a senior procurement communication expert performing a self-critique review.\n\nReview the following negotiation email draft and improve it if needed. Focus on:\n1. TONE: Professional, confident but not aggressive\n2. SPECIFICITY: Includes product name, quantity, specific ask\n3. CREDIBILITY: Sounds like a real business with genuine intent\n4. CLARITY: Clear call to action\n\nOriginal Draft:\nSubject: ${$json.bestSubject}\n\n${$json.bestMessage}\n\nProvide your critique and the FINAL IMPROVED VERSION. Return ONLY valid JSON, no markdown:\n{\n  \"critique\": \"your brief critique (2-3 sentences)\",\n  \"changes_made\": \"what you changed and why\",\n  \"final_subject\": \"final subject line\",\n  \"final_message\": \"final email body ready to send\"\n}` }]) }}",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "a178de69-14c7-462f-af46-b33767a741ef",
      "name": "\u26a1 LLM \u2014 Final Polish Model (GPT-4o)",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        336,
        1440
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "e06737a5-b4f0-42ea-9bb7-6d6bdc3cea36",
      "name": "\ud83d\udd01 Self-Critique Round 2 \u2014 Final Polish",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        432,
        1280
      ],
      "parameters": {
        "text": "={{ JSON.stringify([{ role: 'user', content: `You are a procurement negotiation expert. The first email was sent but received no reply within 24 hours. Apply DPO (Direct Preference Optimization) logic to craft a stronger follow-up.\n\nContext:\n- Supplier: ${$('Parse Critique Result').first().json.supplierName}\n- Product: ${$('Parse Critique Result').first().json.product}\n- Quantity: ${$('Parse Critique Result').first().json.quantity}\n- Budget: $${$('Parse Critique Result').first().json.budget}\n- First angle tried: ${$('Parse Critique Result').first().json.bestAngle}\n- First message score: ${$('Parse Critique Result').first().json.bestScore}\n- All drafted angles: ${JSON.stringify($('Parse Critique Result').first().json.allDrafts.map(d => d.angle))}\n\nThe supplier ignored our first email. Now pick the NEXT BEST angle from the remaining drafts and rewrite it to be:\n1. More assertive and urgent\n2. Mention that we need a response within 48 hours\n3. Hint at competitor alternatives\n4. Shorter and punchier (under 120 words)\n\nReturn ONLY valid JSON:\n{\n  \"angle_used\": \"angle name\",\n  \"subject\": \"follow-up subject line\",\n  \"message\": \"follow-up email body\",\n  \"strategy_reasoning\": \"why this approach works better now\"\n}` }]) }}",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "24ad2dc9-8780-4d69-ad0e-b0ca1a79c3a3",
      "name": "Sticky Note \u2014 Phase 1: Data Ingestion",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2496,
        912
      ],
      "parameters": {
        "color": 3,
        "width": 420,
        "height": 180,
        "content": "## \ud83d\udce5 Phase 1: Data Ingestion\nTriggered when a new supplier row is added to Google Sheets.\nValidates and prepares supplier data (name, product, target price, etc.) before passing to the AI pipeline."
      },
      "typeVersion": 1
    },
    {
      "id": "08e70d92-cca8-4f4c-880a-19941f90d2f4",
      "name": "Sticky Note \u2014 Phase 2: AI Email Drafting (MCTS + Self-Critique)",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1920,
        912
      ],
      "parameters": {
        "color": 5,
        "width": 700,
        "height": 200,
        "content": "## \ud83e\udde0 Phase 2: AI Email Drafting\nUses **MCTS** to simulate 3 negotiation angles, then **two rounds of Self-Critique** to refine and polish the best draft.\n- Round 1: Critique & improve tone/strategy\n- Round 2: Final polish for professionalism\n\nOutputs the best negotiation email draft."
      },
      "typeVersion": 1
    },
    {
      "id": "97657ab8-9e79-428b-870a-d4e1f042a2bc",
      "name": "Sticky Note \u2014 Phase 3: Send & Track Email",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -656,
        912
      ],
      "parameters": {
        "color": 6,
        "width": 460,
        "content": "## \ud83d\udce7 Phase 3: Send & Track\nSends the AI-crafted negotiation email via Gmail and marks the row in Google Sheets as 'Email Sent'.\nThen waits 24 hours for a supplier reply."
      },
      "typeVersion": 1
    },
    {
      "id": "400e674a-b45a-4d97-8cc8-3660ddb3c406",
      "name": "Sticky Note \u2014 Phase 4: Reply Detection & Routing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -32,
        768
      ],
      "parameters": {
        "color": 4,
        "width": 520,
        "height": 175,
        "content": "## \ud83d\udcec Phase 4: Reply Detection & Routing\nChecks Gmail for a supplier reply after the wait period.\n- \u2705 **Reply received** \u2192 Process reply, log in Notion, update Sheets, alert Slack\n- \u274c **No reply** \u2192 Build DPO retry prompt, send follow-up email, notify Slack"
      },
      "typeVersion": 1
    },
    {
      "id": "0655cfe2-fe2c-4188-984b-3d11debe7924",
      "name": "Sticky Note \u2014 Phase 5: Logging & Notifications",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        672,
        800
      ],
      "parameters": {
        "color": 7,
        "width": 440,
        "height": 165,
        "content": "## \ud83d\udcca Phase 5: Logging & Notifications\nAfter a reply is received:\n- Processes and scores the supplier's response\n- Logs full negotiation outcome in **Notion**\n- Updates **Google Sheets** with final status\n- Sends **Slack** alert to procurement team"
      },
      "typeVersion": 1
    },
    {
      "id": "14cd1ae7-0664-441c-ab43-b290ee0cb8c1",
      "name": "Sticky Note \u2014 Phase 6: No-Reply Retry Flow",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        688,
        1504
      ],
      "parameters": {
        "color": 2,
        "width": 420,
        "height": 187,
        "content": "## \ud83d\udd04 Phase 6: No-Reply Retry Flow\nIf no supplier reply after 24 hrs:\n- Builds a **DPO-style retry prompt** for urgency\n- Sends a follow-up email via Gmail\n- Marks retry in Google Sheets\n- Alerts Slack with retry status"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "de414ee2-a696-4e24-a3c3-4e009b64118c",
  "connections": {
    "\u2753 Reply Received?": {
      "main": [
        [
          {
            "node": "\u2699\ufe0f Process & Score Supplier Reply",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "\ud83d\udd01 Self-Critique Round 2 \u2014 Final Polish",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83c\udfc6 Pick Best Draft": {
      "main": [
        [
          {
            "node": "\ud83d\udd01 Self-Critique Round 1 \u2014 Refine Draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u23f3 Wait 24 Hours for Reply": {
      "main": [
        [
          {
            "node": "\ud83d\udcec Check Supplier Reply (Gmail)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd04 Build DPO Retry Prompt": {
      "main": [
        [
          {
            "node": "\ud83d\udce7 Send Follow-Up Retry Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u2705 Mark Email Sent in Sheet": {
      "main": [
        [
          {
            "node": "\u23f3 Wait 24 Hours for Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u2705 Mark Retry Sent in Sheet": {
      "main": [
        [
          {
            "node": "\ud83d\udd14 Slack \u2014 Retry Alert to Team",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udce7 Send Follow-Up Retry Email": {
      "main": [
        [
          {
            "node": "\u2705 Mark Retry Sent in Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcdd Parse Final Critique Output": {
      "main": [
        [
          {
            "node": "\ud83d\udce7 Send Negotiation Email to Supplier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udccb Trigger \u2014 New Supplier Row": {
      "main": [
        [
          {
            "node": "\ud83d\udd0d Validate & Prepare Supplier Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcec Check Supplier Reply (Gmail)": {
      "main": [
        [
          {
            "node": "\u2753 Reply Received?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcca Final Update in Google Sheets": {
      "main": [
        [
          {
            "node": "\ud83d\udd14 Slack \u2014 Alert Procurement Team",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u26a1 LLM \u2014 Critique Model (GPT-4o)": {
      "ai_languageModel": [
        [
          {
            "node": "\ud83d\udd01 Self-Critique Round 1 \u2014 Refine Draft",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "\u26a1 LLM \u2014 Draft Generator (GPT-4o)": {
      "ai_languageModel": [
        [
          {
            "node": "\ud83e\udde0 MCTS \u2014 Generate 3 Negotiation Drafts",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "\u2699\ufe0f Process & Score Supplier Reply": {
      "main": [
        [
          {
            "node": "\ud83d\udcd2 Log Negotiation Result in Notion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udcd2 Log Negotiation Result in Notion": {
      "main": [
        [
          {
            "node": "\ud83d\udcca Final Update in Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd0d Validate & Prepare Supplier Data": {
      "main": [
        [
          {
            "node": "\ud83e\udde0 MCTS \u2014 Generate 3 Negotiation Drafts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u26a1 LLM \u2014 Final Polish Model (GPT-4o)": {
      "ai_languageModel": [
        [
          {
            "node": "\ud83d\udd01 Self-Critique Round 2 \u2014 Final Polish",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udce7 Send Negotiation Email to Supplier": {
      "main": [
        [
          {
            "node": "\u2705 Mark Email Sent in Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd01 Self-Critique Round 1 \u2014 Refine Draft": {
      "main": [
        [
          {
            "node": "\ud83d\udcdd Parse Final Critique Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd01 Self-Critique Round 2 \u2014 Final Polish": {
      "main": [
        [
          {
            "node": "\ud83d\udd04 Build DPO Retry Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83e\udde0 MCTS \u2014 Generate 3 Negotiation Drafts": {
      "main": [
        [
          {
            "node": "\ud83c\udfc6 Pick Best Draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

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

Pro

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

About this workflow

Automate your entire supplier negotiation process with this AI-driven workflow that intelligently drafts, refines, and sends negotiation emails πŸ“§. Using advanced LLM reasoning and multi-angle strategies πŸ€–, it generates high-converting negotiation messages tailored to each…

Source: https://n8n.io/workflows/15686/ β€” original creator credit. Request a take-down β†’

More AI & RAG workflows β†’ Β· Browse all categories β†’

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Automate end-to-end vendor onboarding workflows with an AI-powered autonomous agent built in n8n πŸ€–. This workflow uses advanced MCTS (Monte Carlo Tree Search) reasoning to intelligently map procuremen

Agent, OpenAI Chat, Google Drive +4
AI & RAG

Consultants, agencies, freelancers, and project managers who want to ensure proposals, emails, and tasks are followed up on time.

Google Sheets Trigger, Agent, OpenAI Chat +6
AI & RAG

Who is this for? This template is perfect for agencies, consultancies, freelancers, and project-based teams who want to eliminate repetitive onboarding tasks. If you're tired of manually creating fold

Google Drive Trigger, Google Drive, Slack +5
AI & RAG

Streamline supplier sourcing and decision-making with this AI-powered price comparison automation πŸ€–. This workflow intelligently researches multiple suppliers in real-time, extracts pricing, delivery

Google Sheets Trigger, Agent, HTTP Request +4
AI & RAG

Turn employee recognition into an automated system.

OpenAI Chat, Google Sheets Trigger, Agent +3