DEV Community

Silviu Technology
Silviu Technology

Posted on

LLMs: contratos de salida para agentes cron

He visto varios agentes cron con LLMs fallar no por el modelo, sino por la salida. El job arranca bien, el prompt parece razonable, y aun asi al final nadie sabe si el resultado estaba aprobado, si se publico de verdad o si el sistema solo dejo logs bonitos. Cuando eso pasa a las 3 AM, el problema ya no es de prompting. Es un problema de contrato.

Para mi, un agente programado necesita una salida tan clara como una API. Si el flujo escribe contenido, deberia dejar tambien evidencia verificable: plan, artefacto final, resultado de publicacion y una ruta de corrida facil de inspeccionar. Suena un poco rigido, pero en produccion esa rigidez compra calma.

Por que un agente cron necesita un contrato de salida

Un LLM es bueno generando opciones. Un sistema cron, en cambio, necesita cerrar en una sola decision observable. Si mezclas esas dos naturalezas sin un borde claro, aparecen sintomas muy tipicos:

  1. El job genera una pieza distinta en cada reintento.
  2. El publicador no sabe cual version era la correcta.
  3. La revision posterior se vuelve medio imposible.
  4. El equipo termina confiando en intuicion, no en evidencia.

El contrato de salida resuelve eso obligando al agente a terminar con pocos artefactos y nombres predecibles. En mi cabeza el diagrama verbal es simple: contexto -> plan aprobado -> articulo unico -> publish-result. Cada flecha reduce grados de libertad. No mata la creatividad del modelo, pero si le pone barandas utiles.

Esto se parece a la idea de separar UX y evidencia en reenvios verificados sin crear ansiedad operativa. En ambos casos, el truco no es "hacer mas IA", sino definir mejor que significa exito y como se observa.

El diseno minimo que si aguanta una madrugada

Cuando monto este tipo de automatizacion, intento que cada corrida deje cuatro cosas:

  1. Un run_id unico.
  2. Un plan.json con titulo, keywords, links y esquema.
  3. Un article.raw.md escrito una sola vez.
  4. Un publish-result.json con estado final y URL.

Con eso ya puedes reconstruir casi toda la historia del job sin abrir diez pesta;as. Si una corrida publica algo raro, comparas plan y articulo. Si no publica, lees el resultado. Si publica dos veces, buscas el run_id y ves donde se rompio la disciplina.

Hay una razon practica para esto: la confiabilidad en automatizacion mejora cuando el sistema hace visibles sus transiciones. El reporte State of DevOps de DORA sigue mostrando que equipos con mejores bucles de feedback y observabilidad operan cambios con menos friccion source. No habla solo de LLMs, claro, pero el principio encaja perfecto.

Un ejemplo minimo del contrato seria algo asi:

{
  "run_id": "20260801T112224Z-lucasg88",
  "artifacts": ["plan.json", "article.raw.md", "publish-result.json"],
  "write_once": ["article.raw.md"],
  "final_message": ["selected_account", "title", "run_directory", "published_url"]
}
Enter fullscreen mode Exit fullscreen mode

No es sofisticado. Tampoco intenta describir todo. Solo fija el borde operacional. Y eso, sinceramente, ya evita bastantes dolores tontos.

Tradeoffs entre creatividad y verificabilidad

La objecion comun es: "si cierro demasiado el flujo, el LLM escribe peor". Aveses pasa, pero casi siempre porque el contrato se diseno como una camisa de fuerza y no como una interfaz. Yo prefiero pensar asi:

  1. El plan define restricciones y enfoque.
  2. El articulo conserva libertad dentro de ese marco.
  3. El publicador nunca improvisa contenido.

Ese tercer punto importa mucho. Si el script de publicacion reescribe texto, corrige headings o inventa metadata, ya no tienes un sistema separable. Tienes un generador escondido dentro del ejecutor, y depurarlo despues es un lio.

En stacks backend lo comparo con pruebas limpias de boundary. Algo parecido aparece en estas pruebas limpias de emails transaccionales en FastAPI: cuando el ejecutor solo ejecuta y el plan ya deja la intencion clara, el sistema se vuelve mas legible.

Tambien conviene aceptar un detalle medio incomodo: un poco de imperfeccion humana puede ser deseable en contenido editorial, pero la infraestructura no deberia heredar esa ambiguedad. Puedes tolerar una frase un poco rara; no deberias tolerar un resultado final ambiguo. Esa diferencia no siempre se dise;a bien.

Donde uso un correo temporal desechable sin contaminar el sistema

Aunque este tipo de flujo no depende de branding externo, si hay momentos donde un correo temporal desechable ayuda bastante: pruebas de onboarding, verificaciones aisladas y chequeos de entregabilidad que no quieres mezclar con cuentas reales. La clave es no meter ese recurso en el centro del sistema. Debe vivir en el borde, por escenario, con vida corta y nombres de corrida claros.

Si un equipo mezcla correos de prueba, credenciales reales y seeds como tamp mail com en la misma evidencia, luego nadie sabe que paso de verdad. El LLM tampoco. Solo aprende ruido operacional. Por eso prefiero que el agente reciba contexto limpio y que cualquier inbox efimero quede ligado al run_id, nunca suelto por ahi.

Checklist corto, pero util:

  1. Un artefacto por etapa importante.
  2. Escritura unica del contenido final.
  3. Publicador sin logica editorial.
  4. Evidencia final legible por humanos.

Preguntas frecuentes

Conviene guardar mas de un borrador?

Para exploracion manual, si. Para cron autonomo, casi nunca. Multiplicar borradores complica la trazabilidad y vuelve difuso cual era el artefacto oficial.

Esto tambien sirve fuera de blogging?

Si, bastante. Funciona para agentes que responden tickets, generan changelogs o preparan reportes. El patron real no es "publicar posts"; es terminar con salidas verificables.

Que es lo primero que revisaria si un job falla?

Primero el publish-result.json. Despues compararia plan.json y article.raw.md para ver si la falla fue de ejecucion o de diseno. Parece obvio, pero tener ese orden evita perder tiempo, y aveces evita tocar lo que ya estaba bien.

Top comments (0)