Tu dashboard de Instantly se abre con 200 leads en cola, plantillas preparadas, y ese mismo sentimiento vacío — otro lote de "Hola {firstName}, noté que tu empresa..." a punto de enviarse. Toda agencia odia el cold email. Nosotros también. No porque el outreach no funcione, sino porque cada plataforma que pagábamos aún requería horas de investigación manual, aún enviaba copy que parecía escrito por un bot, y aún costaba $300/mes para hacer lo que sabíamos que Claude podía hacer mejor en segundos. Así que dejamos de alquilar. Conectamos Claude, Hunter, Instantly y Supabase en un sistema que escribe aperturas contextuales desde raspados web en vivo, califica respuestas por intención, y registra cada interacción sin la tasa de SaaS. La arquitectura no es ciencia de cohetes — pero la tasa de respuesta saltó, el trabajo aburrido desapareció, y somos dueños de todo el stack.

Esto no es un post de arquitectura teórica. Hemos estado ejecutando este sistema en producción durante meses, enviando miles de emails personalizados que realmente generan respuestas. Voy a caminar contigo exactamente por qué lo construimos, cómo encajan las piezas, y qué aprendimos de la manera difícil.

Tabla de Contenidos

Por Qué Construimos Nuestro Propio Sistema de Cold Email con Claude, Instantly y Supabase

El Problema Con Outreach Listo para Usar

Probamos los sospechosos usuales. Lemlist. Apollo. Woodpecker. Son herramientas bien para muchos casos de uso. Pero como agencia de desarrollo web headless, nuestras necesidades de outreach eran específicas de maneras que estas plataformas no podían manejar.

Aquí está lo que siguió rompiéndose:

Los campos de personalización genéricos no son personalización. Insertar el nombre de la empresa y el título del trabajo de alguien en una plantilla no engaña a nadie en 2026. Necesitábamos emails que hicieran referencia al actual stack de tecnología del prospecto, sus problemas de rendimiento del sitio, o decisiones arquitectónicas específicas visibles en su sitio web público.

El paso de investigación era el cuello de botella. Nuestro outreach con mejor rendimiento siempre implicaba que alguien del equipo realmente mirara el sitio de un prospecto, lo ejecutara a través de PageSpeed Insights, verificara su framework, y escribiera algo específico. Eso tomaba 10-15 minutos por lead. A escala, eso es un trabajo de tiempo completo.

Los datos vivían en demasiados lugares. Leads en una hoja de cálculo, secuencias de email en otra plataforma, resultados en un tercer dashboard. No podíamos construir bucles de retroalimentación porque nada se hablaba con nada más.

Las integraciones de IA eran superficiales. Algunas plataformas agregaron características de "escritura con IA", pero eran básicamente envolturas GPT que generaban el mismo copy insípido que todos los demás estaban enviando. Sin capacidad de proporcionar contexto personalizado, sin control sobre prompts, sin forma de construir cadenas de razonamiento de múltiples pasos.

Necesitábamos un sistema donde la IA hiciera la investigación, no solo la escritura.

Nuestro Tech Stack y Por Qué Lo Elegimos

Aquí está en lo que aterrizamos después de algunas iteraciones:

Componente Herramienta Rol Costo Mensual
Búsqueda de leads y verificación de email Hunter.io Encontrar y verificar direcciones de email $49 (Starter)
Investigación de IA y redacción Claude (Anthropic API) Analizar prospectos, generar emails personalizados ~$30-60
Base de datos y orquestación Supabase Almacenar leads, gestionar estado, activar workflows $25 (Pro)
Envío de email y warmup Instantly.ai Entregabilidad, infraestructura de envío, warmup $30 (Growth)
Pegamento de automatización Funciones Edge Personalizadas + Cron Conectar todo $0 (incluido en Supabase)

Evaluamos un montón de alternativas. Aquí está la versión corta de por qué elegimos lo que elegimos:

Claude sobre GPT-4: Probamos ambos extensamente. Claude 3.5 Sonnet (y ahora Claude 4 Sonnet en 2025) produjo consistentemente emails que sonaban más naturales y menos "escritos por IA". También fue mejor siguiendo prompts complejos del sistema sin derivarse. El precio era comparable, pero la ventana de contexto más larga de Claude significaba que podíamos proporcionar más datos de investigación por prospecto.

