Biblioteca · Marketing, ventas y analítica con IA

El CRM en piloto automático: HubSpot + IA, negocios que avanzan sin un vendedor encima

Creador65 minActualizado: octubre de 2026
67 de 105 en la biblioteca

Tiempo: unos 25 min de lectura + 40 min de práctica


Lo esencial

Un CRM suele ser un cementerio de datos que nadie captura. El vendedor llama, asiente, anota en un papelito y se le olvida. En el sistema quedan campos vacíos, estados viejos y negocios atorados en "negociación" desde 2022.

Claude convierte el CRM de cementerio en un organismo vivo: lee la correspondencia, actualiza los campos, escribe el seguimiento (follow-up) y detecta quién está listo para comprar ahora mismo.

🎨 Imagínalo así: piensa en un asistente perfecto sentado junto a cada vendedor las 24 horas. Escucha cada conversación, llena la ficha del cliente, pone un recordatorio para dentro de 3 días y sugiere qué decir si el cliente no contesta. Eso es lo que hacen Claude + el MCP de HubSpot.


Conceptos clave

  • HubSpot MCP: Claude lee y escribe directamente en HubSpot con herramientas
  • Llenado automático del CRM: llega un correo → Claude extrae los datos → los campos se actualizan solos
  • AI Lead Scoring (calificación de prospectos con IA): una puntuación de 0 a 100; quién está listo para comprar y quién solo está viendo
  • Automatización del seguimiento: el cliente lleva 3 días sin responder → Claude escribe por su cuenta
  • Automatización del pipeline: un negocio se atoró → Claude lo ve y propone un plan para destrabarlo
  • Pipedrive como alternativa: para quien prefiere otro CRM

Teoría

El problema: por qué los CRM no funcionan

Muchos CRM terminan siendo una libreta cara. Los vendedores capturan datos solo cuando les llaman la atención. El resultado:

  • El jefe no sabe el estado real de los negocios
  • Los prospectos se pierden: escribieron el viernes y el lunes ya nadie se acordó
  • No hay análisis, porque no hay datos
  • El cliente recibe el mismo correo tres veces ("hola, no nos hemos puesto en contacto")

La solución tradicional es obligar a los vendedores a llenar el CRM. Eso nunca funciona.

🎨 Imagínalo así: es como poner un garrafón de agua con un letrero que dice "por favor, anote usted mismo cuánto tomó". Nadie lo va a hacer.

HubSpot MCP: Claude como operador del CRM

HubSpot tiene un servidor MCP con el que Claude trabaja en el CRM. Qué acciones están disponibles (solo lectura o también escritura) depende de la versión del servidor y de los permisos otorgados: revisa la documentación de HubSpot. Con permisos suficientes, Claude puede:

  • Leer contactos: quién es esta persona, historial de interacciones
  • Actualizar campos: puesto, presupuesto, etapa del negocio
  • Crear tareas: "llamar en 2 días"
  • Agregar notas: resumen de la conversación
  • Mover negocios: pasarlos de una etapa del pipeline a otra

Lo clave: Claude hace la rutina solo, sin que intervenga el vendedor. Los pasos importantes (mover un negocio de etapa, escribirles a los clientes) conviene dejarlos con confirmación de una persona.

python
# HubSpot a través de Claude + API
import os
import time
import anthropic
import requests

HUBSPOT_TOKEN = os.environ["HUBSPOT_ACCESS_TOKEN"]

