{
  "id": "DdoucNGUKuzKpOCh",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Finance Research Analyst v5 - Production",
  "tags": [
    {
      "id": "JaNCWi5XTaMmf9J9",
      "name": "AI Employee",
      "createdAt": "2026-04-03T11:53:13.004Z",
      "updatedAt": "2026-04-03T11:53:13.004Z"
    }
  ],
  "nodes": [
    {
      "id": "9cf91144-5158-4ae3-af6c-ad1dce27c26c",
      "name": "Valid Slack Message?",
      "type": "n8n-nodes-base.if",
      "position": [
        -3168,
        1888
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "no-bot-id",
              "operator": {
                "type": "string",
                "operation": "notExists",
                "singleValue": true
              },
              "leftValue": "={{ $json.bot_id }}",
              "rightValue": ""
            },
            {
              "id": "has-text",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.text }}",
              "rightValue": ""
            },
            {
              "id": "is-message",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.type }}",
              "rightValue": "message"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "2d46e584-601a-4778-a11a-1c110173039d",
      "name": "Prepare Slack Context",
      "type": "n8n-nodes-base.code",
      "position": [
        -2944,
        1888
      ],
      "parameters": {
        "jsCode": "const text = ($json.text || '').trim();\nreturn [{ json: {\n  raw_text: text,\n  channel: $json.channel,\n  message_ts: $json.ts,\n  thread_ts: $json.thread_ts || $json.ts,\n  user: $json.user,\n  slack_event: $json,\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "2d4d8426-4e76-4a36-8dad-be131044aece",
      "name": "Build Intent Request",
      "type": "n8n-nodes-base.code",
      "position": [
        -2720,
        1888
      ],
      "parameters": {
        "jsCode": "const body = {\n  model: 'anthropic/claude-haiku-4.5',\n  temperature: 0,\n  messages: [\n    {\n      role: 'system',\n      content: [\n        'You route requests for a UK boutique M&A finance research analyst.',\n        'Return raw JSON only.',\n        'Use intent values: research, pitch, brief, unknown.',\n        'Extract only what is present or safely inferable from the message text.',\n        'Do not claim to know Companies House numbers or websites yet.',\n        'For pitch requests, capture the company_name.',\n        'For brief requests, capture the sector.',\n        'Ensure sector, ticker  and company_url are derived on your own if not provided'\n      ].join(' '),\n    },\n    {\n      role: 'user',\n      content: $json.raw_text,\n    },\n  ],\n  response_format: {\n    type: 'json_schema',\n    json_schema: {\n      name: 'finance_research_intent',\n      strict: true,\n      schema: {\n        type: 'object',\n        additionalProperties: false,\n        properties: {\n          intent: { type: 'string', enum: ['research', 'pitch', 'brief', 'unknown'] },\n          company_name: { type: ['string', 'null'] },\n          sector: { type: ['string', 'null'] },\n          ticker: { type: ['string', 'null'] },\n          company_url: { type: ['string', 'null'] },\n          confidence: { type: ['number', 'null'] },\n          reasoning_note: { type: ['string', 'null'] }\n        },\n        required: ['intent', 'company_name', 'sector', 'ticker', 'company_url', 'confidence', 'reasoning_note']\n      }\n    }\n  }\n};\nreturn [{ json: { ...$json, openrouter_body: body } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "9bf6a6d3-73bd-4b67-8e17-6f7cb2bcb1ed",
      "name": "Intent Classifier",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -2496,
        1888
      ],
      "parameters": {
        "url": "https://openrouter.ai/api/v1/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={{$json.openrouter_body}}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "openRouterApi"
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "d1779c3b-9f06-4212-afaf-97615fe5c61d",
      "name": "Parse Intent",
      "type": "n8n-nodes-base.code",
      "position": [
        -2272,
        1888
      ],
      "parameters": {
        "jsCode": "function parseJson(text) {\n  if (!text) return {};\n  const cleaned = String(text).trim().replace(/^```json\\s*/i, '').replace(/^```/, '').replace(/```$/, '').trim();\n  const first = cleaned.indexOf('{');\n  const last = cleaned.lastIndexOf('}');\n  const candidate = first >= 0 && last >= first ? cleaned.slice(first, last + 1) : cleaned;\n  return JSON.parse(candidate);\n}\nconst content = $json.choices?.[0]?.message?.content || '{}';\nconst parsed = parseJson(content);\nreturn [{ json: {\n  raw_text: $('Prepare Slack Context').item.json.raw_text,\n  channel: $('Prepare Slack Context').item.json.channel,\n  thread_ts: $('Prepare Slack Context').item.json.thread_ts,\n  user: $('Prepare Slack Context').item.json.user,\n  intent: parsed.intent || 'unknown',\n  company_name: parsed.company_name || '',\n  sector: parsed.sector || '',\n  ticker: parsed.ticker || '',\n  company_url: parsed.company_url || '',\n  confidence: parsed.confidence ?? null,\n  reasoning_note: parsed.reasoning_note || '',\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "64fa037a-374d-4206-9b6f-e0331154ea8c",
      "name": "Intent Switch",
      "type": "n8n-nodes-base.switch",
      "position": [
        -2048,
        1856
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "research",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.intent }}",
                    "rightValue": "research"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "pitch",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.intent }}",
                    "rightValue": "pitch"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "brief",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.intent }}",
                    "rightValue": "brief"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "unknown",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.intent }}",
                    "rightValue": "unknown"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "093d6f60-4315-4d8a-97ea-fb5b658d633f",
      "name": "Unknown Intent Response",
      "type": "n8n-nodes-base.code",
      "position": [
        2896,
        1552
      ],
      "parameters": {
        "jsCode": "return [{ json: {\n  channel: $json.channel,\n  thread_ts: $json.thread_ts,\n  reply_text: 'I could not route that request. Try one of: `Research Monzo, fintech`, `Prepare pitch for Monzo`, or `Industry briefing UK fintech`.'\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "060863ca-27ea-4610-b0d5-d1407572c863",
      "name": "Has Research Inputs?",
      "type": "n8n-nodes-base.if",
      "position": [
        -1824,
        976
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.company_name }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "6c0b00e4-5501-4443-8d97-72d131722d48",
      "name": "Research Missing Input Response",
      "type": "n8n-nodes-base.code",
      "position": [
        2880,
        1296
      ],
      "parameters": {
        "jsCode": "return [{ json: {\n  channel: $json.channel,\n  thread_ts: $json.thread_ts,\n  reply_text: 'Research requests need a company name. Example: `Research Revolut, fintech`.'\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "e22e21d1-6b30-47df-ac1b-712c94cb5853",
      "name": "Companies House Search",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1600,
        592
      ],
      "parameters": {
        "url": "=https://api.company-information.service.gov.uk/search/companies?q={{ encodeURIComponent($json.company_name) }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth"
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "f89d57fe-141b-4ce1-a235-e753d64a4b69",
      "name": "Pick Best Company Match",
      "type": "n8n-nodes-base.code",
      "position": [
        -1376,
        592
      ],
      "parameters": {
        "jsCode": "const input = $('Has Research Inputs?').item.json;\nconst target = (input.company_name || '').toLowerCase().trim();\nconst items = Array.isArray($json.items) ? $json.items : [];\nconst ranked = items\n  .filter((item) => item.company_number)\n  .map((item) => {\n    const title = String(item.title || '').toLowerCase();\n    let score = 0;\n    if (item.company_status === 'active') score += 5;\n    if (title === target) score += 20;\n    if (title.startsWith(target)) score += 10;\n    if (title.includes(target)) score += 5;\n    if (item.address_snippet && String(item.address_snippet).toLowerCase().includes('united kingdom')) score += 1;\n    return { item, score };\n  })\n  .sort((a, b) => b.score - a.score);\nconst best = ranked[0]?.item || null;\nreturn [{ json: {\n  ...input,\n  match_found: Boolean(best),\n  company_number: best?.company_number || '',\n  matched_title: best?.title || '',\n  matched_company_status: best?.company_status || '',\n  matched_address: best?.address_snippet || '',\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "0b293fb2-bbe2-46e3-9345-080b15d5bb4b",
      "name": "Company Match Found?",
      "type": "n8n-nodes-base.if",
      "position": [
        -1152,
        592
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.match_found }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "71e8da5c-696f-4a57-913a-6f6abe126de1",
      "name": "Company Not Found Response",
      "type": "n8n-nodes-base.code",
      "position": [
        2880,
        592
      ],
      "parameters": {
        "jsCode": "return [{ json: {\n  channel: $json.channel,\n  thread_ts: $json.thread_ts,\n  reply_text: `Companies House could not find a reliable UK company match for *${$json.company_name}*. Check spelling or provide the registered company name.`\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "9698c1d5-2c0b-414e-b076-5ab3fa636c76",
      "name": "Companies House Profile",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -928,
        64
      ],
      "parameters": {
        "url": "=https://api.company-information.service.gov.uk/company/{{ $json.company_number }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth"
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "7e62dba8-cd88-4a31-89f8-867a08482fe7",
      "name": "Wrap Profile",
      "type": "n8n-nodes-base.code",
      "position": [
        -704,
        64
      ],
      "parameters": {
        "jsCode": "return [{ json: { source: 'profile', data: $json } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "733811d2-c4eb-4ab9-9529-b0be02d31ab1",
      "name": "Companies House Officers",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -928,
        256
      ],
      "parameters": {
        "url": "=https://api.company-information.service.gov.uk/company/{{ $json.company_number }}/officers",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth"
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "dcb05c0f-2b09-4a40-bb70-70e75aec88c4",
      "name": "Wrap Officers",
      "type": "n8n-nodes-base.code",
      "position": [
        -704,
        256
      ],
      "parameters": {
        "jsCode": "return [{ json: { source: 'officers', data: $json } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "2037a207-6dba-48af-bd42-7935ccd25756",
      "name": "Companies House Filings",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -896,
        448
      ],
      "parameters": {
        "url": "=https://api.company-information.service.gov.uk/company/{{ $json.company_number }}/filing-history",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth"
      },
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "db395818-104e-4c9b-957b-7d9fdc9e6f41",
      "name": "Wrap Filings",
      "type": "n8n-nodes-base.code",
      "position": [
        -720,
        448
      ],
      "parameters": {
        "jsCode": "return [{ json: { source: 'filings', data: $json } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "0b5bf1ad-a904-4385-a6ae-1dae8c2a26a2",
      "name": "Company News",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -912,
        768
      ],
      "parameters": {
        "url": "https://api.firecrawl.dev/v2/search",
        "method": "POST",
        "options": {},
        "jsonBody": "={{({ query: `${$json.company_name} ${$json.sector || \"\"} recent company news funding acquisitions`, sources: [\"web\", \"news\"], limit: 8, scrapeOptions: { onlyMainContent: true, formats: [\"markdown\"] } })}}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "2d1842f6-1754-4590-b92d-04f8f26e44c8",
      "name": "Wrap Research News",
      "type": "n8n-nodes-base.code",
      "position": [
        -624,
        800
      ],
      "parameters": {
        "jsCode": "return [{ json: { source: 'news', data: $json } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "0aaf7ac9-a471-4be4-adc3-b1b5b8b99bf9",
      "name": "Website Search",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -880,
        608
      ],
      "parameters": {
        "url": "https://api.firecrawl.dev/v2/search",
        "method": "POST",
        "options": {},
        "jsonBody": "={{({ query: $json.company_url ? `${$json.company_name} ${$json.company_url}` : `${$json.company_name} official website`, sources: [\"web\"], limit: 5, scrapeOptions: { onlyMainContent: true, formats: [\"markdown\"] } })}}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "e0fbbc58-53e4-48c0-87ed-1338e3685ca9",
      "name": "Wrap Website",
      "type": "n8n-nodes-base.code",
      "position": [
        -640,
        624
      ],
      "parameters": {
        "jsCode": "return [{ json: { source: 'website', data: $json } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "fbe54b18-432c-4f6c-9fcb-23855fc8bf98",
      "name": "Has Ticker?",
      "type": "n8n-nodes-base.if",
      "position": [
        -1312,
        896
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.ticker }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "ed0af8bf-7a2c-499a-b89c-6be804a25b90",
      "name": "Alpha Vantage Overview",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -912,
        928
      ],
      "parameters": {
        "url": "=https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol={{ encodeURIComponent($json.ticker) }}&apikey=KEYHERE",
        "options": {}
      },
      "typeVersion": 4.4
    },
    {
      "id": "401249fc-1b4c-4ae8-8d04-58a4b9d39f32",
      "name": "Wrap Alpha Vantage",
      "type": "n8n-nodes-base.code",
      "position": [
        -624,
        960
      ],
      "parameters": {
        "jsCode": "return [{ json: { source: 'alphavantage', data: $json } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "746753eb-a9e6-407a-9189-c347941a9231",
      "name": "No Market Data Placeholder",
      "type": "n8n-nodes-base.code",
      "position": [
        -80,
        992
      ],
      "parameters": {
        "jsCode": "return [{ json: { source: 'alphavantage', data: { skipped: true, reason: 'No public ticker supplied or inferred.' } } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "4344ed39-de97-4bd3-92c4-94e60e9415a7",
      "name": "Merge Research 1",
      "type": "n8n-nodes-base.merge",
      "position": [
        -480,
        144
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "5f5a5dd5-9dfa-4dcf-89ea-a1fb572d34b5",
      "name": "Merge Research 2",
      "type": "n8n-nodes-base.merge",
      "position": [
        -256,
        240
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "e72d8b28-ac7d-446c-9559-a03449845f7e",
      "name": "Merge Research 3",
      "type": "n8n-nodes-base.merge",
      "position": [
        -32,
        240
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "0dee524d-0092-4cc7-af2e-985091c7ddb3",
      "name": "Merge Research 4",
      "type": "n8n-nodes-base.merge",
      "position": [
        192,
        240
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "b50e0fcd-15c8-478c-91a8-94c20ea6ebe8",
      "name": "Merge Research 5",
      "type": "n8n-nodes-base.merge",
      "position": [
        416,
        400
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "86b7b978-04db-4bd3-810b-480e62455c07",
      "name": "Build Research Bundle",
      "type": "n8n-nodes-base.code",
      "position": [
        640,
        400
      ],
      "parameters": {
        "jsCode": "const routed = $('Pick Best Company Match').item.json;\nconst bundle = {\n  channel: routed.channel,\n  thread_ts: routed.thread_ts,\n  raw_text: routed.raw_text,\n  company_name: routed.company_name,\n  sector: routed.sector,\n  ticker: routed.ticker,\n  company_url: routed.company_url,\n  company_number: routed.company_number,\n  matched_title: routed.matched_title,\n  sources: {},\n  warnings: [],\n};\nfor (const item of $input.all()) {\n  const source = item.json.source;\n  if (source) bundle.sources[source] = item.json.data;\n}\nif (bundle.sources.alphavantage?.skipped) bundle.warnings.push(bundle.sources.alphavantage.reason);\nconst websiteHit = Array.isArray(bundle.sources.website?.data) ? bundle.sources.website.data[0] : bundle.sources.website?.data?.[0];\nconst websiteUrl = websiteHit?.url || websiteHit?.metadata?.sourceURL || bundle.company_url || '';\nconst marketCapRaw = bundle.sources.alphavantage?.MarketCapitalization || bundle.sources.alphavantage?.['Global Quote']?.['05. price'] || '';\nbundle.market_cap = marketCapRaw && marketCapRaw !== 'None' ? marketCapRaw : '';\nbundle.website_url = websiteUrl;\nreturn [{ json: bundle }];"
      },
      "typeVersion": 2
    },
    {
      "id": "587e96ce-3c50-407c-8fc9-1c6f109ba499",
      "name": "Build Research Prompt",
      "type": "n8n-nodes-base.code",
      "position": [
        864,
        400
      ],
      "parameters": {
        "jsCode": "const body = {\n  model: 'anthropic/claude-sonnet-4.5',\n  temperature: 0.2,\n  messages: [\n    {\n      role: 'system',\n      content: [\n        'You are a junior finance research analyst for a UK boutique M&A advisory.',\n        'Use only the supplied source data.',\n        'If a field is missing, say it is unavailable rather than inventing it.',\n        'Return raw JSON only.'\n      ].join(' '),\n    },\n    {\n      role: 'user',\n      content: `Create a company research pack for ${$json.company_name} in sector ${$json.sector || 'unknown'} using this source bundle:\\n${JSON.stringify($json)}`,\n    },\n  ],\n  response_format: {\n    type: 'json_schema',\n    json_schema: {\n      name: 'finance_research_output',\n      strict: true,\n      schema: {\n        type: 'object',\n        additionalProperties: false,\n        properties: {\n          profile_markdown: { type: 'string' },\n          slack_summary: { type: 'string' },\n          market_cap_summary: { type: 'string' },\n          risks_summary: { type: 'string' }\n        },\n        required: ['profile_markdown', 'slack_summary', 'market_cap_summary', 'risks_summary']\n      }\n    }\n  }\n};\nreturn [{ json: { ...$json, openrouter_body: body } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "a56a308a-f7bf-414c-a648-26c94fba8ccd",
      "name": "Research AI",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1088,
        400
      ],
      "parameters": {
        "url": "https://openrouter.ai/api/v1/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={{$json.openrouter_body}}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "openRouterApi"
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "7f8a449b-1d98-4df3-abc2-aa1d145cf146",
      "name": "Parse Research Output",
      "type": "n8n-nodes-base.code",
      "position": [
        1312,
        400
      ],
      "parameters": {
        "jsCode": "function parseJson(text) {\n  const cleaned = String(text || '').trim().replace(/^```json\\s*/i, '').replace(/^```/, '').replace(/```$/, '').trim();\n  const first = cleaned.indexOf('{');\n  const last = cleaned.lastIndexOf('}');\n  const candidate = first >= 0 && last >= first ? cleaned.slice(first, last + 1) : cleaned;\n  return JSON.parse(candidate);\n}\nconst content = $json.choices?.[0]?.message?.content || '{}';\nconst parsed = parseJson(content);\nreturn [{ json: {\n  ...$('Build Research Prompt').item.json,\n  profile_markdown: parsed.profile_markdown,\n  slack_summary: parsed.slack_summary,\n  market_cap_summary: parsed.market_cap_summary,\n  risks_summary: parsed.risks_summary,\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "597e20a0-0628-4a4c-923d-6ede7669fe0c",
      "name": "Create Research Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1536,
        400
      ],
      "parameters": {
        "name": "={{$json.company_name.replace(/[\\\\/:*?\"<>|]/g, '-') + ' - research - ' + $now.toFormat('yyyy-LL-dd')}}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "url",
          "value": "=https://drive.google.com/drive/u/0/folders/1GH-YouAAImKugZ11IbqA6Ouw8B9U17-I"
        },
        "resource": "folder"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "662c9eb5-a21b-4d56-98fd-c508cb82cfa2",
      "name": "Create Profile Doc",
      "type": "n8n-nodes-base.googleDocs",
      "position": [
        1760,
        400
      ],
      "parameters": {
        "title": "={{$node[\"Parse Research Output\"].json.company_name}} Company Profile",
        "folderId": "={{$json.id}}"
      },
      "credentials": {
        "googleDocsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "26a8430d-4b11-4af8-a1d4-28c456e23ccd",
      "name": "Update Profile Doc",
      "type": "n8n-nodes-base.googleDocs",
      "position": [
        1984,
        400
      ],
      "parameters": {
        "actionsUi": {
          "actionFields": [
            {
              "text": "={{$node[\"Parse Research Output\"].json.profile_markdown}}",
              "action": "insert"
            }
          ]
        },
        "operation": "update",
        "documentURL": "={{ $json.id }}"
      },
      "credentials": {
        "googleDocsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "7c808348-0c4f-468c-98c7-227cdddf254d",
      "name": "Upsert Company Record",
      "type": "n8n-nodes-base.postgres",
      "position": [
        2208,
        400
      ],
      "parameters": {
        "query": "\nINSERT INTO aiemp_research_analyst_companies (\n  company_name,\n  sector,\n  companies_house_number,\n  registered_address,\n  incorporation_date,\n  sic_codes,\n  directors,\n  market_cap,\n  stock_ticker,\n  website_url,\n  profile_doc_url,\n  last_researched_at\n)\nVALUES (\n  '{{ $node[\"Parse Research Output\"].json.company_name.replace(/'/g, \"''\") }}',\n  '{{ ($node[\"Parse Research Output\"].json.sector || '').replace(/'/g, \"''\") }}',\n  '{{ $node[\"Parse Research Output\"].json.company_number.replace(/'/g, \"''\") }}',\n  '{{ JSON.stringify($node[\"Build Research Bundle\"].json.sources.profile?.registered_office_address || {}).replace(/'/g, \"''\") }}',\n  {{ $node[\"Build Research Bundle\"].json.sources.profile?.date_of_creation ? \"'\" + $node[\"Build Research Bundle\"].json.sources.profile.date_of_creation + \"'\" : 'NULL' }},\n  ARRAY[{{ (($node[\"Build Research Bundle\"].json.sources.profile?.sic_codes || []).map((code) => \"'\" + String(code).replace(/'/g, \"''\") + \"'\").join(',')) || '' }}],\n  '{{ JSON.stringify(($node[\"Build Research Bundle\"].json.sources.officers?.items || []).slice(0, 8).map((officer) => ({ name: officer.name, role: officer.officer_role, appointed_on: officer.appointed_on }))).replace(/'/g, \"''\") }}'::jsonb,\n  {{ $node[\"Build Research Bundle\"].json.market_cap ? $node[\"Build Research Bundle\"].json.market_cap : 'NULL' }},\n  {{ $node[\"Parse Research Output\"].json.ticker ? \"'\" + $node[\"Parse Research Output\"].json.ticker.replace(/'/g, \"''\") + \"'\" : 'NULL' }},\n  {{ $node[\"Build Research Bundle\"].json.website_url ? \"'\" + $node[\"Build Research Bundle\"].json.website_url.replace(/'/g, \"''\") + \"'\" : 'NULL' }},\n  '{{ (\"https://docs.google.com/document/d/\" + $node[\"Create Profile Doc\"].json.id + \"/edit\").replace(/'/g, \"''\") }}',\n  NOW()\n)\nON CONFLICT (companies_house_number) DO UPDATE SET\n  company_name = EXCLUDED.company_name,\n  sector = EXCLUDED.sector,\n  registered_address = EXCLUDED.registered_address,\n  incorporation_date = EXCLUDED.incorporation_date,\n  sic_codes = EXCLUDED.sic_codes,\n  directors = EXCLUDED.directors,\n  market_cap = EXCLUDED.market_cap,\n  stock_ticker = EXCLUDED.stock_ticker,\n  website_url = EXCLUDED.website_url,\n  profile_doc_url = EXCLUDED.profile_doc_url,\n  last_researched_at = NOW();\nSELECT id, company_name, sector, companies_house_number, profile_doc_url, pitch_deck_url\nFROM aiemp_research_analyst_companies\nWHERE companies_house_number = '{{ $node[\"Parse Research Output\"].json.company_number.replace(/'/g, \"''\") }}'\nLIMIT 1;\n",
        "options": {},
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "c4c8e333-b238-4fdd-89a2-648aafdeb909",
      "name": "Save Research Memory",
      "type": "n8n-nodes-base.postgres",
      "position": [
        2432,
        400
      ],
      "parameters": {
        "query": "\nINSERT INTO aiemp_research_analyst_research_memory (company_id, intent, content_text, embedding)\nVALUES (\n  '{{ $node[\"Upsert Company Record\"].json.id }}',\n  'research',\n  '{{ $node[\"Parse Research Output\"].json.profile_markdown.replace(/'/g, \"''\") }}',\n  NULL\n);\nSELECT '{{ $node[\"Upsert Company Record\"].json.id }}' AS company_id;\n",
        "options": {},
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "d5351e91-031f-4477-bedc-5374816a3c15",
      "name": "Update Client DB Research",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2656,
        400
      ],
      "parameters": {
        "columns": {
          "value": {
            "sector": "={{$node[\"Parse Research Output\"].json.sector}}",
            "market_cap": "={{$node[\"Build Research Bundle\"].json.market_cap || \"\"}}",
            "company_name": "={{$node[\"Parse Research Output\"].json.company_name}}",
            "pitch_deck_url": "={{$node[\"Upsert Company Record\"].json.pitch_deck_url || \"\"}}",
            "last_researched": "={{$now.toISO()}}",
            "profile_doc_url": "={{\"https://docs.google.com/document/d/\" + $node[\"Create Profile Doc\"].json.id + \"/edit\"}}",
            "companies_house_number": "={{$node[\"Parse Research Output\"].json.company_number}}"
          },
          "schema": [
            {
              "id": "company_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "company_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "sector",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "sector",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "companies_house_number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "companies_house_number",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "market_cap",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "market_cap",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "last_researched",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "last_researched",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "profile_doc_url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "profile_doc_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "pitch_deck_url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "pitch_deck_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "companies_house_number"
          ]
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "=https://docs.google.com/spreadsheets/d/1yJ-UKOEUqIruCv-IBA33oN4taQTB1TA8M4a6D2iSiOU/edit?gid=0#gid=0"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "2cbd75bd-4b69-4da2-bc4f-354fb6890b02",
      "name": "Research Response",
      "type": "n8n-nodes-base.code",
      "position": [
        2880,
        400
      ],
      "parameters": {
        "jsCode": "const docUrl = `https://docs.google.com/document/d/${$('Create Profile Doc').first().json.id}/edit`;\nreturn [{ json: {\n  channel: $('Parse Research Output').first().json.channel,\n  thread_ts: $('Parse Research Output').first().json.thread_ts,\n  reply_text: `Research complete for *${$('Parse Research Output').first().json.company_name}*\\n\\n${$('Parse Research Output').first().json.slack_summary}\\n\\nProfile doc: ${docUrl}`\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "93e31fc7-fff6-4cd9-85fe-c999006bbc29",
      "name": "Has Pitch Company?",
      "type": "n8n-nodes-base.if",
      "position": [
        -480,
        1968
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.company_name }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "2486f00c-8c80-4494-84b5-d622ff20eabb",
      "name": "Pitch Missing Input Response",
      "type": "n8n-nodes-base.code",
      "position": [
        2880,
        2176
      ],
      "parameters": {
        "jsCode": "return [{ json: {\n  channel: $json.channel,\n  thread_ts: $json.thread_ts,\n  reply_text: 'Pitch requests need a company name. Example: `Prepare pitch for Revolut`.'\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "ee986493-5763-4050-91ca-29b84c8edb8b",
      "name": "Load Company Record",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -256,
        1872
      ],
      "parameters": {
        "query": "\nSELECT * FROM (\n  SELECT\n    c.id,\n    c.company_name,\n    c.sector,\n    c.companies_house_number,\n    c.profile_doc_url,\n    c.pitch_deck_url,\n    c.website_url,\n    c.stock_ticker,\n    c.last_researched_at\n  FROM aiemp_research_analyst_companies c\n  WHERE lower(c.company_name) = lower('{{ $json.company_name.replace(/'/g, \"''\") }}')\n  ORDER BY c.created_at DESC\n  LIMIT 1\n) found\nUNION ALL\nSELECT\n  NULL::uuid,\n  NULL::text,\n  NULL::text,\n  NULL::text,\n  NULL::text,\n  NULL::text,\n  NULL::text,\n  NULL::text,\n  NULL::timestamptz\nWHERE NOT EXISTS (\n  SELECT 1 FROM aiemp_research_analyst_companies c\n  WHERE lower(c.company_name) = lower('{{ $json.company_name.replace(/'/g, \"''\") }}')\n);\n",
        "options": {},
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "58d18b5b-538c-4e26-8d01-1efab45587c7",
      "name": "Has Prior Research?",
      "type": "n8n-nodes-base.if",
      "position": [
        -32,
        1872
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "d521abb4-616d-451c-8669-34ab4f06d938",
      "name": "Pitch Missing Research Response",
      "type": "n8n-nodes-base.code",
      "position": [
        640,
        1776
      ],
      "parameters": {
        "jsCode": "return [{ json: {\n  channel: $('Parse Intent').item.json.channel,\n  thread_ts: $('Parse Intent').item.json.thread_ts,\n  reply_text: `No stored research exists for *${$('Parse Intent').item.json.company_name}*. Run a research request first.`\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "6b8693aa-e5fd-4381-94f2-b3703a383a61",
      "name": "Load Research Memory",
      "type": "n8n-nodes-base.postgres",
      "position": [
        192,
        1936
      ],
      "parameters": {
        "query": "\nSELECT * FROM (\n  SELECT rm.content_text, rm.created_at\n  FROM aiemp_research_analyst_research_memory rm\n  WHERE rm.company_id = '{{ $node[\"Load Company Record\"].json.id }}'\n    AND rm.intent = 'research'\n  ORDER BY rm.created_at DESC\n  LIMIT 1\n) found\nUNION ALL\nSELECT NULL::text, NULL::timestamptz\nWHERE NOT EXISTS (\n  SELECT 1\n  FROM aiemp_research_analyst_research_memory rm\n  WHERE rm.company_id = '{{ $node[\"Load Company Record\"].json.id }}'\n    AND rm.intent = 'research'\n);\n",
        "options": {},
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "e67a1161-1a48-4782-8c28-df474380cad8",
      "name": "Has Research Memory?",
      "type": "n8n-nodes-base.if",
      "position": [
        416,
        1936
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.content_text }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "6555fbbf-de55-4ad6-a959-6a1a06953bc5",
      "name": "Create Pitch Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        640,
        1984
      ],
      "parameters": {
        "name": "={{$node['Load Company Record'].json.company_name.replace(/[\\\\/:*?\"<>|]/g, '-') + ' - pitch - ' + $now.toFormat('yyyy-LL-dd')}}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "url",
          "value": "=https://drive.google.com/drive/u/0/folders/1GH-YouAAImKugZ11IbqA6Ouw8B9U17-I"
        },
        "resource": "folder"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "73cecdcf-4341-4199-9d85-8369d058df27",
      "name": "Build Pitch Prompt",
      "type": "n8n-nodes-base.code",
      "position": [
        864,
        1984
      ],
      "parameters": {
        "jsCode": "const company = $('Load Company Record').item.json;\nconst memory = $('Load Research Memory').item.json.content_text;\nconst body = {\n  model: 'anthropic/claude-haiku-4.5',\n  temperature: 0.2,\n  messages: [\n    {\n      role: 'system',\n      content: [\n        'You prepare pitch materials for a boutique corporate finance team.',\n        'Free-tier mode only: do not invent deal comps, valuation multiples, or proprietary transaction data.',\n        'If comps are unavailable, say so plainly.',\n        'All slide content must be short, presentation-ready, and formatted as concise bullet points.',\n        'Do not write narrative paragraphs for slide fields.',\n        'For profile_summary, financials, opportunity_summary, and comps_note, return 3 to 5 bullets max per field.',\n        'Keep each bullet to one short line where possible.',\n        'If the template contains charts, leave chart content implied by the bullets rather than describing charts in prose.',\n        'Return raw JSON only.'\n      ].join(' '),\n    },\n    {\n      role: 'user',\n      content: `Create pitch materials for ${company.company_name}. Stored research:\\n${memory}\\n\\nImportant: the deck is copied into a slide template. Keep the slide text compact so it fits neatly into text boxes. Use bullet points, not paragraphs.` ,\n    },\n  ],\n  response_format: {\n    type: 'json_schema',\n    json_schema: {\n      name: 'finance_pitch_output',\n      strict: true,\n      schema: {\n        type: 'object',\n        additionalProperties: false,\n        properties: {\n          profile_summary: { type: 'string' },\n          financials: { type: 'string' },\n          opportunity_summary: { type: 'string' },\n          comps_note: { type: 'string' },\n          press_release_markdown: { type: 'string' },\n          slack_summary: { type: 'string' }\n        },\n        required: ['profile_summary', 'financials', 'opportunity_summary', 'comps_note', 'press_release_markdown', 'slack_summary']\n      }\n    }\n  }\n};\nreturn [{ json: {\n  channel: $('Parse Intent').item.json.channel,\n  thread_ts: $('Parse Intent').item.json.thread_ts,\n  company_name: company.company_name,\n  sector: company.sector,\n  openrouter_body: body,\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "23ec349a-0a7e-4a8c-86af-07fbd651e9ca",
      "name": "Pitch AI",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1088,
        1984
      ],
      "parameters": {
        "url": "https://openrouter.ai/api/v1/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={{$json.openrouter_body}}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "openRouterApi"
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "e9a5bba7-06a6-4076-b3e3-092f6d095cfa",
      "name": "Parse Pitch Output",
      "type": "n8n-nodes-base.code",
      "position": [
        1312,
        1984
      ],
      "parameters": {
        "jsCode": "function parseJson(text) {\n  const cleaned = String(text || '').trim().replace(/^```json\\s*/i, '').replace(/^```/, '').replace(/```$/, '').trim();\n  const first = cleaned.indexOf('{');\n  const last = cleaned.lastIndexOf('}');\n  const candidate = first >= 0 && last >= first ? cleaned.slice(first, last + 1) : cleaned;\n  return JSON.parse(candidate);\n}\nconst content = $json.choices?.[0]?.message?.content || '{}';\nconst parsed = parseJson(content);\nreturn [{ json: {\n  ...$('Build Pitch Prompt').item.json,\n  profile_summary: parsed.profile_summary,\n  financials: parsed.financials,\n  opportunity_summary: parsed.opportunity_summary,\n  comps_note: parsed.comps_note,\n  press_release_markdown: parsed.press_release_markdown,\n  slack_summary: parsed.slack_summary,\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "4375166b-caa0-46ff-8dce-3468f2144bdd",
      "name": "Copy Slides Template",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1536,
        1984
      ],
      "parameters": {
        "name": "={{$node[\"Parse Pitch Output\"].json.company_name}} Pitch Deck",
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "1zQv_cbafHzd4JNsr711Rm0558O6W_S1SODc-u6tVS0k"
        },
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{$node[\"Create Pitch Folder\"].json.id}}"
        },
        "operation": "copy",
        "sameFolder": false
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "65b78c5e-1785-46e8-af6f-2fe0bb703209",
      "name": "Create Custom Presentation",
      "type": "n8n-nodes-base.googleSlides",
      "position": [
        1760,
        1984
      ],
      "parameters": {
        "textUi": {
          "textValues": [
            {
              "text": "{company_name}",
              "replaceText": "={{$node[\"Parse Pitch Output\"].json.company_name}}"
            },
            {
              "text": "{sector}",
              "replaceText": "={{$node[\"Parse Pitch Output\"].json.sector || \"\"}}"
            },
            {
              "text": "{profile_summary}",
              "replaceText": "={{$node[\"Parse Pitch Output\"].json.profile_summary}}"
            },
            {
              "text": "{financials}",
              "replaceText": "={{$node[\"Parse Pitch Output\"].json.financials}}"
            },
            {
              "text": "{opportunity_summary}",
              "replaceText": "={{$node[\"Parse Pitch Output\"].json.opportunity_summary}}"
            },
            {
              "text": "{comps_note}",
              "replaceText": "={{$node[\"Parse Pitch Output\"].json.comps_note}}"
            }
          ]
        },
        "options": {},
        "operation": "replaceText",
        "presentationId": "={{$json.id}}"
      },
      "credentials": {
        "googleSlidesOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "a3861a20-dc3c-4e7f-863e-4e906ba07535",
      "name": "Create Press Release Doc",
      "type": "n8n-nodes-base.googleDocs",
      "position": [
        1984,
        1984
      ],
      "parameters": {
        "title": "={{$node[\"Parse Pitch Output\"].json.company_name}} Press Release Draft",
        "folderId": "={{$node[\"Create Pitch Folder\"].json.id}}"
      },
      "credentials": {
        "googleDocsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "4c54db00-6ed1-4588-9cdc-5040fbacbc87",
      "name": "Update Press Release Doc",
      "type": "n8n-nodes-base.googleDocs",
      "position": [
        2208,
        1984
      ],
      "parameters": {
        "actionsUi": {
          "actionFields": [
            {
              "text": "={{$node[\"Parse Pitch Output\"].json.press_release_markdown}}",
              "action": "insert"
            }
          ]
        },
        "operation": "update",
        "documentURL": "={{$json.id}}"
      },
      "credentials": {
        "googleDocsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "d62fbbdd-2198-4854-ad1f-db083e94ad6e",
      "name": "Update Pitch Assets",
      "type": "n8n-nodes-base.postgres",
      "position": [
        2432,
        1984
      ],
      "parameters": {
        "query": "\nUPDATE aiemp_research_analyst_companies\nSET pitch_deck_url = '{{ (\"https://docs.google.com/presentation/d/\" + $node[\"Copy Slides Template\"].json.id + \"/edit\").replace(/'/g, \"''\") }}'\nWHERE id = '{{ $node[\"Load Company Record\"].json.id }}';\nSELECT id, company_name, sector, companies_house_number, profile_doc_url, pitch_deck_url\nFROM aiemp_research_analyst_companies\nWHERE id = '{{ $node[\"Load Company Record\"].json.id }}'\nLIMIT 1;\n",
        "options": {},
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "45ad1354-cba8-408f-a2a7-6d9cb743350c",
      "name": "Update Client DB Pitch",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2656,
        1984
      ],
      "parameters": {
        "columns": {
          "value": {
            "sector": "={{$node[\"Load Company Record\"].json.sector || \"\"}}",
            "market_cap": "",
            "company_name": "={{$node[\"Load Company Record\"].json.company_name}}",
            "pitch_deck_url": "={{\"https://docs.google.com/presentation/d/\" + $node[\"Copy Slides Template\"].json.id + \"/edit\"}}",
            "last_researched": "={{$node[\"Load Company Record\"].json.last_researched_at || \"\"}}",
            "profile_doc_url": "={{$node[\"Load Company Record\"].json.profile_doc_url || \"\"}}",
            "companies_house_number": "={{$node[\"Load Company Record\"].json.companies_house_number || \"\"}}"
          },
          "schema": [
            {
              "id": "company_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "company_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "sector",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "sector",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "companies_house_number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "companies_house_number",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "market_cap",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "market_cap",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "last_researched",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "last_researched",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "profile_doc_url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "profile_doc_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "pitch_deck_url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "pitch_deck_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "companies_house_number"
          ]
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "=https://docs.google.com/spreadsheets/d/1yJ-UKOEUqIruCv-IBA33oN4taQTB1TA8M4a6D2iSiOU/edit?gid=0#gid=0"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "bc1c8cab-bb0c-4bf0-b2fb-b58363817b61",
      "name": "Pitch Response",
      "type": "n8n-nodes-base.code",
      "position": [
        2880,
        1984
      ],
      "parameters": {
        "jsCode": "const deckUrl = `https://docs.google.com/presentation/d/${$('Copy Slides Template').first().json.id}/edit`;\nconst docUrl = `https://docs.google.com/document/d/${$('Create Press Release Doc').first().json.id}/edit`;\nreturn [{ json: {\n  channel: $('Parse Pitch Output').first().json.channel,\n  thread_ts: $('Parse Pitch Output').first().json.thread_ts,\n  reply_text: `Pitch materials ready for *${$('Parse Pitch Output').first().json.company_name}*\\n\\n${$('Parse Pitch Output').first().json.slack_summary}\\n\\nPitch deck: ${deckUrl}\\nPress release draft: ${docUrl}`\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "32982ac8-cf47-4bf5-87b6-9e720f2b7959",
      "name": "Has Brief Sector?",
      "type": "n8n-nodes-base.if",
      "position": [
        -608,
        2496
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.sector }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "438c6f65-01fa-44cf-a850-69b107fc95d8",
      "name": "Brief Missing Sector Response",
      "type": "n8n-nodes-base.code",
      "position": [
        2880,
        2560
      ],
      "parameters": {
        "jsCode": "return [{ json: {\n  channel: $json.channel,\n  thread_ts: $json.thread_ts,\n  reply_text: 'Industry briefings need a sector. Example: `Industry briefing UK fintech`.'\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "15612463-3983-470c-9dde-193dd813ebdd",
      "name": "Sector News",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -64,
        2288
      ],
      "parameters": {
        "url": "https://api.firecrawl.dev/v2/search",
        "method": "POST",
        "options": {},
        "jsonBody": "={{({ query: `${$json.sector} UK mergers acquisitions trends recent news`, sources: [\"web\", \"news\"], limit: 10, scrapeOptions: { onlyMainContent: true, formats: [\"markdown\"] } })}}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "cfb909fd-3d75-4975-a638-76b246c41cdd",
      "name": "Wrap Sector News",
      "type": "n8n-nodes-base.code",
      "position": [
        288,
        2320
      ],
      "parameters": {
        "jsCode": "return [{ json: { source: 'news', data: $json } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "d3e37619-1e6b-48d7-b5c6-95dbb15c8058",
      "name": "ONS M&A Source",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -128,
        2624
      ],
      "parameters": {
        "url": "https://www.ons.gov.uk/businessindustryandtrade/changestobusiness/mergersandacquisitions/bulletins/mergersandacquisitionsinvolvingukcompanies/julytoseptember2024/relateddata",
        "options": {}
      },
      "typeVersion": 4.4
    },
    {
      "id": "c2f28081-28a0-4262-af9a-22fb808473ff",
      "name": "Wrap ONS M&A",
      "type": "n8n-nodes-base.code",
      "position": [
        272,
        2640
      ],
      "parameters": {
        "jsCode": "return [{ json: { source: 'ons', data: $json } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "f2558a5e-85b2-4aea-9898-895c77dd122a",
      "name": "Merge Brief Sources",
      "type": "n8n-nodes-base.merge",
      "position": [
        544,
        2368
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "62d1bfdf-927a-402d-a110-107f875c3c43",
      "name": "Build Brief Bundle",
      "type": "n8n-nodes-base.code",
      "position": [
        1312,
        2368
      ],
      "parameters": {
        "jsCode": "const routed = $('Parse Intent').item.json;\nconst bundle = {\n  channel: routed.channel,\n  thread_ts: routed.thread_ts,\n  sector: routed.sector,\n  raw_text: routed.raw_text,\n  sources: {},\n};\nfor (const item of $input.all()) {\n  if (item.json.source) bundle.sources[item.json.source] = item.json.data;\n}\nreturn [{ json: bundle }];"
      },
      "typeVersion": 2
    },
    {
      "id": "4b76bf83-c93f-4b8c-a093-9b5bbf27be70",
      "name": "Build Brief Prompt",
      "type": "n8n-nodes-base.code",
      "position": [
        1536,
        2368
      ],
      "parameters": {
        "jsCode": "const body = {\n  model: 'anthropic/claude-haiku-4.5',\n  temperature: 0.2,\n  messages: [\n    {\n      role: 'system',\n      content: [\n        'You write concise UK corporate finance industry briefings.',\n        'Use only the supplied inputs.',\n        'ONS data is macro M&A context, not sector deal comps.',\n        'Return raw JSON only.'\n      ].join(' '),\n    },\n    {\n      role: 'user',\n      content: `Create a one-page industry briefing for ${$json.sector}. Source bundle:\\n${JSON.stringify($json)}`,\n    },\n  ],\n  response_format: {\n    type: 'json_schema',\n    json_schema: {\n      name: 'finance_brief_output',\n      strict: true,\n      schema: {\n        type: 'object',\n        additionalProperties: false,\n        properties: {\n          brief_markdown: { type: 'string' },\n          slack_summary: { type: 'string' }\n        },\n        required: ['brief_markdown', 'slack_summary']\n      }\n    }\n  }\n};\nreturn [{ json: { ...$json, openrouter_body: body } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "8062e577-9969-4f07-8240-ce2c9b8f3b20",
      "name": "Brief AI",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1760,
        2368
      ],
      "parameters": {
        "url": "https://openrouter.ai/api/v1/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={{$json.openrouter_body}}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "openRouterApi"
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "d4b2d382-38b6-483b-aa6f-40b3acc513a2",
      "name": "Parse Brief Output",
      "type": "n8n-nodes-base.code",
      "position": [
        1984,
        2368
      ],
      "parameters": {
        "jsCode": "function parseJson(text) {\n  const cleaned = String(text || '').trim().replace(/^```json\\s*/i, '').replace(/^```/, '').replace(/```$/, '').trim();\n  const first = cleaned.indexOf('{');\n  const last = cleaned.lastIndexOf('}');\n  const candidate = first >= 0 && last >= first ? cleaned.slice(first, last + 1) : cleaned;\n  return JSON.parse(candidate);\n}\nconst content = $json.choices?.[0]?.message?.content || '{}';\nconst parsed = parseJson(content);\nreturn [{ json: {\n  ...$('Build Brief Prompt').item.json,\n  brief_markdown: parsed.brief_markdown,\n  slack_summary: parsed.slack_summary,\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "06cdd69b-4319-40a5-a5f3-974fe29132ca",
      "name": "Create Brief Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        2208,
        2368
      ],
      "parameters": {
        "name": "={{$json.sector.replace(/[\\\\/:*?\"<>|]/g, '-') + ' - briefing - ' + $now.toFormat('yyyy-LL-dd')}}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "url",
          "value": "=https://drive.google.com/drive/u/0/folders/1GH-YouAAImKugZ11IbqA6Ouw8B9U17-I"
        },
        "resource": "folder"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "a35f1153-15ec-45ac-8003-91c0f3b46cc6",
      "name": "Create Brief Doc",
      "type": "n8n-nodes-base.googleDocs",
      "position": [
        2432,
        2368
      ],
      "parameters": {
        "title": "={{$node[\"Parse Brief Output\"].json.sector}} Industry Briefing",
        "folderId": "={{$json.id}}"
      },
      "credentials": {
        "googleDocsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "d68a4ee4-853d-4f87-a505-952f601f1a16",
      "name": "Update Brief Doc",
      "type": "n8n-nodes-base.googleDocs",
      "position": [
        2656,
        2368
      ],
      "parameters": {
        "actionsUi": {
          "actionFields": [
            {
              "text": "={{$node[\"Parse Brief Output\"].json.brief_markdown}}",
              "action": "insert"
            }
          ]
        },
        "operation": "update",
        "documentURL": "={{$json.id}}"
      },
      "credentials": {
        "googleDocsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "4d6eaac0-1d55-46d6-831d-d0de933de71a",
      "name": "Brief Response",
      "type": "n8n-nodes-base.code",
      "position": [
        2880,
        2368
      ],
      "parameters": {
        "jsCode": "const docUrl = `https://docs.google.com/document/d/${$('Create Brief Doc').item.json.id}/edit`;\nreturn [{ json: {\n  channel: $('Parse Brief Output').item.json.channel,\n  thread_ts: $('Parse Brief Output').item.json.thread_ts,\n  reply_text: `Industry briefing ready for *${$('Parse Brief Output').item.json.sector}*\\n\\n${$('Parse Brief Output').item.json.slack_summary}\\n\\nBriefing doc: ${docUrl}`\n} }];"
      },
      "typeVersion": 2
    },
    {
      "id": "ba2da684-d4d9-4173-860d-b6900e47f39e",
      "name": "Send Slack Reply",
      "type": "n8n-nodes-base.slack",
      "maxTries": 2,
      "position": [
        3104,
        1776
      ],
      "parameters": {
        "text": "={{$json.reply_text}}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "={{$json.channel}}"
        },
        "otherOptions": {
          "mrkdwn": true,
          "thread_ts": {
            "replyValues": {
              "thread_ts": "={{$json.thread_ts}}"
            }
          },
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 2.3,
      "waitBetweenTries": 3000
    },
    {
      "id": "2c1174db-4489-4c28-a214-01a6508e06b9",
      "name": "Note - Intake and Routing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3536,
        1536
      ],
      "parameters": {
        "color": 7,
        "width": 1736,
        "height": 552,
        "content": "## 1. Intake + Routing\n- Listen for Slack messages in the finance research analyst channel\n- Reject bot / empty events\n- Build a structured prompt for intent classification and provide missing info such as website id\n- Route each request into `research`, `pitch`, `brief`, or unknown"
      },
      "typeVersion": 1
    },
    {
      "id": "b4525287-b8d7-4170-a63c-8aaaa77e3c0c",
      "name": "Note - Research Flow",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2000,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 3224,
        "height": 1356,
        "content": "## 2.1.1 Research Flow\n- Find the best Companies House entity match\n- Pull company profile, officers, filings, web/news context, and market quote\n- Merge the source bundle and ask the model for a research pack\n"
      },
      "typeVersion": 1
    },
    {
      "id": "60f46c24-b61f-4f0a-bc64-337eb67cf3b2",
      "name": "Note - Pitch Flow",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -688,
        1632
      ],
      "parameters": {
        "color": 7,
        "width": 1944,
        "height": 524,
        "content": "## 2.2.1 Pitch Core  Flow\n- Require prior stored research before building any pitch materials\n- Reuse research memory from Postgres\n- Ask the model for compact slide-ready bullet content, not long narrative text\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1dc30505-38b6-4f68-90d6-706c11e6eead",
      "name": "Note - Briefing Flow",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -688,
        2224
      ],
      "parameters": {
        "color": 7,
        "width": 1916,
        "height": 540,
        "content": "## 2.3.1 Briefing Flow\n- Require a sector name\n- Gather sector news plus ONS macro M&A context\n- Merge both sources into one briefing bundle\n- Ask the model for a concise one-page sector briefing\n- Create the briefing folder and Google Doc"
      },
      "typeVersion": 1
    },
    {
      "id": "a402522a-99c9-4750-be75-7e8d41280240",
      "name": "Note - Slack Responses",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3184,
        1632
      ],
      "parameters": {
        "color": 7,
        "width": 420,
        "height": 280,
        "content": "## 3. Slack Replies\n- Every branch ends by building a clean thread reply\n- Research returns the profile doc link\n- Pitch returns the deck and press release links\n- Briefing returns the briefing doc link\n- Unknown or missing-input paths also reply here"
      },
      "typeVersion": 1
    },
    {
      "id": "c5ee6483-5a6d-4c3e-9877-e38a428e2f5f",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1280,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 2048,
        "height": 1360,
        "content": "## 2.1.2. Research Storage\n- Create the research folder and Google Doc\n- Save structured memory to Postgres\n- Sheets update nodeiwith all customers"
      },
      "typeVersion": 1
    },
    {
      "id": "955fdd44-fd4d-43a7-915b-90afc864a5c7",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1280,
        1696
      ],
      "parameters": {
        "color": 7,
        "width": 1766,
        "height": 496,
        "content": "## 2.2.2 Pitch saving\n Copy the Google Slides template and replace placeholders\n- Create the press release draft in Google Docs\n- Save the deck URL back to Postgres\n- Template charts, if any, are left as template visuals only"
      },
      "typeVersion": 1
    },
    {
      "id": "91e24305-ba30-4179-a8cf-8601f6cb3768",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4416,
        1600
      ],
      "parameters": {
        "width": 656,
        "height": 1600,
        "content": "## Finance Research Analyst AI Employee\n\nReal job listing for UK finance M&A analyst and how might automating their role look like. \n\n### How it works\n\n- Slack trigger listens on a specific channel for analyst intents. \n- We cover 3 specific intents - research, pitch deck and industry briefing. AI model classifies this intent and branches to right intent. \n- **Research** (ex. Input Research fintech company revolut)\n --  Fetch UK companies house profile, persons & filings. Free API. \n --  Fetch company news and website information. Firecrawler free.\n --  Fetch Alphavantage if publicly trading company\n -- Merge all data APIs into single package. \n -- AI node to  consolidate research information\n -- Store in google drive and postgreSQL tables. \n -- Respond back to slack thread.\n\n\n- **Pitch** (ex. create pitch deck for revolut)\n --  Pulls pre-existing company \n --  Uses AI to extract key information\n --  Create new deck from existing template\n --  Store in google drive and postgreSQL tables. \n -- Respond back to slack thread.\n\n- **Pitch** (ex. industry briefing for fintech uk)\n --  Pulls ONS M&A information (free site scraping)\n -- Sector news - fire crawler free\n --  Uses AI to extract key information\n --  Store in google drive \n --  Respond back to slack thread.\n\n### How to Setup\n@[youtube](GONk4r8lKIg)\n\n\nResources folder: https://drive.google.com/drive/folders/15xftVTrQLGJN0SjyEQsOM96cWVNuJgDl?usp=sharing\n\n#### Keys Required\n- Openrouter or OpenAI key\n- Firecrawler API\n- Companies house API - Free\n- Google OAuth setup for sheets, docs, drive and slides.\n- Alpha Vantage API - Free\n\n\n### Customisation\n\n- Use telegram or simple form instead of slack- setup is simpler. \n- Use supabase. Can also completely remove if storage is not required, but 'pitch' won't work. \n- Change LLM models to cheaper alternatives such as kimik2.7\n- Expand to using graphs \n- Expand to paid deals datebases"
      },
      "typeVersion": 1
    },
    {
      "id": "9595aa09-a535-45f6-b05b-680c3aed4067",
      "name": "Slack Trigger Request",
      "type": "n8n-nodes-base.slackTrigger",
      "position": [
        -3392,
        1888
      ],
      "parameters": {
        "options": {},
        "trigger": [
          "message"
        ],
        "channelId": {
          "__rl": true,
          "mode": "url",
          "value": "https://app.slack.com/client/T087RB3J8SZ/C0AQV67PTGU"
        }
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b8c9a8b4-cfde-4ad9-8793-04143446b6f4",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1264,
        2256
      ],
      "parameters": {
        "color": 7,
        "width": 1744,
        "height": 512,
        "content": "## 2.3.2 Industry briefing Store\n- Create docs file in google drive.\n- Respond back on slack thread"
      },
      "typeVersion": 1
    },
    {
      "id": "ac364535-66a9-4380-a55c-cc4cd93b86bd",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1024,
        320
      ],
      "parameters": {
        "color": 3,
        "height": 80,
        "content": "### Beware of AI costs\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "callerPolicy": "workflowsFromSameOwner",
    "timeSavedMode": "fixed",
    "availableInMCP": false,
    "executionOrder": "v1",
    "executionTimeout": 180,
    "timeSavedPerExecution": 6
  },
  "versionId": "ccc8ed0f-7b4e-49bf-aa9e-560f0a58d054",
  "connections": {
    "Brief AI": {
      "main": [
        [
          {
            "node": "Parse Brief Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pitch AI": {
      "main": [
        [
          {
            "node": "Parse Pitch Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Ticker?": {
      "main": [
        [
          {
            "node": "Alpha Vantage Overview",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Market Data Placeholder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Research AI": {
      "main": [
        [
          {
            "node": "Parse Research Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sector News": {
      "main": [
        [
          {
            "node": "Wrap Sector News",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Company News": {
      "main": [
        [
          {
            "node": "Wrap Research News",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Intent": {
      "main": [
        [
          {
            "node": "Intent Switch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wrap Filings": {
      "main": [
        [
          {
            "node": "Merge Research 2",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Wrap ONS M&A": {
      "main": [
        [
          {
            "node": "Merge Brief Sources",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Wrap Profile": {
      "main": [
        [
          {
            "node": "Merge Research 1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wrap Website": {
      "main": [
        [
          {
            "node": "Merge Research 4",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Intent Switch": {
      "main": [
        [
          {
            "node": "Has Research Inputs?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Has Pitch Company?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Has Brief Sector?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Unknown Intent Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wrap Officers": {
      "main": [
        [
          {
            "node": "Merge Research 1",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Brief Response": {
      "main": [
        [
          {
            "node": "Send Slack Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ONS M&A Source": {
      "main": [
        [
          {
            "node": "Wrap ONS M&A",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pitch Response": {
      "main": [
        [
          {
            "node": "Send Slack Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Website Search": {
      "main": [
        [
          {
            "node": "Wrap Website",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Brief Doc": {
      "main": [
        [
          {
            "node": "Update Brief Doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Research 1": {
      "main": [
        [
          {
            "node": "Merge Research 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Research 2": {
      "main": [
        [
          {
            "node": "Merge Research 3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Research 3": {
      "main": [
        [
          {
            "node": "Merge Research 4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Research 4": {
      "main": [
        [
          {
            "node": "Merge Research 5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Research 5": {
      "main": [
        [
          {
            "node": "Build Research Bundle",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Brief Doc": {
      "main": [
        [
          {
            "node": "Brief Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wrap Sector News": {
      "main": [
        [
          {
            "node": "Merge Brief Sources",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Brief Sector?": {
      "main": [
        [
          {
            "node": "Sector News",
            "type": "main",
            "index": 0
          },
          {
            "node": "ONS M&A Source",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Brief Missing Sector Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Intent Classifier": {
      "main": [
        [
          {
            "node": "Parse Intent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Research Response": {
      "main": [
        [
          {
            "node": "Send Slack Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Brief Bundle": {
      "main": [
        [
          {
            "node": "Build Brief Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Brief Prompt": {
      "main": [
        [
          {
            "node": "Brief AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Pitch Prompt": {
      "main": [
        [
          {
            "node": "Pitch AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Profile Doc": {
      "main": [
        [
          {
            "node": "Update Profile Doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Pitch Company?": {
      "main": [
        [
          {
            "node": "Load Company Record",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Pitch Missing Input Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Brief Output": {
      "main": [
        [
          {
            "node": "Create Brief Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Pitch Output": {
      "main": [
        [
          {
            "node": "Copy Slides Template",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Profile Doc": {
      "main": [
        [
          {
            "node": "Upsert Company Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wrap Alpha Vantage": {
      "main": [
        [
          {
            "node": "Merge Research 5",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Wrap Research News": {
      "main": [
        [
          {
            "node": "Merge Research 3",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Create Brief Folder": {
      "main": [
        [
          {
            "node": "Create Brief Doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Pitch Folder": {
      "main": [
        [
          {
            "node": "Build Pitch Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Prior Research?": {
      "main": [
        [
          {
            "node": "Load Research Memory",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Pitch Missing Research Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load Company Record": {
      "main": [
        [
          {
            "node": "Has Prior Research?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Brief Sources": {
      "main": [
        [
          {
            "node": "Build Brief Bundle",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Pitch Assets": {
      "main": [
        [
          {
            "node": "Update Client DB Pitch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Intent Request": {
      "main": [
        [
          {
            "node": "Intent Classifier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Company Match Found?": {
      "main": [
        [
          {
            "node": "Companies House Profile",
            "type": "main",
            "index": 0
          },
          {
            "node": "Companies House Officers",
            "type": "main",
            "index": 0
          },
          {
            "node": "Companies House Filings",
            "type": "main",
            "index": 0
          },
          {
            "node": "Company News",
            "type": "main",
            "index": 0
          },
          {
            "node": "Website Search",
            "type": "main",
            "index": 0
          },
          {
            "node": "Has Ticker?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Company Not Found Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Copy Slides Template": {
      "main": [
        [
          {
            "node": "Create Custom Presentation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Research Inputs?": {
      "main": [
        [
          {
            "node": "Companies House Search",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Research Missing Input Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Research Memory?": {
      "main": [
        [
          {
            "node": "Create Pitch Folder",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Pitch Missing Research Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load Research Memory": {
      "main": [
        [
          {
            "node": "Has Research Memory?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Research Memory": {
      "main": [
        [
          {
            "node": "Update Client DB Research",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Valid Slack Message?": {
      "main": [
        [
          {
            "node": "Prepare Slack Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Research Bundle": {
      "main": [
        [
          {
            "node": "Build Research Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Research Prompt": {
      "main": [
        [
          {
            "node": "Research AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Research Output": {
      "main": [
        [
          {
            "node": "Create Research Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Slack Context": {
      "main": [
        [
          {
            "node": "Build Intent Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack Trigger Request": {
      "main": [
        [
          {
            "node": "Valid Slack Message?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upsert Company Record": {
      "main": [
        [
          {
            "node": "Save Research Memory",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Alpha Vantage Overview": {
      "main": [
        [
          {
            "node": "Wrap Alpha Vantage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Companies House Search": {
      "main": [
        [
          {
            "node": "Pick Best Company Match",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Research Folder": {
      "main": [
        [
          {
            "node": "Create Profile Doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Client DB Pitch": {
      "main": [
        [
          {
            "node": "Pitch Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Companies House Filings": {
      "main": [
        [
          {
            "node": "Wrap Filings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Companies House Profile": {
      "main": [
        [
          {
            "node": "Wrap Profile",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pick Best Company Match": {
      "main": [
        [
          {
            "node": "Company Match Found?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Unknown Intent Response": {
      "main": [
        [
          {
            "node": "Send Slack Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Companies House Officers": {
      "main": [
        [
          {
            "node": "Wrap Officers",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Press Release Doc": {
      "main": [
        [
          {
            "node": "Update Press Release Doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Press Release Doc": {
      "main": [
        [
          {
            "node": "Update Pitch Assets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Client DB Research": {
      "main": [
        [
          {
            "node": "Research Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Company Not Found Response": {
      "main": [
        [
          {
            "node": "Send Slack Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Custom Presentation": {
      "main": [
        [
          {
            "node": "Create Press Release Doc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "No Market Data Placeholder": {
      "main": [
        [
          {
            "node": "Merge Research 5",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Pitch Missing Input Response": {
      "main": [
        [
          {
            "node": "Send Slack Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Brief Missing Sector Response": {
      "main": [
        [
          {
            "node": "Send Slack Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pitch Missing Research Response": {
      "main": [
        [
          {
            "node": "Send Slack Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Research Missing Input Response": {
      "main": [
        [
          {
            "node": "Send Slack Reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}