Supabase sobre Airtable o una configuración personalizada de Postgres: Necesitábamos una verdadera base de datos con seguridad de nivel de fila, pero no queríamos gestionar la infraestructura. Supabase nos dio Postgres, Funciones Edge, trabajos Cron, y un dashboard decente — todo en un lugar. Usamos Supabase mucho para proyectos de clientes también, así que el equipo ya lo conocía bien.

Instantly sobre Lemlist o Smartlead: La red de warmup de Instantly es genuinamente buena, su API es limpia, y el precio tenía sentido para nuestro volumen. No necesitamos el constructor de secuencias integrado de Instantly porque manejamos la lógica de secuenciamiento nosotros mismos.

Hunter sobre Apollo o Snov.io: La verificación de email de Hunter es consistentemente la más precisa que hemos probado. Su API de búsqueda de dominio es rápida y la calidad de datos es alta. Apollo tiene más puntos de datos, pero encontramos su precisión de email más baja, lo cual mata la entregabilidad.

Descripción General de la Arquitectura

El sistema funciona en cinco etapas, cada una ejecutándose independientemente:

[Fuentes de Leads] → [Enriquecimiento Hunter] → [BD Supabase] → [Investigación Claude + Copy] → [Envío Instantly]
     ↑                                       ↑                                           |
     |                                       |                                           |
     +----------- Bucle de Retroalimentación -----+-----------------------------------+
  1. Ingesta: Proporcionamos dominios de prospectos de varias fuentes (listas manuales, raspadores, datos de referral)
  2. Enriquecimiento: Hunter encuentra contactos y verifica emails
  3. Almacenamiento: Todo aterriza en Supabase con seguimiento de estado
  4. Investigación + Escritura: Claude analiza cada prospecto y genera copy personalizado
  5. Envío: Emails aprobados se envían a campañas de Instantly
  6. Aprendizaje: Datos de respuesta fluyen de vuelta a Supabase, informando futuras personalizaciones

Cada etapa está desacoplada. Si la API de Hunter se cae, la cola de enriquecimiento simplemente se acumula — no rompe el envío. Si queremos cambiar Claude por un modelo diferente, cambiamos una función.

Por Qué Construimos Nuestro Propio Sistema de Cold Email con Claude, Instantly y Supabase - arquitectura

Encontrando y Enriqueciendo Leads con Hunter

Hunter.io maneja dos trabajos críticos: encontrar la persona correcta en una empresa y verificar que su email realmente funcione.

Aquí está una versión simplificada de nuestra función de enriquecimiento:

import { createClient } from '@supabase/supabase-js';

const HUNTER_API_KEY = Deno.env.get('HUNTER_API_KEY');

async function enrichLead(domain: string) {
  // Búsqueda de dominio para encontrar tomadores de decisiones
  const searchRes = await fetch(
    `https://api.hunter.io/v2/domain-search?domain=${domain}&department=executive,it&api_key=${HUNTER_API_KEY}`
  );
  const searchData = await searchRes.json();
  
  const contacts = searchData.data.emails
    .filter((e: any) => e.confidence > 70)
    .slice(0, 3); // Top 3 contactos por dominio
  
  // Verificar cada email
  for (const contact of contacts) {
    const verifyRes = await fetch(
      `https://api.hunter.io/v2/email-verifier?email=${contact.value}&api_key=${HUNTER_API_KEY}`
    );
    const verifyData = await verifyRes.json();
    
    if (verifyData.data.status === 'valid') {
      await supabase.from('leads').insert({
        domain,
        email: contact.value,
        first_name: contact.first_name,
        last_name: contact.last_name,
        position: contact.position,
        confidence: contact.confidence,
        status: 'enriched',
        enriched_at: new Date().toISOString()
      });
    }
  }
}

Filtramos por los departamentos executive e it porque esos son nuestros compradores — CTOs, VPs de Ingeniería, fundadores técnicos. El filtrado de departamento de Hunter no es perfecto, pero elimina mucho ruido.

