Arnold Moya

Newsletter

February 12, 2026

¿Cómo conectar tu bot con Whataspp?

Ya escuchaste de openclaw. Ese proyecto que explotó hace unas semanas y volvió a su creador en un célebre desarrollador. Quiero hablar de la dependencia que conecta el motor del bot con WhatsApp en tiempo real.

Suscríbete a mi boletín para recibir más contenido como este

@whiskeysockets/baileys es la pieza central: el puente (no oficial) que te deja hablar con WhatsApp Web desde Node. Traducido: tu bot deja de ser una idea y se convierte en un chat real, con QR, sesiones persistentes y reconexiones sin drama.

La receta que funciona hoy (en casi cualquier proyecto) se resume en 5 ideas:

  • Guardar sesión en disco (para no escanear el QR cada vez).
  • Mostrar QR cuando aparezca.
  • Escuchar eventos de conexión (open/close) y reconectar cuando toque.
  • Escuchar mensajes entrantes y extraer texto de forma segura.
  • Responder con sendMessage y listo.

Este es el esqueleto mínimo (TypeScript). En mi repo lo tengo envuelto en una clase (WhatsAppClient) en src/whatsapp.ts, pero la idea es la misma:

import makeWASocket, { useMultiFileAuthState, DisconnectReason } from @whiskeysockets/baileys;
import qrcode from 'qrcode-terminal';

export async function startWhatsApp(onText: (jid: string, text: string) => Promise<void>) {
  const { state, saveCreds } = await useMultiFileAuthState('data/auth');
  const sock = makeWASocket({ auth: state, logger: { level: 'silent' } as any });

  sock.ev.on('creds.update', saveCreds);

  sock.ev.on('connection.update', ({ connection, lastDisconnect, qr }) => {
    if (qr) qrcode.generate(qr, { small: true });

    if (connection === 'close') {
      const code = (lastDisconnect?.error as any)?.output?.statusCode;
      if (code !== DisconnectReason.loggedOut) startWhatsApp(onText); // reconecta
    }
  });

  sock.ev.on('messages.upsert', async ({ type, messages }) => {
    if (type !== 'notify') return;

    for (const msg of messages) {
      if (msg.key.fromMe) continue;
      const jid = msg.key.remoteJid;
      if (!jid || jid.endsWith('@g.us') || jid.endsWith('@broadcast')) continue;

      const text = msg.message?.conversation ?? msg.message?.extendedTextMessage?.text ?? null;
      if (!text) continue;

      await onText(jid, text);
    }
  });

  return sock;
}

Tip práctico: si vas a probar en tu número personal, agrega un filtro (por ejemplo ALLOWED_NUMBER) para que tu bot no le conteste a cualquiera mientras estás iterando.

Checklist rapido (para levantarlo en 10 minutos):

  • pnpm add @whiskeysockets/baileys qrcode-terminal dotenv
  • Define ALLOWED_NUMBER en .env (opcional, pero recomendado en dev)
  • Ejecuta pnpm start y escanea el QR

Qué está vivo hoy

Con pnpm start ya tengo el circuito cerrado: conecta, muestra QR, recibe un Oi y lo devuelve. Nada de magia: solo eventos bien escuchados.

[WhatsApp] Connected as <bot_jid>
[WhatsApp] Message from <sender_jid>: "Oi"
[WhatsApp] Sent to <sender_jid>: "Echo: Oi"

Siguiente paso: reemplazar el modo eco por el flujo real (prompts/herramientas/memoria) sin perder lo más importante: una conexión estable y repetible.

Suscríbete a mi boletín para recibir más contenido como este