whatsapp-closer-agentkit v0.1.0 MIT

Blueprint para Claude Code

Cerrador de
WhatsApp

Este repo no trae la aplicación. Trae las instrucciones para que Claude Code la construya en tu máquina, un archivo por fase, con las versiones fijadas y con la salida literal que tenés que ver en cada paso.

Lo que queda construido es un agente que atiende cada chat entrante con perfil de setter y closer: califica, responde la objeción del playbook, ofrece horarios que existen, agenda, y deja escrito en el CRM en qué quedó.

árbol sin construir · compuerta
PASS · 0 errores
árbol sin construir · suite
50 passed, 203 skipped
chequeos de la compuerta
23
archivos del blueprint
16
comandos
11
dependencias fijadas con ==
30

Cada renglón sale de un comando. Los comandos están en verificación.

01

El problema

Dos problemas, uno arriba del otro

El de abajo es de instalación. pip install no da lo mismo en dos computadoras, y no avisa. El caso que justifica el kit entero está en PINES.md:

fastapi 0.141.1  declara  starlette>=0.46.0   ← sin techo
starlette         1.3.1   2026-06-12          la última que existía
                  1.4.0   2026-08-05  ┐
                  1.4.1   2026-08-05  │  todas DESPUÉS de que
                  1.5.0   2026-08-08  │  fastapi 0.141.1 se
                  1.5.1   2026-08-08  │  congelara
                  1.6.0   2026-08-08  ┘
No falla al instalar. Falla después, raro, y el error no nombra a ninguno de los dos. — PINES.md

Por eso acá nada se fija con >=. Las 30 dependencias, el modelo y la imagen base viven en un solo archivo, y la compuerta rechaza lo generado que no las respete.

El de arriba es de venta. La gente pide un agente de WhatsApp que venda, no un bot de menú: que califique, que responda objeciones, que agende. Hoy se contesta a mano. El que escribe a las tres de la mañana se va con el que le contestó primero.

La respuesta del kit: cuatro tiempos por paso

Cada paso del blueprint viene con la misma forma. Objetivo, qué queda cierto. Hacé esto, el comando, copiable. Tenés que ver, la salida literal, no «debería andar». Si falla, cada modo de falla con su arreglo.

El cuarto existe porque las computadoras son distintas. Un paso sin «Si falla» te deja frente a una pantalla que dice que no y ninguna salida. — blueprint/00-mapa.md

02

Qué clase de repo es

Instrucciones, no aplicación

En el clon no hay carpeta agente/. La escribe tu corrida. Es la diferencia que explica los números de arriba: la compuerta pasa con once chequeos salteados y la suite deja 203 pruebas dormidas, porque esperan un build que todavía no existe.

Lo que sí viene son 16 archivos de blueprint, uno por fase, y 11 comandos en .claude/skills/ que los abren en orden. La regla que repite el mapa: se lee un archivo por fase, no los dieciséis. Cargarlos todos gasta el contexto que la construcción necesita al final.

ComandoQué hace
/startde un clon recién bajado a un cerrador andando: mide el terreno, dice lo que cuesta y lo que tarda, entrevista, construye y despliega local o en Railway
/armar-cerradorconstruye el cerrador entero, fase por fase. /start recorre los mismos archivos, con el arranque y el cierre alrededor
/seguirretoma una construcción a medias, sin pisar nada en silencio
/configurarcatálogo, rango de precio, disponibilidad, escalación, canal interno
/playbooklas objeciones con su respuesta, el tono y el tratamiento
/conectarlas credenciales, que escribe quien instala
/probarsimulador de chat
/revisarcorre la compuerta
/publicardespliega y da de alta el webhook
/bandejaaprueba los borradores de a uno
/soltarpasa el paso 3 a automático, si los números dan

Si la construcción se corta, el estado queda en .wca-estado.json con la fase y el sha256 de cada archivo escrito. Es local y no va a git. Un archivo que cambió no se reescribe en silencio: se dice qué cambió y se espera confirmación, archivo por archivo.

03

Los seis pasos

Seis pasos, y son el contrato

La salida trae los seis elementos siempre, aunque cinco queden salteados. Es lo que deja ver dónde se cortó el ciclo.

1

Recibí el mensaje y traé el contexto.

webhook · historial · ficha del contacto · audio transcripto

2

Detectá la intención y calificá.

presupuesto · urgencia · encaje · score 0 a 100

3

Respondé con el tono de marca y ofrecé horarios que existen.

le escribe a una persona

4

Agendá y confirmá.

