WhatsApp AgentKit
El kit casi no tiene código, y ese es el punto: el código te lo escribe Claude Code en tu computadora, durante una entrevista de diez preguntas. Esta guía te lleva de cero a un número de WhatsApp contestando solo, con trece prompts listos para pegar.
De qué va
Clonas el kit, corres la entrevista y Claude Code te deja el agente completo en tu máquina.
Lo que bajas son diecinueve archivos y casi ninguno es código. El grueso es un solo documento que le dice a Claude Code qué construir: la carpeta del agente, sus dependencias y su Dockerfile no están en GitHub a propósito, y aparecen en tu computadora cuando corres la entrevista.
Necesitas cuatro cosas: Python 3.11 o superior, Claude Code, una llave de Anthropic y una cuenta de WhatsApp API — Zernio o Meta, y aquí te decimos cuál te toca. Docker no hace falta: el servidor construye la imagen del lado de ellos.
No hay que leer ni escribir una línea de Python. Cada vez que hay que tocar código, el tramo trae el prompt que le pegas a Claude Code para que lo haga él, y el comando con el que compruebas tú que quedó.
Si lo que buscas no es un agente que conteste sino uno que además califique al cliente, agende y escriba en tu CRM, eso es otra guía y es bastante más larga: el AgentKit que cierra ventas. El de aquí conversa, entiende y deja los datos en el historial; hacer cosas por ti es un cableado aparte que se explica al final.
El repo
Hainrixz/whatsapp-agentkit
Python, licencia MIT y 494 estrellas. Son diecinueve archivos y casi ninguno es código: «este repo casi no tiene código», dice su propio sitio, porque lo que hay adentro son las instrucciones con las que Claude Code te escribe el agente en tu máquina.
Las dieciséis secciones
Qué vas a tener al final
Un número que contesta solo, y lo que tu agente no hace.
Las cuatro cosas que necesitas
Python, Claude Code, la llave de Anthropic y una cuenta de WhatsApp API.
La llave de Anthropic, clic por clic
Dónde se saca, cómo empieza y por qué solo se ve una vez.
Zernio o Meta: cuál te toca
Una tabla y un criterio. Se elige una sola vez y no hay que volver atrás.
Zernio, clic por clic
La cuenta, la llave, el secreto del webhook y el número de pruebas.
Meta Cloud API, clic por clic
La app de Facebook, los cuatro datos y el App Secret que está escondido.
Tres comandos y ya estás adentro
Qué hace start.sh de verdad, y qué no hace aunque el README diga que sí.
/build-agent y las diez preguntas
Las diez, con la que más rinde marcada, y qué archivos quedan al terminar.
Probarlo en tu compu
Las dos pruebas locales y los tres estados del chequeo de salud.
Los dos pasos que casi todos se saltan
El remote heredado y el .gitignore que deja fuera justo lo que hay que subir.
De tu GitHub a internet
Proyecto, base de datos, variables y el dominio que no se genera solo.
Decirle a WhatsApp a dónde avisar
El alta, la firma, los cinco segundos y los siete reintentos.
Síntoma, causa, arreglo
Las fallas reales de este kit, cada una con su arreglo de una línea.
Cambiarle cosas, y el límite real
Tono, conocimiento, cambiar de proveedor, y cablear de verdad una herramienta.
Lo que cuesta, con fecha
El modelo, el servidor y WhatsApp. Por qué sube la cuenta y cómo se baja.
Preguntas frecuentes
Lo que se pregunta cuando ya está corriendo y aparece la primera duda.
Ficha
WhatsApp AgentKit, de un vistazo
- Nivel
- Intermedio. Copias comandos y haces clics en dos paneles; no escribes código.
- Temas
- WhatsApp API, Claude Code, Zernio o Meta, webhooks, Railway y PostgreSQL.
- Qué necesitas
- Python 3.11 o superior, Claude Code, una llave de Anthropic y una cuenta de WhatsApp API. Docker no hace falta.
- Cuánto toma
- Una sesión sin prisa: la entrevista son diez preguntas y lo demás son clics. Lo que tarde de verdad depende del proveedor que elijas.
01 · el resultado
Qué vas a tener al final, y qué no hace todavía
Antes de instalar nada conviene saber exactamente qué compras con la sesión que estás por empezar. Esta sección es eso: lo que te queda funcionando, lo que no, y cuál de las tres guías de WhatsApp de la bóveda es la tuya.
en una frase
Un número de WhatsApp que contesta solo, con la información de tu negocio, y que se acuerda de cada cliente entre un día y otro.
Tu cliente escribe a las once de la noche y le responde tu agente con tus precios, tu horario y tus condiciones, no con generalidades de internet.
Y si vuelve mañana no empieza de cero: antes de responder, tu agente lee el historial de esa conversación. Es un número, no una app que alguien tenga que descargar.
el dato que nadie espera
El kit casi no tiene código, y es a propósito
Lo que te bajas de GitHub son diecinueve archivos y casi ninguno es programa. El que manda es CLAUDE.md: ochenta kilobytes de instrucciones escritas para que las lea Claude Code, no tú.
El sitio del proyecto lo dice con todas sus letras: «Este repo casi no tiene código».
Lo que no vas a encontrar en GitHub es justamente lo que hace funcionar a tu agente:
- agent/ — el programa que recibe los mensajes y responde.
- config/ — el prompt del sistema y los datos de tu negocio.
- tests/ — las pruebas con las que compruebas que quedó.
- requirements.txt — la lista de lo que hay que instalar.
- Dockerfile y docker-compose.yml — cómo se empaqueta para subirlo.
Nada de eso está en el repositorio: el .gitignore del kit lo excluye a propósito. Aparece en tu computadora cuando corres la entrevista, y lo escribe Claude Code con las respuestas que tú le des. Por eso dos personas que clonen el mismo kit terminan con dos agentes distintos.
Tres negocios, tres agentes distintos
El mismo kit, respondiendo con lo que tú le hayas dado. Lo que cambia entre uno y otro no es el programa: es lo que contestaste en la entrevista y los archivos de tu negocio que le dejaste a mano.
restaurante
El que contesta el menú
- Cuánto cuesta la pizza grande y qué trae.
- A qué hora abren el domingo.
- Qué hay sin gluten y cuáles son las opciones.
clínica o salón
El que contesta servicios y horarios
- Qué servicios hay y cuánto dura cada uno.
- Cuánto cuesta la limpieza y qué incluye.
- Qué días de la semana atiende cada persona.
inmobiliaria
El que filtra antes de que llames
- Qué hay en esa zona y en qué rango de precio.
- Si aceptan mascotas y cuánto piden de depósito.
- Deja escritos en el historial el presupuesto y la zona que pidió el cliente.
Qué pasa entre que tu cliente escribe y le llega la respuesta
Seis pasos. No hace falta que los entiendas para usar el kit, pero el día que algo falle vas a saber en cuál de los seis mirar.
un mensaje, de punta a punta
1 Tu cliente escribe. El mensaje llega al proveedor (Zernio o Meta). 2 El proveedor se lo manda a tu servidor por el webhook. 3 Tu servidor verifica la firma y descarta el aviso si ya lo había recibido antes. 4 Contesta 200 de inmediato y sigue trabajando por su cuenta. 5 Busca el historial de esa conversación y se lo manda a Claude junto con el mensaje y la información de tu negocio. 6 Claude escribe la respuesta y se envía de vuelta por WhatsApp.
Lo que tu agente todavía no hace solo
lo que todavía no hace solo
agent/tools.py se genera, pero no se ejecuta
Claude Code escribe ese archivo con funciones de verdad —reservar una cita, agregar al carrito, registrar un lead— y ahí se quedan: ningún módulo las importa y nunca llegan a Claude.
Lo que tu agente sí hace: conversa, entiende y te deja los datos en el historial. Si tu cliente dice «quiero el martes a las cinco», eso queda escrito y tú lo lees.
Lo que todavía no hace solo: agendar esa cita, cobrarla o descontar stock. Eso es un cableado aparte.
Que sepa tu menú no depende de ese archivo: la información de tu negocio le llega por el prompt del sistema. tools.py hace falta para hacer, no para contestar.
Ese cableado se puede hacer y no lo tienes que escribir tú: el apartado de personalizar trae el prompt que conecta una de esas funciones de punta a punta. Pero es un paso más, y no viene hecho.
Si esta no era tu guía
En la bóveda hay tres caminos para poner un agente en WhatsApp y se parecen poco entre sí. Este es el corto: una entrevista y ya.
WhatsApp AgentKit (esta)
- Cuándo es la tuya
- Quieres un número que conteste solo, con la información de tu negocio, y lo quieres esta semana. Nivel intermedio.
- Qué te cuesta de más
- Casi nada, y ese es el punto. A cambio, tu agente conversa y entiende: hacer cosas por ti se cablea aparte.
El AgentKit que cierra ventas
- Cuándo es la tuya
- La venta se cierra por chat y necesitas calificar al cliente, agendar y que quede escrito en tu CRM. Nivel avanzado.
- Qué te cuesta de más
- Quince fases en vez de una entrevista, modo borrador para revisar antes de mandar y una compuerta de veintitrés chequeos.
OpenWA, el camino del QR
- Cuándo es la tuya
- No quieres pasar por Meta ni por un proveedor: escaneas un código con tu propio WhatsApp. Nivel avanzado.
- Qué te cuesta de más
- Lo hospedas tú y lo mantienes tú. Es el camino con más piezas propias de los tres.
| Guía | Cuándo es la tuya | Qué te cuesta de más |
|---|---|---|
| WhatsApp AgentKit (esta) | Quieres un número que conteste solo, con la información de tu negocio, y lo quieres esta semana. Nivel intermedio. | Casi nada, y ese es el punto. A cambio, tu agente conversa y entiende: hacer cosas por ti se cablea aparte. |
| El AgentKit que cierra ventas | La venta se cierra por chat y necesitas calificar al cliente, agendar y que quede escrito en tu CRM. Nivel avanzado. | Quince fases en vez de una entrevista, modo borrador para revisar antes de mandar y una compuerta de veintitrés chequeos. |
| OpenWA, el camino del QR | No quieres pasar por Meta ni por un proveedor: escaneas un código con tu propio WhatsApp. Nivel avanzado. | Lo hospedas tú y lo mantienes tú. Es el camino con más piezas propias de los tres. |
La que cierra ventas es el AgentKit que cierra ventas, y ahí viven también los plazos de verificación de negocio en Meta.
La del código QR es OpenWA, WhatsApp sin Meta: lo hospedas tú, sin proveedor de por medio.
02 · lo que hace falta
Las cuatro cosas que necesitas
Cuatro para construir tu agente, y dos de ellas se instalan con un comando cada una. Conviene tenerlas antes de empezar, porque el kit revisa dos de las cuatro apenas arranca y se detiene ahí mismo si le falta alguna.
Cada una hace algo distinto y ninguna sustituye a otra: Python es lo que corre tu agente, Claude Code es lo que lo escribe, la llave de Anthropic es lo que lo hace pensar y la cuenta de WhatsApp API es por donde entran y salen los mensajes.
Más adelante vas a abrir dos cuentas más —GitHub en la sección 10 y Railway en la 11—, pero esas se crean sobre la marcha, cuando toque subir tu agente y ponerlo en internet. Hoy no te hacen falta.
Python 3.11 o superior
Es el lenguaje en el que va a estar escrito tu agente, y el que lo mantiene encendido cuando llega un mensaje. La versión no es un detalle: por debajo de 3.11 el kit no arranca.
Según tu sistema:
- Mac: brew install python en la Terminal.
- Windows: descarga el instalador y marca la casilla "Add to PATH" durante la instalación.
- Linux: sudo apt install python3.11
El instalador de Windows se baja de python.org, y esa casilla es la que evita que después el comando de abajo no exista.
Node.js LTS y Claude Code
Claude Code es quien escribe el agente: tú no vas a leer ni escribir una línea de Python. Se instala con npm, que viene dentro de Node.js, así que Node va primero, en su versión LTS.
Si no lo tienes, se baja de nodejs.org. El comando de Claude Code está justo debajo de esta lista.
La llave de Anthropic
Es lo que hace que tu agente piense: cada respuesta que escribe pasa por ahí.
No la saques todavía. De dónde se saca, cómo empieza y por qué solo se ve una vez está en el paso siguiente, clic por clic.
Una cuenta de WhatsApp API
Es por donde entran y salen los mensajes. Hay dos caminos, Zernio o Meta Cloud API, y se toma uno solo.
Cuál te toca es la única decisión de fondo de esta guía y se resuelve dos secciones más abajo, con una tabla y un criterio. Se elige una vez y no hay que volver atrás.
Revisa Python antes de bajar nada
Puede que ya lo tengas puesto. Abre la Terminal, pega esto y mira qué te contesta:
Ver si ya tienes Python
python3 --versionSi responde un número igual o mayor a 3.11 —3.11, 3.12, 3.13—, ya está: no instales nada.
Si responde un número menor, o si te dice que no conoce el comando, instálalo con la ruta de tu sistema y vuelve a correr esta misma línea hasta que el número te cuadre.
Instalar Claude Code, y autenticarlo una vez
Con Node puesto, Claude Code se instala con un comando. Va en la misma Terminal y da igual en qué carpeta estés parado:
Instalar Claude Code
npm install -g @anthropic-ai/claude-codeFalta el paso que casi todo el mundo se salta. Cuando termine de instalar, escribe claude a secas y deja que abra sesión con tu cuenta. Se hace una sola vez y sin eso la herramienta queda instalada pero muda.
Recién cuando claude abre sin pedirte nada conviene seguir al paso de bajar el kit. Ahí se revisa que esté a la mano, y si no lo está el arranque se corta y te pide justo este comando.
lo que NO necesitas
Tres cosas que la gente cree que hacen falta
- Docker. No lo instalas ni ahora ni después: el servidor donde va a vivir tu agente construye la imagen del lado de ellos.
- Tarjeta para probarlo. Si vas por Zernio, la cuenta se abre en el plan gratis sin tarjeta y el número de pruebas no cuesta.
- Saber programar. Tú pegas comandos, haces clics y contestas diez preguntas; leer y escribir Python es trabajo de Claude Code.
Lo único que se paga por uso es lo que tu agente le pregunta a Claude. Cuánto, con números y con fecha, está al final, en la cuenta completa.
03 · la llave
Sacar tu API key de Anthropic, clic por clic
Tu agente le habla a Claude por su cuenta, a las tres de la mañana y sin que tú estés adelante. Para eso necesita una llave propia: un texto largo que Anthropic te entrega una sola vez y que tu servidor presenta cada vez que tiene que pensar una respuesta.
Sacarla son cinco clics y no llega a dos minutos. El único que hay que hacer con cuidado es el último, porque la llave se muestra una vez y después esa pantalla ya no vuelve.
Todo pasa en la consola de Anthropic, que no es la misma página donde chateas con Claude: platform.anthropic.com. Ese enlace te deja directo en la pantalla de las llaves.
Los cinco clics, en orden
Abre platform.anthropic.com
La consola de Anthropic. Es una puerta distinta a la de la app y a la de Claude Code, aunque todo sea de la misma casa.
Crea la cuenta, o entra con la que ya tienes
Si es tu primera vez en la consola, ahí mismo la creas. Tener Claude Code pagado no te salta este paso: son dos cosas separadas.
Settings, y ahí dentro API Keys
Settings es la configuración de la consola, y adentro está la sección API Keys. Los dos rótulos están en inglés.
Create Key
El botón que la crea. Ahí nace la llave, y nace lista para usarse.
Cópiala en ese momento
Empieza con sk-ant-. La vas a necesitar en un rato, cuando corras la entrevista, así que cópiala completa antes de cerrar nada.
la pantalla que no vuelve
Si no la copiaste, no la busques
Anthropic te muestra la llave completa una sola vez, en la pantalla donde nace. Cuando la cierras no hay un «ver de nuevo» escondido en algún menú: no existe.
Tampoco es un drama. Vuelves a Settings → API Keys → Create Key y sacas otra. Lo que se pierde es el minuto, nada más.
cómo sabes que es la buena
Cómo reconoces que tienes la llave correcta
- empieza con
- sk-ant-
- dónde se saca
- platform.anthropic.com → Settings → API Keys → Create Key
- cuántas veces se ve
- Una. Si la pierdes, no se recupera: se crea otra.
- en qué variable va
- ANTHROPIC_API_KEY
- dónde termina
- En el archivo .env de tu carpeta. Ese archivo se queda en tu computadora y nunca sube a GitHub.
- qué no es
- Tu suscripción de Claude Code. Son dos cuentas distintas y cada una se cobra por su lado.
la regla que no se rompe
La llave va en un solo lugar y en ninguno más
No se pega en un chat, ni en un issue de GitHub, ni en una captura de pantalla para pedir ayuda. Quien la vea puede gastar con tu cuenta, y ese consumo se cobra en la tuya.
Su lugar es el archivo .env de tu carpeta, y nada más. Ese archivo no sube a GitHub.
Si se te escapó en alguno de esos lugares, dala por perdida: vuelve a Create Key, saca otra y usa la nueva.
No es lo mismo que tu suscripción de Claude Code
Son dos cuentas con el mismo apellido. La suscripción es para que trabajes tú, con Claude Code abierto en tu computadora. La llave es para que trabaje tu agente, solo, desde el servidor, mientras tú haces otra cosa.
Por eso tener Claude Code pagado no te ahorra la llave, y tener la llave no te da Claude Code. La llave se factura aparte y por uso: pagas por lo que tu agente conversa, no una mensualidad fija.
Cuánto es ese uso —por modelo, por conversación y al mes— está en la sección 15, con su fecha. Los números viven ahí y solo ahí, con el día en que se consultó cada tarifa.
Qué modelo usa tu agente, y cómo se cambia
De fábrica tu agente piensa con claude-sonnet-5. Si quieres otro, no hay que abrir un archivo de código ni entender Python: se cambia el valor de una variable y ya.
Estas son las cuatro que tocan a Anthropic. La primera es la llave que acabas de sacar; las otras tres traen un valor por defecto que ya funciona.
ANTHROPIC_API_KEYLa que acabas de copiar, tal cual, empezando por sk-ant-. No hay dónde volver a verla: si la perdiste, saca otra desde Create Key.
ANTHROPIC_MODELOpcional, con matizclaude-sonnet-5
El modelo con el que piensa tu agente. Las tres opciones son claude-opus-5, claude-sonnet-5 y claude-haiku-4-5, y cambiarlo es reemplazar este texto por el otro.
ANTHROPIC_EFFORTOpcional, con matizlow
Cuánto se detiene a pensar antes de contestar: low, medium o high. Si la dejas vacía, el parámetro ni se envía, que es justo lo que hay que hacer con los modelos viejos, porque no lo aceptan.
ANTHROPIC_MAX_TOKENSOpcional, con matiz4096
El largo máximo de cada respuesta. Viene comentada en el archivo. Cuidado con bajarla: lo que el modelo piensa por dentro también cuenta contra ese tope, así que un número chico corta las respuestas a la mitad.
Si no escribes ninguna de las tres opcionales, tu agente arranca con esos mismos valores.
04 · elegir camino
Zernio o Meta: cuál te toca
Tu agente necesita una puerta por la que entren y salgan los mensajes de WhatsApp. Hay dos, y elegir es la única decisión de la guía que conviene tomar antes de escribir nada. Tranquilo, que no es cara: al final de la sección está qué pasa si eliges mal.
Qué es cada uno
Zernio corre sobre la WhatsApp Cloud API de Meta. No la reemplaza: se para encima y te resuelve las tres partes que más tardan. El Embedded Signup —la ventana de Meta donde eliges o creas tu cuenta de WhatsApp Business y su número, sin salir de ahí—, un inbox donde ves las conversaciones, y webhooks firmados, que es lo que hace que tu agente pueda distinguir un aviso legítimo de uno inventado. No tienes que crear una app de Facebook ni pasar App Review.
Meta Cloud API directo es conectarte tú, sin nadie en medio. Creas una app de Facebook tipo Business, le agregas el producto de WhatsApp, generas tus propias credenciales y das de alta el webhook con tus manos. Nada de eso es difícil: son más pasos, y uno de ellos —App Review— lo revisa Meta y no depende de ti.
Las cuatro diferencias
Esta tabla es del propio kit. Léela por la columna que te interese y fíjate menos en qué camino es «mejor» que en cuál de los dos te pide cosas que hoy no tienes:
App de Facebook
- Zernio
- No hace falta
- Meta Cloud API directo
- Sí, tipo Business
App Review
- Zernio
- No
- Meta Cloud API directo
- Sí
Verificación de negocio
- Zernio
- Desde el Embedded Signup
- Meta Cloud API directo
- Cuenta de Facebook Business verificada
Probar sin número propio
- Zernio
- Sí, número compartido
- Meta Cloud API directo
- Sí, pero antes hay que crear la app
| Zernio | Meta Cloud API directo | |
|---|---|---|
| App de Facebook | No hace falta | Sí, tipo Business |
| App Review | No | Sí |
| Verificación de negocio | Desde el Embedded Signup | Cuenta de Facebook Business verificada |
| Probar sin número propio | Sí, número compartido | Sí, pero antes hay que crear la app |
Ninguna fila habla de dinero, y es a propósito: lo que cuesta cada camino va junto con el resto de los números, en la sección de costos.
el criterio
Una línea y ya elegiste
Si ya tienes tu app de Facebook tipo Business armada y verificada, ve por Meta: el trabajo duro ya lo hiciste.
Si no la tienes, ve por Zernio y te ahorras crear la app y pasar App Review.
Se elige una vez, en la pregunta 9
Esta decisión no se declara en ningún archivo ni se configura dos veces. La entrevista te lo pregunta —es la pregunta 9 de las diez—, y con esa respuesta Claude Code escribe solo el adaptador del que elegiste.
Si eliges Zernio, el archivo que habla con Meta ni siquiera se escribe. Y al revés. Así que cuando mires tu carpeta vas a ver un proveedor y no dos: no es que falte algo, es que lo otro nunca llegó a existir.
la regla de las 24 horas
Lo que WhatsApp te deja mandar, y cuándo
WhatsApp solo permite texto libre —lo que tu agente escriba, con sus propias palabras— dentro de las 24 horas posteriores al último mensaje del cliente. Ese contador se reinicia cada vez que el cliente te vuelve a escribir.
Fuera de esa ventana el texto libre no sale. Lo único que puedes mandar es una plantilla aprobada por Meta: un mensaje escrito de antemano, enviado a revisión y autorizado antes de poder usarlo.
La buena noticia es que este agente siempre responde. Alguien le escribe, él contesta, y eso ocurre siempre dentro de las 24 horas. En la práctica nunca sale de la ventana y nunca vas a necesitar una plantilla.
Dónde sí importa: el día que quieras que tu agente escriba primero —un recordatorio, una promoción, un seguimiento a quien te dejó en visto—, eso ya es otra cosa, y esa sí pide plantilla aprobada.
¿Y si eliges mal?
No pasa nada, y no tienes que volver a empezar. El prompt del sistema con los datos de tu negocio, lo que le cargaste de tu catálogo y el historial de conversaciones no dependen del proveedor: sobreviven al cambio.
Migrar de uno a otro es pedírselo a Claude Code en una frase y darle las credenciales del nuevo.
La frase exacta, con lo que hay que decirle para no perder nada en el camino, está en cambiarle cosas, y el límite real.
05 · Zernio
Crear la cuenta, conectar WhatsApp y sacar la API key
Zernio corre sobre la WhatsApp Cloud API de Meta: pone de su lado el alta con Meta, la bandeja de conversaciones y los avisos firmados. Eso es exactamente lo que te ahorra crear una app de Facebook y pasar por App Review.
De esta sección te llevas dos valores y nada más: la API key, que te la enseña el panel una sola vez, y el secreto del webhook, que no está en ninguna pantalla porque lo inventas tú. Con esos dos, y con el número de pruebas encendido, puedes ver a tu agente contestando el mismo día.
La ruta del panel, tal cual, sin desvíos
Crea la cuenta en zernio.com
El plan Free no pide tarjeta. Con eso alcanza para todo lo que hace esta guía, incluido el número de pruebas.
Connections → Connect new → WhatsApp
Está en el panel, en el menú lateral. «Connect new» abre la lista de canales; el que buscas es WhatsApp.
Completa el Embedded Signup de Meta
Se abre una ventana de Meta dentro del panel. Ahí eliges o creas la cuenta de WhatsApp Business y el número. No sales de Zernio y no creas ninguna app de Facebook.
Settings → API Keys → Create API Key
Otra vez en el menú lateral, ya no en Connections. El botón está arriba de la lista de llaves.
Cópiala en ese momento
Es el paso que más gente pierde. Pégala en tu gestor de contraseñas antes de cerrar el aviso; después no hay dónde volver a verla.
Inventa el secreto del webhook
No lo busques en el panel. Elige una cadena larga y al azar, como una contraseña, y guárdala junto a la llave.
El webhook, todavía no
Ese paso pide la dirección pública de tu agente, que aún no existe. Queda pendiente y se retoma más adelante.
cópiala ahora
La API key se muestra una sola vez
Cuando le das a Create API Key, el panel te la enseña en esa pantalla y no vuelve a enseñártela. Si cierras la ventana sin copiarla, no hay «verla de nuevo»: vuelves a Settings → API Keys → Create API Key, sacas otra y usas esa.
La reconoces por la forma: empieza con sk_ y sigue con 64 caracteres hexadecimales, o sea números y letras de la a a la f. Si lo que pegaste no empieza con sk_, copiaste otra cosa.
Su lugar final es la variable ZERNIO_API_KEY de tu archivo .env. Mientras tanto, guárdala donde guardas contraseñas y no la pegues en un chat.
el secreto lo inventas tú
El secreto del webhook no te lo da Zernio
Es el único dato de esta sección que no sale de una pantalla: lo eliges tú. Y sirve para una cosa muy concreta: comprobar que cada aviso que llega viene de Zernio y no de cualquiera que haya adivinado la dirección de tu agente.
Va a estar escrito en dos lados y tiene que ser el mismo texto exacto en los dos: en tu archivo .env, como ZERNIO_WEBHOOK_SECRET, y en el alta del webhook dentro del panel de Zernio. Si difieren en un carácter, los avisos legítimos se caen.
El alta del webhook no se hace aquí, y no es por orden de lectura: hace falta la dirección pública de tu agente y todavía no existe. Va en la sección del webhook, cuando ya esté desplegado. Por ahora basta con tener el secreto escrito y a mano.
Los dos valores, con el nombre que van a llevar
Estos son los nombres exactos con los que vas a ver escritos tus dos datos. No tienes que abrir ningún archivo a mano: Claude Code te los pide de a uno y los escribe él.
ZERNIO_API_KEYLa que copiaste en Settings → API Keys. Empieza con sk_ y sigue con 64 caracteres hexadecimales. Aquí no hay valor de ejemplo porque es tuya y no se comparte con nadie.
ZERNIO_WEBHOOK_SECRETLa cadena que inventaste tú. El mismo texto exacto va después en el alta del webhook, dentro del panel de Zernio, y de ahí sale la comprobación de que un aviso es legítimo.
El número de pruebas: para qué sirve y para qué no
Zernio presta un número compartido para que veas tu agente andando antes de tener uno propio. Se enciende abriendo una sesión contra tu celular: te llega un WhatsApp con una plantilla llamada sandbox_start y tienes que responderlo desde tu teléfono. Ese «responder» es lo que abre la sesión, y sin él no pasa nada más.
sirve para
Verlo funcionando hoy
- Comprobar que tu agente recibe, entiende y contesta, sin esperar a tener un número propio.
- Probar el tono y las respuestas con tu celular y con el de dos o tres personas de confianza.
- Cerrar el circuito completo y verlo: llega el mensaje, tu agente responde, lo lees en WhatsApp.
no sirve para
Atender clientes
- Atender de verdad: los cupos diarios se agotan con un puñado de conversaciones.
- Dejarlo puesto y olvidarte, porque la sesión vence y hay que volver a abrirla.
- Escribirle tú primero a alguien que no haya respondido la plantilla de arranque.
el número de pruebas, en números
Los cupos, tal como están hoy
- Mensajes
- 50 cada 24 horas.
- Destinatarios
- 5 distintos cada 24 horas.
- Sesiones
- Una sola activa a la vez.
- Sesión pendiente
- Caduca a las 24 horas si nadie responde la plantilla.
- Sesión activada
- Dura 7 días.
Cupos verificados el 17 de septiembre de 2026.
Enciéndelo sin escribir un solo comando
Un detalle que te va a confundir si miras la documentación: para listar los números, la doc de Zernio dice GET /v1/phone-numbers y el documento del kit dice /api/v1/whatsapp/phone-numbers. No tienes que elegir a ciegas, y el prompt tampoco: prueba las dos y se queda con la que responda.
Prompt 01 · Encender el número de pruebas
Córrelo cuando ya tengas el kit y tu llave escrita en el .env. Claude Code hace las llamadas; lo único tuyo es responder el WhatsApp que te va a llegar.
Quiero ver mi agente andando en WhatsApp hoy, con el número de pruebas de Zernio. Hazlo tú de punta a punta. CONTEXTO: - Mi llave de Zernio ya está en el .env de esta carpeta, en la variable ZERNIO_API_KEY. Léela de ahí. No me la pidas por chat. - Base de la API: https://zernio.com/api/v1. La autenticación va en Authorization: Bearer con esa llave. - Para listar los números hay dos rutas en circulación: la doc dice GET /v1/phone-numbers y el CLAUDE.md del kit dice /api/v1/whatsapp/phone-numbers. Prueba las dos y usa la que responda. - Mi celular con WhatsApp, con código de país: [ESCRIBE AQUÍ: +52 55 1234 5678] OBJETIVO: Dejar una sesión del número de pruebas activa contra mi celular, confirmada por la API y no por lo que supones. QUÉ HACER, EN ESTE ORDEN: 1. Descubre el número de pruebas con la ruta que te responda. 2. Abre la sesión con POST /v1/whatsapp/sandbox/sessions y mi celular. 3. Avísame, antes de seguir, que me va a llegar un WhatsApp con la plantilla sandbox_start y que tengo que RESPONDERLO desde mi celular. Espera a que yo confirme que respondí. 4. Consulta el estado de la sesión hasta que la API diga que está activa. RESTRICCIONES DURAS: - NUNCA imprimas mi ZERNIO_API_KEY, ni entera ni en pedazos. - NO abras la sesión contra un número que no sea el que te di. - NO abras una segunda sesión: solo se permite una activa a la vez. - NO me digas que quedó activado si la API no lo confirmó. CRITERIO DE ACEPTACIÓN, compruébalo tú: - La ruta de números respondió 200 y trajo un número. - El estado de la sesión dice que está activa. - Ninguna salida que me muestres contiene la llave. QUÉ REPORTAR AL FINAL: Qué ruta funcionó, el estado de la sesión, y mis tres límites: 50 mensajes y 5 destinatarios distintos cada 24 horas, y que la sesión activada dura 7 días.
Dos cosas antes de seguir. El prompt de aquí arriba no se corre ahora: pide el kit ya bajado y tu llave ya escrita en el .env, que son las secciones 07 y 08. Vuelve por él cuando el chequeo de salud de la sección 09 te conteste ok, y ahí sí vas a ver a tu agente contestando en WhatsApp.
Y si te quedaste con Zernio, la sección de Meta no te toca: sáltatela entera y sigue con la que baja el kit a tu computadora.
06 · Meta
Los cuatro datos que te va a pedir Meta
Son cuatro datos, y viven en dos pantallas distintas del panel de desarrolladores. Dos los copias, uno te lo inventas tú y el cuarto está escondido detrás de un botón que dice Show.
Ninguno se escribe a mano en un archivo: los dejas donde los tengas a la vista y la entrevista te los va a pedir de a uno. Lo único que pide cuidado es el sexto paso, porque ese texto lo eliges tú y tiene que quedar idéntico en dos lugares.
Todo pasa en un solo panel: developers.facebook.com. Antes de empezar, ten abierto dónde vas a pegar los cuatro valores.
La ruta, en este orden
Abre developers.facebook.com
Es el panel de desarrolladores de Meta. Desde ahí se crea todo lo demás.
Crea una app de tipo Business
Meta te pide elegir un tipo cuando creas la app. El que va aquí es Business.
Agrégale el producto WhatsApp
Dentro de tu app, en la lista de productos. A partir de ahí tienes el menú de WhatsApp.
WhatsApp → API Setup: copia el Phone Number ID
Ojo con este: no es el número de teléfono. Es un id numérico, y es lo que le dice a Meta desde qué número sale cada respuesta.
En la misma pantalla, genera un token de acceso permanente
Hay uno de 24 horas para probar rápido y hay uno permanente. El que va aquí es el permanente, y abajo te digo qué pasa si guardas el otro.
Inventa el Verify Token
Este no te lo da Meta ni te lo da nadie: es un texto que eliges tú. El kit sugiere agentkit-verify.
Anótalo tal cual lo escribiste. Va en dos lugares y tienen que ser el mismo texto exacto.
Settings → Basic → App Secret → clic en Show
Está tapado hasta que lo pides. Es con lo que tu agente comprueba que cada mensaje que le llega viene de verdad de Meta.
el token que muerde
Tiene que ser el permanente
Si guardas el de 24 horas, todo funciona hoy y mañana tu agente se queda mudo: sigue recibiendo mensajes y ya no puede contestar ninguno.
El síntoma es tramposo porque no se cae nada. El chequeo de salud contesta 200 y queda en degradado, con el detalle de la credencial rechazada adentro.
Genera el permanente desde el principio y guárdalo donde no se te pierda: esa pantalla no te lo vuelve a mostrar en bandeja.
Los cuatro datos, uno por uno
META_ACCESS_TOKEN
- De dónde sale
- WhatsApp → API Setup, generando el token permanente.
- Para qué lo usa el agente
- Enviar. Es lo que autoriza cada mensaje que sale de tu agente hacia Meta.
META_PHONE_NUMBER_ID
- De dónde sale
- WhatsApp → API Setup.
- Para qué lo usa el agente
- Decir desde qué número sale la respuesta. No es el número de teléfono: es un id numérico.
META_VERIFY_TOKEN
- De dónde sale
- Lo inventas tú. El kit sugiere agentkit-verify.
- Para qué lo usa el agente
- El apretón de manos de una sola vez, cuando das de alta el webhook. Después no se vuelve a usar.
META_APP_SECRET
- De dónde sale
- Settings → Basic → App Secret, clic en Show.
- Para qué lo usa el agente
- Verificar la firma de cada mensaje que entra, uno por uno.
| El dato | De dónde sale | Para qué lo usa el agente |
|---|---|---|
| META_ACCESS_TOKEN | WhatsApp → API Setup, generando el token permanente. | Enviar. Es lo que autoriza cada mensaje que sale de tu agente hacia Meta. |
| META_PHONE_NUMBER_ID | WhatsApp → API Setup. | Decir desde qué número sale la respuesta. No es el número de teléfono: es un id numérico. |
| META_VERIFY_TOKEN | Lo inventas tú. El kit sugiere agentkit-verify. | El apretón de manos de una sola vez, cuando das de alta el webhook. Después no se vuelve a usar. |
| META_APP_SECRET | Settings → Basic → App Secret, clic en Show. | Verificar la firma de cada mensaje que entra, uno por uno. |
Ninguno de los cuatro impide que tu agente arranque, y por eso hay que ponerlos bien desde el principio: si el token está mal, el chequeo de salud queda en degradado; si falta el App Secret, arranca, acepta todo lo que le llegue y solo lo avisa en los registros.
Los dos valores que se escriben tal cual
De todo lo de arriba, estos dos son los únicos que puedes ver escritos aquí. Los otros dos son tuyos y no se publican en ninguna página.
META_VERIFY_TOKENagentkit-verify
Lo inventas tú; este es el que sugiere el kit y sirve perfecto. Va idéntico, letra por letra, en tus variables y en la casilla de Meta cuando des de alta el webhook.
META_API_VERSIONOpcional, con matizv25.0
Ya viene puesta: es la versión de la Graph API con la que tu agente le habla a Meta. Solo se toca si Meta deprecó esa versión.
el 403 que es correcto
Si el verify token no coincide, tu servidor dice que no
Al dar de alta el webhook, Meta llama una sola vez a tu URL con hub.mode=subscribe y el texto que escribiste en la casilla.
Si ese texto no es idéntico al de META_VERIFY_TOKEN, tu servidor devuelve 403. A propósito, y está bien que lo haga.
Devolver 200 ahí le haría creer a Meta que la URL quedó verificada cuando no lo está: te quedarías con un alta que se ve bien y no te entrega un solo mensaje.
El arreglo es aburrido: el mismo texto exacto en los dos lados y vuelves a lanzar la verificación.
La firma viene en otro encabezado
Cada aviso que Meta le manda a tu agente viene firmado, y esa firma viaja en el encabezado X-Hub-Signature-256, con el formato sha256=<hex>. Zernio firma lo mismo, pero en otro encabezado y sin ese prefijo, así que el código que comprueba una de las dos firmas no sirve para la otra.
Por eso Claude Code escribe un adaptador distinto para cada proveedor, y por eso en la entrevista se elige uno solo: el archivo del otro ni se genera.
Los dos encabezados, lado a lado
Meta X-Hub-Signature-256: sha256=<hex> Zernio X-Zernio-Signature: <hex>
Dónde se pega la URL, qué casillas se llenan y por qué hay cinco segundos de por medio va completo en el capítulo del webhook. Aquí solo importaba de dónde sale el App Secret con el que se comprueba esa firma.
Las dos puertas de este camino
Además de los cuatro datos, Meta te pone dos puertas por delante. Ninguna se salta, y ninguna la pone el kit.
- Una cuenta de Facebook Business verificada.
- Pasar App Review.
Cuánto tardan esas dos puertas no lo vas a leer aquí con un número inventado: los plazos viven, fechados y con su fuente, en el AgentKit que cierra ventas. Si al llegar hasta aquí descubres que tu cuenta todavía no está verificada, esa guía es la que te dice qué sigue.
Con esos cuatro datos guardados terminas aquí. El número de pruebas de la sección 05 no te toca: ese es de Zernio, y si te la saltaste hiciste bien.
Por este camino vas a ver a tu agente contestar primero en tu computadora, en la sección 09, y por WhatsApp solo cuando des de alta el webhook, en la 12. Ahora sigue con la sección que baja el kit.
07 · bajar el kit
Tres comandos y ya estás adentro
Tres comandos en la terminal y el kit queda en tu computadora. Van en este orden y de uno en uno; el tercero es el único que hace algo, y aun así no instala nada: solo revisa que tengas lo necesario y deja la carpeta en su sitio.
Abre la terminal y pega el primero tal cual, sin cambiar de carpeta: el kit se baja donde la terminal te deja al abrirla, que es tu carpeta de usuario, y desde ahí funciona igual. Cuando termine vas a tener una carpeta nueva llamada whatsapp-agentkit, y los otros dos se corren ya adentro de ella.
1 · Bajar el kit a tu compu
git clone https://github.com/Hainrixz/whatsapp-agentkit.git2 · Entrar a la carpeta
cd whatsapp-agentkit3 · Preparar el entorno
bash start.shQué hace y qué no hace start.sh
Cuatro cosas, y ninguna es instalar dependencias
- Revisa que tengas Python 3.11 o superior. Si falta o es menor, se detiene ahí mismo.
- Revisa que el comando claude esté disponible. Si no lo está, se detiene y te deja escrita la línea de npm que lo instala.
- Crea la carpeta knowledge/, que es donde después van los archivos de tu negocio.
- Copia .env.example a .env, y solo si .env no existía. Si ya lo tenías, no lo toca.
Eso es todo. Lo que no hace, aunque el README diga que sí, es instalar las dependencias de Python: ese paso ocurre más adelante y lo hace Claude Code por su cuenta, no tú.
Así que si el script termina rápido y sin descargar nada, no se saltó nada. Terminó.
Y si se corta, es por una de dos cosas, las dos de la sección lo que hace falta: o Python no llega a 3.11, o Claude Code no está instalado. Lo resuelves ahí, vuelves a esta carpeta y corres bash start.sh otra vez. No pasa nada por correrlo dos veces.
Cómo sabes que salió bien
Los cuatro chequeos, en el orden en que corren
[1/4] Python 3.11 o superior: listo [2/4] Claude Code en el PATH: listo [3/4] Carpeta knowledge/: creada [4/4] .env creado a partir de .env.example
Cuatro pasos y te devuelve el control de la terminal. El texto exacto lo pone el script y puede cambiar; lo que no cambia es el orden. Si se detiene antes de llegar al cuarto, el motivo queda escrito en la línea donde paró: no hay que ir a buscarlo a ningún registro.
Abrir Claude Code sin salir de la carpeta
Un comando más, y este cambia con quién estás hablando: hasta aquí le hablabas a la terminal, de aquí en adelante le hablas a Claude Code.
Tiene que abrirse dentro de whatsapp-agentkit, porque lo que ve es lo que hay en la carpeta desde donde lo abriste. Si lo abres en otro lado, no encuentra el kit.
Abrir Claude Code en esa carpeta
claudePrompt 02 · El mapa del terreno, antes de la entrevista
Pégalo apenas abra Claude Code, antes de escribir /build-agent. Le dice qué hay en la carpeta y qué falta a propósito. Sin esto, lo más común es que se ponga a buscar el código del agente y te avise de que el repositorio está incompleto, que es justo lo que no pasa.
Acabo de clonar este repositorio y voy a construir mi agente de WhatsApp contigo. Antes de arrancar, ubícate. CONTEXTO, y esto es lo importante: - Este repositorio NO contiene el agente. Contiene las instrucciones con las que tú lo escribes, y CLAUDE.md es ese sistema entero. - Por eso agent/, config/, tests/, requirements.txt, Dockerfile y docker-compose.yml todavía no existen, y está bien que no existan: los vas a escribir tú. No me reportes que faltan. - Lo único que hay son 19 archivos: CLAUDE.md, README.md, start.sh, scripts/audit.py, .env.example y la carpeta .claude/, entre otros. - Yo no programo: no me muestres diffs ni me pidas editar archivos a mano. OBJETIVO: Que quedes ubicado y que yo sepa qué viene, antes de /build-agent. QUÉ HACER, EN ESTE ORDEN: 1. Lee CLAUDE.md completo, de principio a fin. 2. Corre `python3 --version` y dime qué versión hay. 3. Comprueba que existe .env en la raíz. Si no existe, créalo copiando .env.example, sin escribir ningún valor adentro. 4. Explícame en español simple, en diez líneas como máximo: qué archivos vas a escribir, en qué carpetas van a quedar y cuánto dura la entrevista. RESTRICCIONES DURAS: - NO ejecutes /build-agent todavía. Espera a que yo te lo pida. - NO modifiques CLAUDE.md, README.md, start.sh ni .gitignore. - NO inventes credenciales ni pongas valores de ejemplo en .env. - NO instales nada sin avisarme antes qué es y para qué sirve. CRITERIO DE ACEPTACIÓN, compruébalo tú antes de decir que acabaste: - `python3 --version` imprime 3.11 o superior. - `ls .env` muestra el archivo en la raíz de la carpeta. Si alguno falla, dime en español qué falta y cómo lo consigo, y no sigas. QUÉ REPORTAR AL FINAL: La versión de Python, si .env ya existía o lo creaste tú, y tu resumen de diez líneas.
Cuando te conteste con ese resumen de diez líneas, ya estás listo para la entrevista, que es el tramo que sigue.
08 · la entrevista
La entrevista: las diez preguntas que construyen tu agente
Hasta aquí juntaste piezas. Este es el tramo donde se construye el agente, y se construye contestando preguntas en español: diez, una por una, sin un solo archivo que abrir ni una línea que escribir.
Claude Code lee el documento del kit, te entrevista y va escribiendo los archivos conforme le respondes. Ninguno de esos archivos existía cuando clonaste.
Arrancar la entrevista
/build-agentOjo con dónde se escribe: eso no es un comando de la terminal. Primero entras a Claude Code —escribes claude y das enter—, y una vez adentro escribes la diagonal y el nombre en su caja de mensajes. Si lo pegas en la terminal a secas, te va a decir que el comando no existe.
A partir de ahí no te apures: se puede contestar con frases largas y desordenadas. Lo que Claude Code no puede es adivinar lo que no le digas.
Las diez preguntas, y qué decide cada respuesta
No son un formulario: cada respuesta aterriza en un archivo concreto o cambia lo que se va a escribir. Esta es la traducción, pregunta por pregunta.
Cómo se llama tu negocio
Queda en config/business.yaml, el archivo donde vive la información de tu negocio.
A qué se dedica: qué vendes, qué servicios das, quiénes son tus clientes
Esta es la que arma el prompt del sistema, o sea la instrucción permanente que Claude recibe en cada turno de cada conversación. Mientras más concreta sea tu respuesta, menos genérico suena tu agente.
Para qué lo quieres
Seis opciones numeradas: 1 responder preguntas frecuentes, 2 agendar citas, 3 captar clientes y vender, 4 tomar pedidos, 5 dar soporte, 6 otro.
Esta decide qué funciones se escriben en agent/tools.py: agendar deja reservar_cita y cancelar_cita, pedidos deja agregar_al_carrito y confirmar_pedido, y así. Se escriben, pero no se ejecutan solas: conectarlas de verdad es la sección 14.
Cómo se llama tu agente
El nombre con el que se presenta ante tus clientes, no el de la carpeta. Viaja al prompt del sistema junto con lo de la pregunta 2.
Qué tono quieres
Cuatro opciones: 1 profesional y formal, 2 amigable y casual, 3 vendedor y persuasivo, 4 empático y cálido.
Es lo que hace que suene a tu negocio y no a un manual. También va al prompt del sistema.
Tu horario de atención
Es lo que contesta cuando le preguntan si estás abierto. Además queda como una de las funciones que se generan listas, obtener_horario().
¿Tienes archivos? Menú, precios, preguntas frecuentes, catálogo, políticas
Lo que entregues aquí se guarda en la carpeta knowledge/ y es la pregunta que más cambia el resultado. Va aparte, abajo.
Tu llave de Anthropic
La que sacaste en la sección 03, la que empieza con sk-ant-. Queda en el archivo de configuración, nunca dentro del código.
Zernio o Meta
La decisión ya la tomaste en la sección 04 y aquí solo se declara. Claude Code escribe el adaptador de la que elijas y nada más: no genera los dos para que escojas después.
Las credenciales del proveedor que elegiste
Con Zernio son dos datos; con Meta, cuatro. Los tienes de la sección 05 o de la 06, según el camino que te tocó. El prompt del final de esta sección te los pide de a uno y los deja donde van.
la pregunta que más rinde
La 7 es la que separa un agente tuyo de un agente cualquiera
Lo que pongas en knowledge/ se incorpora textualmente al prompt del sistema. La instrucción del sistema es no resumir de más: los precios y las condiciones quedan literales, con su número y su letra chica, no convertidos en «tenemos precios accesibles».
Si tu archivo es grande, prioriza lo que un cliente preguntaría por WhatsApp —cuánto cuesta, si hay disponibilidad, si entregan a domicilio, qué incluye— y deja fuera lo que nadie pregunta por ahí. Eso también te sale más barato: todo lo que metas al prompt del sistema se reenvía en cada turno.
Sobre el formato: el .gitkeep de la carpeta nombra .txt, .md y .csv, y la pregunta 7 acepta además PDF, DOCX, imágenes y JSON. Usa texto plano, que es lo que seguro se lee.
Tres cosas que puedes dejar de cuidar
- Tus llaves nunca terminan escritas dentro del código: van al archivo de configuración, y antes de sobrescribir algo que ya esté en config/ o en las credenciales, Claude Code te pregunta.
- Las dependencias de Python no las instalas tú: mientras corre la entrevista, Claude Code escribe requirements.txt con la lista completa y las instala con pip. Ese es el «más adelante» que anuncia la sección 07.
- Y si te interrumpen a la mitad, no se pierde: el avance queda guardado en config/session.yaml. Vuelves a abrir Claude Code, le dices que retome la entrevista y sigue donde se quedó.
lo que queda en tu carpeta al terminar
whatsapp-agentkit/ ├── agent/ lo que contesta ├── config/ tu negocio y tono ├── knowledge/ tus archivos ├── tests/ las dos pruebas ├── requirements.txt lo que se instala ├── Dockerfile cómo se construye ├── docker-compose.yml todo junto, local ├── .dockerignore lo que no entra └── .env llaves: no se sube
Salvo knowledge/, que ya venía vacía en el clon, nada de eso estaba en GitHub, y no es un descuido: el kit lo excluye a propósito porque es tuyo, no suyo. Si al terminar te falta alguno, la entrevista no llegó hasta el final.
Prompt 03 · Las credenciales, una por una
Pégalo en Claude Code cuando la entrevista llegue a las preguntas 8, 9 y 10. Te las pide de a una, las deja donde van y te avisa si algo quedó a medias.
Configura las credenciales de mi agente. Hazlo tú; yo te las paso. CONTEXTO: - Estoy dentro de la carpeta del kit. start.sh ya creó el archivo .env a partir de .env.example: es el único que se toca aquí. - Es para la prueba local, no para un servidor. - El proveedor que ya elegí: [ESCRIBE AQUÍ: zernio o meta] OBJETIVO: Que la configuración quede lista para arrancar en mi computadora, sin un valor inventado. QUÉ HACER, EN ESTE ORDEN: 1. Pídeme las credenciales UNA POR UNA y espera mi respuesta antes de pedir la siguiente. No me mandes una lista. 2. Pon WHATSAPP_PROVIDER con el proveedor que te di, en minúsculas. 3. ZERNIO_WEBHOOK_SECRET y META_VERIFY_TOKEN los invento yo. Pídemelos igual y avísame que ESE MISMO texto va después en el alta del webhook. 4. Deja PORT=8000, ENVIRONMENT=development y DATABASE_URL en SQLite: sqlite+aiosqlite:///./agentkit.db 5. Borra o comenta TODAS las variables del proveedor que NO elegí. 6. Que no quede ZERNIO_BASE_URL declarada y vacía: una URL sin https:// hace que el envío falle antes de salir a la red. RESTRICCIONES DURAS: - NUNCA escribas una credencial mía en el chat ni en un commit. - NO inventes valores. Si falta uno, detente y pídemelo. - NO agregues variables que no estén en .env.example. - NO toques .gitignore aquí. CRITERIO DE ACEPTACIÓN, compruébalo tú antes de decir que acabaste: - `grep -c "^WHATSAPP_PROVIDER=" .env` devuelve 1. - Ninguna obligatoria del proveedor que elegí quedó vacía. - No queda ZERNIO_BASE_URL con valor vacío y sin comentar. - `git check-ignore .env` confirma que está ignorado. Si alguno falla, arréglalo y vuelve a comprobar. QUÉ REPORTAR AL FINAL: Los NOMBRES de las variables que quedaron puestas y de las que comentaste —nunca sus valores— y cada criterio de arriba, uno por línea.
09 · probarlo
Hablar con tu agente antes de que hable un cliente
Ya tienes tu agente en la carpeta. Antes de subirlo a internet hay dos pruebas, y hay que hacer las dos: una revisa que conteste bien y la otra que el servidor levante. Son cosas distintas y una puede pasar con la otra rota.
Las dos corren en tu computadora. No hace falta WhatsApp, ni webhook, ni dominio: nadie de afuera puede escribirle todavía, así que es el momento de equivocarse.
Prueba 1 — háblale tú, desde la terminal
Las dos pruebas van en la terminal, no dentro de Claude Code: si lo dejaste abierto desde la entrevista, ciérralo y vuelve a la terminal, o abre una ventana nueva y entra a la carpeta con cd whatsapp-agentkit. El primer comando abre un chat ahí mismo. Le escribes como si fueras un cliente y te contesta como le contestaría a un cliente: con el tono que elegiste en la entrevista y con lo que dejaste en knowledge/.
Prueba 1 · el chat en la terminal
python tests/test_local.pyconversación de prueba
Tú: hola, ¿están abiertos hoy? Agente: Hola. Hoy atendemos de 9 a 19 h. Tú: ¿cuánto cuesta el corte? Agente: Corte 250 pesos. Con barba, 350. Tú: ¿aceptan tarjeta? Agente: Sí, y transferencia o efectivo.
Eso es todo lo que hace, y es exactamente lo que quieres ver antes que un cliente: si aquí se inventa un precio, en WhatsApp se lo inventa igual.
Gasta de verdad
No es un simulador
Cada respuesta de esta prueba es un mensaje real al modelo y sale de tu llave de Anthropic, igual que si te hubiera escrito un cliente. Probar diez veces cuesta como diez conversaciones.
Cuánto es eso en dinero, con fecha y por modelo, está en lo que cuesta.
Prueba 2 — que el servidor levante
La segunda prueba no habla con nadie. Solo comprueba que el programa arranca y que puede decirte cómo se siente. Deja esta terminal corriendo: mientras el comando esté vivo, el servidor está de pie.
Prueba 2 · levanta el servidor
uvicorn agent.main:app --reload --port 8000Ahora abre otra terminal —la primera quedó ocupada— y pregúntale a tu agente cómo está. Eso es el chequeo de salud:
El chequeo de salud
curl http://localhost:8000/Los tres estados, y dónde está el detalle de cada uno
Ese comando devuelve una línea de texto con un campo llamado «status». Tiene tres valores posibles, y cada uno se arregla en un lugar distinto. Esta es la tabla que vas a volver a mirar cuando ya esté en internet:
"status":"ok"
- Qué significa
- Arrancó y las credenciales del proveedor respondieron.
- Dónde mirar el detalle
- —
"status":"degradado"
- Qué significa
- Arrancó, pero el proveedor no contestó bien: va a recibir mensajes y no va a poder responderlos.
- Dónde mirar el detalle
- Dentro de conexion.detalle
"status":"error"
- Qué significa
- Ni siquiera pudo armar el proveedor: falta WHATSAPP_PROVIDER o está mal escrita.
- Dónde mirar el detalle
- En detalle, en la raíz
| Lo que devuelve | Qué significa | Dónde mirar el detalle |
|---|---|---|
| "status":"ok" | Arrancó y las credenciales del proveedor respondieron. | — |
| "status":"degradado" | Arrancó, pero el proveedor no contestó bien: va a recibir mensajes y no va a poder responderlos. | Dentro de conexion.detalle |
| "status":"error" | Ni siquiera pudo armar el proveedor: falta WHATSAPP_PROVIDER o está mal escrita. | En detalle, en la raíz |
lo que devuelve el chequeo de salud
si arrancó (ok o degradado):
{"status":"degradado",
"service":"agentkit",
"proveedor":"ProveedorZernio",
"conexion":{"ok":false,"detalle":"..."}}
si no pudo ni armar el proveedor:
{"status":"error",
"service":"agentkit",
"detalle":"<el error>"}Por eso la tercera columna de la tabla: el detalle de «degradado» viene metido dentro de conexion, y el de «error» va suelto arriba del todo. Si buscas en el lugar equivocado, parece que no dice nada.
Por qué siempre contesta 200
El código de respuesta no te sirve aquí
Ese chequeo devuelve 200 aunque las credenciales estén mal, y es a propósito. Si contestara con un error, Railway daría el despliegue por caído y lo reiniciaría sin parar, y tú nunca alcanzarías a leer el diagnóstico.
Así que el 200 no es la buena noticia. La buena noticia es el campo «status». Un agente con la llave del proveedor rechazada contesta 200 y dice «degradado», y va a recibir mensajes que no va a poder responder.
Si no te gusta cómo contesta
Nada de esto se arregla tocando código. Le dices a Claude Code qué te chirría —que se alarga, que saluda raro, que no menciona el horario— y él ajusta config/prompts.yaml, que es donde vive la personalidad de tu agente.
Qué se puede cambiar, hasta dónde, y qué cosas no se arreglan con el prompt está en cambiarle cosas, y el límite real.
La puerta
No sigas con esto en rojo
Si en tu computadora no contesta, en internet tampoco. Lo único que cambia allá es que se suman el webhook, el dominio y las variables del panel: tres cosas nuevas que pueden fallar encima de la que ya está fallando.
La regla es corta. Hasta que el chat de prueba sostenga una conversación y el chequeo de salud diga «ok», no se pasa a la siguiente sección.
Prompt 04 · Probar el agente en tu computadora
Corre las dos pruebas, traduce el chequeo de salud al español y repite hasta que diga ok.
Prueba mi agente en mi computadora y tradúceme el resultado. CONTEXTO: - Estoy en la carpeta del kit. La entrevista ya corrió: existen agent/, config/, tests/ y mi .env. - No hay webhook ni servidor público: esto es local. - Yo no leo Python. Explícame en español y sin jerga. OBJETIVO: Que las dos pruebas locales pasen y que yo entienda el resultado. QUÉ HACER, EN ESTE ORDEN: 1. Corre `python tests/test_local.py` y mándale tres mensajes como si fueras un cliente mío. 2. Levanta el servidor con `uvicorn agent.main:app --reload --port 8000`. 3. En otra terminal corre `curl http://localhost:8000/` y léeme el campo "status", no el código HTTP. 4. Traduce ese campo con esta regla, exacta: - "ok": arrancó y las credenciales del proveedor respondieron. - "degradado": el proveedor no contestó bien. Lee conexion.detalle, dime qué variable falta o qué credencial rechazaron, y corrígela. - "error": no pudo ni armar el proveedor. Lee detalle en la raíz y revisa WHATSAPP_PROVIDER: va zernio o meta, en minúsculas. 5. Si no dio "ok", arréglalo y repite desde el paso 2 hasta que diga "ok". RESTRICCIONES DURAS: - NO me digas "responde 200, todo bien": este servidor contesta 200 a propósito aunque las credenciales estén mal. Vale el campo "status". - NO toques config/prompts.yaml sin preguntarme antes. - NO cambies el modelo para ahorrar: esa decisión es mía. - NO borres ni reescribas mi .env. CRITERIO DE ACEPTACIÓN, compruébalo tú: - `python tests/test_local.py` sostiene una charla de tres turnos. - `curl http://localhost:8000/` devuelve "status":"ok". Si falla alguno, arréglalo y vuelve a comprobar antes de decirme que terminaste. QUÉ REPORTAR AL FINAL: La conversación completa, el "status" que salió, qué significa, y qué tocaste.
10 · a tu GitHub
Mandarlo a tu GitHub: los dos pasos que casi todos se saltan
Tu agente ya contesta en tu computadora. Para que conteste cuando tu computadora está apagada tiene que vivir en un servidor, y el camino a ese servidor pasa por un repositorio tuyo en GitHub. Son dos pasos y los dos tienen trampa: el primero te va a fallar con un error que parece grave y no lo es, y el segundo no falla — que es peor, porque sube un repositorio incompleto sin decirte nada.
Ninguno de los dos pide entender git. Piden saber que existen.
por qué te va a fallar el comando que buscaste en Google
Estás parado dentro de un repositorio que no es tuyo
Cuando clonaste el kit no bajaste una carpeta de archivos: bajaste el repositorio de git completo, con su historial y con un remote llamado origin que apunta al repo público de AgentKit.
Por eso las dos recetas que salen primero cuando buscas «subir mi proyecto a GitHub» no aplican aquí. git init no va, porque el repositorio ya existe. Y git remote add origin aborta antes de hacer nada:
lo que ves en la terminal
$ git remote add origin https://github.com/TU-USUARIO/mi-agente.git error: remote origin already exists.
No rompiste nada. Git te está avisando que ese nombre ya está ocupado por el repositorio ajeno. Se suelta el heredado, se pone el tuyo, y sigues. Lo que nunca va aquí es git init.
Los tres pasos, en orden
Crea el repositorio en GitHub, y créalo vacío
En github.com/new. Sin README, sin .gitignore y sin licencia: las tres casillas se dejan en blanco. Todo lo que va a subir ya lo tienes en tu computadora.
Reemplaza el .gitignore antes de empujar
Este es el paso que casi nadie ve y el único que no avisa cuando se salta. Está explicado completo aquí abajo.
Suelta el remote heredado, pon el tuyo y empuja
En ese orden, y solo después el commit y el push. El prompt del final lo hace de punta a punta y comprueba el resultado antes de decirte que terminó.
El segundo paso: el .gitignore del kit deja fuera justo lo que hay que subir
El kit es un repositorio público de plantilla y su .gitignore está escrito para mantenerlo limpio: excluye agent/, config/, tests/, requirements.txt, Dockerfile y docker-compose.yml. Allá tiene sentido, porque esos archivos no están en GitHub a propósito: los escribe Claude Code en tu máquina durante la entrevista.
En tu repositorio pasa exactamente al revés: eso es lo que el servidor necesita para construir tu agente. Si empujas sin tocarlo, subes un repositorio sin agente y el servidor construye la nada. El error que te sale después habla del build, no del .gitignore, y ahí se va la tarde.
tiene que entrar
Lo que hoy está ignorado y debe dejar de estarlo
- agent/ — tu agente entero.
- config/ — el prompt del sistema y los datos de tu negocio.
- tests/ — las pruebas locales.
- requirements.txt — la lista de dependencias que el servidor instala.
- Dockerfile — la receta con la que el servidor construye la imagen.
- docker-compose.yml.
sigue fuera
Lo que no sube ni después del cambio
- .env — ahí viven la llave de Anthropic y la de tu proveedor.
- *.db, *.sqlite y *.sqlite3 — la base de datos local.
- __pycache__/ y *.py[cod].
- .venv/ y venv/.
- knowledge/* — tus archivos del negocio, salvo knowledge/.gitkeep.
- config/session.yaml — el estado de la entrevista.
- .DS_Store, Thumbs.db, .vscode/ y .idea/.
Los tres comandos que te tocan a ti
El primero suelta el repositorio ajeno, el segundo apunta al tuyo y el tercero comprueba que los archivos del agente van a subir de verdad. En el segundo cambias TU-USUARIO y el nombre del repositorio por los tuyos.
Soltar el repo ajeno
git remote remove originApuntar al tuyo
git remote add origin https://github.com/TU-USUARIO/mi-agente.gitComprobar que los archivos del agente sí van a subir
git ls-files | grep -E "agent/main.py|Dockerfile"la secuencia completa, de arriba a abajo
git remote remove origin git remote add origin https://github.com/TU-USUARIO/mi-agente.git git add . git commit -m "feat: mi agente de WhatsApp" git branch -M main git push -u origin main
Esa secuencia está aquí para que reconozcas lo que pasa en pantalla, no para que la escribas: el prompt del final la corre por ti y se detiene si algo no cuadra.
Cómo compruebas que quedó bien sin entender git
git ls-files lista los archivos que el repositorio va a subir. No hace falta leerla entera: son tres cosas.
- Aparece agent/main.py. Si no está, el .gitignore sigue siendo el del kit y el paso 2 quedó pendiente.
- Aparece Dockerfile. Es la receta con la que el servidor construye tu agente; sin él no hay nada que desplegar.
- No aparece .env. Ahí están tus llaves, y un repositorio en GitHub las deja a la vista de quien pase.
Si .env alcanzó a subir, borrarlo del repositorio no alcanza: quedó en el historial. Genera una llave nueva de Anthropic y otra de tu proveedor, jubila las viejas y cámbialas en tu .env.
otra opción, y esta no tiene vuelta atrás
Si prefieres no arrastrar el historial de AgentKit
Hay un camino más corto: borrar la carpeta de git del clon y empezar uno nuevo, con rm -rf .git && git init, antes que todo lo demás. Después ya no hay remote heredado que soltar y el primer comando de arriba sobra.
Lo que cuesta: borras el historial completo del kit y eso no se deshace. No hay papelera ni deshacer. Si no tienes clarísimo que no lo quieres, quédate con la secuencia de arriba, que llega al mismo lugar sin romper nada.
Prompt 05 · Sube tu agente a tu repositorio, de punta a punta
Reemplaza el .gitignore, suelta el remote heredado, empuja y comprueba que .env no subió.
Quiero subir mi agente a MI repositorio de GitHub. Hazlo tú de punta a punta. CONTEXTO, y esto es lo importante: - Estoy parado DENTRO del clon del repo público de AgentKit. Ya hay un repositorio de git aquí y su remote "origin" apunta al repo de otra persona. Por eso `git init` no aplica y `git remote add origin` va a fallar con "remote origin already exists". - El .gitignore de este clon excluye a propósito agent/, config/, tests/, requirements.txt, Dockerfile y docker-compose.yml. Eso es exactamente lo que yo sí necesito subir: si no lo cambias, mi repo queda vacío y el despliegue construye la nada. - Mi repositorio vacío, ya creado en GitHub sin README y sin .gitignore: [PEGA AQUÍ la URL, por ejemplo https://github.com/mi-usuario/mi-agente.git] OBJETIVO: Que mi repositorio tenga el agente completo y NO tenga ningún secreto. QUÉ HACER, EN ESTE ORDEN: 1. Reemplaza el .gitignore por uno de producción que siga ignorando .env, *.db, __pycache__/, .venv/, knowledge/* salvo knowledge/.gitkeep y config/session.yaml — y que YA NO ignore agent/, config/, tests/, requirements.txt, Dockerfile ni docker-compose.yml. 2. Suelta el remote heredado con `git remote remove origin`. 3. Agrega el mío con `git remote add origin` y la URL que te di. 4. `git add .`, commit "feat: mi agente de WhatsApp", `git branch -M main`, `git push -u origin main`. 5. Si el push falla por autenticación, dime en español qué me pide GitHub. No inventes credenciales ni tokens. RESTRICCIONES DURAS: - NUNCA ejecutes `git init` en esta carpeta. - NUNCA hagas `rm -rf .git` sin pedirme permiso y explicarme que eso borra el historial sin vuelta atrás. - El archivo .env NO puede entrar al commit bajo ninguna circunstancia. - NO subas nada de knowledge/ salvo el .gitkeep: son datos de mi negocio. - NO empujes a un repositorio que no sea el que te di. CRITERIO DE ACEPTACIÓN, compruébalo tú antes de decirme que terminaste: - `git remote -v` muestra SOLO mi URL. - `git ls-files | grep -E "^agent/main\.py$"` devuelve una línea. - `git ls-files | grep -E "^Dockerfile$"` devuelve una línea. - `git ls-files | grep -c "^\.env$"` devuelve 0. Si alguno falla, arréglalo y vuelve a comprobar. No me reportes éxito con un criterio en rojo. QUÉ REPORTAR AL FINAL: La URL de mi repositorio, cuántos archivos subieron, la confirmación explícita de que .env NO está en el repositorio, y el resultado de cada criterio de arriba en una línea cada uno.
11 · Railway
De tu GitHub a internet, con los nombres de cada botón
Railway toma tu repositorio, construye la imagen a partir del Dockerfile en sus servidores y deja tu agente corriendo en una dirección pública. Docker no hace falta en tu computadora: lo único que tiene que estar bien es lo que subiste.
Son seis pasos y el orden importa en uno solo: la base de datos va antes que las variables, porque una de las variables es una referencia a la base y no puedes referenciar algo que todavía no existe.
Los seis pasos, en orden
Crear el proyecto
Entra a railway.app y crea tu cuenta si todavía no la tienes: ahí mismo se abre el dashboard, que es la pantalla donde vive todo lo de esta sección.
Dentro: New Project, después GitHub repo. Busca el repositorio de tu agente y dale Deploy Now.
Si tu cuenta todavía no tiene GitHub enlazado, Railway te lo pide ahí mismo.
La base de datos, primero
Clic derecho en el canvas del proyecto, o el botón Create, y de ahí Database y Add PostgreSQL. Queda como un servicio aparte, al lado del tuyo.
El CLAUDE.md del kit llama New a ese mismo menú: es el mismo camino con otra etiqueta.
Las variables, en tu servicio
Haz clic en TU servicio —el del agente, no el de la base— y entra a Variables. Las seis de abajo van ahí.
Si las cargas en el servicio de PostgreSQL, tu agente no las ve y arranca como si no existieran.
Nada de PORT
Es el único de los seis que consiste en no hacer algo: no agregues una variable PORT. Railway la pone él.
El dominio
Tu servicio, Settings, Networking, Public Networking y ahí Generate Domain. Te queda una dirección del tipo tu-app.up.railway.app.
Si antes creaste un TCP Proxy, el botón no aparece hasta que lo borres.
Verificar
Abre tu dirección en el navegador o corre el comando de aquí abajo. Tiene que contestar ok.
Las seis variables del despliegue
Estas son las que necesita tu agente para funcionar allá arriba. Las de tu .env local no viajan solas: el archivo .env se queda en tu computadora a propósito, y aquí se escriben a mano una por una.
ANTHROPIC_API_KEYLa misma llave de Anthropic que tienes en tu .env local, la que empieza con sk-ant-. No es una nueva.
ANTHROPIC_MODELOpcional, con matizclaude-sonnet-5
Si no la pones, tu agente usa claude-sonnet-5. Las otras dos opciones son claude-opus-5 y claude-haiku-4-5, y lo que cambia entre ellas es lo que te cuesta cada conversación.
WHATSAPP_PROVIDERExactamente una de estas dos palabras, en minúsculas: zernio o meta. La que elegiste al principio. Si falta o va mal escrita, el chequeo de salud contesta error y tu agente no atiende a nadie.
ENVIRONMENTOpcional, con matizproduction
Fuera de Railway el valor por omisión es development. Aquí va production, escrito así, en minúsculas.
DATABASE_URL${{Postgres.DATABASE_URL}}Se escribe tal cual, con las dos llaves de cada lado: es una referencia al servicio de PostgreSQL, no una dirección. Si tu servicio de base quedó con otro nombre, ese nombre va en lugar de Postgres.
ZERNIO_* o META_*Las del proveedor que elegiste, iguales a las de tu .env: con Zernio, ZERNIO_API_KEY y ZERNIO_WEBHOOK_SECRET; con Meta, META_ACCESS_TOKEN, META_PHONE_NUMBER_ID, META_VERIFY_TOKEN y META_APP_SECRET. El secreto del webhook y el verify token los inventaste tú: aquí va el mismo valor exacto, no uno nuevo.
Las tres que muerden
Si te saltas la base
Arranca igual, y se olvida de todos cada vez que despliegas
Sin DATABASE_URL tu agente no falla: cae a SQLite dentro del contenedor. Y ese disco es efímero. Cada redespliegue —cada push, cada cambio de variable— borra el historial de todas las conversaciones, y tus clientes vuelven a empezar de cero contigo.
La otra mitad: Railway no copia sola la URL de la base. Hay que escribir la referencia con las llaves dobles, ${{Postgres.DATABASE_URL}}, y si tu servicio de base quedó con otro nombre, ese nombre va en lugar de Postgres.
Lo que Railway no hace solo
Dos cosas que parecen automáticas y no lo son
El dominio no se genera solo. Railway despliega y no te da dirección hasta que se la pides: tu servicio, Settings, Networking, Public Networking, Generate Domain.
Agregar o cambiar una variable tampoco la aplica. Queda como staged changes, en espera, hasta que revisas el cambio y despliegas. Si cambiaste una variable y tu agente sigue comportándose igual que antes, casi siempre es esto.
No agregues PORT
La variable que rompe el despliegue por estar de más
Railway inyecta PORT cuando arranca el contenedor, y el Dockerfile lo respeta a propósito: el CMD va en forma shell para que ${PORT:-8000} se expanda en ese momento y no antes.
Si la fijas tú en 8000, el contenedor arranca, se ve verde en el dashboard y nunca recibe tráfico.
Comprobar que tu agente está vivo en internet
curl https://tu-app.up.railway.app/Cambia tu-app por el dominio que te dio Railway. Si en vez de ok te contesta degradado o error, no lo adivines: el diagnóstico se lee igual que en local, y ahí está qué significa cada estado y en qué campo viene el detalle.
Prompt 06 · De tu repositorio a Railway
Claude Code revisa el repositorio antes de que abras Railway y después te dicta los clics con el nombre literal de cada botón.
Voy a subir mi agente a Railway. Prepara tú el repositorio y después díctame los clics con el nombre de cada botón.
CONTEXTO:
- Mi agente ya está en MI repositorio de GitHub y corre en local.
- Railway construye la imagen en sus servidores. No tengo Docker instalado.
- Railway inyecta la variable PORT.
- Mi repositorio: [PEGA AQUÍ la URL de tu repositorio]
OBJETIVO:
Que mi agente corra en una dirección pública de Railway, con PostgreSQL conectado y el chequeo de salud contestando "ok".
QUÉ HACER, EN ESTE ORDEN:
1. Antes de que yo abra Railway, revisa mi repositorio:
- que el CMD del Dockerfile use ${PORT:-8000} en forma shell y no un 8000 fijo;
- que requirements.txt diga sqlalchemy[asyncio]>=2.0.52 y traiga asyncpg>=0.31.0;
- que .env NO esté subido: `git ls-files | grep -c "^\.env$"`.
2. Si corregiste algo, haz commit y push a main.
3. Dicta los clics, uno por línea, con el nombre literal del botón: crear el proyecto, agregar PostgreSQL ANTES que las variables, cargarlas en MI servicio, generar el dominio y verificar.
4. Dame la lista de variables, una por línea, con su valor. Los pego yo en Railway.
5. Cuando te avise que terminé, corre tú el curl a mi dirección y dime qué contestó.
RESTRICCIONES DURAS:
- NO agregues ni me hagas agregar una variable PORT.
- NO escribas la cadena de conexión de PostgreSQL a mano: en DATABASE_URL va la referencia ${{Postgres.DATABASE_URL}}, tal cual.
- NO me dejes saltarme PostgreSQL "por ahora".
- NO copies valores de mi .env dentro de ningún archivo del repo.
- NO me pidas que instale Docker.
CRITERIO DE ACEPTACIÓN, compruébalo tú:
- `curl https://<mi-dominio>/` devuelve "status":"ok".
- En la lista de variables que me diste no aparece PORT.
- DATABASE_URL es la referencia con llaves dobles, no una cadena postgresql:// a mano.
QUÉ REPORTAR AL FINAL:
Qué tocaste en el repositorio y por qué, la lista de variables como quedó, mi dirección pública y el curl en una línea.Hasta aquí llegan los clics de este proyecto. Ponerle tu propio dominio, tener un entorno de pruebas aparte del que ven tus clientes, cambiar variables por entorno, deshacer un despliegue que salió mal o dejar que cada push se publique solo es otro tema y tiene su guía: All Deploy. Ahí está eso, y lo mismo cuando el destino no es Railway.
12 · el webhook
El webhook: decirle a WhatsApp a dónde avisar
Un webhook es la dirección a la que tu proveedor toca el timbre cuando entra un mensaje. Nada más que eso. Tu agente ya está en internet y ya sabe contestar, pero todavía no hay nadie que le avise: el mensaje llega al proveedor y ahí se queda.
Por eso este paso va al final y no antes: hace falta la URL pública, la que quedó cuando generaste el dominio. La que se pega en el panel es esa misma con /webhook al final, y ese pedacito es de los que se olvidan: sin él el aviso llega a la raíz, que solo sabe decir si tu agente está vivo.
Con Zernio, clic por clic
Cinco clics en el panel donde ya sacaste la llave. Ten a mano la URL de tu servicio y el secreto que inventaste.
Webhooks → Create webhook
En el panel de Zernio, la sección Webhooks, y ahí el botón Create webhook.
La URL, con /webhook al final
Pega la URL pública de tu servicio y agrégale /webhook. Queda del estilo https://tu-app.up.railway.app/webhook.
Secret: el mismo texto, carácter por carácter
En la casilla Secret va exactamente el valor que cargaste en ZERNIO_WEBHOOK_SECRET. Si no coinciden, la firma no cuadra y tu servidor rechaza cada aviso con un 401.
Marca el evento message.received
Es el único que necesitas: es el aviso de que entró un mensaje.
Guardar, y después Send test
Guarda el webhook y usa el botón Send test. Si tu servidor contesta 200, el circuito está armado.
Estos nombres de pantalla salen de la documentación del propio kit. Si en tu panel alguna etiqueta se llama distinto, el orden es el mismo: crear el webhook, pegar la URL, poner el secreto, marcar el evento.
Con Meta, clic por clic
El mismo trámite en la consola de desarrolladores, con un nombre distinto para cada cosa.
WhatsApp → Configuration
En developers.facebook.com, dentro de tu app: el producto WhatsApp, y ahí Configuration.
Callback URL
La URL pública de tu servicio con /webhook al final, igual que en el caso de arriba.
Verify Token: el mismo texto exacto
El valor que pusiste en META_VERIFY_TOKEN. Meta se lo manda una sola vez a tu servidor para comprobar que esa URL es tuya.
Suscríbete al campo messages
En la lista de campos del webhook, marca messages. Es el que trae lo que escriben tus clientes.
Guardar
Guarda y espera a que Meta marque la URL como verificada.
Si el verify token no coincide, tu servidor responde 403 a propósito. Contestarle 200 le haría creer a Meta que la URL quedó verificada sin estarlo, y después no llegaría ni un mensaje.
Qué hace tu agente con cada aviso, y por qué
El aviso no se atiende de frente. Pasa por dos filtros antes de que nadie lea el mensaje, y la respuesta al proveedor sale antes que la respuesta al cliente. Cada una de las tres decisiones tapa una falla distinta.
por qué revisa antes de leer
Primero la firma, después el mensaje
Cada aviso viene firmado. Tu agente calcula la firma que debería tener y, si no cuadra, tira el aviso sin leerlo: así nadie que conozca tu URL puede inventarle mensajes.
Esa revisión solo ocurre si cargaste el secreto. Lo de abajo es exactamente eso.
el aviso que llega dos veces
Ignora los repetidos
Cada mensaje trae su identificador. Si el mismo llega dos veces, se responde una sola vez.
Llega dos veces más seguido de lo que parece: la entrega del proveedor es de las que prefieren repetir un aviso antes que perderlo.
por qué contesta antes de pensar
Contesta «recibido» de inmediato y piensa después
Lo primero que hace tu agente al recibir un aviso es decirle al proveedor que lo recibió. Recién después busca el historial, le pregunta a Claude y manda la respuesta por WhatsApp.
No es capricho: el proveedor espera un 2xx en unos cinco segundos, y pensar tarda más que eso. Si no lo recibe, reintenta el mismo mensaje hasta siete veces.
Y siete reintentos no son siete avisos perdidos en el aire: son siete respuestas. Tu cliente vería siete veces lo mismo.
el que se deja vacío y no avisa
Sin secreto, la puerta queda abierta
Si ZERNIO_WEBHOOK_SECRET queda vacío —o META_APP_SECRET, si fuiste por Meta—, la verificación de firma devuelve verdadero y deja pasar todo lo que llegue a tu URL.
Lo que lo hace traicionero: tu agente arranca igual, el chequeo de salud no mira esto, y lo único que avisa es una línea en los registros. Viene vacío de fábrica para que puedas probar sin trabarte.
Cárgalo antes de atender clientes de verdad, y pon el mismo valor en el alta del webhook. Mientras esté vacío, cualquiera que sepa tu URL puede inyectarle mensajes a tu agente.
Cómo se ve cuando ya quedó
Que el alta se haya guardado no prueba nada. Esto sí: le escribes al número de tu agente desde tu propio celular y las tres cosas pasan una detrás de otra.
el circuito cerrado
tú, desde tu celular → Hola, ¿a qué hora abren? el registro del servidor → POST /webhook 200 · mensaje recibido tu agente, en WhatsApp → Abrimos de lunes a sábado, de 9 a 19.
Prompt 07 · Dar de alta el webhook y comprobarlo de verdad
Empieza mirando el chequeo de salud y se para ahí si tu agente todavía no puede responder. No te dice que terminó hasta que la respuesta llegue a tu celular.
Da de alta el webhook de mi agente y no me digas que terminaste hasta que me llegue una respuesta al celular. CONTEXTO: - Mi agente ya está desplegado. Su URL pública es: [PEGA AQUÍ la URL, por ejemplo https://mi-app.up.railway.app] - Mi proveedor es [ESCRIBE AQUÍ: zernio o meta]. - El secreto del webhook ya está cargado en las variables de mi servicio: ZERNIO_WEBHOOK_SECRET con Zernio, META_VERIFY_TOKEN y META_APP_SECRET con Meta. OBJETIVO: Que yo escriba desde mi celular y me conteste mi agente. QUÉ HACER, EN ESTE ORDEN: 1. Primero `curl <mi URL>/` y dime qué dice "status". Si dice "degradado" o "error", PÁRATE AHÍ y dime qué variable corregir: dar de alta un webhook contra un agente que no puede responder no sirve de nada. 2. Si dice "ok", dicta los clics de mi panel uno por línea, con la URL exacta que tengo que pegar: la mía con /webhook al final. 3. Recuérdame que el secreto del panel tiene que ser el mismo texto exacto que la variable del servidor. 4. Con Zernio: evento message.received, guardar, botón Send test, y dime qué código tiene que contestar mi servidor. Con Meta: suscribirme al campo messages y guardar. 5. Pídeme que le escriba al número desde mi celular y espera a que yo te diga qué pasó. RESTRICCIONES DURAS: - NO me digas que deje el secreto vacío "para probar". - NO des de alta el webhook contra localhost ni contra una URL de prueba. - NO me digas que quedó listo porque el alta se guardó. Solo cuenta si llegó la respuesta a mi celular. CRITERIO DE ACEPTACIÓN, compruébalo tú: - `curl <mi URL>/` devuelve "status":"ok". - Yo te confirmo que escribí desde el celular y llegó la respuesta. QUÉ REPORTAR AL FINAL: La URL que quedó dada de alta, el evento o campo al que me suscribí, y si llegó la respuesta al celular.
hasta aquí el montaje
Ya está: tu número contesta solo
Cuando esa respuesta llega a tu celular, terminaste de construir. Tu agente vive en internet, atiende su propio número y guarda el historial de cada conversación en la base que le agregaste en Railway.
Queda una sola condición antes de apuntarle clientes de verdad, y es la de aquí arriba: que el secreto del webhook no se haya quedado vacío.
Las cuatro secciones que siguen ya no construyen nada. Son qué mirar cuando algo falla, cómo cambiarle el tono o los precios, cuánto te va a costar al mes y las dudas que suelen quedar.
Y una cosa que se resuelve sola: tu agente siempre le contesta a quien le escribió, así que nunca sale de la ventana de 24 horas que impone WhatsApp — de qué va esa ventana, en la sección donde eliges proveedor.
13 · cuando algo falla
Cuando algo falla: síntoma, causa, arreglo
Esta sección es una tabla de búsqueda, no una lectura. Cuando algo deja de funcionar, el orden que ahorra horas es siempre el mismo: primero le preguntas a tu agente cómo está, y solo después buscas tu síntoma en las fichas de abajo.
Ninguna de estas dieciocho fallas llega con un aviso claro. Casi todas se ven como silencio: el número no contesta, la respuesta no sale, el historial desapareció. Por eso cada ficha empieza por lo que ves en pantalla, no por la causa.
empieza siempre por aquí
Antes de tocar nada, pregunta el chequeo de salud
Un curl a la raíz de tu URL y lees el status: si dice error, el motivo está en detalle; si dice degradado, está en conexion.detalle. Esa sola línea te dice cuál de las fichas de abajo te toca, y te evita cambiar cosas al azar.
Los tres estados, y por qué los tres contestan 200, están en probarlo en tu compu.
El diagnóstico de un solo comando
curl https://tu-app.up.railway.app/Las dieciocho fallas de este kit
Busca por la primera línea de cada ficha: es exactamente lo que estás viendo. La causa y el arreglo vienen debajo, en ese orden.
01 · git
El remote heredado
- el síntoma
- git remote add origin responde: error: remote origin already exists.
- la causa
- Estás dentro del clon del kit y su origin apunta al repo ajeno.
- el arreglo
- git remote remove origin y después git remote add origin con el tuyo. Nunca git init aquí.
02 · git
El repo subió casi vacío
- el síntoma
- Subiste a GitHub y el repo se ve casi vacío; Railway construye y falla.
- la causa
- El .gitignore del kit excluye agent/, config/, tests/, requirements.txt, Dockerfile y docker-compose.yml.
- el arreglo
- Reemplaza el .gitignore antes del push. Comprueba con git ls-files: tienen que aparecer agent/main.py y Dockerfile.
03 · salud
Dice degradado
- el síntoma
- El chequeo de salud dice status degradado.
- la causa
- El servidor arrancó pero el chequeo de conexión con el proveedor falló: va a recibir mensajes y no va a poder contestarlos.
- el arreglo
- Lee conexion.detalle, que nombra la variable que falta o la credencial rechazada, y corrígela en Variables.
04 · salud
Dice error
- el síntoma
- El chequeo de salud dice status error.
- la causa
- Ni siquiera se pudo armar el proveedor: WHATSAPP_PROVIDER falta, está vacía o mal escrita.
- el arreglo
- Lee detalle en la raíz y pon WHATSAPP_PROVIDER=zernio o =meta, exactamente en minúsculas.
05 · webhook
Dice ok y aun así nadie recibe respuesta
- el síntoma
- El chequeo de salud dice ok pero nadie recibe respuesta.
- la causa
- El webhook no está dado de alta, apunta a otra URL, le falta el /webhook al final, o no marcaste message.received.
- el arreglo
- Vuelve a la sección 12. En Zernio usa Send test: si tu servidor responde 200, el circuito está.
06 · envío
El mensaje entra y la respuesta no sale
- el síntoma
- Llega el mensaje, el registro lo muestra, y la respuesta nunca sale.
- la causa
- La llave del proveedor es inválida o la URL de la API quedó apuntando a un lugar inexistente.
- el arreglo
- Si tienes ZERNIO_BASE_URL declarada y vacía en tu .env, bórrala o coméntala: una URL vacía no tiene esquema https:// y el envío falla antes de salir a la red.
07 · duplicados
Tus clientes reciben lo mismo varias veces
- el síntoma
- Tus clientes reciben la misma respuesta varias veces.
- la causa
- El webhook no está contestando 2xx en 5 segundos y el proveedor reintenta hasta 7 veces.
- el arreglo
- Pídele a Claude Code que verifique que no haya trabajo pesado antes de devolver la respuesta. La respuesta va primero, el trabajo después.
08 · firma
Cualquiera le puede inyectar mensajes
- el síntoma
- Cualquiera que sepa tu URL le puede inyectar mensajes a tu agente.
- la causa
- ZERNIO_WEBHOOK_SECRET (o META_APP_SECRET) está vacío: la verificación de firma devuelve verdadero y solo avisa en los registros.
- el arreglo
- Carga el secreto del webhook en Variables y pon el mismo valor en el alta del webhook. Redespliega.
09 · memoria
Se olvida de todos sus clientes
- el síntoma
- Tu agente se olvida de todos sus clientes cada vez que despliegas.
- la causa
- No cargaste DATABASE_URL en Railway: cayó a SQLite dentro del contenedor, y ese disco es efímero.
- el arreglo
- Agrega PostgreSQL y escribe DATABASE_URL = ${{Postgres.DATABASE_URL}} en las Variables de tu servicio.
10 · Railway
Desplegó y la URL no responde
- el síntoma
- Railway dice que desplegó pero la URL no responde nada.
- la causa
- El servicio no tiene dominio público: Railway no lo pone solo.
- el arreglo
- Tu servicio, Settings, Networking, Public Networking, Generate Domain.
11 · Railway
Cambiaste una variable y no pasó nada
- el síntoma
- Cambiaste una variable en Railway y no pasó nada.
- la causa
- Los cambios de variables quedan como staged changes hasta que los revisas y despliegas.
- el arreglo
- Aplica el cambio desde el dashboard y espera el redespliegue.
12 · Railway
Arranca y nunca le llega tráfico
- el síntoma
- El contenedor arranca en Railway pero nunca le llega tráfico.
- la causa
- Fijaste PORT a mano.
- el arreglo
- Borra la variable PORT. El Dockerfile usa ${PORT:-8000} en forma shell justamente para esto.
13 · arranque
Muere al arrancar con greenlet_spawn
- el síntoma
- Tu agente muere al arrancar con un error de greenlet_spawn.
- la causa
- Falta el extra [asyncio] de SQLAlchemy.
- el arreglo
- En requirements.txt tiene que decir sqlalchemy[asyncio]>=2.0.52, no sqlalchemy a secas.
14 · arranque
Agregaste PostgreSQL y ya no arranca
- el síntoma
- Agregaste PostgreSQL y tu agente no arranca.
- la causa
- Falta asyncpg: la memoria reescribe la URL a postgresql+asyncpg://.
- el arreglo
- asyncpg>=0.31.0 en requirements.txt, aunque en local uses SQLite.
15 · Meta
Verificó la URL y después nada
- el síntoma
- Meta dice que verificó la URL y después no llega nada.
- la causa
- El verify token no coincidía y el servidor devolvió 403 a propósito.
- el arreglo
- Que META_VERIFY_TOKEN sea el mismo texto exacto en Variables y en la casilla de Meta. Reintenta la verificación.
16 · respuestas
Se cortan a la mitad
- el síntoma
- Las respuestas se cortan a la mitad.
- la causa
- ANTHROPIC_MAX_TOKENS demasiado bajo: el razonamiento interno del modelo también cuenta contra ese tope.
- el arreglo
- Súbelo o déjalo en el default de 4096.
17 · instalación
start.sh se corta en el paso 2
- el síntoma
- bash start.sh se corta en el paso 2.
- la causa
- Claude Code no está instalado o no quedó en el PATH.
- el arreglo
- npm install -g @anthropic-ai/claude-code, corre claude una vez para autenticarte, y vuelve a bash start.sh.
18 · contenido
Inventa un precio
- el síntoma
- Tu agente inventa un precio.
- la causa
- Ese dato no está en config/prompts.yaml ni en knowledge/.
- el arreglo
- Pon el precio en un .txt dentro de knowledge/ y pídele a Claude Code que regenere el prompt. Si tu agente ya está en línea, que además haga el push: hasta entonces el cambio vive solo en tu computadora.
La segunda herramienta: los registros
En desarrollo tu agente escribe su propio detalle en los registros y deja fuera el ruido de las librerías, a propósito: ahí se lee lo que hizo tu agente con tu mensaje, no lo que hizo Python por debajo.
Prompt 08 · Diagnostica en orden, sin que yo lea registros
Pégaselo a Claude Code con tu URL y tu síntoma. Va del estado a la causa sin saltarse pasos, y termina dejándote una sola cosa por hacer.
Mi agente de WhatsApp no hace lo que debería. Diagnostícalo tú, en orden, sin que yo lea registros. CONTEXTO: - Mi agente está desplegado y su URL pública es [PEGA AQUÍ https://tu-app.up.railway.app] - Mi proveedor es [ESCRIBE AQUÍ: zernio o meta]. - Lo que yo veo es [ESCRIBE AQUÍ el síntoma, con tus palabras]. - No programo. Resuélvelo tú y explícame en español. OBJETIVO: Encontrar la causa, arreglarla y dejarme una sola cosa por hacer. QUÉ HACER, EN ESTE ORDEN: 1. curl a la raíz y clasifica el status. "error": la causa es WHATSAPP_PROVIDER, en detalle, para ahí. "degradado": está en conexion.detalle, para ahí. "ok": sigue bajando. 2. No llega nada: revisa el alta del webhook, la URL terminada en /webhook y el evento message.received marcado. 3. Llega y no sale respuesta: credenciales de envío del proveedor y si ZERNIO_BASE_URL quedó declarada y vacía. 4. Contesta varias veces: que devuelva 2xx antes de trabajar y descarte por id los avisos repetidos. 5. Se olvida de conversaciones viejas: DATABASE_URL. 6. Inventa precios: config/prompts.yaml y knowledge/. 7. Cambié una variable en Railway y no pasó nada: staged changes. RESTRICCIONES DURAS: - NO me digas "responde 200, está todo bien": responde 200 aun degradado, a propósito. - NO cambies el modelo ni el prompt a ver si así funciona. - NO borres la base de datos ni el archivo .env. - NO me digas que los duplicados se quitan borrando webhooks: el aviso repetido ya se descarta por su id. Lo que sí los provoca es no contestar 2xx en cinco segundos. - NO me reportes una causa sin comprobar los pasos anteriores. CRITERIO DE ACEPTACIÓN, compruébalo tú: - curl a la raíz devuelve "status":"ok". - Le escribo al número y llega una sola respuesta. QUÉ REPORTAR AL FINAL: Tres cosas y nada más: cuál era la causa, qué cambiaste tú, y qué tengo que hacer yo.
Si tu síntoma es de Railway y lo que te falta es el camino del menú, los clics están en la sección 11; si es el alta del webhook, en la 12. Y si lo que cambiaste fue un archivo y no una variable, el push que lo pone en línea está en personalizarlo después. Aquí van los síntomas, no el paso a paso.
14 · personalizarlo
Personalizarlo después, y el límite que nadie te dice
Tu agente no queda congelado el día que lo pones en línea. Cambiarle el tono, enseñarle un precio nuevo o contarle de un servicio que acabas de abrir es cuestión de minutos, y no se toca código: se tocan dos archivos de texto.
Lo que sí cuesta trabajo es otra cosa, y conviene saberla antes de prometérsela a un cliente.
Lo fácil, que de verdad es fácil
Abres la carpeta de tu agente en la terminal, arrancas Claude Code y se lo pides en español, con tus palabras. Estas tres cosas entran por ahí:
- El tono: que salude más corto, que hable de tú, que deje de usar signos de admiración.
- Información nueva: un precio que subió, el horario de los sábados, un servicio que acabas de abrir.
- Lo que no debe decir: que no prometa tiempos de entrega, que no negocie descuentos, que no opine de la competencia.
Todo eso vive en config/prompts.yaml, que es la personalidad, y en config/business.yaml, que son los datos de tu negocio. Son dos archivos de texto: pídele a Claude Code que los edite y que te diga en español qué cambió.
el paso que se olvida
Lo que cambias en tu computadora no llega solo a tu número
Editar esos archivos cambia el agente de tu computadora, no el que está atendiendo. El que atiende corre en Railway, y Railway construye desde tu repositorio de GitHub: mientras el cambio no llegue ahí, tu cliente sigue recibiendo el precio viejo, y nada falla ni te avisa.
Así que pídele a Claude Code, en la misma sentada, que haga el commit y el push a main. Ese push es el que dispara el redespliegue, y cuando termina, tu número ya contesta con lo nuevo.
Los archivos de knowledge/ son la excepción: siguen sin salir de tu máquina. Lo que viaja es el prompt del sistema ya armado, en config/prompts.yaml. Por eso, cuando metas un precio nuevo ahí, el pedido va completo: guárdalo, regenera el prompt, y haz el push.
el límite real
agent/tools.py se escribe, y hoy nadie lo llama
Durante la entrevista, Claude Code genera agent/tools.py con tres funciones listas para usarse y con un bloque de funciones sugeridas según para qué dijiste que querías el agente:
- Listas: cargar_info_negocio(), obtener_horario() y buscar_en_knowledge().
- Si dijiste agendar citas: obtener_slots_disponibles, reservar_cita, cancelar_cita.
- Si dijiste pedidos: agregar_al_carrito, ver_carrito, confirmar_pedido.
- Si dijiste leads o ventas: registrar_lead, calificar_lead, escalar_a_vendedor.
- Si dijiste soporte: crear_ticket, consultar_ticket, escalar_ticket.
Pero ningún módulo importa ese archivo y nadie le pasa tools= a la API. O sea: las funciones están escritas y nunca se ejecutan.
Conectarlas al ciclo de uso de herramientas es un trabajo aparte. No es imposible ni es larguísimo, pero no sale de la entrevista: sale del primer prompt de aquí abajo.
Entonces por qué sí se sabe tu menú
Porque la información de tu negocio no le llega por herramientas: le llega por el prompt del sistema, que se arma con config/prompts.yaml, config/business.yaml y lo que dejaste en knowledge/. El agente lo lee completo en cada turno, y por eso contesta precios, horarios y condiciones sin ejecutar nada.
La frontera es esa: para contestar no hace falta nada de tools.py; hace falta para hacer. Conversar, entender y dejar los datos en el historial ya lo hace hoy. Agendar, cobrar o apartar stock no, hasta que alguien lo cablee.
Qué cuesta cada cambio
La misma pregunta contestada por columnas: dónde se toca, y cuánto trabajo es de verdad.
Cambiar el tono
- Dónde se toca
- config/prompts.yaml
- Cuánto cuesta en trabajo
- Minutos. Se lo pides a Claude Code en español, lo reescribe él, y el push lo pone en línea.
Agregar información: un precio, un horario, un servicio
- Dónde se toca
- config/business.yaml y un .txt en knowledge/
- Cuánto cuesta en trabajo
- Minutos. Lo que pongas en knowledge/ entra literal al prompt, sin resumir, y viaja con el push.
Que ejecute una acción de verdad: agendar, cobrar, apartar stock
- Dónde se toca
- agent/tools.py y el ciclo de uso de herramientas, dentro de agent/
- Cuánto cuesta en trabajo
- Un trabajo aparte, con su prueba. Es el primer prompt de aquí abajo.
Cambiar de proveedor
- Dónde se toca
- El adaptador del proveedor, WHATSAPP_PROVIDER y el alta del webhook
- Cuánto cuesta en trabajo
- Una sentada. El adaptador lo genera Claude Code; los clics del panel los das tú.
Un segundo agente para otro negocio
- Dónde se toca
- Otra carpeta, otra entrevista, otro número
- Cuánto cuesta en trabajo
- Se monta aparte y no toca al que ya está corriendo.
| Lo que quieres | Dónde se toca | Cuánto cuesta en trabajo |
|---|---|---|
| Cambiar el tono | config/prompts.yaml | Minutos. Se lo pides a Claude Code en español, lo reescribe él, y el push lo pone en línea. |
| Agregar información: un precio, un horario, un servicio | config/business.yaml y un .txt en knowledge/ | Minutos. Lo que pongas en knowledge/ entra literal al prompt, sin resumir, y viaja con el push. |
| Que ejecute una acción de verdad: agendar, cobrar, apartar stock | agent/tools.py y el ciclo de uso de herramientas, dentro de agent/ | Un trabajo aparte, con su prueba. Es el primer prompt de aquí abajo. |
| Cambiar de proveedor | El adaptador del proveedor, WHATSAPP_PROVIDER y el alta del webhook | Una sentada. El adaptador lo genera Claude Code; los clics del panel los das tú. |
| Un segundo agente para otro negocio | Otra carpeta, otra entrevista, otro número | Se monta aparte y no toca al que ya está corriendo. |
El tope de la respuesta también cuenta lo que el modelo piensa
ANTHROPIC_MAX_TOKENS viene comentada en el .env y su valor por default es 4096. Es el techo de lo que el agente puede escribir de una sola vez.
En los modelos actuales, el razonamiento interno cuenta contra ese mismo tope. No es solo lo que ve el cliente.
Por eso, si lo dejas con el margen justo, una pregunta que exija pensar deja al agente sin espacio para contestar y la respuesta sale cortada a la mitad. Si lo vas a mover, muévelo con holgura: 4096 aguanta bien una conversación de WhatsApp.
Los tres prompts para pegar
Prompt 09 · Cablear una herramienta de verdad
Conecta una función de agent/tools.py al ciclo de uso de herramientas, con una prueba que falla si la función no se llama.
Quiero que una función de agent/tools.py se ejecute de verdad. Hazlo tú de punta a punta. CONTEXTO: - Mi agente ya corre y contesta por WhatsApp. - agent/tools.py existe, con sus funciones ya escritas. Que yo sepa, ningún módulo lo importa y ninguna llamada a la API lleva tools=, así que hoy no se ejecuta ninguna. - La acción que quiero que ejecute: [ESCRIBE AQUÍ: por ejemplo, reservar una cita] - El sistema donde tiene que quedar registrada: [ESCRIBE AQUÍ: por ejemplo, mi calendario de Google] OBJETIVO: Que esa acción quede hecha en el otro sistema cuando un cliente la pide por WhatsApp, y que el agente solo la confirme si quedó hecha. QUÉ HACER, EN ESTE ORDEN: 1. Revisa agent/ y confírmame, con archivo y línea, que hoy nadie importa tools.py y que ninguna llamada lleva tools=. Si ya estaba cableado, dímelo y no toques nada. 2. Escribe la función en agent/tools.py y atrapa sus errores. 3. Decláramela como herramienta, con su esquema de entrada. 4. Implementa el ciclo completo: manda las herramientas en la llamada, ejecuta la que el modelo pida, devuélvele el resultado y deja que redacte la respuesta final. 5. Escribe una prueba en tests/ que FALLE si la función no se llama. 6. Ajusta config/prompts.yaml para que el agente nunca confirme algo que la herramienta no devolvió como hecho. RESTRICCIONES DURAS: - Si la herramienta devuelve error, el agente NO confirma nada: dice que hubo un problema y ofrece pasar con una persona. - NUNCA inventes datos que salen del otro sistema: horarios, folios, precios o disponibilidad. - NINGUNA credencial en el código. Todas por variable de entorno. - NO conectes contra mi sistema de producción sin avisarme antes. - NO toques la verificación de firma, la deduplicación por id, ni el hecho de que el servidor contesta 200 antes de ponerse a trabajar. Si rompes eso, el proveedor reintenta hasta siete veces y mis clientes reciben la misma respuesta siete veces. CRITERIO DE ACEPTACIÓN, compruébalo tú: - La prueba nueva pasa, y vuelve a fallar si desconectas la llamada. - python tests/test_local.py pasa. - curl http://localhost:8000/ contesta "status":"ok". - Un error simulado del otro sistema termina sin confirmación. QUÉ REPORTAR AL FINAL: Qué archivos tocaste, cómo se llama la herramienta, qué contesta si falla, y el resultado de cada criterio en una línea.
El que sigue es para otra cosa, y hay quien no lo abre nunca: cambiar de proveedor. Como en la entrevista se generó solo el adaptador del que elegiste, pasar de Zernio a Meta —o al revés— es escribir el otro desde cero. Guárdalo para el día que te mudes.
Prompt 10 · Cambiar de proveedor sin perder nada
Genera el adaptador nuevo con la misma interfaz, recoge las credenciales una por una y deja intactos tu prompt y tu historial.
Quiero cambiar de proveedor de WhatsApp. Hazlo tú de punta a punta. CONTEXTO: - Mi agente ya corre. El proveedor que uso hoy: [ESCRIBE AQUÍ: zernio o meta] - El proveedor al que me quiero pasar: [ESCRIBE AQUÍ: zernio o meta] - En la entrevista se generó SOLO el adaptador del que elegí; el del proveedor nuevo no existe todavía. - Esto cambia por dónde entran y salen los mensajes, no lo que mi agente dice ni lo que ya conversó. OBJETIVO: Que el agente reciba y responda por el proveedor nuevo sin perder una sola conversación ni una línea de mi prompt. QUÉ HACER, EN ESTE ORDEN: 1. Lee el adaptador que ya existe y anota su interfaz: qué métodos expone, qué recibe y qué devuelve. 2. Escribe el adaptador nuevo con esa MISMA interfaz. El resto del agente no se debe enterar del cambio. 3. Pídeme las credenciales del proveedor nuevo UNA POR UNA, diciéndome de qué pantalla sale cada una, y escríbelas en el .env. 4. Cambia WHATSAPP_PROVIDER al valor nuevo, en minúsculas. 5. Cuando el nuevo ya esté probado, borra el adaptador viejo y sus variables del .env. 6. Explícame en español qué cambia al dar de alta el webhook: la URL sigue terminando en /webhook, pero la firma viaja distinto. En Zernio llega en el encabezado X-Zernio-Signature, con el hex en minúsculas. En Meta llega en X-Hub-Signature-256, con el prefijo sha256= por delante. RESTRICCIONES DURAS: - NO toques config/prompts.yaml, config/business.yaml ni knowledge/. - NO borres la base de datos ni el historial de conversaciones. - NO dejes los dos adaptadores activos al mismo tiempo. - NO des de baja el webhook viejo hasta que el nuevo esté probado con un mensaje real. - NINGUNA credencial en el código. CRITERIO DE ACEPTACIÓN, compruébalo tú: - curl http://localhost:8000/ contesta "status":"ok". - git ls-files | grep -c "^\.env$" devuelve 0. - config/prompts.yaml y config/business.yaml quedaron sin cambios. QUÉ REPORTAR AL FINAL: Qué proveedor quedó activo, qué archivos creaste y borraste, los pasos que me tocan a mí en el panel del proveedor nuevo, y el resultado de cada criterio en una línea.
El último es el de todos los días. Cada vez que suba un precio, abras los sábados o quieras que salude más corto, es este el que copias, y no hace falta tocar nada de lo anterior.
Prompt 11 · Afinar el tono y enseñarle lo que falta
Ajusta prompts.yaml y business.yaml, mete los precios literales en knowledge/ y lo prueba con tres preguntas.
Quiero cambiarle el tono a mi agente y enseñarle lo que le falta. Hazlo tú. CONTEXTO: - Mi agente ya corre. Su personalidad vive en config/prompts.yaml y los datos de mi negocio en config/business.yaml. - Lo que guardo en knowledge/ se incorpora al prompt del sistema. - El tono que quiero: [ESCRIBE AQUÍ: por ejemplo, más corto, de tú y sin tanto adorno] - Lo que hoy no sabe y debería saber: [ESCRIBE AQUÍ: por ejemplo, la lista de precios nueva y el horario de los sábados] OBJETIVO: Que conteste con mi tono y con mis datos nuevos, y que siga diciendo que no sabe cuando no sabe. QUÉ HACER, EN ESTE ORDEN: 1. Ajusta el tono en config/prompts.yaml y los datos fijos en config/business.yaml. 2. Guarda los precios y los horarios como texto plano en knowledge/, un archivo por tema, e incorpóralos LITERALES al prompt: precios, horarios y condiciones no se resumen ni se redondean. 3. Deja escrita la regla de que, si no sabe algo, lo dice y ofrece pasar con una persona en vez de aproximar. 4. Corre tres pruebas y muéstrame las respuestas completas: una pregunta sobre el dato nuevo, una que le intente sacar un descuento, y una sobre algo que el agente no sabe. RESTRICCIONES DURAS: - NO subas nada de knowledge/ a GitHub: son datos de mi negocio. - NO resumas ni redondees precios, horarios ni condiciones. - NO inventes un dato que no esté en knowledge/ ni en config/. - NO toques agent/ ni el .env. CRITERIO DE ACEPTACIÓN, compruébalo tú: - git check-ignore imprime la ruta de cada archivo de knowledge/. - git ls-files knowledge/ muestra solo knowledge/.gitkeep. - python tests/test_local.py pasa. - En la prueba del descuento el agente no concede ninguno. QUÉ REPORTAR AL FINAL: Qué archivos tocaste, qué guardaste en knowledge/, las tres respuestas de prueba tal cual salieron, y el resultado de cada criterio en una línea.
Y si al final resulta que lo que necesitas es que además califique al cliente, agende y escriba en tu CRM, no lo cablees pieza por pieza: eso ya está resuelto en el AgentKit que cierra ventas.
15 · los números
Lo que cuesta de verdad, con la fecha en que se midió
Cada número de aquí abajo va con el día en que se consultó, y eso no es un adorno: estos precios se mueven, y el que más rápido se mueve es el de Meta. Si estás leyendo esto meses después, la fila de Meta es la primera que tienes que volver a mirar.
Las tarifas de Anthropic y los planes de Railway se verificaron el 17 de septiembre de 2026. Lo de WhatsApp con Meta trae una fecha más vieja, de agosto, porque esa es la fuente que hay.
Lo que te van a cobrar, pieza por pieza
El kit
- Cuánto
- Gratis. Licencia MIT
- Consultado el
- 17-sep-2026
Railway · Trial
- Cuánto
- Un grant único de 5 USD. 1 GB de RAM, vCPU compartida y 5 servicios por proyecto
- Consultado el
- 17-sep-2026
Railway · Free
- Cuánto
- 0 USD al mes, con 1 USD de crédito de uso cada mes
- Consultado el
- 17-sep-2026
Railway · Hobby
- Cuánto
- 5 USD al mes, que ya incluyen 5 USD de uso
- Consultado el
- 17-sep-2026
Railway · la letra chica de este proyecto
- Cuánto
- La base de datos es un segundo servicio encendido las 24 horas, y cuenta contra tu uso
- Consultado el
- 17-sep-2026
Anthropic · al mes
- Cuánto
- Con Sonnet 5, 300 conversaciones salen ≈ 13 USD y 1.000 ≈ 44 USD. Con Haiku 4.5, ≈ 7 y ≈ 22 USD
- Consultado el
- 17-sep-2026
WhatsApp con Zernio
- Cuánto
- Las 2 primeras cuentas conectadas son gratis y sin tarjeta. El número de pruebas no cuesta. Un número propio arranca en 3 USD al mes según el país
- Consultado el
- 17-sep-2026
WhatsApp con Meta
- Cuánto
- Si el cliente escribió primero y contestas dentro de las 24 h, hoy ese mensaje no se cobra. Las plantillas sí: por mensaje entregado y por país, del orden de 0,01 USD en India a 0,025 en Estados Unidos
- Consultado el
- 13-ago-2026
| Concepto | Cuánto | Consultado el |
|---|---|---|
| El kit | Gratis. Licencia MIT | 17-sep-2026 |
| Railway · Trial | Un grant único de 5 USD. 1 GB de RAM, vCPU compartida y 5 servicios por proyecto | 17-sep-2026 |
| Railway · Free | 0 USD al mes, con 1 USD de crédito de uso cada mes | 17-sep-2026 |
| Railway · Hobby | 5 USD al mes, que ya incluyen 5 USD de uso | 17-sep-2026 |
| Railway · la letra chica de este proyecto | La base de datos es un segundo servicio encendido las 24 horas, y cuenta contra tu uso | 17-sep-2026 |
| Anthropic · al mes | Con Sonnet 5, 300 conversaciones salen ≈ 13 USD y 1.000 ≈ 44 USD. Con Haiku 4.5, ≈ 7 y ≈ 22 USD | 17-sep-2026 |
| WhatsApp con Zernio | Las 2 primeras cuentas conectadas son gratis y sin tarjeta. El número de pruebas no cuesta. Un número propio arranca en 3 USD al mes según el país | 17-sep-2026 |
| WhatsApp con Meta | Si el cliente escribió primero y contestas dentro de las 24 h, hoy ese mensaje no se cobra. Las plantillas sí: por mensaje entregado y por país, del orden de 0,01 USD en India a 0,025 en Estados Unidos | 13-ago-2026 |
Ninguna de estas filas se inventó aquí: cada una es lo que decía la página de precios del proveedor el día de la tercera columna. Vuelve a comprobarlas antes de presupuestarle a un cliente.
Una línea sobre la ventana de 24 horas, porque es la que hace barata la parte de WhatsApp: mientras el cliente escriba primero y tú contestes dentro de ese día, hoy Meta no cobra esa respuesta, y este agente siempre responde. Cómo funciona y por qué casi nunca sales de ella está donde eliges proveedor.
El único número que puedes bajar tú mismo
El modelo lo eliges con la variable ANTHROPIC_MODEL y se cambia sin tocar nada más. Sonnet 5 es el que viene puesto:
Opus 5 · claude-opus-5
- Entrada / salida por millón
- 5 / 25 USD
- Por conversación de 8 idas y vueltas
- ≈ 0,11 USD
Sonnet 5 · claude-sonnet-5 · el que viene puesto
- Entrada / salida por millón
- 2 / 10 USD
- Por conversación de 8 idas y vueltas
- ≈ 0,04 USD
Haiku 4.5 · claude-haiku-4-5
- Entrada / salida por millón
- 1 / 5 USD
- Por conversación de 8 idas y vueltas
- ≈ 0,02 USD
| Modelo | Entrada / salida por millón | Por conversación de 8 idas y vueltas |
|---|---|---|
| Opus 5 · claude-opus-5 | 5 / 25 USD | ≈ 0,11 USD |
| Sonnet 5 · claude-sonnet-5 · el que viene puesto | 2 / 10 USD | ≈ 0,04 USD |
| Haiku 4.5 · claude-haiku-4-5 | 1 / 5 USD | ≈ 0,02 USD |
La columna de la derecha no es una tarifa, es una cuenta: el volumen que trae el kit son 8 idas y vueltas, un prompt del sistema de unos 1.500 tokens, cerca de 16.000 tokens de entrada y 1.200 de salida. Ese volumen se midió contra el repo el 19 de agosto de 2026 y las tarifas el 17 de septiembre de 2026. Si tu prompt es más largo, tu número es más alto.
las tres cosas que mueven la cuenta
Por qué la factura no se parece a tu cantidad de mensajes
- Tu agente no te cuesta por mensaje, te cuesta por token. En cada turno se le reenvía a Claude el prompt del sistema completo más el historial de esa conversación, así que el mensaje diez cuesta más que el primero, y cien personas preguntando sin comprar cuestan lo mismo que cien comprando.
- El razonamiento interno del modelo cuenta contra ANTHROPIC_MAX_TOKENS, y esos tokens se cobran a la tarifa de salida, la más alta de las dos que trae la tabla de arriba. Aun así no son los que mandan en la factura: con ese mismo volumen, el grueso de lo que pagas es la entrada.
- Las plantillas no salen en tu primera cuenta. Mientras solo contestes dentro de la ventana de 24 horas no hay plantilla que pagar; aparecen cuando eres tú quien escribe primero, y se cobran por mensaje entregado y por país.
Y la forma más efectiva de bajar todo esto no es cambiar de modelo: es no meter en el prompt información que tus clientes nunca preguntan. Cada línea de más se vuelve a pagar en cada turno de cada conversación.
ponlo en el calendario
1 de octubre de 2026
Hoy, si el cliente te escribió primero y contestas dentro de la ventana de 24 horas, Meta no cobra esa respuesta. Lo que se paga son las plantillas, por mensaje entregado.
Meta anunció que desde el 1 de octubre de 2026 pasa a cobrar por mensaje de negocio, e incluye respuestas que hoy salen gratis justamente por caer dentro de esa ventana.
Es un anuncio y aquí va sin cifra propia a propósito: la única cuenta que va a servir es la que esté publicada en la página de precios de Meta el día que la leas. Si tu agente vive de contestar, míralo antes de esa fecha y no después.
16 · preguntas frecuentes
Preguntas frecuentes
Doce preguntas que llegan cuando el agente ya está corriendo. Las que tienen dueño en otra sección se contestan en dos líneas y te mandan ahí.
¿Necesito saber programar?
No. Claude Code escribe el código; tú contestas preguntas sobre tu negocio en español.
Lo que haces a mano es pegar comandos y hacer clics en dos paneles. No abres un archivo de Python en ningún momento.
¿Puedo usarlo con mi negocio real?
Sí, después de probarlo en tu computadora. Tres cosas antes de apuntarle clientes de verdad.
Tu propio número, no el de pruebas, que caduca. PostgreSQL puesto en el despliegue, o el historial se borra en cada redespliegue. Y el secreto del webhook cargado, o cualquiera que sepa tu URL le puede inyectar mensajes al agente.
¿Y si el agente no sabe algo?
Depende de lo que tengas escrito en tu prompt del sistema. Esa regla —si no sabe algo, lo dice y ofrece pasar con una persona— no viene puesta de fábrica: se escribe en config/prompts.yaml.
Si aun así se inventó un precio, es que ese dato no está ni en la información del negocio ni en la carpeta knowledge. Ponlo en un archivo de texto dentro de knowledge y pídele a Claude Code que regenere el prompt del sistema.
Dejarla escrita es parte de afinar el agente: el prompt 11 de la sección 14 se la dicta a Claude Code junto con el tono y los datos que le falten.
¿Entonces agenda citas o no?
No por sí solo. Conversa, entiende y te deja los datos en el historial de la conversación: quién es, qué quiere y para cuándo.
Ejecutar la acción —reservar el horario, cobrar, descontar stock— es un cableado aparte, y eso lo resuelve la sección 14.
¿Puede escribirle primero a un cliente?
No de entrada, y no es un límite del kit: es la ventana de 24 horas de WhatsApp. Fuera de ese plazo hace falta una plantilla aprobada por Meta.
Como tu agente siempre responde, en la práctica nunca sale de la ventana; la regla completa está al elegir proveedor.
¿Cuánto cuesta?
El kit es gratis y de licencia MIT. Lo que se paga es el modelo por token, el servidor donde vive tu agente y, si usas un número propio, el número.
Las tarifas con su fecha, el costo por conversación y por qué la cuenta sube con el volumen están en la sección de costos.
¿Por qué mi repositorio de GitHub se ve casi vacío?
Porque no reemplazaste el .gitignore antes de subir. El que trae el kit excluye a propósito la carpeta del agente, su configuración, las pruebas, el archivo de dependencias y el Dockerfile: justo lo que el despliegue necesita.
Se arregla cambiando el .gitignore y volviendo a empujar, y el paso completo está en la sección 10. La comprobación es que git ls-files muestre agent/main.py y Dockerfile.
¿Puedo probar sin número de WhatsApp?
Sí, con el número de pruebas de Zernio. Tiene límites: 50 mensajes y 5 destinatarios distintos cada 24 horas, una sola sesión activa, y la que se activa dura 7 días.
Sirve para verlo funcionando, no para atender clientes; cómo se abre está en la sección 05.
¿Necesito Docker?
No. Railway construye la imagen en sus servidores, a partir del Dockerfile que te deja Claude Code.
Si no tienes Docker instalado, no te trabes ahí: no lo vas a correr en tu máquina.
¿Qué pasa con mis datos?
Tu agente corre en tu infraestructura: tu servidor, tu base de datos y tus llaves. El kit no tiene backend propio ni telemetría, así que del lado del kit nadie ve tus conversaciones.
Pasar, pasan por dos lugares más, y con este kit no se evitan: por tu proveedor —Zernio tiene su propia bandeja de conversaciones; con Meta van por su Cloud API— y por la API de Anthropic, que es la que escribe cada respuesta con tu llave.
Los archivos de la carpeta knowledge no salen de tu máquina: el .gitignore los deja fuera de GitHub. Lo que sí viaja es su contenido, porque durante la entrevista se incorpora literal al prompt del sistema, y ese archivo —config/prompts.yaml— sí sube a tu repositorio. Si hay algo que no quieres ni en tu repositorio privado, no lo pongas en knowledge.
¿Puedo tener varios agentes?
Sí: un clon del kit por negocio. Cada uno con su número, su secreto del webhook, su repositorio y su servicio.
Lo que nunca se comparte es la base de datos. Aquí abajo está el prompt que monta el segundo sin tocar el primero.
¿Cuál es la diferencia con la guía del Closer?
Esta contesta; aquella cierra. El agente de aquí conversa, entiende y te deja los datos.
Si la venta se cierra por chat y necesitas calificar al cliente, agendar y escribir en tu CRM, el AgentKit que cierra ventas son quince fases y una compuerta de chequeos: otra guía, y bastante más larga.
Montar un segundo agente sin tocar el primero
Un negocio, un clon. El riesgo no es clonar: es que los dos terminen apuntando al mismo lado y se pisen.
Lo que no se comparte
Cuatro cosas tienen que ser distintas entre los dos
- El número de WhatsApp: cada agente atiende el suyo.
- El secreto del webhook, que lo inventas tú: uno por agente, nunca copiado del otro.
- El repositorio de GitHub y el servicio donde lo despliegas.
- La base de datos. Dos instancias contra la misma base le contestan dos veces a la misma persona.
Prompt 12 · Clonar el kit para un segundo negocio
Deja la carpeta nueva lista para su propia entrevista y comprueba que la del primer agente no cambió. No corre /build-agent: eso lo decides tú después.
Quiero montar un SEGUNDO agente de WhatsApp para otro negocio sin tocar el que ya tengo. Hazlo tú. CONTEXTO: - Ya tengo un agente hecho con whatsapp-agentkit en esta carpeta, y no se toca. - El segundo sale de un clon aparte del mismo repositorio público: https://github.com/Hainrixz/whatsapp-agentkit.git - La carpeta nueva va al mismo nivel que esta, no adentro: [ESCRIBE AQUÍ: el nombre, por ejemplo mi-agente-2] OBJETIVO: Dejar el segundo clon listo para su entrevista, con el primero intacto. QUÉ HACER, EN ESTE ORDEN: 1. Sal de esta carpeta y clona el repositorio en la nueva. 2. En la carpeta nueva corre bash start.sh y dime qué verificó: Python 3.11 o superior, que claude esté en el PATH, la carpeta knowledge y la copia de .env.example a .env. 3. Comprueba que la carpeta del primer agente no cambió y dímelo. 4. Hazme la lista de lo que tiene que ser distinto entre los dos: número de WhatsApp, secreto del webhook, repositorio de GitHub, servicio de despliegue y base de datos. RESTRICCIONES DURAS: - NO modifiques ningún archivo del primer agente. - NO copies el .env del primero al segundo. - NO reutilices el webhook, el secreto ni la base de datos del primero: dos instancias contra la misma base le contestan dos veces a la misma persona. - NO corras /build-agent todavía. Esto solo deja la carpeta lista. CRITERIO DE ACEPTACIÓN, compruébalo tú: - La carpeta nueva existe y es hermana de esta, no está dentro. - Dentro de ella hay CLAUDE.md, start.sh, .env y la carpeta knowledge. - git status en la carpeta del primer agente no muestra cambios. Si alguno falla, arréglalo y vuelve a comprobar. QUÉ REPORTAR AL FINAL: La ruta de la carpeta nueva, qué verificó start.sh, la confirmación de que el primer agente no fue tocado, y la lista del punto 4.
Revisar el kit con su propio auditor
El kit trae un script que se revisa a sí mismo: seis chequeos sobre el repositorio. Sirve cuando algo no cuadra y quieres descartar que el problema venga de ahí.
Prompt 13 · Correr el auditor y que te lo traduzcan
Corre scripts/audit.py y te devuelve los seis chequeos en español, uno por línea. Es un diagnóstico: no arregla nada y no sube nada.
Corre el auditor del kit y explícame el resultado en español. No arregles nada. CONTEXTO: - Estoy dentro del clon de whatsapp-agentkit y no programo: la salida de ese script en crudo no me dice nada. - El script es scripts/audit.py y hace seis chequeos sobre el kit. Sale con código 1 si alguno falla. - El chequeo de enlaces necesita conexión y se puede saltar con la bandera --skip-links. OBJETIVO: Saber si el kit está sano y, si no lo está, qué es lo que falla. QUÉ HACER, EN ESTE ORDEN: 1. Corre python3 scripts/audit.py. 2. Si falla por conexión o se queda colgado en los enlaces, vuelve a correrlo con python3 scripts/audit.py --skip-links y avísame que ese chequeo quedó sin correr. 3. Tradúceme los seis chequeos, uno por línea, con pasó o falló: que compilen los bloques de código de CLAUDE.md, que el YAML se entienda, que no queden rastros de los proveedores retirados, que toda variable de entorno usada esté documentada en .env.example, que los enlaces del README respondan, y que las imágenes existan y midan al menos 600 px de ancho. 4. Si alguno falló, dime en una línea qué significa eso para mí. RESTRICCIONES DURAS: - NO arregles nada. Esto es un diagnóstico, no una reparación. - NO instales dependencias sin avisarme. La única excepción es pyyaml si el script se queja de que falta: pídemelo y espera mi sí. - NO subas nada a GitHub ni hagas ningún commit. CRITERIO DE ACEPTACIÓN, compruébalo tú: - Me diste los seis chequeos, cada uno con pasó o falló. - Si usaste --skip-links, lo dijiste explícitamente. - git status muestra lo mismo que antes de correr el script. QUÉ REPORTAR AL FINAL: Con qué código salió el script, los seis chequeos traducidos uno por línea, y qué tengo que hacer yo, si es que hay algo.
Si tu pregunta es un síntoma concreto —dice degradado, no llega nada, el agente se olvida de todo—, está en la tabla de la sección 13, con su causa y su arreglo.
Guía de la bóveda
Lo que te queda cuando cierras esta página
Un número de WhatsApp que contesta a cualquier hora, escrito por Claude Code en tu computadora a partir de diez respuestas tuyas, corriendo en un servidor que no es tu máquina y con el historial de cada conversación guardado en una base que sobrevive a los redespliegues.
También te queda claro dónde está el límite, que es lo que casi nadie dice en voz alta: tu agente conversa, entiende y deja los datos escritos en el historial. Agendar, cobrar o descontar inventario es un cableado aparte, y la sección 14 te lo deja hecho con un prompt.
Y sabes en qué se te va el dinero: no en mensajes, en tokens. Cada turno le reenvía a Claude el prompt del sistema completo —el que lleva los datos de tu negocio— más el historial, así que el mensaje diez cuesta más que el primero. Bajarlo no es cambiar de modelo, es sacar del prompt lo que tus clientes nunca preguntan.
Lo que esta guía no repite
WhatsApp Closer AgentKit: el que además cierra
El agente de aquí contesta y te deja los datos escritos. Si tu venta se cierra por chat —calificar, contestar la objeción con tu propio argumentario, ofrecer horarios que de verdad existen en tu calendario, agendar y dejar la etapa anotada en el CRM—, ese es el otro kit: quince fases, modo borrador y una compuerta de veintitrés chequeos antes de publicar. Es más trabajo, y es el trabajo correcto cuando el chat es tu embudo.
OpenWA: el mismo resultado por el camino del QR
Esta guía va por la API oficial, con un número que nadie te puede tumbar. Allá está el otro camino: conectas tu número escaneando un QR, igual que en WhatsApp Web, sin pasar por Meta. Corre en una máquina tuya y puede dejar de funcionar el día que WhatsApp lo decida.
All Deploy: todo lo demás del despliegue
De Railway aquí van solo los clics de este proyecto: la referencia de la base, el dominio que no se genera solo y la variable de puerto que no hay que tocar. Dominio propio, previews, variables por entorno y rollback viven allá.
De dónde salió cada dato
Lo que promete esta página
Que cada comando, cada ruta de menú y cada nombre de variable salieron del kit tal como está hoy, y que los precios y los límites se verificaron el 17 de septiembre de 2026. Lo que no promete es que sigan iguales: Meta anunció un cambio para el 1 de octubre de 2026 —cobrar por mensaje de negocio, incluidas respuestas que hoy no se cobran— que conviene confirmar en su página de precios el día que leas esto, y los paneles de Zernio y Railway se mueven sin avisar. Si lo que ves en tu pantalla no coincide con lo que dice aquí, manda tu pantalla.
Lo nuevo sale primero en Instagram
Ahí publico lo que voy probando antes de que termine convertido en una guía como esta.
@soyenriquerocha