Una cosa que aprendimos: nunca saltes la verificación de email. Incluso con las puntuaciones de confianza de Hunter, aún verificamos cada dirección. Una tasa de rebote superior al 3% arruinará la reputación del dominio de envío. Hemos visto dominios pasar del 95% de colocación en bandeja de entrada al 40% de carpeta de spam por un mal lote.

Enviamos aproximadamente 500 créditos de búsquedas Hunter por semana, que cabe cómodamente en su plan Starter.

Personalización de IA con Claude

Aquí es donde las cosas se ponen interesantes. La integración de Claude no es solo "escribe me un cold email." Es una tubería multi-paso de investigación y escritura.

Paso 1: Análisis del Sitio Web

Antes de que Claude escriba cualquier cosa, le proporcionamos datos sobre el sitio web del prospecto. Raspamos información básica usando una función ligera:

async function analyzeProspectSite(domain: string) {
  // Obtener homepage y páginas clave
  const homepage = await fetch(`https://${domain}`);
  const html = await homepage.text();
  
  // Extraer señales de tecnología del HTML
  const signals = {
    hasNextJs: html.includes('__next') || html.includes('_next/static'),
    hasReact: html.includes('react') || html.includes('__REACT'),
    hasWordPress: html.includes('wp-content') || html.includes('wp-includes'),
    hasShopify: html.includes('shopify') || html.includes('cdn.shopify'),
    hasGatsby: html.includes('gatsby'),
    usesJQuery: html.includes('jquery'),
    metaGenerator: extractMeta(html, 'generator'),
    pageSize: html.length,
    // ... más señales
  };
  
  // Ejecutar verificación de PageSpeed vía API
  const psiData = await fetchPageSpeedInsights(domain);
  
  return {
    ...signals,
    performanceScore: psiData.lighthouseResult.categories.performance.score * 100,
    lcp: psiData.lighthouseResult.audits['largest-contentful-paint'].numericValue,
    cls: psiData.lighthouseResult.audits['cumulative-layout-shift'].numericValue,
    fid: psiData.lighthouseResult.audits['max-potential-fid'].numericValue
  };
}

Esto le da a Claude datos reales con los que trabajar. No "Hola, noté que tu empresa hace X" — más como "Tu homepage LCP es 4.2 segundos y aún estás ejecutando jQuery junto con React, lo que agrega 90KB a tu bundle inicial."

Paso 2: Prompt de Investigación de Claude

Usamos la API de Claude con un prompt de sistema cuidadosamente diseñado. Aquí está una versión simplificada:

const researchPrompt = `Eres un desarrollador web senior analizando el sitio web de un prospecto para una agencia de desarrollo headless. Dados los siguientes datos técnicos sobre su sitio, identifica:

1. Su actual stack de tecnología (sé específico)
2. 2-3 problemas concretos de rendimiento o arquitectura
3. Qué una migración a una arquitectura headless moderna podría mejorar
4. Una observación específica, no obvia, que muestre análisis genuino

NO seas genérico. Si no puedes encontrar algo específico, dilo.
NO menciones "en el panorama digital de hoy" u relleno similar.
Sé directo y técnico.

Datos del sitio:
${JSON.stringify(siteAnalysis, null, 2)}

Prospecto: ${lead.first_name} ${lead.last_name}, ${lead.position} en ${lead.domain}`;

const research = await anthropic.messages.create({
  model: 'claude-sonnet-4-20250514',
  max_tokens: 1000,
  messages: [{ role: 'user', content: researchPrompt }]
});

Paso 3: Generación de Email

La salida de investigación se alimenta en una segunda llamada a Claude que escribe el email actual. Dividir investigación de escritura fue una percepción clave — cuando intentamos hacer ambas en un prompt, los emails eran peores. Claude saltaría la investigación para llegar a la escritura más rápido.