escribe en la agenda

5

Escribí la etapa, el resumen y el próximo paso en el CRM.

escribe en la base

6

Pasá el chat a un humano cuando corresponde.

enojo · precio fuera de rango · palabra de escalación

Los pasos 3, 4 y 5 escriben afuera. El modo por defecto es borrador: redactan, muestran y esperan confirmación explícita. Pasar a automatico lo decide quien instala, y se hace con /soltar.

Los seis invariantes

Ningún archivo del blueprint los puede romper, y cada uno tiene su chequeo en la compuerta.

  • Las firmas se verifican sobre el cuerpo crudo, con hmac.compare_digest. Reserializar el JSON para firmarlo pasa todas las pruebas y falla todas las entregas reales.
  • Todo lo que sale pasa por un solo enviar(): ventana de 24 horas, chequeo de baneo, y nunca escribirle primero a quien no escribió.
  • Un solo cliente HTTP, con timeout= explícito.
  • Ninguna credencial en el árbol. Los secretos los escribe quien instala, nunca una tool call.
  • Ningún precio ni plazo que no esté en el catálogo. Ninguna objeción que no esté en el playbook: se nombra y se deja para el humano.
  • Las versiones y el modelo salen de PINES.md y de ningún otro lado.

04

Qué queda construido

Las piezas que escribe la corrida

PiezaCómo queda
Proveedormeta, zernio o demo, contra una sola interfaz. demo no pide credenciales y no es un transporte falso: reproduce entregas grabadas, con los mismos bytes crudos, la misma cabecera de firma y el mismo camino de deduplicación.
Audiose transcribe con la API de Whisper (OPENAI_API_KEY). Sin esa clave el paso 1 se detiene con el motivo escrito, no con una transcripción inventada.
Imagenla lee el modelo de Anthropic que ya está configurado. No hay una clave de visión que conseguir.
AgendaGoogle Calendar: el evento, y el recordatorio 24 horas antes.
CRMla tabla leads, y el paso 5 escribiendo en ella.
Panel y APIagente/servidor.py: diez rutas y once métodos —el GET y el POST de /webhook/{proveedor} comparten camino—, la API detrás de PANEL_TOKEN y una vista que se abre en el navegador.
Desplieguela laptop, un Mac Mini o Railway. Railway es el default del blueprint, pero la elección la hace quien instala.
Bandejalos borradores se resuelven de a uno. Aprobar no manda: vuelve a correr el paso con confirmado en verdadero, y manda el único enviar().

Las credenciales son 18 variables, y env.example trae los nombres y de dónde se saca cada valor. Nunca un valor. La única que hace falta siempre es la de Anthropic: el modo demo se ahorra las credenciales de WhatsApp, no el modelo que redacta.

05

Cómo se verifica

Dos comandos, y los podés correr vos

Esto es lo que dio un árbol sin construir, o sea sin la carpeta agente/. No lo copies de acá: corré los dos comandos y compará.

$ .venv/bin/python scripts/auditar.py

