AutomationFlowsAI & RAG › Master Agent - Orchestrator

Master Agent - Orchestrator

Master Agent - Orchestrator. Uses httpRequest, telegram, telegramTrigger. Scheduled trigger; 43 nodes.

Cron / scheduled trigger★★★★★ complexity43 nodesHTTP RequestTelegramTelegram Trigger
AI & RAG Trigger: Cron / scheduled Nodes: 43 Complexity: ★★★★★ Added:

This workflow follows the HTTP Request → Telegram 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
{
  "name": "Master Agent - Orchestrator",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 2
            }
          ]
        }
      },
      "id": "2bffc3c6-1e99-4b14-af07-f2ce34ef7556",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// Trading Hours - Chicago Time (CT)\n// Futures Session: Sun 5PM CT -> Fri 4PM CT\n// Flatten: 3:55 PM CT (close all - prop firm rule)\n// No new positions after 3:50 PM CT\n// Maintenance: 4:00-5:00 PM CT daily\n\nconst now = new Date();\nconst ct = new Intl.DateTimeFormat('en-US', {\n  timeZone: 'America/Chicago',\n  hour: 'numeric', minute: 'numeric', hour12: false,\n  weekday: 'short'\n}).formatToParts(now);\n\nconst ctH = parseInt(ct.find(p => p.type === 'hour').value);\nconst ctM = parseInt(ct.find(p => p.type === 'minute').value);\nconst ctDay = ct.find(p => p.type === 'weekday').value;\n\n// Weekend\nif (ctDay === 'Sat') return [];\nif (ctDay === 'Sun' && ctH < 17) return [];\nif (ctDay === 'Fri' && ctH >= 16) return [];\n\n// Daily maintenance 4:00-5:00 PM CT\nif (ctH === 16) return [];\n\n// Bot active check\nconst sd = $getWorkflowStaticData('global');\nif (sd.botActive === false) return [];\n\n// Flatten at 3:55 PM CT\nconst shouldFlatten = (ctH === 15 && ctM >= 55);\n// No new positions after 3:50 PM CT\nconst noNewPositions = (ctH === 15 && ctM >= 50);\n\nreturn [{json: {\n  timestamp: now.toISOString(),\n  ctHour: ctH, ctMinute: ctM, ctDay,\n  shouldFlatten, noNewPositions,\n  session: ctH >= 17 ? 'evening' : ctH < 9 ? 'overnight' : 'day'\n}}];"
      },
      "id": "ae49f216-e4a2-4217-86f6-b309f7e9eb93",
      "name": "Check Trading Hours",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// Auth not needed - using TradersPost webhook\n// Return mock token to keep flow working\nreturn [{ json: { accessToken: \"not-needed-traderspost\", mdAccessToken: \"not-needed\", cached: true } }];"
      },
      "id": "b4484f9e-7bb8-4671-87d1-57a322746820",
      "name": "Auth Manager",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        500,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "cond-needs-auth",
              "leftValue": "={{ $json.needsAuth }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "d08e73ca-3638-4bc1-b857-2cef0cc3b61c",
      "name": "IF Needs Auth",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        750,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// Tradovate auth not needed\nreturn [{ json: { accessToken: \"not-needed\" } }];"
      },
      "id": "2d7da3e7-70dc-4c18-8957-889f71d21bad",
      "name": "HTTP Auth Tradovate",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1000,
        150
      ]
    },
    {
      "parameters": {
        "jsCode": "// No token to cache\nreturn [{ json: { accessToken: \"not-needed\", cached: true } }];"
      },
      "id": "fd1afb03-70f6-49bc-829a-13add1389751",
      "name": "Cache Token",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1250,
        150
      ]
    },
    {
      "parameters": {
        "jsCode": "// Tradovate API not available for prop firms\n// Return mock account data\nreturn [{ json: { accountId: 0, name: \"LucidTrading\", accountSpec: \"Lucid\", status: \"Active\" } }];"
      },
      "id": "09f76bcf-95de-4d08-aa9c-1e0e4e58fe8e",
      "name": "HTTP Get Account",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1800,
        50
      ]
    },
    {
      "parameters": {
        "jsCode": "// Tradovate API not available for prop firms\n// Return empty positions (tracked internally)\nreturn [{ json: { positions: [] } }];"
      },
      "id": "77655247-a407-42e2-948c-e6faaff791e8",
      "name": "HTTP Get Positions",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1800,
        200
      ]
    },
    {
      "parameters": {
        "jsCode": "const sd=$getWorkflowStaticData('global');\nreturn[{json:{qty:sd.qty||1,maxDrawdownMNQ:sd.maxDD||500,maxDailyTrades:sd.maxTrades||10,symbol:sd.symbol||'MNQM5',strategies:sd.strategies||'ALL'}}];"
      },
      "id": "6dda88c1-f5c4-4594-a293-16fb9f9f44c0",
      "name": "Get Config",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1800,
        350
      ]
    },
    {
      "parameters": {
        "jsCode": "const candles1mRaw = $('HTTP MNQ 1m').first().json;\nconst candles5mRaw = $('HTTP MNQ 5m').first().json;\nlet mgcCandles1mRaw, mgcCandles5mRaw;\ntry { mgcCandles1mRaw = $('HTTP MGC 1m').first().json; } catch(e) { mgcCandles1mRaw = { values: [] }; }\ntry { mgcCandles5mRaw = $('HTTP MGC 5m').first().json; } catch(e) { mgcCandles5mRaw = { values: [] }; }\nconst config = $('Get Config').first().json;\n\nfunction parseCandles(data) {\n  const values = data?.values || data?.body?.values || [];\n  return values.reverse().map(v => ({\n    time: v.datetime, open: parseFloat(v.open), high: parseFloat(v.high),\n    low: parseFloat(v.low), close: parseFloat(v.close), volume: parseInt(v.volume || 0)\n  }));\n}\n\nconst candles_1m = parseCandles(candles1mRaw);\nconst candles_5m = parseCandles(candles5mRaw);\nif (candles_1m.length === 0) { return [{ json: { error: 'No data', indicators: {}, candles_1m: [], candles_5m: [] } }]; }\n\nfunction calcEMA(data, period) {\n  if (data.length < period) return { value: 0, series: [] };\n  const k = 2 / (period + 1);\n  let ema = data.slice(0, period).reduce((s, v) => s + v, 0) / period;\n  const series = [ema];\n  for (let i = period; i < data.length; i++) { ema = data[i] * k + ema * (1 - k); series.push(ema); }\n  return { value: ema, series };\n}\n\nfunction calcRSI(closes, period) {\n  if (closes.length < period + 1) return 50;\n  let gains = 0, losses = 0;\n  for (let i = 1; i <= period; i++) { const d = closes[i] - closes[i-1]; if (d > 0) gains += d; else losses -= d; }\n  let avgG = gains / period, avgL = losses / period;\n  for (let i = period + 1; i < closes.length; i++) { const d = closes[i] - closes[i-1]; avgG = (avgG * (period - 1) + (d > 0 ? d : 0)) / period; avgL = (avgL * (period - 1) + (d < 0 ? -d : 0)) / period; }\n  if (avgL === 0) return 100;\n  return 100 - 100 / (1 + avgG / avgL);\n}\n\nfunction calcATR(candles, period) {\n  if (candles.length < period + 1) return 0;\n  const trs = [];\n  for (let i = 1; i < candles.length; i++) { trs.push(Math.max(candles[i].high - candles[i].low, Math.abs(candles[i].high - candles[i-1].close), Math.abs(candles[i].low - candles[i-1].close))); }\n  let atr = trs.slice(0, period).reduce((s, v) => s + v, 0) / period;\n  for (let i = period; i < trs.length; i++) { atr = (atr * (period - 1) + trs[i]) / period; }\n  return atr;\n}\n\nfunction calcBB(closes, period, stdDev) {\n  if (closes.length < period) return { upper: 0, middle: 0, lower: 0, width: 0 };\n  const slice = closes.slice(-period);\n  const mean = slice.reduce((s, v) => s + v, 0) / period;\n  const variance = slice.reduce((s, v) => s + (v - mean) ** 2, 0) / period;\n  const std = Math.sqrt(variance);\n  return { upper: mean + stdDev * std, middle: mean, lower: mean - stdDev * std, width: (2 * stdDev * std) / mean };\n}\n\nfunction calcVWAP(candles) {\n  if (candles.length === 0) return { value: 0, upper1SD: 0, lower1SD: 0, upper2SD: 0, lower2SD: 0 };\n  let cumVol = 0, cumTP = 0, cumTP2 = 0;\n  for (const c of candles) { const tp = (c.high + c.low + c.close) / 3; const vol = c.volume || 1; cumVol += vol; cumTP += tp * vol; cumTP2 += tp * tp * vol; }\n  const vwap = cumTP / cumVol; const variance = cumTP2 / cumVol - vwap * vwap; const std = Math.sqrt(Math.max(0, variance));\n  return { value: vwap, upper1SD: vwap + std, lower1SD: vwap - std, upper2SD: vwap + 2*std, lower2SD: vwap - 2*std };\n}\n\nfunction calcVolumeDelta(candles) {\n  let cum = 0;\n  return candles.map(c => { const d = c.close >= c.open ? c.volume : -c.volume; cum += d; return { time: c.time, buyVol: c.close >= c.open ? c.volume : 0, sellVol: c.close < c.open ? c.volume : 0, delta: d, cumDelta: cum }; });\n}\nfunction findSwings(candles, lookback) {\n  const highs = [], lows = [];\n  for (let i = lookback; i < candles.length - lookback; i++) {\n    let isH = true, isL = true;\n    for (let j = 1; j <= lookback; j++) {\n      if (candles[i].high <= candles[i-j].high || candles[i].high <= candles[i+j].high) isH = false;\n      if (candles[i].low >= candles[i-j].low || candles[i].low >= candles[i+j].low) isL = false;\n    }\n    if (isH) highs.push({ price: candles[i].high, index: i, time: candles[i].time });\n    if (isL) lows.push({ price: candles[i].low, index: i, time: candles[i].time });\n  }\n  return { swingHighs: highs, swingLows: lows };\n}\n\nfunction findFVGs(candles, tf) {\n  const fvgs = [];\n  for (let i = 2; i < candles.length; i++) {\n    if (candles[i].low > candles[i-2].high) fvgs.push({ type: 'BULLISH', high: candles[i].low, low: candles[i-2].high, timeframe: tf, time: candles[i].time });\n    if (candles[i].high < candles[i-2].low) fvgs.push({ type: 'BEARISH', high: candles[i-2].low, low: candles[i].high, timeframe: tf, time: candles[i].time });\n  }\n  return fvgs;\n}\n\nfunction findOrderBlocks(candles, tf) {\n  const obs = [];\n  for (let i = 1; i < candles.length - 1; i++) {\n    const curr = candles[i], next = candles[i+1];\n    const bigMove = Math.abs(next.close - next.open) > Math.abs(curr.close - curr.open) * 1.5;\n    if (curr.close < curr.open && next.close > next.open && bigMove) obs.push({ type: 'BULLISH', high: curr.open, low: curr.close, timeframe: tf, time: curr.time });\n    if (curr.close > curr.open && next.close < next.open && bigMove) obs.push({ type: 'BEARISH', high: curr.close, low: curr.open, timeframe: tf, time: curr.time });\n  }\n  return obs;\n}\n\nfunction detectMarketStructure(swings) {\n  const { swingHighs: sh, swingLows: sl } = swings;\n  if (sh.length < 2 || sl.length < 2) return \"NEUTRAL\";\n  const hh = sh[sh.length-1].price > sh[sh.length-2].price;\n  const hl = sl[sl.length-1].price > sl[sl.length-2].price;\n  const lh = sh[sh.length-1].price < sh[sh.length-2].price;\n  const ll = sl[sl.length-1].price < sl[sl.length-2].price;\n  if (hh && hl) return \"BULLISH\";\n  if (lh && ll) return \"BEARISH\";\n  return \"NEUTRAL\";\n}\n\nfunction detectSFP(candles, swings) {\n  const sfps = [];\n  const last5 = candles.slice(-5);\n  for (const c of last5) {\n    for (const sl of swings.swingLows) { if (c.low < sl.price && c.close > sl.price) sfps.push({ type: 'BULLISH', price: sl.price, time: c.time }); }\n    for (const sh of swings.swingHighs) { if (c.high > sh.price && c.close < sh.price) sfps.push({ type: 'BEARISH', price: sh.price, time: c.time }); }\n  }\n  return sfps;\n}\n\nfunction detectEqualHL(swings, tolerance) {\n  const result = [];\n  for (let i = 0; i < swings.swingHighs.length; i++) {\n    let count = 1;\n    for (let j = i + 1; j < swings.swingHighs.length; j++) { if (Math.abs(swings.swingHighs[i].price - swings.swingHighs[j].price) <= tolerance) count++; }\n    if (count >= 2) result.push({ type: 'EQUAL_HIGHS', price: swings.swingHighs[i].price, count });\n  }\n  for (let i = 0; i < swings.swingLows.length; i++) {\n    let count = 1;\n    for (let j = i + 1; j < swings.swingLows.length; j++) { if (Math.abs(swings.swingLows[i].price - swings.swingLows[j].price) <= tolerance) count++; }\n    if (count >= 2) result.push({ type: 'EQUAL_LOWS', price: swings.swingLows[i].price, count });\n  }\n  return result;\n}\n\nfunction findOpeningRange(candles) {\n  const now = new Date();\n  const etH = now.getUTCHours() - 5;\n  if (etH < 9 || etH > 11) return null;\n  const orCandles = candles.filter(c => { const t = new Date(c.time); const h = t.getUTCHours() - 5; const m = t.getUTCMinutes(); return h === 9 && m >= 30 && m < 45; });\n  if (orCandles.length === 0) return null;\n  return { high: Math.max(...orCandles.map(c => c.high)), low: Math.min(...orCandles.map(c => c.low)), range: Math.max(...orCandles.map(c => c.high)) - Math.min(...orCandles.map(c => c.low)) };\n}\nconst closes1m = candles_1m.map(c => c.close);\nconst closes5m = candles_5m.map(c => c.close);\n\nconst ema9 = calcEMA(closes1m, 9);\nconst ema21 = calcEMA(closes1m, 21);\nconst ema50 = calcEMA(closes1m, 50);\nconst ema9_5m = calcEMA(closes5m, 9);\nconst ema21_5m = calcEMA(closes5m, 21);\nconst ema50_5m = calcEMA(closes5m, 50);\n\nconst rsi1m = calcRSI(closes1m, 14);\nconst rsi5m = calcRSI(closes5m, 14);\nconst atr1m = calcATR(candles_1m, 14);\nconst atr5m = calcATR(candles_5m, 14);\nconst bb1m = calcBB(closes1m, 20, 2);\nconst bb5m = calcBB(closes5m, 20, 2);\nconst vwap = calcVWAP(candles_1m);\nconst volumeDelta = calcVolumeDelta(candles_1m);\nconst avgVolume = candles_1m.reduce((s, c) => s + c.volume, 0) / candles_1m.length;\n\nconst swings1m = findSwings(candles_1m, 3);\nconst swings5m = findSwings(candles_5m, 3);\nconst fvgs1m = findFVGs(candles_1m, '1m');\nconst fvgs5m = findFVGs(candles_5m, '5m');\nconst obs1m = findOrderBlocks(candles_1m, '1m');\nconst obs5m = findOrderBlocks(candles_5m, '5m');\nconst structure1m = detectMarketStructure(swings1m);\nconst structure5m = detectMarketStructure(swings5m);\nconst sfps = detectSFP(candles_5m, swings5m);\nconst tolerance = atr5m * 0.3;\nconst equalHL = detectEqualHL(swings5m, tolerance);\nconst openingRange = findOpeningRange(candles_1m);\n\nconst lastCandle = candles_1m[candles_1m.length - 1];\nconst lastDelta = volumeDelta[volumeDelta.length - 1] || {};\nconst emaCross1m = ema9.series.length > 1 && ema21.series.length > 1 ? (ema9.series[ema9.series.length-2] < ema21.series[ema21.series.length-2] && ema9.value > ema21.value ? 'BULLISH' : ema9.series[ema9.series.length-2] > ema21.series[ema21.series.length-2] && ema9.value < ema21.value ? 'BEARISH' : 'NONE') : 'NONE';\n\nconst indicators = {\n  price: lastCandle.close, symbol: config.symbol || 'MNQM6',\n  ema: { ema9: ema9.value, ema21: ema21.value, ema50: ema50.value, ema9_5m: ema9_5m.value, ema21_5m: ema21_5m.value, ema50_5m: ema50_5m.value, cross1m: emaCross1m },\n  rsi: { rsi1m, rsi5m },\n  atr: { atr1m, atr5m },\n  bb: { bb1m, bb5m },\n  vwap,\n  volume: { current: lastCandle.volume, average: avgVolume, ratio: avgVolume > 0 ? lastCandle.volume / avgVolume : 0, delta: lastDelta },\n  swings: { swings1m: swings1m, swings5m: swings5m },\n  fvgs: { fvgs1m: fvgs1m.slice(-5), fvgs5m: fvgs5m.slice(-5) },\n  orderBlocks: { obs1m: obs1m.slice(-3), obs5m: obs5m.slice(-3) },\n  structure: { structure1m, structure5m },\n  sfps: sfps.slice(-3),\n  equalHL: equalHL.slice(-5),\n  openingRange,\n  supports: swings1m.swingLows.slice(-3).map(s => s.price),\n  resistances: swings1m.swingHighs.slice(-3).map(s => s.price)\n};\n\nreturn [{ json: { indicators, candles_1m: candles_1m.slice(-20), candles_5m: candles_5m.slice(-20), symbol: indicators.symbol } }];"
      },
      "id": "4491260d-d27c-4a37-b924-171d0bb6bb91",
      "name": "Calculate Indicators",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2100,
        400
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "BK6ybQX7wBErUfzo",
          "mode": "id",
          "cachedResultUrl": "/workflow/BK6ybQX7wBErUfzo"
        },
        "options": {}
      },
      "id": "347931ee-d80b-4983-9687-7ff379dc5ebf",
      "name": "Layer 1: Session Agent",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.1,
      "position": [
        2400,
        200
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "j2U5LCMVRG1pYQYW",
          "mode": "id",
          "cachedResultUrl": "/workflow/j2U5LCMVRG1pYQYW"
        },
        "options": {}
      },
      "id": "0a94ea9c-b0c4-43f7-8fad-1dbe9b4f2dc2",
      "name": "Layer 1: Correlation Agent",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.1,
      "position": [
        2400,
        400
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "aiDx8Q4nDoAMqaqb",
          "mode": "id",
          "cachedResultUrl": "/workflow/aiDx8Q4nDoAMqaqb"
        },
        "options": {}
      },
      "id": "3a9cbab7-4808-4a0c-aaba-78ca1ff73dde",
      "name": "Layer 1: News Agent",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.1,
      "position": [
        2400,
        600
      ]
    },
    {
      "parameters": {
        "jsCode": "const sessionSignal = $('Layer 1: Session Agent').first().json;\nconst corrSignal = $('Layer 1: Correlation Agent').first().json;\nconst newsSignal = $('Layer 1: News Agent').first().json;\n\n// News VETO check\nif (newsSignal.signal === 'HOLD' && newsSignal.urgency === 'HIGH') {\n  return [{ json: { proceed: false, reason: 'News Agent VETO: ' + newsSignal.reasoning, signals: { session: sessionSignal, correlation: corrSignal, news: newsSignal } } }];\n}\n\n// Session check\nconst session = sessionSignal.session || {};\nif (session.shouldTrade === false) {\n  return [{ json: { proceed: false, reason: 'Session filter: ' + (session.reason || 'Not in trading session'), signals: { session: sessionSignal, correlation: corrSignal, news: newsSignal } } }];\n}\n\n// Flatten warning\nif (session.flattenWarning) {\n  return [{ json: { proceed: false, reason: 'Flatten warning: close to market close', signals: { session: sessionSignal, correlation: corrSignal, news: newsSignal } } }];\n}\n\n// Lunch hour low vol\nconst now = new Date();\nconst etH = now.getUTCHours() - 5;\nif (etH >= 12 && etH < 13) {\n  return [{ json: { proceed: false, reason: 'Lunch hour - low volume', signals: { session: sessionSignal, correlation: corrSignal, news: newsSignal } } }];\n}\n\nreturn [{ json: { proceed: true, signals: { session: sessionSignal, correlation: corrSignal, news: newsSignal }, macroBias: corrSignal.macroBias || 'NEUTRAL', sessionInfo: session } }];"
      },
      "id": "16aa1120-09f9-4864-aef0-77c4cbcbbeff",
      "name": "Layer 1 Gate",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2700,
        400
      ]
    },
    {
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "id": "c2",
              "leftValue": "={{$json.proceed}}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "3093f85f-1ac6-444f-8fff-069881aac5ff",
      "name": "IF Proceed to Layer 2",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        2950,
        400
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "Km5Wty5vyEawreXQ",
          "mode": "id",
          "cachedResultUrl": "/workflow/Km5Wty5vyEawreXQ"
        },
        "options": {}
      },
      "id": "0738699a-26d8-4635-b2df-ec2da238e2dd",
      "name": "Layer 2: ICT Agent",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.1,
      "position": [
        3250,
        150
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "yhE0Mnn94e8XFHHT",
          "mode": "id",
          "cachedResultUrl": "/workflow/yhE0Mnn94e8XFHHT"
        },
        "options": {}
      },
      "id": "08590185-1f0b-4914-8242-227da83f63f4",
      "name": "Layer 2: Volume Agent",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.1,
      "position": [
        3250,
        330
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "QwVYR6gWpN6p14mc",
          "mode": "id",
          "cachedResultUrl": "/workflow/QwVYR6gWpN6p14mc"
        },
        "options": {}
      },
      "id": "b5b4a4a9-6184-41b2-ae19-5c0922b4a2d7",
      "name": "Layer 2: Technical Agent",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.1,
      "position": [
        3250,
        510
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "Ej5F6JsfGwrruKOd",
          "mode": "id",
          "cachedResultUrl": "/workflow/Ej5F6JsfGwrruKOd"
        },
        "options": {}
      },
      "id": "1bcefbc5-f03a-452b-999a-2fbfa5fde08b",
      "name": "Layer 2: Fibonacci Agent",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.1,
      "position": [
        3250,
        690
      ]
    },
    {
      "parameters": {
        "jsCode": "const ictSignal = $('Layer 2: ICT Agent').first().json;\nconst volSignal = $('Layer 2: Volume Agent').first().json;\nconst techSignal = $('Layer 2: Technical Agent').first().json;\nconst fibSignal = $('Layer 2: Fibonacci Agent').first().json;\nconst layer1 = $('Layer 1 Gate').first().json;\n\nconst allSignals = [ictSignal, volSignal, techSignal, fibSignal];\nconst buySignals = allSignals.filter(s => s.signal === 'BUY');\nconst sellSignals = allSignals.filter(s => s.signal === 'SELL');\nconst holdSignals = allSignals.filter(s => s.signal === 'HOLD');\n\nconst consensus = buySignals.length > sellSignals.length ? 'BUY' : sellSignals.length > buySignals.length ? 'SELL' : 'HOLD';\nconst agreeing = consensus === 'BUY' ? buySignals : consensus === 'SELL' ? sellSignals : [];\nconst avgConfidence = agreeing.length > 0 ? agreeing.reduce((s, a) => s + a.confidence, 0) / agreeing.length : 0;\n\nreturn [{ json: {\n  signals: { ict: ictSignal, volume: volSignal, technical: techSignal, fibonacci: fibSignal },\n  layer1: layer1.signals,\n  consensus, agreementCount: agreeing.length, avgConfidence: parseFloat(avgConfidence.toFixed(2)),\n  macroBias: layer1.macroBias || 'NEUTRAL'\n}}];"
      },
      "id": "4e4e9ca5-b079-4fe5-8581-0ec3b33036d0",
      "name": "Merge All Signals",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        3550,
        400
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.anthropic.com/v1/messages",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "x-api-key",
              "value": "={{$credentials.httpHeaderAuth.value}}"
            },
            {
              "name": "anthropic-version",
              "value": "2023-06-01"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{{JSON.stringify({model:\"claude-sonnet-4-20250514\",max_tokens:1024,system:\"You are the MASTER TRADER orchestrator. You receive signals from 4 specialist agents and decide the final action.\\n\\nRULES:\\n1. 3+ agents agree = high confidence, execute if R:R >= 2\\n2. 2 agents agree with confidence > 0.75 = execute if R:R >= 2.5\\n3. 1 agent with confidence > 0.90 = execute if R:R >= 3\\n4. Agents conflict (BUY vs SELL) = HOLD\\n5. News HOLD with HIGH urgency = always HOLD\\n6. Kill Zone active = +20% weight to ICT\\n\\nWEIGHTS: ICT 30%, Volume 25%, Technical 25%, Fibonacci 20%\\n\\nUse SL/TP from highest confidence agent.\\n\\nRESPOND ONLY with JSON: {action,symbol,qty,entry,stopLoss,takeProfit,agentsAgreed,masterConfidence,reasoning,riskPerTrade}\",messages:[{role:\"user\",content:\"Signals: \"+JSON.stringify($json.signals)+\"\\nSession: \"+JSON.stringify($json.session)+\"\\nNews: \"+JSON.stringify($json.news)+\"\\nCorrelation: \"+JSON.stringify($json.correlation)}]})}}}",
        "options": {}
      },
      "id": "894feb98-9d78-417f-ab00-5c9d8f39cdc9",
      "name": "Master Claude Decision",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        3850,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "const response = $input.first().json;\nlet body = '';\ntry {\n  if (response.body) body = typeof response.body === 'string' ? response.body : JSON.stringify(response.body);\n  else body = JSON.stringify(response);\n} catch(e) { body = ''; }\n\n// Extract JSON from Claude response\nconst jsonMatch = body.match(/\\{[\\s\\S]*?\"action\"[\\s\\S]*?\\}/);\nif (!jsonMatch) {\n  return [{ json: { action: 'HOLD', reasoning: 'Could not parse Claude response', masterConfidence: 0 } }];\n}\n\ntry {\n  const decision = JSON.parse(jsonMatch[0]);\n  const result = {\n    action: decision.action || 'HOLD',\n    symbol: decision.symbol || 'MNQM6',\n    qty: decision.qty || 1,\n    entry: decision.entry || 0,\n    stopLoss: decision.stopLoss || 0,\n    takeProfit: decision.takeProfit || 0,\n    agentsAgreed: decision.agentsAgreed || [],\n    masterConfidence: decision.masterConfidence || 0,\n    reasoning: decision.reasoning || '',\n    riskPerTrade: decision.riskPerTrade || 0\n  };\n\n  // Check flatten/noNewPositions from Check Trading Hours\n  let tradingHours = {};\n  try { tradingHours = $('Check Trading Hours').first().json; } catch(e) {}\n\n  if (tradingHours.shouldFlatten) {\n    result.action = 'FLATTEN';\n    result.reasoning = 'FLATTEN: 3:55 PM CT - closing all positions (prop firm rule)';\n  } else if (tradingHours.noNewPositions && result.action !== 'HOLD') {\n    result.action = 'HOLD';\n    result.reasoning = 'BLOCKED: No new positions after 3:50 PM CT';\n  }\n  result.shouldFlatten = tradingHours.shouldFlatten || false;\n  result.noNewPositions = tradingHours.noNewPositions || false;\n\n  return [{ json: result }];\n} catch(e) {\n  return [{ json: { action: 'HOLD', reasoning: 'JSON parse error: ' + e.message, masterConfidence: 0 } }];\n}"
      },
      "id": "7c3f1d79-891d-4edd-9dc7-ffebb9b5607e",
      "name": "Parse Master Decision",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        4150,
        400
      ]
    },
    {
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "id": "c3",
              "leftValue": "={{$json.action}}",
              "rightValue": "HOLD",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "05c3c585-d610-4f4b-af31-34b17e3cf382",
      "name": "IF Execute Trade",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        4450,
        400
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "ZDFUioPIsSM4eZ5D",
          "mode": "id",
          "cachedResultUrl": "/workflow/ZDFUioPIsSM4eZ5D"
        },
        "options": {}
      },
      "id": "c4b2fca0-5cb9-40b1-a744-1b5f66364559",
      "name": "Risk Master",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.1,
      "position": [
        4750,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "id": "c4",
              "leftValue": "={{$json.approved}}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "3c429a71-486b-4a34-99a0-83c601bc057c",
      "name": "IF Risk Approved",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        5050,
        300
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $getWorkflowStaticData(\"global\").tradersPostWebhookUrl || \"https://webhooks.traderspost.io/trading/webhook/YOUR_UUID/YOUR_PASSWORD\" }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ ticker: $json.symbol === \"MNQM5\" ? \"MNQ\" : \"MGC\", action: $json.action.toLowerCase(), sentiment: $json.action === \"BUY\" ? \"long\" : \"short\", orderType: \"market\", quantity: $json.qty || 1, takeProfit: { limitPrice: $json.takeProfit }, stopLoss: { type: \"stop\", stopPrice: $json.stopLoss }, extras: { strategy: $json.reasoning, agents: ($json.agentsAgreed || []).join(\",\"), confidence: $json.masterConfidence } }) }}",
        "options": {
          "response": {
            "response": {
              "fullResponse": true
            }
          }
        }
      },
      "id": "71c27341-167e-4f91-876a-10154c9039cc",
      "name": "TradersPost Webhook",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        5350,
        200
      ]
    },
    {
      "parameters": {
        "chatId": "952561982",
        "text": "=\ud83e\udd16 *TRADE EXECUTADO via TradersPost*\\n\\n{{ $json.action }} {{ $json.symbol }}\\nQty: {{ $json.qty }}\\nEntry: {{ $json.entry }}\\nSL: {{ $json.stopLoss }}\\nTP: {{ $json.takeProfit }}\\nConfian\u00e7a: {{ ($json.masterConfidence * 100).toFixed(0) }}%\\nAgentes: {{ ($json.agentsAgreed || []).join(', ') }}\\n\\n\ud83d\udcdd {{ $json.reasoning }}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "8d534a6a-b81c-447b-a9c3-c8e883724a86",
      "name": "Telegram Notify",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        5350,
        400
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "952561982",
        "text": "=\u26d4 *TRADE REJEITADO*\n\nSinal: {{$('Parse Master Decision').first().json.action}} {{$('Parse Master Decision').first().json.symbol}}\nMotivo: {{$json.reason}}\n\nDrawdown: {{$json.riskReport?.drawdownUsed || '0%'}}\nTrades hoje: {{$json.riskReport?.tradesToday || 0}}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "3bf53e5c-4bfa-4824-acf9-64cac1abcc04",
      "name": "Telegram Risk Rejected",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        5350,
        600
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nconst positions = $('HTTP Get Positions').first().json || [];\nconst accounts = $('HTTP Get Account').first().json || [];\nconst config = $('Get Config').first().json;\nconst selectedAccount = staticData.selectedAccount || '';\n\n// Find active account\nconst account = selectedAccount ? accounts.find(a => a.name === selectedAccount) : accounts[0];\nif (!account) return [{ json: { closeAll: false, reason: 'No account found' } }];\n\n// Calculate daily P&L from positions\nconst openPnL = Array.isArray(positions) ? positions.reduce((s, p) => s + (p.unrealizedPnL || 0), 0) : 0;\nconst dailyPnL = (staticData.dailyPnL || 0) + openPnL;\n\n// Drawdown check\nconst maxDrawdown = config.maxDrawdownMNQ || 500;\nconst drawdownPct = Math.abs(dailyPnL) / maxDrawdown * 100;\n\nlet closeAll = false;\nlet reason = '';\nlet reduceQty = false;\n\nif (dailyPnL <= -maxDrawdown) {\n  closeAll = true;\n  reason = 'MAX DRAWDOWN HIT: $' + Math.abs(dailyPnL).toFixed(2) + ' (limit: $' + maxDrawdown + ')';\n  staticData.botActive = false;\n} else if (drawdownPct >= 70) {\n  reduceQty = true;\n  reason = 'Drawdown at ' + drawdownPct.toFixed(0) + '% - reducing position size to 1';\n}\n\n// Max trades per day check\nconst maxTrades = staticData.maxTradesPerDay || 10;\nif ((staticData.tradesThisDay || 0) >= maxTrades) {\n  closeAll = false;\n  staticData.botActive = false;\n  reason = 'Max trades reached: ' + staticData.tradesThisDay + '/' + maxTrades;\n}\n\nreturn [{ json: { closeAll, reduceQty, reason, dailyPnL, drawdownPct: parseFloat(drawdownPct.toFixed(1)), account: account.name, openPositions: Array.isArray(positions) ? positions.length : 0 } }];"
      },
      "id": "02213524-3f6f-4e74-bcf0-202977382aaa",
      "name": "Risk Manager",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        4750,
        600
      ]
    },
    {
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "id": "c5",
              "leftValue": "={{$json.closeAll}}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "20f40b53-eea2-4105-ab9d-ecb9e4b3b274",
      "name": "IF Close All",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        5050,
        600
      ]
    },
    {
      "parameters": {
        "chatId": "952561982",
        "text": "=\ud83d\udea8 *DRAWDOWN ALERT*\n\n{{$('Risk Manager').first().json.alert}}\n\nAll positions liquidated. Bot paused.\nUse /start to reactivate.",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "caa9f808-f797-449e-b4d9-07325343396f",
      "name": "Telegram Alert Drawdown",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        5650,
        800
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "id": "44908b30-d7f3-4fd3-97fc-62bb5b68d640",
      "name": "Telegram Commands",
      "type": "n8n-nodes-base.telegramTrigger",
      "typeVersion": 1.1,
      "position": [
        0,
        1400
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.message.text }}",
                    "rightValue": "/status",
                    "operator": {
                      "type": "string",
                      "operation": "startsWith"
                    }
                  }
                ]
              }
            },
            {
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.message.text }}",
                    "rightValue": "/config",
                    "operator": {
                      "type": "string",
                      "operation": "startsWith"
                    }
                  }
                ]
              }
            },
            {
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.message.text }}",
                    "rightValue": "/stop",
                    "operator": {
                      "type": "string",
                      "operation": "startsWith"
                    }
                  }
                ]
              }
            },
            {
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.message.text }}",
                    "rightValue": "/start",
                    "operator": {
                      "type": "string",
                      "operation": "startsWith"
                    }
                  }
                ]
              }
            },
            {
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.message.text }}",
                    "rightValue": "/agents",
                    "operator": {
                      "type": "string",
                      "operation": "startsWith"
                    }
                  }
                ]
              }
            },
            {
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.message.text }}",
                    "rightValue": "/conta",
                    "operator": {
                      "type": "string",
                      "operation": "startsWith"
                    }
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "id": "380807bb-87f9-4f06-a85a-3896a0716cad",
      "name": "Switch Commands",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3,
      "position": [
        300,
        1400
      ]
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nconst msg = '\ud83d\udcca *BOT STATUS*\n' +\n  '\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n' +\n  '\ud83d\udd39 Bot: ' + (staticData.botActive !== false ? '\u2705 ATIVO' : '\u26d4 PARADO') + '\n' +\n  '\ud83d\udd39 Conta: ' + (staticData.selectedAccount || 'auto') + '\n' +\n  '\ud83d\udd39 MNQ qty: ' + (staticData.maxQtyMNQ || 1) + '\n' +\n  '\ud83d\udd39 MGC qty: ' + (staticData.maxQtyMGC || 1) + '\n' +\n  '\ud83d\udd39 P&L hoje: $' + (staticData.dailyPnL || 0).toFixed(2) + '\n' +\n  '\ud83d\udd39 Trades hoje: ' + (staticData.tradesThisDay || 0) + '\n' +\n  '\ud83d\udd39 Max drawdown: $' + (staticData.maxDrawdownMNQ || 500) + '\n' +\n  '\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501';\nreturn [{ json: { chatId: '952561982', text: msg, parse_mode: 'Markdown' } }];"
      },
      "id": "08a1e66b-e99b-45ec-ab2d-1243f5cde2a8",
      "name": "Handle Status",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        600,
        1200
      ]
    },
    {
      "parameters": {
        "jsCode": "const staticData = $getWorkflowStaticData('global');\nconst text = $('Telegram Commands').first().json.message?.text || '';\nconst parts = text.trim().split(' ');\nconst cmd = parts[0].toLowerCase();\nlet reply = '';\n\nif (cmd === '/config') {\n  if (parts.length >= 3) {\n    const key = parts[1].toUpperCase();\n    const val = parts[2];\n    if (key === 'MNQ') { staticData.maxQtyMNQ = parseInt(val); reply = '\u2705 MNQ qty: ' + val; }\n    else if (key === 'MGC') { staticData.maxQtyMGC = parseInt(val); reply = '\u2705 MGC qty: ' + val; }\n    else if (key === 'DRAWDOWN') { staticData.maxDrawdownMNQ = parseInt(val); reply = '\u2705 Max drawdown: $' + val; }\n    else { reply = '\u274c Chave desconhecida: ' + key; }\n  } else {\n    reply = '\u2699\ufe0f *CONFIG ATUAL*\\\n' +\n      'MNQ qty: ' + (staticData.maxQtyMNQ || 1) + '\\\n' +\n      'MGC qty: ' + (staticData.maxQtyMGC || 1) + '\\\n' +\n      'Max Drawdown: $' + (staticData.maxDrawdownMNQ || 500) + '\\\n' +\n      'Webhook: ' + (staticData.tradersPostWebhookUrl ? '\u2705 Configurado' : '\u274c N\u00e3o configurado') + '\\\n' +\n      '\\\nUse: /config MNQ 2';\n  }\n} else if (cmd === '/conta' || cmd === '/account') {\n  if (parts.length > 1) {\n    staticData.selectedAccount = parts[1];\n    reply = '\u2705 Conta selecionada: ' + parts[1];\n  } else {\n    reply = '\ud83d\udccb Conta atual: ' + (staticData.selectedAccount || 'auto');\n  }\n} else if (cmd === '/webhook') {\n  if (parts.length > 1) {\n    staticData.tradersPostWebhookUrl = parts.slice(1).join(' ');\n    reply = '\u2705 TradersPost webhook configurado!';\n  } else {\n    reply = '\ud83d\udccb Webhook: ' + (staticData.tradersPostWebhookUrl || 'n\u00e3o configurado') + '\\\nUse: /webhook URL_COMPLETA';\n  }\n} else if (cmd === '/stop') {\n  staticData.botActive = false;\n  reply = '\ud83d\uded1 Bot PARADO';\n} else if (cmd === '/start') {\n  staticData.botActive = true;\n  reply = '\ud83d\udfe2 Bot ATIVADO';\n} else if (cmd === '/status') {\n  reply = '\ud83d\udcca *STATUS*\\\n' +\n    'Bot: ' + (staticData.botActive !== false ? '\ud83d\udfe2 Ativo' : '\ud83d\uded1 Parado') + '\\\n' +\n    'P&L Dia: $' + (staticData.dailyPnL || 0).toFixed(2) + '\\\n' +\n    'Trades Hoje: ' + (staticData.tradesThisDay || 0) + '\\\n' +\n    'Conta: ' + (staticData.selectedAccount || 'auto') + '\\\n' +\n    'Webhook: ' + (staticData.tradersPostWebhookUrl ? '\u2705' : '\u274c') + '\\\n' +\n    'Execu\u00e7\u00e3o: TradersPost';\n} else {\n  reply = '\u2753 Comando n\u00e3o reconhecido.\\\nUse: /status /config /start /stop /conta /webhook';\n}\n\nreturn [{ json: { reply } }];"
      },
      "id": "bfc844a5-249e-4cfb-99a8-bca9a91268b8",
      "name": "Handle Config",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        600,
        1350
      ]
    },
    {
      "parameters": {
        "jsCode": "const sd=$getWorkflowStaticData('global');sd.botActive=false;\nreturn[{json:{chatId:'952561982',text:'\ud83d\uded1 Bot STOPPED. Use /start to reactivate.'}}];"
      },
      "id": "a8ec4493-79e2-4d38-af15-08b3a34465e7",
      "name": "Handle Stop",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        600,
        1500
      ]
    },
    {
      "parameters": {
        "jsCode": "const sd=$getWorkflowStaticData('global');sd.botActive=true;\nreturn[{json:{chatId:'952561982',text:'\u2705 Bot STARTED. Trading active.'}}];"
      },
      "id": "6cfebd40-456b-4d54-876d-032a681db8f0",
      "name": "Handle Start",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        600,
        1650
      ]
    },
    {
      "parameters": {
        "chatId": "={{$json.chatId}}",
        "text": "={{$json.text}}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "a2be58fb-0a20-4437-ae4e-894870e87703",
      "name": "Telegram Reply",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        900,
        1500
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "chooseBranch",
        "output": "mixed"
      },
      "id": "5d883d0a-50c6-4ad5-9260-3b3d676df2b8",
      "name": "Merge Auth",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        1500,
        300
      ]
    },
    {
      "parameters": {
        "url": "https://api.twelvedata.com/time_series?symbol=NQ&interval=1min&outputsize=100&apikey=72309ee97bfe49f29f0f7a92d5337601",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        1800,
        500
      ],
      "id": "4795866d-dcd4-4ed4-8368-65dd1b724959",
      "name": "HTTP MNQ 1m"
    },
    {
      "parameters": {
        "url": "https://api.twelvedata.com/time_series?symbol=NQ&interval=5min&outputsize=100&apikey=72309ee97bfe49f29f0f7a92d5337601",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        1800,
        650
      ],
      "id": "2e857f8e-a053-43ff-8c60-c2503f572ae0",
      "name": "HTTP MNQ 5m"
    },
    {
      "parameters": {
        "url": "https://api.twelvedata.com/time_series?symbol=GC&interval=1min&outputsize=100&apikey=72309ee97bfe49f29f0f7a92d5337601",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        1800,
        800
      ],
      "id": "3b07a0bd-c985-496e-a188-650e70247ecc",
      "name": "HTTP MGC 1m"
    },
    {
      "parameters": {
        "url": "https://api.twelvedata.com/time_series?symbol=GC&interval=5min&outputsize=100&apikey=72309ee97bfe49f29f0f7a92d5337601",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        1800,
        950
      ],
      "id": "55747481-2f8c-4262-a564-2a91594835aa",
      "name": "HTTP MGC 5m"
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Check Trading Hours",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Trading Hours": {
      "main": [
        [
          {
            "node": "Auth Manager",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Auth Manager": {
      "main": [
        [
          {
            "node": "IF Needs Auth",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Needs Auth": {
      "main": [
        [
          {
            "node": "HTTP Auth Tradovate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Auth Tradovate": {
      "main": [
        [
          {
            "node": "Cache Token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Cache Token": {
      "main": [
        [
          {
            "node": "Merge Auth",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Get Config": {
      "main": [
        [
          {
            "node": "Calculate Indicators",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Indicators": {
      "main": [
        [
          {
            "node": "Layer 1: Session Agent",
            "type": "main",
            "index": 0
          },
          {
            "node": "Layer 1: Correlation Agent",
            "type": "main",
            "index": 0
          },
          {
            "node": "Layer 1: News Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Layer 1: Session Agent": {
      "main": [
        [
          {
            "node": "Layer 1 Gate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Layer 1: Correlation Agent": {
      "main": [
        [
          {
            "node": "Layer 1 Gate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Layer 1: News Agent": {
      "main": [
        [
          {
            "node": "Layer 1 Gate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Layer 1 Gate": {
      "main": [
        [
          {
            "node": "IF Proceed to Layer 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Proceed to Layer 2": {
      "main": [
        [
          {
            "node": "Layer 2: ICT Agent",
            "type": "main",
            "index": 0
          },
          {
            "node": "Layer 2: Volume Agent",
            "type": "main",
            "index": 0
          },
          {
            "node": "Layer 2: Technical Agent",
            "type": "main",
            "index": 0
          },
          {
            "node": "Layer 2: Fibonacci Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Layer 2: ICT Agent": {
      "main": [
        [
          {
            "node": "Merge All Signals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Layer 2: Volume Agent": {
      "main": [
        [
          {
            "node": "Merge All Signals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Layer 2: Technical Agent": {
      "main": [
        [
          {
            "node": "Merge All Signals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Layer 2: Fibonacci Agent": {
      "main": [
        [
          {
            "node": "Merge All Signals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge All Signals": {
      "main": [
        [
          {
            "node": "Master Claude Decision",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Master Claude Decision": {
      "main": [
        [
          {
            "node": "Parse Master Decision",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Master Decision": {
      "main": [
        [
          {
            "node": "IF Execute Trade",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Execute Trade": {
      "main": [
        [
          {
            "node": "Risk Master",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Risk Master": {
      "main": [
        [
          {
            "node": "IF Risk Approved",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Risk Approved": {
      "main": [
        [
          {
            "node": "Telegram Notify",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Telegram Risk Rejected",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Risk Manager": {
      "main": [
        [
          {
            "node": "IF Close All",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Close All": {
      "main": [
        [
          {
            "node": "Telegram Alert Drawdown",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Commands": {
      "main": [
        [
          {
            "node": "Switch Commands",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch Commands": {
      "main": [
        [
          {
            "node": "Handle Status",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Config",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Stop",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Start",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Status": {
      "main": [
        [
          {
            "node": "Telegram Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Config": {
      "main": [
        [
          {
            "node": "Telegram Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Stop": {
      "main": [
        [
          {
            "node": "Telegram Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Start": {
      "main": [
        [
          {
            "node": "Telegram Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Auth": {
      "main": [
        [
          {
            "node": "Get Config",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP Get Positions",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP Get Account",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP MNQ 1m",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP MNQ 5m",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP MGC 1m",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP MGC 5m",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP MNQ 1m": {
      "main": [
        [
          {
            "node": "Calculate Indicators",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP MNQ 5m": {
      "main": [
        [
          {
            "node": "Calculate Indicators",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP MGC 1m": {
      "main": [
        [
          {
            "node": "Calculate Indicators",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP MGC 5m": {
      "main": [
        [
          {
            "node": "Calculate Indicators",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate"
  },
  "versionId": "32b3da06-b0e1-48b7-97c6-ef987da0c26b",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "Pqz0wsUoweK9nQx5",
  "tags": []
}

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

Master Agent - Orchestrator. Uses httpRequest, telegram, telegramTrigger. Scheduled trigger; 43 nodes.

Source: https://gist.github.com/milhomao/d655da62da9295eb74d7fa72d2aafcd0 — 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

Master Agent - Orchestrator. Uses httpRequest, telegram, telegramTrigger. Scheduled trigger; 46 nodes.

HTTP Request, Telegram, Telegram Trigger
AI & RAG

Chanchito_PROD. Uses googleGemini, postgres, telegram, httpRequest. Scheduled trigger; 94 nodes.

Google Gemini, Postgres, Telegram +4
AI & RAG

Author: Nguyen Thieu Toan Category: Community & Knowledge Automation Tags: Telegram, Reddit, n8n Forum, AI Summarization, Gemini, Groq

Groq Chat, Output Parser Structured, Memory Mongo Db Chat +5
AI & RAG

System Architecture Two integrated N8N workflows providing automated US stock portfolio management through Telegram:

Output Parser Autofixing, OpenAI Chat, Perplexity +10
AI & RAG

This cutting-edge n8n workflow is a comprehensive automation solution designed to streamline various Instagram operations. It combines an intelligent AI chatbot for direct message management, automate

Agent, OpenRouter Chat, Output Parser Structured +4