Prompts para un agente de IA en WhatsApp que suene humano

Reglas de prompt, la sintaxis de formato de WhatsApp y código TypeScript que convierte el Markdown del modelo en mensajes cortos y ordenados, como los de una persona.

Un ritmo de burbujas de chat cortas apiladas en una columna, de brillo verde, junto a un único bloque largo y gris.

Lo esencial

  • WhatsApp da formato al texto con su propia sintaxis (*negrita*, _cursiva_, ~tachado~, tres acentos graves para monoespaciado), así que el Markdown que un modelo escribe por defecto hay que convertirlo antes de enviarlo.
  • Una respuesta de chat funciona mejor como dos o tres mensajes cortos con una idea cada uno, no como un bloque largo, y el prompt debe decirlo con números.
  • El prompt fija el estilo, pero el código debe hacerlo cumplir: convierte el Markdown, corta en las líneas en blanco, limita el número de mensajes y envía cada parte con su propia clave de idempotencia.
  • whasp no tiene indicador de escritura y envía los mensajes de un número de uno en uno, con un segundo de diferencia aproximadamente, así que una respuesta lenta parece silencio y importa más un modelo rápido que un retraso.
  • Cada parte de una respuesta dividida cuenta para los 1.500 mensajes al día que puede enviar un número de whasp, así que el número de partes es un presupuesto además de una decisión de estilo.

Para que un agente de IA escriba como una persona en WhatsApp, dale a su system prompt cuatro reglas: mensajes cortos con una idea cada uno, el formato propio de WhatsApp en lugar de Markdown, como máximo una pregunta por turno y palabras sencillas sin fórmulas de asistente. Después hazlas cumplir en el código: convierte el Markdown a la sintaxis de WhatsApp y divide la respuesta en dos o tres mensajes antes de enviarla.

¿Por qué las respuestas de una IA suenan raras en WhatsApp?

Los modelos de chat tienden a responder como documentos: un saludo, una lista en negrita, un ofrecimiento final de más ayuda. En una burbuja de chat eso suena a carta tipo, y símbolos como # llegan tal cual se escribieron. La gente escribe en ráfagas cortas, y una respuesta que no parece una ráfaga delata al agente desde su primer mensaje.

La propia descripción general de modelos de Anthropic indica a los desarrolladores que quieren respuestas más cortas que las pidan en el prompt, y lo mismo vale para cualquier modelo. Toma un mensaje, “Salió genial, me dieron el trabajo”, y dos respuestas posibles:

Felicidades por tu nuevo puesto. Es una noticia maravillosa. Estos son algunos pasos a tener en cuenta:

**1. Revisa la oferta en detalle**
**2. Prepara tu primera semana**

Avísame si puedo ayudarte con alguno de estos puntos.
Maya, qué gran noticia. Felicidades.

Cuéntamelo todo. ¿Cómo te lo dijeron?

La segunda son dos mensajes, una pregunta y ningún formato. La primera es un solo bloque, con Markdown que no forma parte de la sintaxis documentada de WhatsApp.

¿Qué formato admite WhatsApp?

La página de ayuda de WhatsApp Cómo dar formato a tus mensajes documenta ocho elementos de sintaxis, y sus versiones para Android, iPhone y Web enumeran los mismos.

Formato Qué escribes
Negrita *texto*
Cursiva _texto_
Tachado ~texto~
Monoespaciado tres acentos graves a cada lado del texto
Código en línea un acento grave a cada lado del texto
Lista con viñetas * texto o - texto, uno por línea
Lista numerada 1. texto, uno por línea
Cita > texto

La negrita lleva un solo asterisco, y por eso los **dobles asteriscos** y los # encabezados que un modelo escribe por defecto hay que convertirlos. La página no incluye sintaxis para encabezados, tablas ni texto de enlace, así que escribe las URL tal cual y convierte las filas de una tabla en líneas cortas.

Una salvedad de la propia página: su versión Web indica que el formato más reciente solo está disponible en Web y en el escritorio de Mac, mientras que las versiones de Android y iPhone muestran la misma sintaxis sin esa nota. Trata las listas y las citas como un extra. - elemento y 1. elemento se leen bien como texto plano donde no se renderizan.