def update_crm_from_email(email_text: str, contact_id: str):
    client = anthropic.Anthropic()

    # Paso 1: Claude extrae datos estructurados del correo
    extraction = client.messages.create(
        model="claude-sonnet-5-5",
        max_tokens=500,
        messages=[{
            "role": "user",
            "content": f"""Extrae del correo del cliente los siguientes datos en JSON:
            - contact_name: nombre del cliente
            - company: empresa
            - interest: qué le interesa concretamente
            - budget_hint: pista sobre el presupuesto (si la hay)
            - next_step: qué hay que hacer después
            - urgency: urgencia (low/medium/high)

            Correo: {email_text}

            Devuelve solo el JSON, sin explicaciones."""
        }]
    )

    import json
    data = json.loads("".join(b.text for b in extraction.content if b.type == "text"))

    # Paso 2: actualizamos el contacto en HubSpot
    headers = {
        "Authorization": f"Bearer {HUBSPOT_TOKEN}",
        "Content-Type": "application/json"
    }

    # Actualizamos las propiedades del contacto.
    # HubSpot llena por su cuenta el campo notes_last_contacted (solo lectura), así que
    # el resumen del correo lo guardamos como nota (ver la práctica abajo), no como propiedad.
    update_payload = {
        "properties": {
            "hs_lead_status": "IN_PROGRESS"
        }
    }

    response = requests.patch(
        f"https://api.hubapi.com/crm/v3/objects/contacts/{contact_id}",
        headers=headers,
        json=update_payload
    )

    # Paso 3: creamos una tarea de seguimiento si la urgencia es alta
    if data.get("urgency") == "high":
        task_payload = {
            "properties": {
                "hs_task_subject": f"Seguimiento urgente: {data.get('contact_name')}",
                "hs_timestamp": str(int(time.time() * 1000)),  # fecha límite de la tarea, campo obligatorio
                "hs_task_status": "NOT_STARTED",
                "hs_task_priority": "HIGH",
                "hubspot_owner_id": "owner_id_aqui"
            }
        }
        requests.post(
            "https://api.hubapi.com/crm/v3/objects/tasks",
            headers=headers,
            json=task_payload
        )

    return data

AI Lead Scoring: quién está listo para comprar ahora

No todos los prospectos son iguales. Uno está viendo por curiosidad; otro llama porque su director le dijo "compra antes de que termine el trimestre". Claude los distingue por las señales en la conversación.

Señales de alta disposición:

  • Pregunta por plazos concretos ("¿cuándo podemos empezar?")
  • Menciona a la competencia ("los estoy comparando con X")
  • Hace preguntas sobre integración ("tenemos SAP, ¿cómo se conecta?")
  • Dice su presupuesto o pregunta directamente por precios

Señales de baja disposición:

  • "Solo estamos explorando el mercado"
  • Nada concreto sobre plazos
  • Lleva varias semanas sin contestar los correos
python
def score_lead(contact_history: str) -> dict:
    client = anthropic.Anthropic()

    response = client.messages.create(
        model="claude-sonnet-5-5",
        max_tokens=300,
        messages=[{
            "role": "user",
            "content": f"""Califica la disposición de compra del prospecto en una escala de 0 a 100.

            Historial de interacciones:
            {contact_history}

            Devuelve JSON:
            {{
                "score": número de 0 a 100,
                "reasoning": "explicación breve",
                "recommended_action": "qué hacer ahora mismo",
                "hot_signals": ["lista de señales de disposición"],
                "risk_signals": ["lista de señales de alerta"]
            }}"""
        }]
    )

    import json
    return json.loads("".join(b.text for b in response.content if b.type == "text"))

# Ejemplo de uso
history = """
- 15 de abril: primera llamada, preguntaron por las funciones
- 18 de abril: mandaron su lista de requisitos
- 22 de abril: pidieron una demo
- 25 de abril: después de la demo preguntaron "¿cuál es el plazo mínimo de implementación?"
- 28 de abril: escribieron "nuestro director quiere reunirse la próxima semana"
"""

result = score_lead(history)
# score: 87
# recommended_action: "Confirmar de inmediato la reunión con el director, preparar la propuesta comercial"