const emailPrompt = `Escribe un cold email de un desarrollador senior de una agencia web headless.

Notas de investigación:
${research.content[0].text}

Reglas:
- 4-6 oraciones máximo. Cada oración debe justificar su lugar.
- Lidera con la observación técnica más específica.
- Sin adulación. Sin "Me encanta lo que estás haciendo".
- Un CTA claro: pregunta si querrían ver una auditoría de rendimiento.
- Suena como un desarrollador, no como un vendedor.
- Usa su nombre. Sin apellido en el saludo.
- Línea de asunto: corta, específica a su problema técnico, minúscula.`;

¿El resultado? Emails que se abren con cosas como "Tu tienda Shopify Plus está renderizando en el servidor las páginas de productos que podrían ser generadas estáticamente — eso está agregando 2+ segundos a cada vista de producto" en lugar de "Noté tu impresionante empresa y quería comunicarme."

Supabase como Capa de Orquestación

Supabase es el cerebro de la operación. Aquí está nuestro esquema central:

create table leads (
  id uuid primary key default gen_random_uuid(),
  domain text not null,
  email text,
  first_name text,
  last_name text,
  position text,
  confidence int,
  status text default 'new', -- new, enriched, researched, drafted, approved, sent, replied, bounced
  site_analysis jsonb,
  research_notes text,
  email_subject text,
  email_body text,
  instantly_campaign_id text,
  sent_at timestamptz,
  opened_at timestamptz,
  replied_at timestamptz,
  created_at timestamptz default now(),
  updated_at timestamptz default now()
);

create index idx_leads_status on leads(status);
create index idx_leads_domain on leads(domain);

El campo status impulsa todo. Los trabajos Supabase Cron se ejecutan cada 15 minutos, recogiendo leads en cada etapa y empujándolos a la siguiente:

-- Cron: Procesar leads enriquecidos a través de investigación Claude
select cron.schedule(
  'process-research',
  '*/15 * * * *',
  $$select net.http_post(
    'https://your-project.supabase.co/functions/v1/process-research',
    '{}',
    '{"Authorization": "Bearer your-service-key"}'::jsonb
  )$$
);

Procesamos por lotes 20 leads por ejecución para mantenernos dentro de los límites de velocidad de Claude y mantener los costos predecibles.

La columna site_analysis JSONB es increíblemente útil. Podemos consultar todos nuestros leads para encontrar patrones — como "muéstrame todos los leads ejecutando WordPress con una puntuación de rendimiento por debajo de 50" — y construir campañas dirigidas de esos segmentos.

Envío a Escala con Instantly

Instantly maneja la entrega de email actual. Empujamos emails aprobados a través de su API:

async function pushToInstantly(lead: Lead) {
  const response = await fetch('https://api.instantly.ai/api/v1/lead/add', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      api_key: INSTANTLY_API_KEY,
      campaign_id: lead.instantly_campaign_id,
      skip_if_in_workspace: true,
      leads: [{
        email: lead.email,
        first_name: lead.first_name,
        last_name: lead.last_name,
        company_name: lead.domain,
        personalization_1: lead.email_subject,
        personalization_2: lead.email_body
      }]
    })
  });
  
  if (response.ok) {
    await supabase
      .from('leads')
      .update({ status: 'sent', sent_at: new Date().toISOString() })
      .eq('id', lead.id);
  }
}

Las plantillas de campaña de Instantly usan variables {{personalization_1}} y {{personalization_2}}, que asignan al sujeto y cuerpo generados por Claude. La campaña misma es solo un caparazón — toda la inteligencia vive en nuestro sistema.

Executamos 3 cuentas de envío a través del warmup de Instantly durante al menos 2 semanas antes de enviar cualquier outreach. El warmup de dominio no es opcional. Aprendimos esto de la manera difícil con nuestro primer dominio siendo marcado dentro de una semana.

Configuración de Entregabilidad

Nuestra infraestructura de envío:

  • 3 dominios (variaciones de nuestra marca, no nuestro dominio principal)
  • SPF, DKIM, y DMARC configurados en todos ellos
  • Cuentas Google Workspace (no Outlook — Google maneja mejor cold email en nuestras pruebas)
  • Warmup de Instantly ejecutándose continuamente, incluso en días de envío activo
  • Máximo 35 emails por cuenta por día
  • Intervalos de envío aleatorios entre 3-7 minutos

