← Blog

Tu agente trabaja a su hora: crons y webhooks que le llegan solos

19 de octubre de 2026 · Héctor (blissmo) Campos

Un agente que sólo trabaja cuando le escribes es un asistente. Un agente que trabaja a las 8 de la mañana sin que nadie lo despierte, o que reacciona cuando entra un pago, ya es parte de la operación. La diferencia no está en el modelo. Está en dos piezas de plomería: algo que lo llame a su hora y algo que le guarde los avisos mientras no está.

En EasyBits, la plataforma donde corren mis agentes, construí las dos piezas en octubre: crons y buzones de eventos. Aquí van los comandos que uso y lo que falló. Los criterios sirven con cualquier programador de tareas.

Un cron es una alarma que llama a algo

Un cron es una tarea que se repite con un horario. En EasyBits un cron puede hacer tres cosas cuando suena:

  1. Llamar a una URL https pública, con un secreto de tu bóveda como header si la URL lo pide.
  2. Mandarle un turno a uno de tus agentes, con una instrucción en texto.
  3. Correr un comando en una caja desechable: monta tus archivos, ejecuta, guarda la salida y se destruye.

Se instala el CLI y se inicia sesión en el navegador:

npm i -g @easybits.cloud/cli
easybits login

Un reporte de ventas que le pido a mi agente cada lunes a las 9, sólo las próximas 4 semanas:

easybits crons create "Reporte" --cron "0 9 * * 1" --times 4 \
  --agent <agentId> --prompt "Mándame el resumen de ventas"

Un aviso diario a las 8:30 a una URL propia:

easybits crons create "Despertador" --cron "30 8 * * *" \
  --url https://www.ghosty.studio/api/v2/me/push --method POST \
  --body '{"title":"Hora de estudiar"}' --secret GHOSTY_PUSH_TOKEN

La zona horaria por default es America/Mexico_City; se cambia con --tz. Un cron puede repetirse como mucho cada 5 minutos.

Los crons que no terminan solos se olvidan

El cron más peligroso es el que nadie recuerda que existe. Sigue llamando a una URL que ya no sirve, o le manda a un agente un turno que ya nadie lee, y cada turno cuesta.

Por eso casi todos mis crons tienen fin:

Un cron de una sola vez se apaga al correr y queda en la lista como terminado, con su historial, sin ocupar cupo.

Antes de crear cualquier cron uso --dry-run. Valida todo y enseña las próximas 3 ejecuciones en hora local, sin crear nada:

easybits crons create "Aviso" --at 23:00 --url https://mi-app.com/api/aviso --method POST --dry-run

Te recomiendo la misma costumbre con cualquier programador de tareas: ver las próximas ejecuciones en tu hora antes de guardar.

Correr un comando con los datos de tu app

Con --run, el trabajo lo hace una caja desechable. Sube tus archivos con --file, pasa secretos de tu bóveda como variables de entorno con --secret y, con --machine, el comando recibe la configuración y los secretos de una de tus apps sin copiarlos:

easybits crons create "Altas del día" --cron "0 9 * * *" \
  --run "python3 cuenta.py" --file cuenta.py --machine mi-app

Éxito es que el comando salga con código 0. El tope es de 600 segundos y la caja se destruye al terminar. Cada ejecución guarda el código de salida y la cola de la salida estándar:

easybits crons runs "Altas del día" --logs --limit 5

Esperar un cron desde la terminal es un comando

A veces quiero que algo pase justo después de que termine un cron. crons wait se queda esperando la siguiente ejecución, imprime su salida y sale con su código, así que encaja con un &&:

easybits crons wait "Altas del día" --timeout 2h && echo "listo"

Con un comando (--run), el código de salida es el del comando. Con los otros tipos, 0 si salió bien y 1 si no.

Un buzón de eventos le da a tu agente una URL para webhooks

El problema inverso: un servicio externo quiere avisarle algo a tu agente, pero tu agente corre en tu laptop o en una terminal y no tiene URL pública.

Para eso hice los buzones de eventos. Un buzón es una URL de webhook: cualquiera le escribe con POST y lo que llega te alcanza en vivo si estás escuchando, o te espera guardado si no.

easybits inbox create pagos      # imprime la URL
easybits inbox listen pagos      # en vivo: una línea JSON por evento; se reconecta solo
easybits inbox read pagos        # lo que llegó mientras no estabas; lo marca como leído

La URL tiene la forma /hooks/<token>, y el token es la autorización para escribir. Quien tenga la URL puede escribir en tu buzón. Si se filtra, la cambias:

easybits inbox rotate pagos --yes

Los headers se guardan salvo las credenciales, así que la firma de tu proveedor de pagos llega completa. Verifícala antes de creerle a un evento: un buzón público recibe lo que le manden.

Como listen escribe una línea JSON por evento, se conecta con jq o con lo que use tu agente para leer la terminal:

easybits inbox listen pagos --since 0 | jq .json

Cada buzón guarda 7 días por default (de 1 a 30), hasta 1,000 eventos, con cuerpos de hasta 256 KB.

Un cron puede avisarle a un buzón

Las dos piezas se juntan. Un cron puede dejar cada resultado como evento en un buzón:

easybits crons update "Altas del día" --notify inbox:pagos --notify-on always

Así, cuando tu agente arranca una sesión, lee su buzón y sabe qué corrió mientras no estaba y qué falló. Por default el aviso sale sólo si falla; --notify-on always avisa siempre.

Lo que falló en el camino

Tres errores reales de octubre:

Un copiloto para quien no quiere escribir cron a mano

En el panel de crons de EasyBits vive Bittor, un agente que arma el cron a partir de lo que le pides en palabras y explica por qué falló uno. Puede leer tus bases de datos para responder sobre tus datos, pero sólo con consultas SELECT. Nunca cambia nada por su cuenta: cada alta, cambio, borrado o ejecución sale como tarjeta y tú la apruebas.

Los límites dependen del plan: Byte, gratis, trae 3 crons y 3 buzones; Mega, a $499 MXN al mes (hoy en promoción a $299), trae 20 y 20; Tera, a $2,490 MXN al mes, trae 100 y 100.

¿Qué tarea de tu negocio depende hoy de que alguien se acuerde de hacerla a la misma hora? Ponle hora a tu agente y dale una URL para sus avisos en https://www.easybits.cloud.