auditar · whatsapp-closer-agentkit · sin agente/: todavía no se construyó

  [ok      ] 01 blueprint-existe   16 archivo(s) citados por 28, todos con contenido
  [ok      ] 02 manifiesto         7 plantillas al día con el manifiesto.
  [ok      ] 05 pines              30 pines en 1 archivo(s), MODELO=claude-opus-5, imagen python:3.12-slim, verif
  [salteado] 06 deps-imports       no existe agente/: esto corre después de /armar-cerrador
  [ok      ] 08 secretos           104 archivos revisados, 7 patrones
  [ok      ] 17 contrato-control   6/6 mutaciones rechazadas
  [ok      ] 19 pruebas            50 passed, 203 skipped in 0.25s · 203 salteado(s): 0 sólo en vivo, 203 esperan
  [salteado] 23 censo-de-campos    el censo no corrió en este árbol: no hay EVIDENCIA/censo.json. Corrélo con `.v

auditar: PASS · 0 errores · 1 aviso · 11 salteados
  un salteado no es un aprobado: leé el motivo de cada uno.

Recorte: van 8 de los 23 renglones, verbatim. El bloque desliza a la derecha. Los cortes al final del renglón son de la herramienta. Los segundos cambian en cada corrida.

$ .venv/bin/python -m pytest -q

50 passed, 203 skipped in 0.25s

Los 11 salteados y las 203 dormidas son el estado correcto de un árbol sin build: esperan agente/. La compuerta lo dice con un aviso y no con un error, por eso mismo. Ese es el único aviso de esta corrida. En cuanto el build exista, dejan de estar salteadas y hay que volver a mirar. Un segundo aviso aparece si git todavía no tiene en el índice los archivos del núcleo, así que sobre una copia a medio commitear puede darte distinto.

Qué mide la compuerta

23 chequeos. Los primeros veintidós miran el árbol: que el blueprint esté entero, que las plantillas no se hayan derivado del manifiesto, que las versiones sean las de PINES.md, que no haya un secreto escrito en un archivo, que haya un solo cliente HTTP y un solo enviar(), que el esquema de salida no acepte una mutación que debería rechazar.

La compuerta no abre un socket ni lee un secreto, y eso es a propósito: un chequeo que sale a la red se queda esperando un timeout con mala conexión, y ahí no hay reporte.

El chequeo 23: el censo de campos

El vigesimotercero mide un piso más arriba. Va campo por campo del contrato de salida, lo muta, y vuelve a correr la suite: si ningún nodo se pone rojo, ese campo lo declara el contrato y no lo afirma nadie.

En un clon no puede correr, porque no hay salida que mutar:

$ .venv/bin/python scripts/auditar.py --censo

censo: no se pudo medir. el censo necesita el build: no existe
agente/ciclo.py, así que no hay ninguna salida que mutar y los 43
campos declarados quedan sin medir. La mitad estática —la lista
`SIN_ASERCION` contra el esquema— sí corre en el chequeo 23 sin build

Ya corrió una vez sobre un build. De los 43 campos: 31 afirmados, 3 que el esquema fija y no tienen mutante posible, y 9 sin aserción. Ese número está publicado, con los nueve nombres, en PENDIENTES.md.

Seis generaciones

Seis corridas independientes construyeron el agente desde este blueprint. Las tres últimas cerraron en 217, 231 y 253 passed, con la compuerta en PASS · 0 errores · 0 avisos · 0 salteados.

Esos números no salen de este clon y no pueden: acá no hay agente/. Lo que da un clon recién bajado es lo de arriba, y eso sí lo podés reproducir en tu máquina en dos comandos.

06

Los límites

Lo que no hace, y lo que todavía falta

Lo que el agente no hace

  • No inventa precios ni promociones. Lo que no está en el catálogo que le pasás, no existe. Un descuento inventado por un agente lo termina pagando el negocio.
  • No responde objeciones que no estén en tu playbook. Las nombra y las deja para el humano.
  • No escribe primero. Contesta a quien le escribió. No hace envíos masivos y no abre conversaciones frías: eso es lo que hace que Meta baje el número.
  • No negocia un precio fuera de rango. Eso escala, siempre.
  • No sigue contestando después de una escalación. Ni para despedirse.
  • No borra ni reordena nada del CRM. Agrega y actualiza la fila del contacto.

Un límite que no pone el agente

Fuera de la ventana de 24 horas desde el último mensaje del contacto, WhatsApp solo deja mandar plantillas aprobadas. El recordatorio del paso 4 cae casi siempre afuera de esa ventana, así que necesita una plantilla dada de alta por Meta, y la aprobación tarda.

La compuerta en verde no quiere decir que ande contra Meta

Quiere decir que el kit está bien armado. Lo que se cierra a mano, una vez, con tus credenciales, está en PENDIENTES.md, cada uno con cómo se ve cuando falla:

  • La firma del webhook contra tu secreto. Cuando falla, el handler contesta 401 y con Meta el mensaje no llega, sin error a la vista.
  • El token permanente de Meta, no el de 24 horas. Cuando falla, todo anda la primera tarde y a la mañana siguiente hay 401 en cada envío, sin ningún cambio de tu lado.
  • La plantilla del recordatorio, aprobada antes de agendar la primera cita real.
  • La tabla leads y el permiso de escritura de tu clave.

Nueve campos que ninguna prueba afirma

Los encontró el censo y están publicados con nombre y apellido, no escondidos:

calificacion/intencion          crm/resumen
calificacion/urgencia           crm/proximo_paso
respuesta/objecion_detectada    crm/proximo_paso_fecha
respuesta/objecion_en_playbook  pregunta
                                supuestos

El peor de los nueve es objecion_en_playbook: lo que decide es si el playbook se buscó o no, que es lo único que separa este agente de un bot de menú.

Un camino frenado

Para Google Calendar, authorized_user llega hasta el final. service_account está detenido: el token pide un JWT firmado con RS256 y ninguna librería que lo haga está en PINES.md. Está declarado, no improvisado.