El Pegamento de Automatización

Las Funciones Edge de Supabase conectan todo. Aquí está el flujo en pseudocódigo:

Cada 15 minutos:
  1. Recoger leads con status='new', ejecutar enriquecimiento Hunter → status='enriched'
  2. Recoger leads con status='enriched', ejecutar análisis de sitio → status='analyzed'
  3. Recoger leads con status='analyzed', ejecutar investigación Claude + generación de email → status='drafted'
  4. (Humano revisa emails redactados en dashboard de Supabase)
  5. Recoger leads con status='approved', empujar a Instantly → status='sent'
  6. Extraer datos de engagement de API de Instantly → actualizar opened_at, replied_at

El paso 4 es importante. No automatizamos completamente el envío. Cada email recibe revisión humana antes de que salga. Esto atrapa la ocasional alucinación (Claude una vez afirmó que un sitio fue construido con Remix cuando claramente era Next.js) y nos deja agregar toques personales.

El paso de revisión toma aproximadamente 2-3 segundos por email ya que Claude hace correctamente el 95% del trabajo. Aprobamos en lotes usando una simple vista de dashboard de Supabase.

Resultados y Lo Que Aprendimos

Hemos estado ejecutando este sistema desde Q1 2025. Aquí hay números reales:

| Métrica | Nuestro Sistema | Promedio de Industria (2026) | |--------|-----------|------------------------|| | Tasa de Apertura | 62% | 24% | | Tasa de Respuesta | 8.4% | 1-3% | | Tasa de Respuesta Positiva | 4.1% | 0.5-1% | | Tasa de Rechazo | 0.8% | 3-5% | | Costo Por Lead Contactado | $0.18 | $0.50-2.00 | | Tiempo Por Lead (humano) | ~5 segundos (revisión) | 10-15 minutos |

La tasa de apertura es alta porque las líneas de asunto son específicas. "tu shopify lcp es 4.2s" se abre. "Pregunta rápida" no.

La tasa de respuesta es alta porque los emails demuestran conocimiento técnico genuino. Cuando un CTO lee un email que identifica correctamente su stack de tecnología y un problema real de rendimiento, es más probable que se enganche — incluso si sabe que es outreach.

Lo Que No Funcionó

Envío completamente automatizado (sin revisión humana): Intentamos esto durante dos semanas. Claude alucinó detalles de stack de tecnología aproximadamente el 5% del tiempo. Esa es una tasa de error baja para un LLM, pero enviar un email que dice "tu aplicación React" a alguien ejecutando Vue es peor que enviar un email genérico. El daño de confianza es real.

Emails largos: Nuestros primeros prompts de Claude generaron emails de 8-10 oraciones. Las tasas de respuesta eran la mitad de lo que vemos ahora con 4-6 oraciones. Más corto es mejor. Siempre.

Enviar más de 40 emails por día por cuenta: La entregabilidad cae verticalmente. 30-35 es el punto dulce en 2026.

Usar Claude para seguimientos basados en aperturas: Intentamos generar emails de seguimiento activados por aperturas. Los seguimientos se sentían invasivos y la conversión no valía el costo. Ahora enviamos un seguimiento simple, no basado en IA, tres días después.

Desglose de Costos

Aquí está lo que esto nos cuesta mensualmente, procesando aproximadamente 2,000 leads:

Servicio Costo Mensual Notas
Hunter.io (Starter) $49 500 búsquedas + verificaciones
Anthropic API (Claude) $45 ~2,000 investigaciones + generaciones de email
Supabase (Pro) $25 Base de datos, Funciones Edge, Cron
Instantly (Growth) $30 Envío, warmup, analytics
Google Workspace (3 cuentas) $21 Infraestructura de envío
Dominios (3) $10 Costo anual amortizado
Total ~$180 $0.09 por lead procesado

Compara eso con el plan $79/mes de Apollo (enriquecimiento limitado, secuencias básicas) o el $69/mes por asiento de Lemlist. Estamos gastando menos y obteniendo resultados dramáticamente mejores porque la personalización es real, no basada en plantillas.

