{
  "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
          }
        ]
      ]
    }
  }
}