AI AgentsTutorialCLIWhatsApp

Cómo crear un agente de IA sin escribir el boilerplate

Instalas dos cosas y después describes el agente que quieres. Tu coding agent lo escribe, lo deploya y lo prueba. Tu trabajo es entender los conceptos lo suficiente para pedir lo correcto.

Redactado por: Victor VillalobosRevisado por: Jennifer Villalobos11 de agosto de 202611 min de lectura
Ver como Markdown

Casi todas las guías sobre cómo crear un agente de IA te entregan cien líneas para tipear. Un loop, un dispatcher de tools, un handler de webhook, un store de conversaciones. Las tipeas, funcionan en tu laptop, y el tutorial se declara terminado.

Esa era la forma correcta de guía hace dos años. Ya no lo es, porque en tu editor ya tienes un agente que escribe código, y el boilerplate es exactamente en lo que es bueno.

Así que esta guía tiene otra forma. Instalas dos cosas. Después describes lo que quieres en lenguaje natural, y tu coding agent hace el scaffolding, lo deploya, lo prueba y lee los logs. Lo que tienes que aportar es lo que él no puede: saber de qué está hecho un agente, lo suficiente para pedir el correcto y para detectar una respuesta mala.

Qué convierte algo en un agente

Vale la pena ser preciso, porque la palabra se estiró hasta dejar de significar algo, y porque un modelo mental vago produce un prompt vago.

Un prompt es una llamada. Texto que entra, texto que sale.

Un agente es un loop. El modelo recibe un objetivo y un conjunto de tools. Decide qué tool llamar, ve el resultado y vuelve a decidir. Sigue hasta cumplir el objetivo o hasta rendirse.

while not done:
    decision = model(conversation, tools)
    if decision.is_final_answer:
        done = True
    else:
        result = run_tool(decision.tool, decision.args)
        conversation.append(result)

Ese loop es toda la idea. Los frameworks agregan memoria, retries, tracing y handoff entre agentes, pero si los desarmas encuentras esto.

No vas a escribir ese loop. El runtime se hace cargo. Necesitas entenderlo porque cada falla que vas a debuggear es una falla de ese loop: corrió demasiadas veces, llamó la tool equivocada, o nunca llamó ninguna.

La consecuencia práctica: un agente vale lo que valen sus tools. Un modelo sin tools puede hablar de tu política de devoluciones. Un modelo con una tool lookup_order puede decirle a un cliente dónde está su paquete. Casi todo el valor vive en las tools, lo que significa que casi todo tu prompt debería tratar sobre ellas.

Las cinco decisiones antes de pedir nada

Estas son las que un coding agent no puede tomar por ti, porque son decisiones de negocio vestidas de decisiones técnicas. Diez minutos acá te ahorran una semana.

1. ¿Qué tiene permitido hacer el agente? Escribe la lista de tools primero. lookup_order, book_slot, transfer_to_human. Si la lista queda vacía, quieres un chatbot, no un agente, y conviene leer la comparación antes de construir cualquiera de los dos.

2. ¿Qué pasa cuando no está seguro? Todo agente llega a una pregunta que no puede responder. Las dos opciones honestas son: decirlo y detenerse, o pasar a una persona. Elige una ahora. La falla que estás evitando es el agente que inventa una respuesta con total seguridad, y eso es una decisión de diseño, no un problema del modelo.

3. ¿Qué canal? Esto define tu arquitectura, y es la pregunta que más se salta. Va más abajo.

4. ¿Qué no debe hacer nunca? Prometer una fecha de entrega. Aprobar un reembolso sobre cierto monto. Dar consejo médico. Esto se convierte en líneas del prompt, y si no lo dices en voz alta ahora, no va a estar ahí.

5. ¿Cómo te vas a enterar de que se rompió? Si tu respuesta es "un cliente nos va a avisar", no tienes un plan de observabilidad. Tienes una fila de reclamos.

Escritas, esas cinco respuestas son casi todo tu prompt. Ese es el punto de escribirlas.

Elegir el canal

Tus clientes ya tienen un lugar donde leen mensajes. La pregunta es en cuál los encuentras.

CanalBueno paraEl detalle
WhatsAppSoporte, reservas, cualquier cosa conversacional en LATAM, Brasil, India, sudeste asiático, sur de EuropaVerificación de negocio, y solo puedes escribir libremente 24 horas después de que ellos escriban
SMSLlegar a cualquiera con un teléfono, alertas, verificaciónEn Estados Unidos necesitas registro A2P 10DLC antes de que las carriers entreguen
EmailContexto largo, adjuntos, hilos, B2BLa deliverability es una disciplina aparte: DKIM, SPF y una reputación de dominio que puedes quemar
VozQuien no va a escribir, público mayor, manos ocupadasEl presupuesto de latencia no perdona. Dos segundos de silencio se leen como llamada cortada
Telegram, Instagram, MessengerComunidades y marcas de consumo donde la audiencia ya vive ahíCada uno tiene su modelo de identidad y sus rate limits