Para contexto, este sistema ha generado directamente leads que se convirtieron en desarrollo Next.js y desarrollo Astro proyectos que valen 50-100x el costo mensual. El ROI es absurdo.

Preguntas Frecuentes

¿Cuánto tiempo tomó construir este sistema? La primera versión funcional tomó aproximadamente dos semanas de esfuerzo de tiempo parcial — quizás 40 horas totales. Hemos iterado sobre él continuamente desde entonces, principalmente ajustando prompts de Claude y agregando manejo de casos extremos. Si estás cómodo con Funciones Edge de Supabase y APIs REST, podrías obtener una versión básica funcionando en un fin de semana.

¿No es esto simplemente spam con pasos extra? Pregunta justa. La diferencia es que cada email contiene una observación técnica genuina sobre el sitio web del destinatario. No estamos disparando "reunámonos" a 10,000 personas. Estamos enviando insights específicos y útiles a una lista dirigida de personas que realmente tienen los problemas que resolvemos. Nuestra tasa de baja es inferior al 0.5%, lo que sugiere que los destinatarios no lo ven como spam tampoco.

¿Por qué Claude en lugar de GPT-4 o Gemini? Probamos los tres. Claude siguió nuestros prompts del sistema más confiablemente — especialmente las restricciones como "no seas genérico" y "no uses frases de relleno". GPT-4 derivaría hacia lenguaje de ventas incluso con instrucciones explícitas de no hacerlo. Gemini era rápido pero la calidad de salida era inconsistente. Esto puede cambiar a medida que los modelos evolucionan, y nuestro sistema está diseñado para cambiar modelos fácilmente.

¿Cómo manejas cumplimiento de GDPR y CAN-SPAM? Todo nuestro outreach se dirige a emails comerciales (no personales), incluye nuestra dirección física, y tiene una opción clara de baja en cada email. Para GDPR, procesamos datos bajo interés legítimo para outreach B2B, mantenemos registros de actividades de procesamiento, y honramos solicitudes de eliminación inmediatamente a través de un webhook automatizado. También purgamos leads más antiguos que 90 días de nuestra base de datos automáticamente. Habla con un abogado para tu situación específica — esto no es consejo legal.

¿Qué sucede cuando un lead responde? Las respuestas fluyen de vuelta desde la API de Instantly a Supabase. Recibimos una notificación de Slack por cada respuesta, y un humano toma el control de la conversación inmediatamente. Nunca usamos IA para manejo de respuestas. Una vez que alguien se enganche, merece una persona real. Los prospectos interesados se dirigen a nuestra página de contacto o directamente a un enlace de reserva de llamada.

¿Puede este enfoque funcionar para servicios no técnicos? La pieza de análisis del sitio es específica para desarrollo web, pero el patrón arquitectónico — enriquecer leads, usar IA para investigar y personalizar, enviar a través de una herramienta dedicada — funciona para cualquier outreach B2B. Solo necesitarías diferentes entradas de investigación. Una agencia de diseño podría analizar patrones de diseño visual y UX. Una agencia de marketing podría extraer métricas de SEO. La clave es alimentar a Claude datos reales, no pedirle que invente cosas.

¿Cuál es la parte más difícil de mantener este sistema? Mantenimiento de prompts. A medida que los modelos de Claude se actualizan, los prompts que funcionaban perfectamente a veces necesitan ajuste. También pasamos tiempo monitoreando entregabilidad de email — verificando Google Postmaster Tools, vigilando picos de tasa de spam, rotando cuentas de envío. Es quizás 2-3 horas por semana de mantenimiento total.

¿Venderías esto como un producto? Hemos pensado en ello, pero honestamente la ventaja competitiva es demasiado valiosa. Si cada agencia ejecutara exactamente este mismo sistema, la efectividad caería porque los destinatarios comenzarían a ver emails investigados por IA en todas partes. Por ahora, lo mantemos como una herramienta interna. Si quieres ayuda construyendo algo similar para tu negocio, ponte en contacto — hemos ayudado a algunos clientes a configurar sistemas similares como parte de nuestro desarrollo de headless CMS.