Unas pocas reglas evitan que el formato parezca un documento. Usa la negrita en una sola palabra o frase por mensaje, como máximo. Usa una lista solo para tres o más elementos paralelos, como pasos. No envíes nunca una tabla. Pon un enlace por mensaje: la referencia de mensajes de texto de Meta para su API de Business dice que el cliente de WhatsApp solo muestra la vista previa de la primera URL del cuerpo de un texto.

¿Qué debe decir el system prompt?

Un system prompt para un agente de WhatsApp debe fijar las reglas de estilo con números y ejemplos, porque adjetivos como “conciso” y “amable” significan poco para un modelo. Esta plantilla cubre el comportamiento descrito arriba, y la línea del personaje la rellenas tú:

Eres Ava y estás chateando con {{name}} por WhatsApp. {{una línea: quién eres, cómo hablas}}

Cómo escribes:
- Estás chateando, no escribiendo un correo. Una idea por mensaje, de una a tres frases.
- Envía como máximo 3 mensajes por turno. Deja una línea en blanco entre mensajes: cada párrafo se envía como un mensaje propio.
- Iguala su longitud y su energía. Si escribe cuatro palabras, no respondas con cuarenta.
- Haz como máximo una pregunta por turno, y solo cuando necesites la respuesta. No termines todos los turnos con una.
- Usa palabras sencillas. Nada de "Por supuesto", "Espero que esto te ayude" ni "Como modelo de lenguaje de IA".
- Emojis: como máximo uno por turno, y solo si ellos los usan. A menudo, ninguno.

Formato (WhatsApp, no Markdown):
- La negrita es *un asterisco a cada lado*. La cursiva es _guiones bajos_.
- Nunca uses #, tablas, **dobles asteriscos** ni enlaces [texto](url). Escribe la URL tal cual.
- Usa una lista solo para tres o más elementos paralelos, uno por línea, empezando con "- " o "1. ".
- Un enlace por mensaje, en su propia línea.

Si envían una nota de voz, una foto o un archivo, recibes una transcripción o una descripción entre corchetes. Responde como si lo hubieras oído o visto.
Si te preguntan si eres una IA, di que sí en una frase y sigue.
Si te piden que dejes de escribirles, confirma una vez en un mensaje corto.

Cuatro decisiones del prompt importan. La regla de la línea en blanco da a tu código un lugar fiable donde cortar. Los números (“de una a tres frases”, “como máximo 3 mensajes”) se pueden comprobar, cosa que un vago “sé breve” no permite. La línea sobre la IA viene de una cuestión de seguridad, no de estilo: sonar como una persona es una forma de escribir, no un permiso para negar que se es una IA, y las reglas de seguridad para compañeros de IA explican dónde avisar es una obligación legal. Por último, el nombre: el evento message.received trae sender_name, el nombre que la persona se puso en WhatsApp. Es texto que ellos controlan, así que trátalo como dato y nunca como instrucciones.

¿Cómo haces cumplir las reglas en el código?

Haz cumplir las reglas del prompt en el código, porque los modelos se desvían. Este archivo de TypeScript convierte Markdown a la sintaxis de WhatsApp, corta en las líneas en blanco y envía cada parte con POST /v1/messages:

