{
  "name": "Revenue Ops CRM Sync and Enrichment",
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "03e50be0-bd1f-4444-8912-a426aa3efb76",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 6
            }
          ]
        }
      },
      "id": "six_hour_trigger",
      "name": "6 Hour Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1,
      "position": [
        220,
        320
      ]
    },
    {
      "parameters": {
        "resource": "deal",
        "operation": "search",
        "additionalFields": {}
      },
      "id": "hubspot_search_deals",
      "name": "HubSpot Search Deals",
      "type": "n8n-nodes-base.hubspot",
      "typeVersion": 2.2,
      "position": [
        470,
        320
      ]
    },
    {
      "parameters": {
        "jsCode": "return $input.all().map((item) => {\n  const daysInStage = Number(item.json.daysInStage || item.json.stageAgeDays || 18);\n  const amount = Number(item.json.amount || item.json.dealValue || 12000);\n\n  let deterministicScore = 30;\n  if (daysInStage > 14) deterministicScore += 25;\n  if (daysInStage > 30) deterministicScore += 20;\n  if (amount >= 10000) deterministicScore += 15;\n\n  return {\n    json: {\n      ...item.json,\n      deterministicScore,\n      daysInStage,\n      amount,\n    },\n  };\n});"
      },
      "id": "deterministic_deal_risk",
      "name": "Deterministic Deal Risk",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        700,
        320
      ]
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "={{'You assess revenue pipeline slippage. Return strict JSON with keys aiScore (0-100), priority (at_risk|healthy), summary (string). Deal payload: ' + JSON.stringify($json)}}",
        "options": {}
      },
      "id": "ai_deal_risk_agent",
      "name": "AI Deal Risk Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        940,
        220
      ]
    },
    {
      "parameters": {
        "model": {
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "id": "openai_chat_model",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.3,
      "position": [
        940,
        520
      ]
    },
    {
      "parameters": {
        "jsCode": "return $input.all().map((item) => {\n  const rawCandidate =\n    item.json.output ??\n    item.json.text ??\n    item.json.response ??\n    item.json.result ??\n    item.json;\n\n  let parsed = {};\n\n  if (typeof rawCandidate === 'string') {\n    try {\n      parsed = JSON.parse(rawCandidate);\n    } catch (error) {\n      parsed = { summary: rawCandidate };\n    }\n  } else if (rawCandidate && typeof rawCandidate === 'object') {\n    parsed = rawCandidate;\n  }\n\n  const pickNumber = (...keys) => {\n    for (const key of keys) {\n      const value = Number(parsed[key]);\n      if (Number.isFinite(value) && value > 0) return value;\n    }\n    return 0;\n  };\n\n  const pickString = (...keys) => {\n    for (const key of keys) {\n      const value = parsed[key];\n      if (typeof value === 'string' && value.trim()) return value.trim();\n    }\n    return '';\n  };\n\n  return {\n    json: {\n      aiScore: pickNumber('aiScore', 'score', 'riskScore', 'severityScore', 'readinessScore'),\n      aiPriority: pickString('priority', 'queue', 'recommendation', 'decision'),\n      aiSummary: pickString('summary', 'rationale', 'reason', 'triageSummary', 'recommendation') || 'ai_response_unavailable',\n      aiPayload: parsed,\n    },\n  };\n});"
      },
      "id": "parse_ai_output",
      "name": "Parse AI Output",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1160,
        220
      ]
    },
    {
      "parameters": {
        "mode": "combine"
      },
      "id": "merge_ai_with_rules",
      "name": "Merge AI with Rules",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        1160,
        360
      ]
    },
    {
      "parameters": {
        "jsCode": "return $input.all().map((item) => {\n  const deterministicScore = Number(item.json.deterministicScore || 0);\n  const aiScore = Number(item.json.aiScore || 0);\n  const dealRiskScore = aiScore > 0\n    ? Math.round((deterministicScore * 0.65) + (aiScore * 0.35))\n    : deterministicScore;\n\n  const health = dealRiskScore >= 70 ? 'at_risk' : 'healthy';\n\n  return {\n    json: {\n      ...item.json,\n      dealRiskScore,\n      health,\n      riskSummary: item.json.aiSummary || 'deterministic fallback used',\n    },\n  };\n});"
      },
      "id": "final_deal_decision",
      "name": "Final Deal Decision",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1380,
        360
      ]
    },
    {
      "parameters": {
        "resource": "contact",
        "operation": "upsert",
        "email": "={{\"owner@example.com\"}}",
        "additionalFields": {}
      },
      "id": "hubspot_sync_owner_contact",
      "name": "HubSpot Sync Owner Contact",
      "type": "n8n-nodes-base.hubspot",
      "typeVersion": 2.2,
      "position": [
        1600,
        480
      ]
    },
    {
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{$json.dealRiskScore}}",
              "operation": "largerEqual",
              "value2": 70
            }
          ]
        }
      },
      "id": "at_risk_check",
      "name": "At Risk Deal?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1600,
        320
      ]
    },
    {
      "parameters": {
        "resource": "databasePage",
        "operation": "create",
        "databaseId": {
          "mode": "url",
          "value": "https://www.notion.so/00000000000000000000000000000000"
        },
        "title": "={{\"RevOps: \" + ($json.health || \"healthy\") + \" | score \" + ($json.dealRiskScore || 0)}}",
        "simple": true
      },
      "id": "notion_revops_log",
      "name": "Notion RevOps Log",
      "type": "n8n-nodes-base.notion",
      "typeVersion": 2.2,
      "position": [
        1820,
        360
      ]
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "post",
        "select": "channel",
        "channelId": {
          "mode": "id",
          "value": "C01234567"
        },
        "messageType": "text",
        "text": "={{\"\ud83d\udea8 At-risk deal detected | score \" + ($json.dealRiskScore || 0) + \" | days \" + ($json.daysInStage || 0)}}"
      },
      "id": "slack_at_risk_alert",
      "name": "Slack At Risk Alert",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.4,
      "position": [
        1820,
        180
      ]
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "post",
        "select": "channel",
        "channelId": {
          "mode": "id",
          "value": "C01234567"
        },
        "messageType": "text",
        "text": "={{\"\u2705 Deal health normal | score \" + ($json.dealRiskScore || 0)}}"
      },
      "id": "slack_healthy_update",
      "name": "Slack Healthy Update",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.4,
      "position": [
        1820,
        540
      ]
    },
    {
      "parameters": {
        "resource": "message",
        "operation": "send",
        "sendTo": "={{\"owner@example.com\"}}",
        "subject": "RevOps Deal Health Summary",
        "message": "={{\"Health: \" + ($json.health || \"healthy\") + \"\\nScore: \" + ($json.dealRiskScore || 0) + \"\\nSummary: \" + ($json.riskSummary || \"N/A\")}}"
      },
      "id": "gmail_revops_summary",
      "name": "Gmail RevOps Summary",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.2,
      "position": [
        2050,
        360
      ]
    }
  ],
  "connections": {
    "6 Hour Trigger": {
      "main": [
        [
          {
            "node": "HubSpot Search Deals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HubSpot Search Deals": {
      "main": [
        [
          {
            "node": "Deterministic Deal Risk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Deterministic Deal Risk": {
      "main": [
        [
          {
            "node": "AI Deal Risk Agent",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Merge AI with Rules",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Deal Risk Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "AI Deal Risk Agent": {
      "main": [
        [
          {
            "node": "Parse AI Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Output": {
      "main": [
        [
          {
            "node": "Merge AI with Rules",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge AI with Rules": {
      "main": [
        [
          {
            "node": "Final Deal Decision",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Final Deal Decision": {
      "main": [
        [
          {
            "node": "At Risk Deal?",
            "type": "main",
            "index": 0
          },
          {
            "node": "HubSpot Sync Owner Contact",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "At Risk Deal?": {
      "main": [
        [
          {
            "node": "Slack At Risk Alert",
            "type": "main",
            "index": 0
          },
          {
            "node": "Notion RevOps Log",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack Healthy Update",
            "type": "main",
            "index": 0
          },
          {
            "node": "Notion RevOps Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notion RevOps Log": {
      "main": [
        [
          {
            "node": "Gmail RevOps Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}