{
  "id": "6SmexSPg5EApcVTo",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AI-Powered Wealth Management",
  "tags": [],
  "nodes": [
    {
      "id": "09bdd0fa-1be8-4151-84ec-fca21d83cfb7",
      "name": "Trigger: Portfolio Updated",
      "type": "n8n-nodes-base.googleSheetsTrigger",
      "position": [
        -432,
        208
      ],
      "parameters": {
        "event": "rowUpdate",
        "options": {
          "columnsToWatch": [
            "Trigger_Status"
          ]
        },
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1zvjvsgxrtNQSeULTIs21Be0p2xzTZMU-mxFsV_B46ug/edit#gid=0",
          "cachedResultName": "\u0936\u0940\u091f1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1zvjvsgxrtNQSeULTIs21Be0p2xzTZMU-mxFsV_B46ug",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1zvjvsgxrtNQSeULTIs21Be0p2xzTZMU-mxFsV_B46ug/edit?usp=drivesdk",
          "cachedResultName": "Wealth Management - Portfolio Updates"
        }
      },
      "credentials": {
        "googleSheetsTriggerOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b7107526-0faf-4824-aabb-0dc5d996bcc0",
      "name": "Parse Trades & Tickers",
      "type": "n8n-nodes-base.code",
      "position": [
        -208,
        208
      ],
      "parameters": {
        "jsCode": "for (const item of $input.all()) {\n  // 1. Parse the stringified trades from Google Sheets into a real JSON object\n  const trades = JSON.parse(item.json.Trades_Made);\n  item.json.trades_parsed = trades;\n\n  // 2. Extract just the ticker symbols (e.g., \"AAPL,NVDA\") for our News API\n  const tickers = trades.map(trade => trade.ticker).join(',');\n  item.json.tickers_list = tickers;\n}\nreturn $input.all();"
      },
      "typeVersion": 2
    },
    {
      "id": "3f48d70c-d38c-481b-848f-746412aadd60",
      "name": "Mock: Client Risk Profile",
      "type": "n8n-nodes-base.set",
      "position": [
        16,
        208
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "4a0267ba-97ed-46be-8fa1-b7be9107332a",
              "name": "Client_Risk_Profile",
              "type": "string",
              "value": "Conservative"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "01655eee-4c00-4e96-aeef-c7410c79eaef",
      "name": "Mock: Market Context",
      "type": "n8n-nodes-base.set",
      "position": [
        240,
        208
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "8a88e3df-e1c5-4cce-ade2-6cf2a9e7d4b0",
              "name": "Market_Context",
              "type": "string",
              "value": "Tech stocks are currently experiencing high volatility due to supply chain issues. We are shifting capital towards more stable, high-demand sectors like defense and AI infrastructure."
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "a2a5d510-ffb3-4f2b-983a-eeff39dd0a74",
      "name": "AI: Draft Client Email",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        464,
        208
      ],
      "parameters": {
        "text": "=You are a senior wealth management advisor. Write a concise, professional and easy-to-understand email to your client explaining recent changes to their portfolio. \n\nDo not use overly complex financial jargon. Adjust your tone based on the client's risk profile.\n\nHere is the context for the email:\nClient Name: {{ $json.Client_Name }}\nClient Risk Profile: {{ $json.Client_Risk_Profile }}\nRecent Market News: {{ $json.Market_Context }}\nTrades Executed: {{ JSON.stringify($json.trades_parsed) }}\n\nFormat the email with:\n1. A polite greeting.\n2. What changed in their portfolio.\n3. Why we made the change (reference the market news).\n4. The expected impact on their portfolio.\n5. A professional sign-off.",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "087de054-d7d8-44d8-adad-e2d9c79b339f",
      "name": "LLM: Gemini",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        464,
        416
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c5a83320-1dd4-4677-aab3-caa35a5ecb08",
      "name": "Slack: Request Advisor Approval",
      "type": "n8n-nodes-base.slack",
      "position": [
        816,
        208
      ],
      "parameters": {
        "text": "= *New Portfolio Update Draft for {{ $('Mock: Market Context').item.json.Client_Name }}*   *Drafted Email:* > {{ $json.output }}  *Action Required:*  <{{ $execution.resumeUrl }}?action=approve|Approve & Send to Client>  <{{ $execution.resumeUrl }}?action=reject|Reject & Discard>\n\n",
        "user": {
          "__rl": true,
          "mode": "id",
          "value": "U0AP17N3QRY"
        },
        "select": "user",
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "291ae347-4121-487f-bacf-57ce07307817",
      "name": "Wait: Advisor Action",
      "type": "n8n-nodes-base.wait",
      "position": [
        1040,
        208
      ],
      "parameters": {
        "resume": "webhook",
        "options": {},
        "resumeUnit": "days",
        "resumeAmount": 2,
        "limitWaitTime": true
      },
      "typeVersion": 1.1
    },
    {
      "id": "781ced2c-33ee-4305-84b6-7e7fef34ac4b",
      "name": "Route: Approve vs Reject",
      "type": "n8n-nodes-base.switch",
      "position": [
        1264,
        208
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "29be4920-80af-467f-80a5-31e84a4da0a9",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.query.action }}",
                    "rightValue": "approve"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "25305078-bc02-4569-8014-569af3f37d0f",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "= {{ $json.query.action }}",
                    "rightValue": "reject"
                  }
                ]
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": 1
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "946e95f0-b396-4581-a779-8d681cc93840",
      "name": "Gmail: Send to Client",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1488,
        112
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "={{ $('AI: Draft Client Email').item.json.output }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "Important Update Regarding Your Portfolio",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c35846b1-170e-4a68-8147-14acd7e39b27",
      "name": "Sheet: Mark as Completed",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1712,
        112
      ],
      "parameters": {
        "columns": {
          "value": {
            "Client_ID": "={{ $('Trigger: Portfolio Updated').item.json.Client_ID }}",
            "Trigger_Status": "Completed"
          },
          "schema": [
            {
              "id": "Client_ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Client_ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Client_Name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Client_Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Trades_Made",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Trades_Made",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Trigger_Status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Trigger_Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Client_ID"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1zvjvsgxrtNQSeULTIs21Be0p2xzTZMU-mxFsV_B46ug/edit#gid=0",
          "cachedResultName": "\u0936\u0940\u091f1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1zvjvsgxrtNQSeULTIs21Be0p2xzTZMU-mxFsV_B46ug",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1zvjvsgxrtNQSeULTIs21Be0p2xzTZMU-mxFsV_B46ug/edit?usp=drivesdk",
          "cachedResultName": "Wealth Management - Portfolio Updates"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "f63ac374-88cd-4eed-9bb9-14fbaf1fffab",
      "name": "Slack: Draft Rejected Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        1488,
        320
      ],
      "parameters": {
        "text": "= *Draft discarded.* The AI-generated email for {{ $('Parse Trades & Tickers').item.json.Client_Name }} was rejected and has not been sent. Please reach out to the client manually.",
        "user": {
          "__rl": true,
          "mode": "id",
          "value": "U0AP17N3QRY"
        },
        "select": "user",
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "dbbce757-21f5-429e-a6b5-497df3f764de",
      "name": "Sheet: Mark 'Needs Review'",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1712,
        320
      ],
      "parameters": {
        "columns": {
          "value": {
            "Client_ID": "={{ $('Trigger: Portfolio Updated').item.json.Client_ID }}",
            "Trigger_Status": "Needs Manual Review"
          },
          "schema": [
            {
              "id": "Client_ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Client_ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Client_Name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Client_Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Trades_Made",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Trades_Made",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Trigger_Status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Trigger_Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Client_ID"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1zvjvsgxrtNQSeULTIs21Be0p2xzTZMU-mxFsV_B46ug/edit#gid=0",
          "cachedResultName": "\u0936\u0940\u091f1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1zvjvsgxrtNQSeULTIs21Be0p2xzTZMU-mxFsV_B46ug",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1zvjvsgxrtNQSeULTIs21Be0p2xzTZMU-mxFsV_B46ug/edit?usp=drivesdk",
          "cachedResultName": "Wealth Management - Portfolio Updates"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "63a49551-adbf-4810-8779-d4f8a5e6100b",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -832,
        -432
      ],
      "parameters": {
        "width": 688,
        "height": 496,
        "content": "## AI-Powered Wealth Management\n\n## How it works:\nThis workflow detects when a client's portfolio is updated in Google Sheets. It formats the trade data, pulls the client's risk profile and uses an AI Agent to draft a personalized explanation email. The workflow pauses and sends the draft to an advisor via Slack. It only emails the client if the advisor clicks \"Approve.\"\n\n## Setup steps:\n\nConnect Google Sheets credentials to the Trigger and both Update nodes.\n\nConnect your AI model credentials (e.g., Google Gemini / OpenAI) to the Chat Model node.\n\nConnect Slack credentials and set the correct Advisor Channel ID.\n\nAdd your email credentials to the Gmail node."
      },
      "typeVersion": 1
    },
    {
      "id": "b02193de-e1de-4883-b94a-f7c8bbca9aff",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -512,
        80
      ],
      "parameters": {
        "color": 7,
        "width": 912,
        "height": 320,
        "content": "## Data Ingestion & Formatting\nWatches Google Sheets for \"Pending\" portfolio changes. It parses the raw trade data into a clean JSON format and attaches the client's risk profile and market context."
      },
      "typeVersion": 1
    },
    {
      "id": "3575740e-88fd-4e7e-8982-4a4bb5a8dbef",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        448,
        80
      ],
      "parameters": {
        "color": 7,
        "width": 960,
        "height": 320,
        "content": "## AI Drafting & Human-in-the-Loop\nThe AI writes a personalized client email based on the context. The workflow then halts (Wait node) and sends a Slack message with Approve/Reject links to the advisor."
      },
      "typeVersion": 1
    },
    {
      "id": "274b5029-08aa-49a7-b922-0cff0513f299",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1440,
        -64
      ],
      "parameters": {
        "color": 7,
        "width": 496,
        "height": 560,
        "content": "## Execution & Logging\nRoutes based on the advisor's click.\nApproved: Emails the client and marks the sheet \"Completed.\"\nRejected: Alerts the advisor to handle manually and marks the sheet \"Needs Review.\""
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "566316e5-53dd-415b-a93b-b427ec148a90",
  "connections": {
    "LLM: Gemini": {
      "ai_languageModel": [
        [
          {
            "node": "AI: Draft Client Email",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Mock: Market Context": {
      "main": [
        [
          {
            "node": "AI: Draft Client Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait: Advisor Action": {
      "main": [
        [
          {
            "node": "Route: Approve vs Reject",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail: Send to Client": {
      "main": [
        [
          {
            "node": "Sheet: Mark as Completed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI: Draft Client Email": {
      "main": [
        [
          {
            "node": "Slack: Request Advisor Approval",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Trades & Tickers": {
      "main": [
        [
          {
            "node": "Mock: Client Risk Profile",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route: Approve vs Reject": {
      "main": [
        [
          {
            "node": "Gmail: Send to Client",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Slack: Draft Rejected Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mock: Client Risk Profile": {
      "main": [
        [
          {
            "node": "Mock: Market Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger: Portfolio Updated": {
      "main": [
        [
          {
            "node": "Parse Trades & Tickers",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack: Draft Rejected Alert": {
      "main": [
        [
          {
            "node": "Sheet: Mark 'Needs Review'",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack: Request Advisor Approval": {
      "main": [
        [
          {
            "node": "Wait: Advisor Action",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}