🎨 Imagínalo así: es como un vendedor experimentado que en 30 segundos ve "este va a comprar" o "este nada más nos está quitando el tiempo". Solo que la IA lo hace con los 500 prospectos a la vez y su criterio no cambia según el humor del día. Aun así se puede equivocar, así que revisa sus calificaciones de vez en cuando.

Automatizar el seguimiento: el cliente no contestó

La forma más común de perder un negocio: el cliente dijo "lo pienso" y luego silencio. Al vendedor le da pena volver a escribir. O se le olvida.

Claude escribe el seguimiento por su cuenta, en el momento adecuado y con el tono adecuado:

python
def generate_followup(
    contact_name: str,
    last_interaction: str,
    days_since_contact: int,
    deal_stage: str
) -> str:
    client = anthropic.Anthropic()

    response = client.messages.create(
        model="claude-sonnet-5-5",
        max_tokens=400,
        messages=[{
            "role": "user",
            "content": f"""Escribe un correo de seguimiento para el cliente.

            Contexto:
            - Nombre: {contact_name}
            - Último contacto: {last_interaction}
            - Días sin respuesta: {days_since_contact}
            - Etapa del negocio: {deal_stage}

            Requisitos:
            - Corto (3-4 oraciones)
            - Sin presionar y sin suplicar
            - Aporta valor (un artículo, una idea, un caso)
            - Un solo llamado a la acción claro
            - En español, tono profesional pero cercano"""
        }]
    )

    return "".join(b.text for b in response.content if b.type == "text")

Automatizar el pipeline: el negocio se atoró

Los negocios se atoran. Es normal. Lo que no es normal es que nadie lo note durante meses.

Cada semana, Claude revisa el pipeline y encuentra los "negocios zombi":

python
def audit_pipeline(deals: list) -> list:
    client = anthropic.Anthropic()

    deals_text = "\n".join([
        f"- {d['name']}: etapa '{d['stage']}', "
        f"última acción hace {d['days_stale']} días, "
        f"monto {d['amount']}"
        for d in deals
    ])

    response = client.messages.create(
        model="claude-sonnet-5-5",
        max_tokens=800,
        messages=[{
            "role": "user",
            "content": f"""Analiza el pipeline de ventas y señala los negocios con problemas.

            Negocios:
            {deals_text}

            Para cada negocio con problemas (atorado más de 14 días) da:
            1. Diagnóstico: por qué se atoró
            2. Plan para destrabarlo: 2-3 pasos concretos
            3. Recomendación: seguir o cerrarlo como perdido

            Formato: una lista con un encabezado por cada negocio."""
        }]
    )

    return "".join(b.text for b in response.content if b.type == "text")

Pipedrive como alternativa

Si HubSpot te parece caro o complicado, mira Pipedrive: es más sencillo y está hecho para ventas. Los planes y si hay plan gratis, revísalos en los sitios de ambos servicios.

Aspecto HubSpot Pipedrive
Plan gratis ✅ Sí (con límites) Revisa en su sitio
Soporte de MCP ✅ Tiene servidor MCP ⚠️ Revisa la documentación; la API siempre está disponible
Precio Revisa hubspot.com Revisa pipedrive.com
Complejidad Alta Media
Mejor para Marketing + ventas Solo ventas

La API de Pipedrive es muy sencilla: Claude trabaja con ella sin problema mediante solicitudes HTTP normales, incluso sin MCP.


Práctica

Tarea: que el CRM se actualice solo cuando llega un correo nuevo

Qué vamos a construir: llega un correo de un cliente → Claude lo lee → actualiza solo la ficha en HubSpot → crea una tarea si hace falta.

Paso 1: Obtén un token de la API de HubSpot

