Hoy tienes dos tipos de agente de IA trabajando, y hacen cosas distintas.
Uno vive en tu editor. Claude Code, Cursor, Copilot, Codex. Lee tu repo y escribe código.
El otro atiende a tus clientes. Contesta el teléfono, responde en WhatsApp, consulta una orden, agenda una reunión.
Esto trata de apuntar el primero al segundo. No de que sigas un tutorial mientras tu agente mira. Tú creas la cuenta de Zavu y haces login, y desde ahí tu coding agent arma el agente, escribe las tools, lo deploya, lo testea, lee los logs y corrige lo que encuentra.
Por qué tu coding agent no puede hacer esto hoy
Pídele a cualquier coding agent que "agregue WhatsApp a mi app" y vas a recibir código que se ve bien. Que se vea bien es justamente el problema.
Inventa nombres de endpoints. Ignora la ventana de 24 horas de WhatsApp, así que el primer envío de template falla en producción y no en dev. Escribe un webhook handler sin verificación de firma. Elige SMS para un mensaje que lleva una imagen.
Nada de esto es que el modelo sea malo. Simplemente nunca vio esta API, y no te lo va a decir.
Dos piezas lo resuelven, y cada una hace un trabajo distinto:
| Pieza | Qué le da a tu coding agent | Cómo se agrega |
|---|---|---|
| Skills | Conocimiento: endpoints, reglas de canal, error codes, convenciones | npx skills add zavudev/zavu-skills |
| CLI | Manos: scaffold, deploy, test, logs, correr una tool en local | npx zavudev |
Quién hace qué
La división no es "tú haces lo fácil". Es: tú haces lo que legal, financiera o físicamente necesita una persona.
| Tú | Tu coding agent |
|---|---|
| Creas la cuenta de Zavu | Encuentra o crea el sender |
Corres zavu login y autorizas en el browser | Arma la function |
| Apruebas comprar un número, si hace falta | Escribe defineAgent y cada defineTool |
| Conectas WhatsApp Business por el signup de Meta | Setea los secrets |
| Lees el diff antes de que lo publique | Deploya, testea, lee logs, corrige, vuelve a deployar |
La única parte que tipeas
bashnpx skills add zavudev/zavu-skills npx zavudev login
El installer te pregunta en qué coding agents instalar las skills. Son archivos markdown que se cargan solos cuando la tarea lo amerita, así que no corre nada hasta que es relevante. Hay soporte para más de 40, incluyendo Claude Code, Cursor, Copilot, Codex, Cline, Gemini CLI, Amp y Warp.
login abre el browser, entras, eliges el proyecto y das Authorize. La key queda en ~/.zavu/credentials.json con permisos 0600 y tu agente la usa de ahí en adelante. En una máquina sin browser, setea ZAVUDEV_API_KEY y saltea el paso.
Ese es el setup. De aquí en adelante hablas.
Qué le meten las skills en la cabeza al modelo
| Skill | Qué enseña |
|---|---|
zavu-rules | Siempre cargada. Ecosistema de SDKs, auth, convenciones, business rules |
functions | defineAgent, defineTool, deploy, debugging |
ai-agent | Configuración de agentes, providers, flows, tools, knowledge bases |
voice-agent | Agentes de voz, saludos, transferencias, límites de llamada |
send-message | Árbol de decisión de canal y todos los message types |
webhook-setup | Verificación de firma, retry policy, manejo de eventos |
whatsapp-templates | Creación de templates, aprobación de Meta, botones OTP |
broadcast-campaign | Crear, revisar, enviar, monitorear |
contacts-management | Contactos multi-canal, merge, introspection |
phone-numbers | Búsqueda, compra, requisitos regulatorios |
Después describes lo que quieres
textConstruye un agente de Zavu para mi pizzería en WhatsApp. Tiene que mostrar el menú, consultar disponibilidad de mesas y tomar reservas. Las reservas viven en mi Postgres en DATABASE_URL. Usa mi sender actual, deploya, y testéalo antes de decirme que funciona.
No se espera que conozcas los comandos de abajo. Están para que reconozcas lo que pasa por la pantalla, y para que notes cuándo tu agente se saltó un paso.
bashnpx zavudev whoami # qué proyecto estoy por tocar npx zavudev senders list # el sender al que se engancha npx zavudev fn init --template restaurant-booking -y npx zavudev fn secrets set SENDER_ID "jn76vnxet8g5nq661by3v06y1581bmmn" npx zavudev fn secrets set DATABASE_URL "postgres://..." npx zavudev deploy
whoami es el que hay que mirar. Deployar un agente al proyecto equivocado es el tipo de error que se queda callado un día entero.
Si prefieres que arranque de algo probado y no de un archivo en blanco, hay un catálogo:
bashnpx zavudev agents catalog
textid name voice tools category fermi Fermi, Lead Qualification yes 5 sales curie Curie, Customer Support yes 5 support kepler Kepler, Video Call Booking yes 2 frontDesk hopper Hopper, Lead Capture and Booking yes 5 sales aria Aria, Multi-channel concierge yes 3 frontDesk atlas Atlas, Product Expert yes 0 support
Le dices "arranca de kepler" y corre agents pull kepler, que baja TypeScript real y editable, tuyo, no una caja negra. Atlas no tiene tools a propósito: responde desde una knowledge base, y un agente que solo necesita leer tu documentación no debería recibir la capacidad de escribir en ningún lado.
Lee lo que escribió
Esta es la parte que merece tu atención, porque es la parte con la que vas a convivir.
tsimport { defineAgent, defineTool } from "@zavudev/functions" defineAgent({ senderId: process.env.SENDER_ID!, name: "Bella", provider: "zavu", model: "openai/gpt-4o-mini", channels: ["whatsapp", "sms"], prompt: "Eres la mesa de pedidos de Tony's Pizza. Responde en una o dos frases.", }) defineTool({ name: "check_order_status", description: "Busca una orden. Llama esto antes de responder sobre una.", parameters: { type: "object", properties: { orderId: { type: "string" } }, required: ["orderId"], }, handler: async ({ orderId }) => { const res = await fetch("https://api.example.com/orders/" + orderId) if (!res.ok) return { ok: false, reason: "not_found" } return { ok: true, ...(await res.json()) } }, })
Dos cosas para revisar siempre.
provider: "zavu" es el gateway administrado: sin API key propia, sin una relación de billing aparte, el costo del LLM sale de tu balance de Zavu. Si tu agente cableó una key cruda de OpenAI en su lugar, eso fue una decisión que nadie le pidió.
El código es la fuente de verdad. Borra la llamada a defineAgent y el próximo deploy borra el agente. No hay un segundo lugar donde también existe y se desincroniza en silencio.
Nunca registraste un webhook ni cableaste un trigger, y eso no es un olvido. defineAgent({ senderId }) es el vínculo: ese sender ahora entrega cada mensaje entrante a este agente.
Publica un agente de voz igual de fácil
textEl mismo agente, pero que también conteste el teléfono. Saludo en español, transferencia a +14155551234 cuando pidan hablar con una persona, corte duro a los 12 minutos.
tsdefineAgent({ senderId: process.env.SENDER_ID!, name: "Bella", provider: "zavu", model: "openai/gpt-4o-mini", channels: ["voice", "whatsapp"], voice: { enabled: true, model: "openai/gpt-4o", greeting: "Hola, gracias por llamar a Tony's. ¿En qué te ayudo?", greetings: { en: "Hi, thanks for calling Tony's." }, interruptible: true, maxCallDurationMinutes: 12, transferPhoneNumber: "+14155551234", }, prompt: "Eres la mesa de pedidos de Tony's Pizza.", })
interruptible es barge-in: quien llama puede cortar al agente a mitad de frase, que es lo que hace que una llamada se sienta como una llamada. Voz necesita un número asignado al sender y la feature de Voice Agents habilitada para tu team.
Se debuggea solo, y ese es todo el punto
Escribir el agente es la mitad fácil. La mitad que decide si sirve es el loop: correrlo, leer qué salió mal, corregirlo, correrlo de nuevo. Cada paso de ese loop es un comando, así que tu agente corre el loop en vez de narrártelo.
textEl agente dio el precio equivocado para ORD-12345. Corre agents test contra esa orden, lee fn logs y agents executions, encuentra dónde falló, corrígelo y vuelve a deployar.
Lo que usa:
bashnpx zavudev agents test --sender "$SENDER_ID" --message "dónde está la orden ORD-12345?" npx zavudev fn invoke --tool check_order_status --args '{"orderId":"ORD-1"}' npx zavudev fn logs --tail npx zavudev agents executions --sender "$SENDER_ID" npx zavudev messages list --limit 10
agents test no entrega nada a nadie, no cobra nada, no deja registro. fn invoke corre un handler en tu máquina en menos de un segundo, contra código sin commitear y con los envíos mockeados, así que separa "la tool está rota" de "el prompt está mal". Los últimos tres son la evidencia: tus logs, cada ejecución del agente con las tools que llamó y lo que costó cada una, y cada mensaje que entró y salió.
Eso es un loop real. El agente tiene conocimiento por las skills, manos por el CLI, y ahora evidencia.
¿Hace falta el MCP server?
Existe, y si tu coding agent tiene terminal lo puedes saltear.
Envuelve la misma REST API que el CLI ya espeja comando por comando, así que te agrega una segunda cosa que autenticar y cubre estrictamente menos. Correr un handler en local contra código sin commitear no es una operación de API, así que ningún MCP puede ofrecerlo. Úsalo cuando el agente no tiene shell.
Lo que no puede hacer sin ti
Tres cosas, y cada una se detiene por una razón.
Comprar un número gasta tu dinero. El CLI lo deja detrás de una confirmación explícita, y así debe quedar. Un agente que provisiona números sin supervisión es un incidente de billing esperando un mal loop.
Conectar WhatsApp Business es el signup de Meta. Una persona pasa por el browser, acepta los términos de Meta y elige el negocio. Nadie puede automatizar tu consentimiento.
Publicar a producción es tu decisión. deploy es un solo comando, que es exactamente por qué el diff merece treinta segundos. Lee qué hacen las tools de verdad antes de que corran contra clientes reales.
Cómo se cobra esto en Zavu
Nada de lo que hace tu coding agent cuesta dinero. Las skills, el CLI, los SDKs, deploy y cada redeploy después son gratis. Se te cobra por un agente que corre, no por uno que se construye.
El plan cubre que corra. Free es $0 con 2.000 mensajes, 3.000 emails y 100.000 unidades de invocación de functions. Hobby es $25 al mes con 100.000 mensajes, 100.000 emails y 1M de unidades, y Standard y Growth suben esos números. Una unidad es una invocación de 128 MB, así que una function de 256 MB gasta 2 por llamada. En el plan free la cuota de functions es un tope duro: los requests se rechazan en vez de facturarse.
La entrega es por mensaje. Cada canal tiene su tarifa, y el tráfico que pasa el allowance de tu plan se cobra por mensaje: $0.003 en Hobby, $0.002 en Standard, $0.001 en Growth. El overage de email es $0.90 por mil. Los planes pagos además depositan un crédito mensual en tu balance, que es de donde salen los primeros envíos.
El modelo, solo si es el nuestro. Con provider: "zavu" el LLM se mide por token contra tu balance de Zavu, y cada cargo nombra el modelo y la cantidad de tokens, así que puedes leer la cuenta línea por línea. Si traes tu propia key, Zavu no cobra nada por inferencia: le pagas a OpenAI o Anthropic directo. En los dos casos necesitas balance positivo, porque la respuesta que manda el agente es un mensaje y los mensajes cuestan.
La voz es por minuto conectado. El pipeline administrado son $0.0625 por minuto más telefonía, contados desde que atienden hasta que cortan. Los modelos estándar están cubiertos por esa tarifa; un modelo premium suma su propio costo por tokens. Al colocar la llamada se reserva un estimado corto y se liquida contra la duración real al terminar.
Lo que conviene saber antes de arrancar: el loop de desarrollo es gratis. agents test no entrega nada, no registra ejecución y no cobra. fn invoke corre el handler en tu propia máquina. Tu coding agent puede correr, leer, corregir y volver a correr toda la tarde sin tocar la cuenta. Lo primero que pagas es un cliente real recibiendo una respuesta real.
Las tarifas se mueven. La página de precios es la que está al día.
Tres reglas que mantienen esto honesto
Un dry run no es una prueba. agents test ejercita el path de texto e imprime warnings sobre lo que no puede demostrar: un agente deshabilitado, tools que ese path nunca va a llamar, metadata de contacto que solo existe en una conversación real. Si tu agente te reporta un test en verde como "funciona", esos warnings son justo lo que se saltó.
Las tools no corren en el path de texto plano. Corren en voz, y dentro del step tool de un flow. El deploy igual imprime "Tools synced" para un agente de solo texto, porque las tools quedan registradas. Registrada no es invocada. Si tu agente de WhatsApp necesita consultar algo, ese paso va en un flow.
Nunca devuelvas un success falso. Un handler que reporta { booked: true } cuando no agendó nada hace que el agente le diga a una persona real que su mesa existe. Devuelve la falla. Esta es la forma más común en que un agente que pasa todos los tests termina lastimando a un cliente, y vale la pena decirlo explícito en tu prompt.
Dónde te deja esto
Un agente que atiende a tus clientes es un archivo en tu repo. Tiene un prompt, unas tools, un comando de deploy y un log que puedes leer. El mismo review, el mismo version control, el mismo rollback que todo lo demás que publicas.
Tú pusiste la cuenta y el criterio. El agente que ya está en tu editor puso el resto.