Saltar al contenido principal

Cómo Conectar WhatsApp con Google Gemini Cómo Conectar WhatsApp con Google Gemini

Cómo Conectar WhatsApp con Google Gemini

Combina whatsmeow-node con el SDK de Google GenAI para crear un chatbot de WhatsApp potenciado por Gemini. Los mensajes entran por WhatsApp, se envían a Gemini para obtener una respuesta, y la respuesta vuelve al usuario — con indicadores de escritura mientras el modelo piensa.

Requisitos Previos

  • Una sesión vinculada de whatsmeow-node (Cómo Vincular)
  • Una API key de Google AI (configurada como variable de entorno GEMINI_API_KEY) — obtén una en ai.google.dev
  • El SDK de Google GenAI: npm install @google/genai

Paso 1: Configurar Ambos Clientes

import { createClient } from "@whatsmeow-node/whatsmeow-node";
import { GoogleGenAI } from "@google/genai";

const client = createClient({ store: "session.db" });
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });

const SYSTEM_PROMPT = "You are a helpful WhatsApp assistant. Keep responses concise — under 500 characters when possible, since this is a chat interface.";

Paso 2: Manejar Mensajes Entrantes

client.on("message", async ({ info, message }) => {
if (info.isFromMe) return;

const text =
(message.conversation as string) ??
(message.extendedTextMessage as { text?: string } | undefined)?.text;
if (!text) return;

await client.sendChatPresence(info.chat, "composing");

const reply = await askGemini(info.sender, text);
await client.sendMessage(info.chat, { conversation: reply });
});

Paso 3: Enviar a Gemini

async function askGemini(userJid: string, userMessage: string): Promise<string> {
const response = await ai.models.generateContent({
model: "gemini-2.5-flash",
contents: userMessage,
config: {
systemInstruction: SYSTEM_PROMPT,
},
});

return response.text ?? "I couldn't generate a response.";
}

Paso 4: Agregar Historial de Conversación

Gemini soporta chat multi-turno a través de la API chats.create(). Almacena una sesión de chat por usuario:

import type { Chat } from "@google/genai";

const chats = new Map<string, Chat>();

function getChat(userJid: string): Chat {
let chat = chats.get(userJid);
if (!chat) {
chat = ai.chats.create({
model: "gemini-2.5-flash",
config: {
systemInstruction: SYSTEM_PROMPT,
},
});
chats.set(userJid, chat);
}
return chat;
}

async function askGemini(userJid: string, userMessage: string): Promise<string> {
const chat = getChat(userJid);
const response = await chat.sendMessage({ message: userMessage });
return response.text ?? "I couldn't generate a response.";
}

Ejemplo Completo

import { createClient } from "@whatsmeow-node/whatsmeow-node";
import { GoogleGenAI } from "@google/genai";
import type { Chat } from "@google/genai";

const client = createClient({ store: "session.db" });
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });

const SYSTEM_PROMPT =
"You are a helpful WhatsApp assistant. Keep responses concise — under 500 characters when possible, since this is a chat interface.";

const chats = new Map<string, Chat>();

function getChat(userJid: string): Chat {
let chat = chats.get(userJid);
if (!chat) {
chat = ai.chats.create({
model: "gemini-2.5-flash",
config: {
systemInstruction: SYSTEM_PROMPT,
},
});
chats.set(userJid, chat);
}
return chat;
}

async function askGemini(userJid: string, userMessage: string): Promise<string> {
const chat = getChat(userJid);
const response = await chat.sendMessage({ message: userMessage });
return response.text ?? "I couldn't generate a response.";
}

client.on("message", async ({ info, message }) => {
if (info.isFromMe) return;

const text =
(message.conversation as string) ??
(message.extendedTextMessage as { text?: string } | undefined)?.text;
if (!text) return;

console.log(`${info.pushName}: ${text}`);
await client.sendChatPresence(info.chat, "composing");

try {
const reply = await askGemini(info.sender, text);
await client.sendMessage(info.chat, { conversation: reply });
console.log(`${reply.slice(0, 80)}...`);
} catch (err) {
console.error("Gemini API error:", err);
await client.sendMessage(info.chat, {
conversation: "Sorry, I'm having trouble right now. Try again in a moment.",
});
}
});

client.on("logged_out", ({ reason }) => {
console.error(`Logged out: ${reason}`);
client.close();
process.exit(1);
});

async function main() {
const { jid } = await client.init();
if (!jid) {
console.error("Not paired! See: How to Pair WhatsApp");
process.exit(1);
}
await client.connect();
await client.sendPresence("available");
console.log("Gemini bot is online!");

process.on("SIGINT", async () => {
await client.sendPresence("unavailable");
await client.disconnect();
client.close();
process.exit(0);
});
}

main().catch(console.error);

Errores Comunes

Bucles de eco

Siempre verifica info.isFromMe primero. Sin esto, el bot envía un mensaje, ve su propio mensaje, lo envía a Gemini y responde de nuevo — para siempre.

Exposición de la API key

Nunca escribas tu API key directamente en el código. Usa variables de entorno (GEMINI_API_KEY) o un archivo .env (agregado a .gitignore).

El historial de chat está en memoria

Los objetos Chat se almacenan en un Map y se pierden al reiniciar. Para persistencia, guarda el historial de conversación en una base de datos y recrea los chats con la opción history.