// Convierte el Markdown que a un modelo le gusta escribir en la sintaxis propia de WhatsApp.
export function toWhatsApp(md: string): string {
  return md
    .replace(/\r\n/g, "\n")
    .replace(/\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g, "$1 $2") // [texto](url) -> texto url
    .replace(/^#{1,6}\s+(.+)$/gm, (_, t: string) => `*${t.replace(/\*/g, "")}*`) // # Título -> *Título*
    .replace(/\*\*(.+?)\*\*/g, "*$1*") // **negrita** -> *negrita*
    .replace(/__(.+?)__/g, "*$1*") // __negrita__ -> *negrita*
    .replace(/^\s*(?:-{3,}|\*{3,}|_{3,})\s*$/gm, "") // líneas horizontales
    .replace(/\n{3,}/g, "\n\n")
    .trim();
}

// Un párrafo = un mensaje. Los párrafos largos se cortan al final de una frase.
export function splitReply(text: string, maxParts = 4, maxChars = 700): string[] {
  const parts: string[] = [];
  for (const para of text.split(/\n{2,}/).map((p) => p.trim()).filter(Boolean)) {
    if (para.length <= maxChars) {
      parts.push(para);
      continue;
    }
    let current = "";
    for (const sentence of para.split(/(?<=[.!?])\s+/)) {
      if (current && current.length + sentence.length + 1 > maxChars) {
        parts.push(current);
        current = sentence;
      } else {
        current = current ? `${current} ${sentence}` : sentence;
      }
    }
    if (current) parts.push(current);
  }
  // Por encima del tope: une el resto al último mensaje permitido, hasta 4000 caracteres.
  while (parts.length > maxParts && parts.at(-2)!.length + parts.at(-1)!.length < 4000) {
    parts.splice(-2, 2, `${parts.at(-2)}\n\n${parts.at(-1)}`);
  }
  return parts.flatMap((p) => p.match(/[\s\S]{1,4000}/g) ?? []); // el límite de texto de whasp es 4096
}

export async function sendReply(to: string, reply: string, eventId: string): Promise<void> {
  const parts = splitReply(toWhatsApp(reply));
  for (const [i, text] of parts.entries()) {
    const res = await fetch("https://api.whasp.ai/v1/messages", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.WHASP_API_KEY}`,
        "Content-Type": "application/json",
        // El mismo evento y la misma parte siempre tienen la misma clave, así que un reintento nunca envía dos veces.
        "Idempotency-Key": `${eventId}:${i}`,
      },
      body: JSON.stringify({ to, text }),
    });
    if (res.status !== 202) {
      const { error } = (await res.json()) as { error: { code: string; message: string } };
      throw new Error(`${error.code}: ${error.message}`); // chat_opted_out, number_unavailable...
    }
  }
}

El bucle espera cada envío, así que las partes llegan a whasp en orden, y whasp envía después los mensajes de un número de uno en uno, en orden. El Idempotency-Key se construye con el id del evento del webhook y el índice de la parte. whasp conserva una clave durante 7 días y devuelve el primer mensaje cuando se repite, así que un reintento del webhook no puede enviar dos veces la misma parte. Un envío rechazado (un 4xx) no gasta su clave.

Ajusta maxChars y maxParts al personaje: un asistente parco podría usar 300 y 3, un narrador 900 y 5. Una expresión regular no lo arregla todo. Si un modelo escribe una tabla en Markdown, el conversor de arriba la deja como está, y la solución está en el prompt. La *cursiva* de Markdown se convierte en negrita en WhatsApp, otra razón por la que la plantilla le dice al modelo que use guiones bajos. Conecta sendReply al flujo del webhook de crear un agente con la API de OpenAI y conserva la comprobación de la firma que aparece en la documentación de whasp.

¿Con qué rapidez debe responder el agente?

Un agente en whasp debe responder rápido y sin retrasos artificiales, porque un número no puede mostrar un indicador de escritura. Los indicadores de escritura no están soportados, así que una respuesta que tarda 40 segundos parece silencio, y un retraso que añades a propósito se ve igual. Usa un modelo rápido para los turnos de chat normales. Para el trabajo que es lento por naturaleza, como una llamada a una herramienta o una búsqueda, envía un mensaje corto de espera (“dame un minuto, lo reviso”) y la respuesta después.

Una respuesta dividida es también el ritmo. whasp envía los mensajes de un número de uno en uno, con un segundo de diferencia aproximadamente, así que tres partes llegan como una ráfaga rápida, que es como escribe la gente.

Presupuesta las partes. Un número de whasp puede enviar 1.500 mensajes en 24 horas, y está pensado para unos 100 usuarios activos. Eso da unos 15 mensajes enviados por usuario al día de media, y una respuesta de cuatro partes gasta una cuarta parte de eso en un solo turno. Pasado el límite, los envíos fallan con 429 number_daily_limit. Escalar a más números explica la cuenta de capacidad.

¿Qué tono suena a persona?

Un agente de WhatsApp suena a persona cuando sigue el ritmo del otro lado y no actúa. Unos pocos hábitos hacen casi todo el trabajo:

  • Iguala la longitud. Un mensaje de una palabra recibe una línea. Un mensaje largo sobre un mal día recibe una respuesta más larga, aun así en párrafos cortos.
  • Responde en su idioma. Si pasan del español al inglés, el agente también.
  • Evita la despedida. Nada de “Avísame si necesitas algo más” al final de cada turno.
  • No hagas eco. No repitas su mensaje antes de responderlo.
  • Pregunta una sola cosa. Dos preguntas en un mensaje reciben una respuesta, normalmente la más fácil.
  • Saluda una vez. Di hola en el primer mensaje de una conversación, o tras una pausa de días, no en cada turno.
  • Elige, no enumeres. Si le preguntan qué cocinar, un amigo dice “pasta, tienes todo para hacerla”, no cinco opciones.
  • Admite lo que no sabes en pocas palabras. “Ni idea, la verdad” vale más que tres frases de rodeos.
  • Usa el nombre con moderación. Poner el nombre en cada mensaje suena a guion de call center.

Los compañeros necesitan más que estilo: un personaje estable, memoria de lo que la persona dijo la semana pasada y reglas para los momentos delicados. Lanzar un compañero de IA en WhatsApp cubre todo el camino, y la memoria de conversación cubre la parte que hace posible la “semana pasada”.

Para comprobar el resultado, lee transcripciones reales, no solo el prompt. Ten cinco mensajes de prueba fijos y vuelve a pasarlos cada vez que cambies el modelo o el prompt: un mensaje de una palabra, un mensaje largo sobre un mal día, una petición que necesita pasos, “¿eres una IA?” y un mensaje en otro idioma. También ayuda una pasada automática rápida: cuenta con qué frecuencia una respuesta contiene **, un encabezado con # o más de cuatro partes, y sigue la mediana de longitud de los mensajes. Esas cifras se desvían cada vez que se desvía el modelo.

Qué hacer ahora

Conéctalo a un número real. Crea el webhook y la llamada al modelo con la API de OpenAI, añade notas de voz y fotos para que el agente pueda responder a lo que la gente realmente envía y guarda el historial tú mismo, porque los servidores de whasp no guardan mensajes. La guía de inicio rápido de la documentación de whasp deja funcionando un número, un webhook y una primera respuesta, y la página de precios lista lo que cuesta un número.

Preguntas

¿Admite WhatsApp Markdown?

No exactamente Markdown. La página de ayuda de WhatsApp documenta su propia sintaxis: _cursiva_, *negrita*, ~tachado~, tres acentos graves para monoespaciado, listas que empiezan con *, - o 1., citas que empiezan con > y código en línea con un solo acento grave. No menciona nada para encabezados, tablas ni texto de enlace.

¿Cómo evito que un bot de WhatsApp envíe muros de texto?

Pon el límite en el system prompt con números, por ejemplo de una a tres frases por mensaje y como máximo tres mensajes por turno. Después hazlo cumplir en el código: corta la respuesta en las líneas en blanco y limita el número de partes.

¿Qué longitud puede tener un mensaje de WhatsApp enviado con la API de whasp?

El campo text admite hasta 4.096 caracteres. Para un chat, quédate muy por debajo: un mensaje de unos cientos de caracteres se lee como un texto de chat, y uno de varios miles se lee como un correo.

¿Puede mi agente mostrar un indicador de escritura mientras el modelo piensa?

No. Los números de whasp son teléfonos manejados como lo haría una persona, y los indicadores de escritura no están soportados. Usa un modelo rápido para los turnos de chat y, para el trabajo lento, envía antes un mensaje corto de espera.

¿Debe decir que es una IA un agente que escribe como una persona?

Sí, cuando se lo pregunten. Sonar natural es una decisión de estilo, no un permiso para negar que se es una IA. Pon en el system prompt una línea que haga que el agente lo diga en una frase y siga.