Blueprint para Claude Code
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ó.
==Cada renglón sale de un comando. Los comandos están en verificación.
01
El problema
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.
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
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.
| Comando | Qué hace |
|---|---|
/start | de 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-cerrador | construye el cerrador entero, fase por fase. /start recorre los mismos archivos, con el arranque y el cierre alrededor |
/seguir | retoma una construcción a medias, sin pisar nada en silencio |
/configurar | catálogo, rango de precio, disponibilidad, escalación, canal interno |
/playbook | las objeciones con su respuesta, el tono y el tratamiento |
/conectar | las credenciales, que escribe quien instala |
/probar | simulador de chat |
/revisar | corre la compuerta |
/publicar | despliega y da de alta el webhook |
/bandeja | aprueba los borradores de a uno |
/soltar | pasa 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
La salida trae los seis elementos siempre, aunque cinco queden salteados. Es lo que deja ver dónde se cortó el ciclo.
Recibí el mensaje y traé el contexto.
webhook · historial · ficha del contacto · audio transcripto
Detectá la intención y calificá.
presupuesto · urgencia · encaje · score 0 a 100
Respondé con el tono de marca y ofrecé horarios que existen.
le escribe a una persona
Agendá y confirmá.
escribe en la agenda
Escribí la etapa, el resumen y el próximo paso en el CRM.
escribe en la base
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.
Ningún archivo del blueprint los puede romper, y cada uno tiene su chequeo en la compuerta.
hmac.compare_digest. Reserializar el JSON para firmarlo pasa todas las
pruebas y falla todas las entregas reales.enviar(): ventana de 24 horas, chequeo
de baneo, y nunca escribirle primero a quien no escribió.timeout= explícito.PINES.md y de ningún otro lado.04
Qué queda construido
| Pieza | Cómo queda |
|---|---|
| Proveedor | meta, 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. |
| Audio | se 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. |
| Imagen | la lee el modelo de Anthropic que ya está configurado. No hay una clave de visión que conseguir. |
| Agenda | Google Calendar: el evento, y el recordatorio 24 horas antes. |
| CRM | la tabla leads, y el paso 5 escribiendo en ella. |
| Panel y API | agente/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. |
| Despliegue | la laptop, un Mac Mini o Railway. Railway es el default del blueprint, pero la elección la hace quien instala. |
| Bandeja | los 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
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.
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 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 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
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.
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:
leads y el permiso de escritura de tu clave.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ú.
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.