{
  "name": "Dossier antes de cada reunión comercial (plano de Saphia Labs)",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 30
            }
          ]
        }
      },
      "id": "tr",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "operation": "getAll",
        "calendar": {
          "__rl": true,
          "mode": "list",
          "value": "primary"
        },
        "returnAll": true,
        "timeMin": "={{ $now.toISO() }}",
        "timeMax": "={{ $now.plus({ hours: 2 }).toISO() }}",
        "options": {
          "singleEvents": true
        }
      },
      "id": "cal",
      "name": "Calendar: próximas 2 horas",
      "type": "n8n-nodes-base.googleCalendar",
      "typeVersion": 1.3,
      "position": [
        260,
        0
      ],
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "operation": "read",
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "TU_SPREADSHEET_ID"
        },
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "dossiers"
        },
        "options": {}
      },
      "id": "done",
      "name": "Sheets: dossiers ya enviados",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        520,
        0
      ],
      "executeOnce": true,
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "jsCode": "const hechos = new Set($input.all().map(i => String(i.json.evento_id || '')));\nconst eventos = $('Calendar: próximas 2 horas').all().map(i => i.json).filter(e => e && e.id);\nconst PROPIOS = ['TU_DOMINIO.com'];\nconst out = [];\nfor (const e of eventos) {\n  if (hechos.has(e.id)) continue;\n  const ext = (e.attendees || []).map(a => a.email || '').filter(m => m && !PROPIOS.includes(m.split('@')[1]));\n  if (!ext.length) continue;\n  const dominio = ext[0].split('@')[1];\n  out.push({ json: { evento_id: e.id, titulo: e.summary || '', inicio: (e.start || {}).dateTime || '', organizador: (e.organizer || {}).email || '', dominio, invitados: ext.join(', '), url: 'https://' + dominio } });\n}\nreturn out;"
      },
      "id": "sel",
      "name": "Code: reuniones con externos",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        780,
        0
      ]
    },
    {
      "parameters": {
        "url": "={{ $json.url }}",
        "options": {
          "timeout": 15000,
          "response": {
            "response": {
              "responseFormat": "text"
            }
          }
        }
      },
      "id": "http",
      "name": "HTTP: sitio de la empresa",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1040,
        0
      ],
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "jsCode": "const ev = $('Code: reuniones con externos').item.json;\nconst html = typeof $input.item.json.data === 'string' ? $input.item.json.data : '';\nconst texto = html.replace(/<script[\\s\\S]*?<\\/script>/gi, ' ').replace(/<style[\\s\\S]*?<\\/style>/gi, ' ').replace(/<[^>]+>/g, ' ').replace(/\\s+/g, ' ').trim().slice(0, 5000);\nreturn { json: { ...ev, sitio: texto || '(no se pudo leer el sitio)' } };",
        "mode": "runOnceForEachItem"
      },
      "id": "clean",
      "name": "Code: texto del sitio",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1300,
        0
      ]
    },
    {
      "parameters": {
        "resource": "text",
        "operation": "message",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "claude-sonnet-5-5"
        },
        "messages": {
          "values": [
            {
              "role": "user",
              "content": "={{ 'REUNIÓN: ' + $json.titulo + ' · ' + $json.inicio + '\\nEMPRESA (dominio): ' + $json.dominio + '\\nINVITADOS: ' + $json.invitados + '\\n\\nTEXTO DEL SITIO\\n' + $json.sitio }}"
            }
          ]
        },
        "options": {
          "system": "Eres analista de preventa de [organización], que ofrece [qué ofrecemos]. Prepara un dossier de una página para una reunión con la empresa indicada (sitio web adjunto; busca además noticias de los últimos 6 meses). Estructura:\n1. Qué hace la empresa, en 2 frases, con fuente.\n2. Tres hechos recientes relevantes (lanzamientos, contrataciones, cambios), cada uno con fecha y fuente.\n3. Dónde podríamos ayudar: 2 o 3 hipótesis conectadas a lo que ofrecemos, marcadas como hipótesis.\n4. Tres preguntas para abrir la conversación.\n5. Señales de alerta: cosas que sugieren que no es buen momento.\nReglas: cada afirmación con su fuente (URL); si no encuentras algo, dilo en vez de rellenar; nada sobre personas que no sea su cargo público; máximo 300 palabras.",
          "maxTokens": 4000,
          "webSearch": true,
          "maxUses": 3
        }
      },
      "id": "cl",
      "name": "Claude: armar dossier (con búsqueda web)",
      "type": "@n8n/n8n-nodes-langchain.anthropic",
      "typeVersion": 1,
      "position": [
        1560,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "const ev = $('Code: texto del sitio').item.json;\nconst texto = ($input.item.json.content || []).filter(b => b.type === 'text').map(b => b.text).join('\\n').trim();\nreturn { json: { ...ev, dossier: texto } };",
        "mode": "runOnceForEachItem"
      },
      "id": "tx",
      "name": "Code: texto del dossier",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1820,
        0
      ]
    },
    {
      "parameters": {
        "resource": "draft",
        "subject": "=Dossier: {{ $json.titulo }}",
        "emailType": "text",
        "message": "={{ $json.dossier }}",
        "options": {
          "sendTo": "={{ $json.organizador }}"
        }
      },
      "id": "gm",
      "name": "Gmail: borrador al organizador",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        2080,
        -100
      ]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "TU_SPREADSHEET_ID"
        },
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "dossiers"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "evento_id": "={{ $('Code: texto del dossier').item.json.evento_id }}",
            "fecha": "={{ $now.toISO() }}",
            "empresa": "={{ $('Code: texto del dossier').item.json.dominio }}",
            "enviado": "borrador"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "evento_id",
              "displayName": "evento_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "fecha",
              "displayName": "fecha",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "empresa",
              "displayName": "empresa",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "enviado",
              "displayName": "enviado",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ]
        },
        "options": {}
      },
      "id": "sh",
      "name": "Sheets: marcar enviado",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        2340,
        -100
      ]
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Calendar: próximas 2 horas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calendar: próximas 2 horas": {
      "main": [
        [
          {
            "node": "Sheets: dossiers ya enviados",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sheets: dossiers ya enviados": {
      "main": [
        [
          {
            "node": "Code: reuniones con externos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: reuniones con externos": {
      "main": [
        [
          {
            "node": "HTTP: sitio de la empresa",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP: sitio de la empresa": {
      "main": [
        [
          {
            "node": "Code: texto del sitio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: texto del sitio": {
      "main": [
        [
          {
            "node": "Claude: armar dossier (con búsqueda web)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Claude: armar dossier (con búsqueda web)": {
      "main": [
        [
          {
            "node": "Code: texto del dossier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: texto del dossier": {
      "main": [
        [
          {
            "node": "Gmail: borrador al organizador",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail: borrador al organizador": {
      "main": [
        [
          {
            "node": "Sheets: marcar enviado",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "timezone": "America/Bogota"
  },
  "meta": {
    "templateCredsSetupCompleted": false,
    "probadoEn": "n8n 2.41.6, octubre 2026",
    "preparacion": "Pon tu dominio en \"Code: reuniones con externos\" y describe tu organización y oferta en el prompt. Crea una pestaña \"dossiers\" con encabezado evento_id, fecha, empresa, enviado para no repetir dossiers. Reemplaza TU_SPREADSHEET_ID. La búsqueda web está activada en el nodo de Anthropic (hasta 3 búsquedas por dossier).",
    "fuente": "https://saphialabs.com/recursos/flujos/#f8"
  }
}