A octubre de 2026, HubSpot está desactivando la creación de apps del tipo anterior (Private Apps): para cuentas nuevas desde el 28.09.2026 y para las existentes desde el 26.10.2026. Para integraciones "servidor a servidor" ahora se recomienda una Service Key (a octubre de 2026 en beta pública; se crea desde la plataforma para desarrolladores de HubSpot). Los pasos exactos en la interfaz cambian, así que sigue la documentación vigente en developers.hubspot.com. Si ya tienes una app del tipo anterior, su token funciona igual: en el encabezado Authorization: Bearer ....

  1. Crea una Service Key (o usa el token de una app que ya tengas) con estos permisos (scopes): crm.objects.contacts.read, crm.objects.contacts.write, crm.objects.deals.read, crm.objects.deals.write, y para notas y tareas, los permisos de esos objetos
  2. Copia el token y guárdalo en el archivo .env (nunca lo subas a Git)
bash
# .env
HUBSPOT_ACCESS_TOKEN=<token de HubSpot>
ANTHROPIC_API_KEY=sk-ant-...

Paso 2: Crea el script que procesa los correos entrantes

python
# email_processor.py
import os
import json
import time
import anthropic
import requests
from dotenv import load_dotenv

load_dotenv()

client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
HUBSPOT_TOKEN = os.environ["HUBSPOT_ACCESS_TOKEN"]

def process_incoming_email(
    email_from: str,
    email_subject: str,
    email_body: str
):
    """Procesa un correo entrante y actualiza el CRM"""

    print(f"Procesando correo de: {email_from}")

    # 1. Claude analiza el correo
    analysis = client.messages.create(
        model="claude-sonnet-5-5",
        max_tokens=600,
        messages=[{
            "role": "user",
            "content": f"""Analiza el correo entrante del cliente.

Asunto: {email_subject}
De: {email_from}
Texto: {email_body}

Devuelve JSON sin texto adicional:
{{
    "intent": "inquiry/complaint/purchase_ready/follow_up/other",
    "summary": "resumen breve en 1-2 oraciones",
    "key_points": ["lista de puntos importantes"],
    "urgency": "low/medium/high",
    "sentiment": "positive/neutral/negative",
    "next_action": "siguiente acción concreta",
    "follow_up_days": número de días tras los cuales escribir si no hay respuesta
}}"""
        }]
    )

    data = json.loads("".join(b.text for b in analysis.content if b.type == "text"))
    print(f"Análisis: {data['intent']}, urgencia: {data['urgency']}")

    # 2. Buscamos el contacto en HubSpot por email
    headers = {
        "Authorization": f"Bearer {HUBSPOT_TOKEN}",
        "Content-Type": "application/json"
    }

    search_response = requests.post(
        "https://api.hubapi.com/crm/v3/objects/contacts/search",
        headers=headers,
        json={
            "filterGroups": [{
                "filters": [{
                    "propertyName": "email",
                    "operator": "EQ",
                    "value": email_from
                }]
            }],
            "properties": ["email", "firstname", "lastname", "hs_lead_status"]
        }
    )

    contacts = search_response.json().get("results", [])

    if contacts:
        contact_id = contacts[0]["id"]
        contact_name = (
            contacts[0]["properties"].get("firstname", "") + " " +
            contacts[0]["properties"].get("lastname", "")
        ).strip() or email_from

        # 3. Actualizamos el contacto
        update_response = requests.patch(
            f"https://api.hubapi.com/crm/v3/objects/contacts/{contact_id}",
            headers=headers,
            json={
                "properties": {
                    "hs_lead_status": "IN_PROGRESS" if data["intent"] == "purchase_ready" else "OPEN"
                }
            }
        )

        # 4. Agregamos una nota
        note_response = requests.post(
            "https://api.hubapi.com/crm/v3/objects/notes",
            headers=headers,
            json={
                "properties": {
                    "hs_note_body": f"Análisis del correo:\n{data['summary']}\n\nPuntos clave:\n" +
                                   "\n".join(f"• {p}" for p in data["key_points"]),
                    "hs_timestamp": str(int(time.time() * 1000))
                },
                "associations": [{
                    "to": {"id": contact_id},
                    "types": [{"associationCategory": "HUBSPOT_DEFINED", "associationTypeId": 202}]
                }]
            }
        )

        # 5. Creamos una tarea si la urgencia es alta
        if data["urgency"] == "high" or data["intent"] == "purchase_ready":
            task_response = requests.post(
                "https://api.hubapi.com/crm/v3/objects/tasks",
                headers=headers,
                json={
                    "properties": {
                        "hs_task_subject": f"[CALIENTE] Responder: {contact_name} — {email_subject}",
                        "hs_timestamp": str(int(time.time() * 1000)),
                        "hs_task_status": "NOT_STARTED",
                        "hs_task_priority": "HIGH",
                        "hs_task_body": data["next_action"]
                    }
                }
            )
            print(f"Tarea urgente creada para {contact_name}")

        print(f"CRM actualizado para {contact_name}")
        return {"status": "updated", "contact": contact_name, "analysis": data}

    else:
        # No se encontró el contacto: creamos uno nuevo
        print(f"Contacto nuevo: {email_from}")
        create_response = requests.post(
            "https://api.hubapi.com/crm/v3/objects/contacts",
            headers=headers,
            json={
                "properties": {
                    "email": email_from,
                    "hs_lead_status": "NEW"
                }
            }
        )
        return {"status": "created", "contact": email_from, "analysis": data}