El widget de chat no está en esa tabla a propósito. Un widget solo alcanza a gente que ya está en tu sitio. Todos los canales de arriba alcanzan a la gente donde ya está, y por eso un agente en WhatsApp se usa y el mismo agente detrás de un widget no.

El setup: dos comandos

terminal
npx skills add zavudev/zavu-skills npx zavudev@latest login

Hacen dos trabajos distintos, y conviene saber cuál es cuál.

Las skills le dan conocimiento a tu coding agent. Pídele a cualquier coding agent "agrega WhatsApp a mi app" sin ellas y vas a obtener código que se ve bien. Que se vea bien es el problema: inventa nombres de endpoints, ignora la ventana de 24 horas así que el primer envío en producción falla y en dev nunca falló, y escribe un handler de webhook sin verificación de firma. Eso no es que el modelo sea débil. Simplemente nunca vio esta API, y no te lo va a decir. Las skills son markdown plano que se carga solo cuando la tarea coincide, y el instalador te pregunta a qué coding agents instalarlas. Hay más de cuarenta soportados, incluidos Claude Code, Cursor, Copilot, Codex, Cline, Gemini CLI, Amp y Warp.

El CLI le da manos. Scaffolding, secrets, deploy, test, logs. login abre el navegador, entras, eliges el proyecto y das Authorize. La key queda en ~/.zavu/credentials.json y tu agente la usa de ahí en adelante. En una máquina sin navegador, setea ZAVUDEV_API_KEY en su lugar.

Eso es todo lo que tipeas. De acá en adelante, hablas.

El prompt

Ahora usa las cinco respuestas. Un buen prompt para esto no es ingenioso, es específico:

> Constrúyeme un agente de soporte para mi tienda online en WhatsApp.>> Tiene que responder preguntas sobre pedidos. Dale una tool que busque un pedido por ID contra https://api.example.com/orders/{id}, usando STORE_API_KEY desde secrets. Dale una segunda tool que pase la conversación a un humano, que hace POST a nuestro webhook de guardia.>> Reglas: responder en dos frases o menos, nunca inventar una fecha de entrega, y si no encuentra un pedido decirlo y ofrecer una persona. Para reembolsos sobre USD 200 usar siempre la tool de handoff en vez de decidir.>> Deployalo y pruébalo con "¿dónde está el pedido 4471?"

Tu coding agent va a hacer el scaffolding de la function, escribir el agente y las dos tools, setear los secrets, deployar y correr el test. Fíjate en qué hizo que ese prompt funcionara: eran las decisiones 1, 2 y 4 de la lista de arriba, dichas en voz alta. Nada ahí es sintaxis.

Qué escribió, y qué revisas

Esto no lo tipeas. Lo lees, porque revisar el diff es la parte que sigue siendo tuya:

TypeScript
import { defineAgent, defineTool } from "@zavudev/functions" defineAgent({ senderId: process.env.SENDER_ID!, name: "Nora", provider: "zavu", model: "openai/gpt-4o-mini", prompt: Eres Nora, soporte de una tienda online. Responde en dos frases o menos. Si no encuentras un pedido, dilo y ofrece pasar al cliente con una persona. Nunca inventes una fecha de entrega., }) defineTool({ name: "lookup_order", description: "Get the current status of a customer order. Use when the customer mentions an order number or asks where their package is.", parameters: { type: "object", properties: { orderId: { type: "string" } }, required: ["orderId"], }, handler: async ({ orderId }) => { const res = await fetch(https://api.example.com/orders/${orderId}, { headers: { Authorization: Bearer ${process.env.STORE_API_KEY} }, }) return res.json() }, })

Tres cosas que mirar, en este orden:

Las descripciones de las tools. "Use when the customer mentions an order number or asks where their package is" es lo que lee el modelo al decidir si la llama. Esta es la línea de mayor apalancamiento del archivo, y es la que un coding agent escribe flojo más seguido. Si solo dice "busca un pedido", haz que diga cuándo, y cuándo no.

Tus reglas, efectivamente presentes. Cada "nunca" que pediste debería aparecer en el string del prompt. Si falta uno, no lo va a hacer cumplir la buena intención.

La regla de escalamiento en dos lugares. La política va en el prompt para que el modelo la conozca. El gatillo va en la descripción de la tool para que el modelo reconozca el momento. Un agente que "sabe" que debe escalar pero nunca lo hace casi siempre tiene el segundo faltando.

Lo que no estás revisando: el loop, el límite de turnos, el historial por contacto, la verificación de firma del webhook, la ventana de 24 horas de WhatsApp. El runtime se hace cargo de todo eso, que es la razón por la que no hay boilerplate en este archivo.

Probar antes que un cliente

terminal
npx zavudev agents test --agent <agentId> --message "¿dónde está el pedido 4471?"

Corre el agente real con el prompt real y el knowledge base real, devuelve lo que diría, no entrega nada a nadie y no cobra nada. Tu coding agent puede correrlo en loop mientras itera. Agrega --json para hacer asserts en CI.

Dos detalles lo hacen más honesto que la mayoría de los previews. Devuelve warnings con cosas que son ciertas de tu agente pero que un dry run no puede probar: el agente deshabilitado, o tools que existen pero que no se le ofrecieron al modelo en esa corrida. Y por defecto no ejecuta las tools, porque un ensayo que cobra la tarjeta de un cliente no es un ensayo. Cuando quieras el loop completo, pasa executeTools y revisa executedToolCalls para ver qué corrió.

Un test en verde no prueba que el agente funcione en vivo. Prueba que el prompt hace lo que crees, que es justo lo que no tenías claro.

Iterar es prompear más

No vuelves al editor. Dices qué estuvo mal:

> Respondió "tu pedido va en camino" sin llamar la tool. Aprieta la descripción de la tool para que dispare cada vez que se mencione un pedido, redeploya y prueba de nuevo con el mismo mensaje.

Esto funciona porque el resumen del deploy es legible por máquina y el test es un comando, así que tu coding agent puede cerrar el ciclo solo: cambia, deploya, prueba, lee, cambia otra vez.

Una cosa que conviene saber de ese resumen. + es creado, ~ es que existía y fue reescrito, = (unchanged) es que no difería nada. Los marcadores describen lo que el deploy escribió, no lo que el agente ahora dice. Para verificar que un cambio llegó al modelo, pon una palabra distintiva en el prompt que editaste y revisa que vuelva desde agents test. Y lee las líneas arriba del ✓: los warnings se imprimen antes de la línea de éxito, y cubren los casos donde un deploy en verde no hizo lo que parece.

Partir de algo que ya funciona

Suele ser más rápido que describir un agente desde cero:

terminal
npx zavudev agents catalog npx zavudev agents pull fermi --sender <senderId>

catalog lista agentes listos para soporte, captura de leads y reservas, con su cantidad de tools y si contestan llamadas. pull te deja uno en tu repo como código real y editable que es tuyo, con el prompt y todas las tools ya escritas. Después apuntas tu coding agent ahí: "cambia esto para una clínica dental y usa nuestra API de reservas".

npx zavudev agents init corre todo el proceso como un comando guiado, incluida la creación del sender.

Qué sale mal en producción

Cinco fallas, en el orden en que las vas a conocer. Cada una es también un buen prompt para tu coding agent, porque puede leer los mismos registros que tú.

Responde con seguridad y se equivoca. Casi siempre es un prompt que nunca le dio permiso de fallar. Agrega la frase explícita: "Si no lo sabes, di que no lo sabes." Después revisa knowledgeChunksUsed en el registro de ejecución. Cero, en un agente con documentos adjuntos, significa que la respuesta no salió de tu contenido.

Dice que va a consultar algo y nunca lo hace. La respuesta parece que llamó una tool. Nada llegó a tu endpoint. Revisa toolCalls en la ejecución: cero en un agente con tools configuradas significa que el modelo respondió sin llamar ninguna. Casi siempre la descripción de la tool no coincide con las palabras que usan los clientes.

Responde dos veces. Llegan dos mensajes en un segundo, corren dos loops, ambos contestan. Maneja el caso de una conversación que ya se está procesando.

Es lento. Cada tool call es un round trip, y el modelo espera. En WhatsApp tienes unos segundos antes de que el silencio se lea como roto, así que marca el mensaje como leído y muestra el indicador de "escribiendo". En voz tienes cerca de un segundo, y por eso las tools de un agente de voz tienen que ser rápidas o parecerlo.

Funciona y nadie sabe explicar por qué. npx zavudev agents executions te da los tool calls, los argumentos, los resultados y los errores de un agente deployado. Pásale esa salida a tu coding agent y pregúntale qué cambió.

Límites honestos

Algunas cosas para las que un agente no debería ser la respuesta.

Si la tarea es determinista, pide una función. Un agente que siempre llama la misma tool en el mismo orden es un workflow con un impuesto de modelo de lenguaje encima.

Si una respuesta equivocada sale cara, el agente necesita un humano en el camino de aprobación, no mejor prompting. Reembolsos, orientación médica y cualquier cosa legalmente vinculante entran en esta categoría.

Si no tienes tools, tienes una interfaz de búsqueda sobre tus documentos. Puede ser genuinamente útil. No es un agente, y llamarlo así crea expectativas que no vas a poder cumplir.

Y el límite de este flujo en particular: tu coding agent va a hacer todo lo de la columna derecha, pero tú sigues creando la cuenta, autorizando el login, aprobando la compra de un número, conectando WhatsApp Business por el signup de Meta, y leyendo el diff antes de que salga. Esos son los pasos que legal, financiera o físicamente necesitan una persona.

Para seguir

Necesitas ayuda? Contáctanos o únete a nuestra comunidad en Discord para soporte.

Get started

Listo para empezar?

Comienza a construir gratis, o agenda una llamada para discutir tu caso de uso específico.

Cómo crear un agente de IA (guía 2026) | Zavu Blog