WhatsApp como herramienta en LangChain y CrewAI (Python)
Para usar WhatsApp como herramienta en LangChain o CrewAI, escribes una función de Python que llama a la API de ZapZap (por ejemplo POST /send/text), la registras con el decorador tool y se la entregas al agente. El punto crítico es lo que rodea a esa función: validación del número, lista permitida, límite de volumen y aprobación humana. Abajo están los dos frameworks con código, en las versiones actuales al 27/10/2026.
Publicado el · 6 min de lectura
Este artículo también está disponible en: Português · English
Cómo un agente usa la API de WhatsApp como herramienta
En los frameworks de agentes, una herramienta (tool) es una función con nombre, descripción y esquema de parámetros. El modelo de IA lee la descripción, decide si la herramienta ayuda en la tarea y devuelve los argumentos; el framework ejecuta la función y devuelve el resultado al modelo. Para WhatsApp, las funciones son finas: cada una llama a un endpoint de la API.
Dos consecuencias de diseño. La descripción de la herramienta es parte del prompt: escríbela como una instrucción clara, diciendo qué hace, el formato del número (código de país, solo dígitos) y cuándo no usarla. Y la función es el lugar de los candados: el modelo puede equivocarse o ser inducido por texto malicioso, así que la validación no puede depender de él.
Versiones y estado del ecosistema
Estado comprobado en PyPI el 27/10/2026: langchain 1.4.7, langchain-core 1.7.0 y crewai 1.15.30. Los dos proyectos cambian rápido y han tenido rupturas entre versiones mayores; los ejemplos usan create_agent de LangChain 1.x y el decorador tool de CrewAI 1.x. Si usas otra versión, consulta su documentación antes de copiar.
A esta fecha no existe un paquete de ZapZap para LangChain o CrewAI ni un servidor MCP propio; lo que existe es la API REST y el archivo OpenAPI. Por eso las herramientas de abajo son código tuyo, sobre la API. Para el camino por MCP, mira la guía del servidor MCP de WhatsApp.
Capa compartida: un cliente Python con candados
Escribe primero un módulo que hable con la API y aplique las reglas. Los dos frameworks lo reutilizan. Valida el formato del número, restringe los destinatarios a una lista permitida, limita el tamaño del texto y cuenta los envíos por hora. Esto queda fuera del prompt a propósito.
Las credenciales vienen de variables de entorno. Instala con pip install requests langchain crewai y define ZAPZAP_INSTANCE_ID, ZAPZAP_API_KEY, ZAPZAP_API_SECRET, ZAPZAP_ALLOWED (números separados por coma) y, para habilitar el envío real, ZAPZAP_ENABLE_SEND=true.
Python (zapzap_tools.py)
import os
import re
import time
import requests
BASE = "https://api.zapzapapi.com/api/v1/" + os.environ["ZAPZAP_INSTANCE_ID"]
HEADERS = {
"Content-Type": "application/json",
"x-api-key": os.environ["ZAPZAP_API_KEY"],
"x-api-secret": os.environ["ZAPZAP_API_SECRET"],
}
ALLOWED = {n for n in os.environ.get("ZAPZAP_ALLOWED", "").split(",") if n}
SEND_ENABLED = os.environ.get("ZAPZAP_ENABLE_SEND") == "true"
MAX_PER_HOUR = 20
_sent = []
def _post(path, body):
r = requests.post(BASE + path, json=body, headers=HEADERS, timeout=30)
r.raise_for_status()
return r.text
def status_instancia():
r = requests.get(BASE + "/instance/status", headers=HEADERS, timeout=30)
r.raise_for_status()
return r.text
def verificar_numeros(numeros):
if not numeros or len(numeros) > 50 or not all(re.fullmatch(r"\d{10,15}", n) for n in numeros):
raise ValueError("invalid numbers: use country code and digits only")
return _post("/chat/check", {"numbers": numeros})
def enviar_texto(numero, texto):
if not SEND_ENABLED:
return "sending disabled (safe mode)"
if not re.fullmatch(r"\d{10,15}", numero):
raise ValueError("invalid number: use country code and digits only")
if numero not in ALLOWED:
raise PermissionError("number not in the allowed list")
if not texto or len(texto) > 1000:
raise ValueError("text empty or too long")
agora = time.time()
_sent[:] = [t for t in _sent if agora - t < 3600]
if len(_sent) >= MAX_PER_HOUR:
raise RuntimeError("hourly limit reached")
_sent.append(agora)
return _post("/send/text", {"number": numero, "text": texto})LangChain: registrar las funciones como herramientas y crear el agente
En LangChain, el decorador tool (de langchain_core.tools) convierte la función en herramienta; el docstring se vuelve la descripción y las anotaciones de tipo se vuelven el esquema. create_agent arma el agente con el modelo, las herramientas y el prompt de sistema. El modelo viene del proveedor que configures (el string en formato proveedor:modelo lo completas tú), y el costo de ese proveedor es aparte.
La invocación recibe una lista de mensajes y devuelve el estado con los mensajes finales. Para exigir aprobación humana antes del envío, LangChain ofrece mecanismos de interrupción (middleware y checkpointer); como la API varía por versión, el ejemplo mantiene el envío desactivado por defecto y deja la aprobación de tu lado, según la documentación de tu versión.
Python (LangChain)
from langchain.agents import create_agent
from langchain_core.tools import tool
import zapzap_tools as zap
@tool
def status_whatsapp() -> str:
"""Mostra se a instancia de WhatsApp esta conectada."""
return zap.status_instancia()
@tool
def verificar_numeros_whatsapp(numeros: list[str]) -> str:
"""Verifica quais numeros tem WhatsApp. Use DDI e so digitos, ex: 5511999999999."""
return zap.verificar_numeros(numeros)
@tool
def enviar_whatsapp(numero: str, texto: str) -> str:
"""Envia uma mensagem de texto. Use so quando o usuario pedir explicitamente. Numero com DDI e so digitos."""
return zap.enviar_texto(numero, texto)
agente = create_agent(
"SEU_PROVEDOR:SEU_MODELO",
tools=[status_whatsapp, verificar_numeros_whatsapp, enviar_whatsapp],
system_prompt="Voce ajuda a equipe com tarefas de WhatsApp. Nunca envie mensagem sem pedido explicito. Se faltar dado, pergunte.",
)
resultado = agente.invoke(
{"messages": [{"role": "user", "content": "Veja se a instancia esta conectada e se 5511999999999 tem WhatsApp."}]}
)
print(resultado["messages"][-1].content)CrewAI: agentes, tareas y la misma capa de candados
En CrewAI, el decorador tool (de crewai.tools) crea la herramienta a partir de la función y del nombre. Defines un Agent con rol, objetivo e historia, una Task con descripción y salida esperada, y una Crew que une ambos. kickoff ejecuta. El modelo se configura según la documentación de CrewAI para el proveedor que uses.
CrewAI brilla cuando hay más de un rol, por ejemplo un agente que redacta el mensaje y otro que revisa el tono antes del envío. Para WhatsApp, vale un diseño en el que el agente de envío solo reciba texto ya revisado y la Task de envío exija confirmación humana (el parámetro human_input de la Task, según la documentación de la versión).
Python (CrewAI)
from crewai import Agent, Crew, Task
from crewai.tools import tool
import zapzap_tools as zap
@tool("verificar_numeros_whatsapp")
def verificar_numeros_whatsapp(numeros: list[str]) -> str:
"""Verifica quais numeros tem WhatsApp. Use DDI e so digitos, ex: 5511999999999."""
return zap.verificar_numeros(numeros)
@tool("enviar_whatsapp")
def enviar_whatsapp(numero: str, texto: str) -> str:
"""Envia uma mensagem de texto para um numero da lista permitida."""
return zap.enviar_texto(numero, texto)
operador = Agent(
role="Operador de WhatsApp",
goal="Executar tarefas de WhatsApp com seguranca e sem enviar nada que nao tenha sido pedido",
backstory="Voce cuida do canal de WhatsApp da empresa e segue as regras da lista permitida.",
tools=[verificar_numeros_whatsapp, enviar_whatsapp],
)
tarefa = Task(
description="Verifique se o numero 5511999999999 tem WhatsApp e informe o resultado. Nao envie mensagens.",
expected_output="Uma frase dizendo se o numero tem WhatsApp.",
agent=operador,
)
crew = Crew(agents=[operador], tasks=[tarefa])
print(crew.kickoff())Qué candados mantener, sin importar el framework
| Candado | Dónde queda | Por qué |
|---|---|---|
| Lista permitida de números | En la función, no en el prompt | El modelo puede equivocarse o ser inducido |
| Validación de formato | En la función | Evita números inválidos e inyección en campos |
| Límite por hora | En la función o en la cola | Contiene un error de bucle del agente |
| Aprobación humana | En el framework o en tu flujo | Última barrera antes del envío real |
| Modo seguro por defecto | Variable de entorno | Desarrollar sin enviar de verdad |
| Log de toda llamada | En la función | Auditoría y depuración |
| Instancia dedicada | En la cuenta | Aísla el riesgo del número principal |
Los agentes entran en bucles, repiten herramientas y se confunden. Define un número máximo de pasos en el framework y trata cualquier excepción de la función como un resultado legible para el modelo, sin exponer credenciales. Los mensajes recibidos que el agente lee son entrada no confiable: un cliente puede escribir instrucciones dirigidas al modelo, y la lista permitida y la aprobación son lo que impide el daño.
Del prototipo a producción: límites del canal y próximos pasos
La herramienta es solo el brazo; el canal mantiene sus reglas. El envío automatizado está sujeto a los Términos de WhatsApp, y ningún agente reduce el riesgo de restricción del número; puede aumentarlo si empieza conversaciones en frío en volumen. Usa el agente para responder a quien escribió primero, apoyar al equipo y ejecutar tareas internas. La guía de antibloqueo y la protección de datos valen aquí como en cualquier envío.
Para recibir los mensajes que el agente va a tratar, configura el webhook de la instancia (mira webhook y la guía de multimedia por webhook) y entrega el evento al agente por una cola. La referencia de rutas está en API de WhatsApp, y el paso a paso de la cuenta en el inicio rápido.
Resumen rápido
- Una herramienta de agente es una función de Python que llama a un endpoint de la API; el docstring es la descripción que lee el modelo.
- En LangChain 1.x usa tool y create_agent; en CrewAI 1.x usa el decorador tool con Agent, Task y Crew.
- Pon los candados en la función: lista permitida, validación, límite por hora y modo seguro por defecto.
- Exige aprobación humana antes del envío real y trata los mensajes leídos como entrada no confiable.
- No existe un paquete ni un servidor MCP propio de ZapZap para estos frameworks al 27/10/2026; la base es la API REST.
Sigue leyendo
Lee también
Preguntas frecuentes
¿Existe un plugin de ZapZap para LangChain o CrewAI?
No, al 27/10/2026. Lo que existe es la API REST con referencia por endpoint y archivo OpenAPI, y un paquete de nodos para n8n. Los ejemplos de la guía son código tuyo sobre la API, usando el decorador tool de cada framework.
¿Cómo evito que el agente envíe a cualquier número?
Pon la lista permitida dentro de la función de la herramienta, no en el prompt, y valida el formato del número. Suma un límite por hora, modo seguro por defecto y aprobación humana antes del envío real.
¿Qué framework elegir: LangChain o CrewAI?
LangChain atiende bien un agente único con varias herramientas y flujos controlados. CrewAI es más natural cuando hay roles distintos (redactar, revisar, enviar). Para WhatsApp, la decisión pesa menos que los candados y la aprobación humana.
¿El agente puede recibir mensajes de WhatsApp?
Sí, por el webhook de la instancia: registra una URL, activa el evento messages y entrega cada evento al agente por una cola, filtrando los mensajes propios y los eventos duplicados. Las herramientas cubren el envío y las consultas.
¿Necesito un modelo de IA específico?
No. Los frameworks aceptan varios proveedores; usa el que tengas con credencial. Prueba con conversaciones reales y prefiere modelos buenos para llamar herramientas, midiendo costo y latencia en tu caso.
Dale a tu agente un canal de WhatsApp
Crea la cuenta, verifica tu teléfono y recibe el crédito de bienvenida, sin depositar (uno por teléfono, sujeto a la campaña vigente). Conecta un número por código QR y prueba las herramientas en modo seguro.