# Prueba
if __name__ == "__main__":
    result = process_incoming_email(
        email_from="[email protected]",
        email_subject="Queremos implementar su sistema",
        email_body="""
        ¡Buenas tardes!

        Estamos evaluando varias soluciones para automatizar ventas.
        Su producto nos interesó. Tenemos un equipo de 15 vendedores,
        el presupuesto está por definirse y nos gustaría empezar este mismo trimestre.

        ¿Podríamos tener una demo la próxima semana?

        Iván Pérez, Director de Ventas
        """
    )
    print(json.dumps(result, ensure_ascii=False, indent=2))

Paso 3: Pruébalo

bash
python email_processor.py

Paso 4: Conéctalo a correos reales

Opciones de integración:

  • Gmail: Google Apps Script → llama a tu script cuando llega un correo nuevo
  • Outlook: Power Automate → solicitud HTTP → tu endpoint
  • Tu propio servidor de correo: un hook al recibir el correo
  • Servicio de webhooks: Zapier / n8n → vigila el correo → llama al script

⚠️ Los correos de clientes contienen datos personales. Mándale a Claude solo lo que la tarea necesita, y revisa la lección Regulación de la IA y cumplimiento.


Herramientas y recursos

  • HubSpot: hubspot.com (tiene un CRM gratis para empezar)
  • Documentación de la API de HubSpot: developers.hubspot.com
  • Pipedrive: pipedrive.com (más sencillo que HubSpot, de pago)
  • python-dotenv: para guardar las claves de forma segura
  • Modelos de Claude: los nombres en el código son a octubre de 2026; precios y versiones vigentes: Lo vigente
  • n8n: para orquestar sin código (lección n8n + IA)
  • Zapier: para integrarte con Gmail/Outlook sin programar

Ideas clave

Un CRM no muere por mal software, muere por la captura manual. Claude se encarga de la mayor parte de esa captura: lee los correos, propone actualizaciones de campos y crea tareas. El vendedor se enfoca en hablar con los clientes, no en llenar fichas, y conviene revisar por muestreo lo que hace la IA.

El lead scoring convierte la intuición en un sistema: en lugar de "me parece que este ya está listo", una calificación concreta de 87/100 con su justificación y una recomendación.

Lo más importante: esto no reemplaza a los vendedores, les da superpoderes. Cada vendedor tiene un asistente de IA que no se cansa ni se olvida de nada.


Siguiente lección

→ La máquina de SEO: el stack completo con Claude Code

La marca se guarda solo en este navegador y no se envía a ningún sitio. Mi progreso