Módulo 5 — Presupuesto y control: costo, tiempo y contexto

6. Condiciones de parada y límites de gasto

Descripción

Al terminar esta lección vas a poder definir, antes de delegarle cualquier tarea a un agente, tres límites duros —número de iteraciones, tiempo de reloj y gasto en dólares— que se cumplen solos, sin que dependas de tu propio juicio en el momento en que ya llevas media hora invertida. Y vas a poder reconocer, mientras una sesión todavía está corriendo, las tres señales de que entró en un bucle improductivo, para decidir con criterio —no con la esperanza de que el próximo turno sea el bueno— si conviene reducir el alcance, cambiar de modelo, rehacer la especificación o simplemente terminar la tarea tú mismo.

Esto importa porque el escenario que arruina una tarde no es la tarea que falla rápido y visible —esa la notas enseguida—. Es la que parece a punto de resolverse turno tras turno: el agente encontró "casi" la causa, hizo "casi" el fix correcto, y cada turno individual parece razonable seguir pagándolo. Un ingeniero que revisa el gasto del mes y encuentra una sola sesión de depuración que consumió $18 y cuarenta y cinco minutos sin producir un fix utilizable no tiene un caso raro: tiene el resultado normal de no haber puesto un número antes de empezar.

Conexión con el módulo: la lección anterior fue sobre el costo escondido de abrir varios frentes de trabajo en paralelo —la revisión también se multiplica—. Esta lección es sobre el otro extremo: cuándo cortar una tarea, sola o en paralelo, antes de que siga consumiendo presupuesto sin acercarse al resultado. Una aclaración de vocabulario importante para no confundir esta lección con otra cosa que vas a encontrar en otras guías del ecosistema: el corte del que habla esta lección es de presupuesto —turnos, tiempo, dólares—, no de confianza en el resultado que el agente ya produjo. Si lo que necesitas es decidir si un diff terminado se corrige o se descarta por baja calidad, esa pregunta ya la respondiste en la lección 7 del Módulo 4. Aquí la tarea todavía está corriendo, y ni siquiera hay, muchas veces, un diff completo que revisar todavía.

El plomero que fija el tope antes de abrir la pared

Llamas a un plomero por una filtración que no se ve a simple vista. Un profesional con oficio te dice algo antes de tocar la primera pared: "reviso durante dos horas; si en dos horas no encontré el origen, freno, te cuento qué descarté y decidimos juntos el siguiente paso, en vez de seguir abriendo paredes a ciegas." Ese número —dos horas— no lo decide a la hora y media, mirando cuánta pared ya rompió y sintiendo que "está cerca". Lo decide antes de que exista ninguna pared rota, cuando todavía no hay ninguna presión para seguir "un poco más".

La razón por la que ese número se fija antes, y no durante, no es un capricho de organización: es que durante la tarea existe un sesgo real que empuja siempre en la misma dirección. Cuando ya llevas hora y media de trabajo invertido, parar se siente como admitir que esa hora y media fue en vano, y esa sola sensación —no un cálculo real de cuánto falta— alcanza para que sigas rompiendo pared. Un límite fijado de antemano no necesita que en el momento tengas la claridad para resistir ese sesgo: el número ya está tomado, y lo único que queda es cumplirlo.

Con un agente de código pasa lo mismo, con una diferencia práctica a favor: la tarea es fácil de cuantificar en tres unidades distintas, y cada una detecta un tipo distinto de sesión que se fue de control.

LímiteQué controlaCómo se define en Claude CodeQué pasa al llegar
Iteraciones (turnos)Cuántas idas y vueltas del agente permites antes de frenar--max-turns N (solo modo print, claude -p)El proceso termina solo, con un código de salida distinto de cero — no sigue iterando esperando que el turno siguiente sea el bueno
GastoCuántos dólares de API permites que consuma esa tarea--max-budget-usd N.NN (solo modo print)El proceso termina antes de superar el monto, con el mismo tipo de salida por error
Tiempo de relojCuánto tiempo real permites que corra, sin importar cuántos turnos o dólares lleve consumidosNo existe un flag nativo para esto — se envuelve la llamada con el comando timeout de Unix, o se cronometra a mano en una sesión interactivatimeout mata el proceso al cumplirse el plazo, con el código de salida estándar 124

Fíjate que las tres columnas de la derecha son independientes entre sí. Una tarea puede agotar los diez turnos permitidos sin gastar ni la mitad del presupuesto en dólares, si cada turno es barato pero el agente necesita muchas idas y vueltas. Y una tarea puede quedarse sin tiempo mucho antes de agotar turnos o dólares, si cada turno individual es barato en tokens pero tarda minutos en tiempo real —por ejemplo, porque corre una suite de pruebas lenta entre cada intento—. Por eso el límite de tiempo no es redundante con los otros dos: atrapa un tipo de sesión fuera de control que los otros dos no ven venir.

Ejemplo trabajado

El job nocturno inventory_sync.py, que sincroniza el inventario con un proveedor externo, falla con un timeout genérico aproximadamente 1 de cada 15 corridas. No hay ningún patrón visible en los logs sobre cuándo pasa. Antes de delegar el diagnóstico, defines los tres límites — no mientras la sesión corre, ahora, antes de escribir el prompt:

  • Turnos: 10. Si en diez idas y vueltas el agente no aisló la causa, algo en el enfoque no está funcionando y diez turnos más no lo van a resolver solos.
  • Gasto: $4.00. Suficiente para una investigación real con lectura de varios archivos y logs, no tan holgado como para no notar si la sesión se disparó.
  • Tiempo de reloj: 25 minutos. Un valor generoso para una tarea de diagnóstico ambiguo, pero finito.

Comando:

timeout 25m claude -p --max-turns 10 --max-budget-usd 4.00 \
  "El job src/jobs/inventory_sync.py falla con un timeout \
   aproximadamente 1 de cada 15 corridas. Investiga la causa \
   revisando el archivo y los logs en logs/inventory_sync/, \
   y propón un fix. No toques ningún otro job." \
  > session.log
echo "Código de salida: $?"

Qué esperar, según cuál de los tres límites se cumple primero:

  • Si el agente resuelve la tarea antes de tocar cualquiera de los tres números, claude termina normalmente, session.log tiene el resultado, y el código de salida es 0. Ese es el caso en el que los límites nunca se activaron porque no hicieron falta.
  • Si se agotan los diez turnos o los $4.00 antes de que pasen los 25 minutos, claude es quien termina el proceso por su cuenta: un código de salida distinto de cero, y una indicación de que se alcanzó el límite de turnos o de presupuesto, no un error de la tarea en sí. El límite hizo exactamente lo que le pediste que hiciera.
  • Si pasan los 25 minutos sin que se hayan agotado ni los turnos ni el presupuesto —por ejemplo, porque cada turno incluye correr el job completo contra un entorno de prueba y eso tarda varios minutos por intento—, es timeout quien mata el proceso desde afuera, y $? va a mostrar 124: el código estándar con el que timeout señala que fue él quien cortó, no la tarea la que terminó por su cuenta.

Los tres desenlaces son formas legítimas de que la sesión termine. Ninguno significa "el agente falló" en el sentido de haber hecho algo mal — significa que el límite que definiste antes de empezar hizo su trabajo.

Si trabajas en sesión interactiva y no en modo print: ninguno de los dos flags aplica —ambos son exclusivos de claude -p—. La forma de imponer los mismos tres límites en una conversación normal es manual: decides el número antes de empezar ("no más de diez turnos con este mismo enfoque, no más de $4, no más de 25 minutos"), pones un temporizador, y revisas /usage —la misma herramienta de la lección 2— cada tantos turnos para saber en qué punto vas. El límite existe igual; lo que cambia es que nadie lo hace cumplir por ti, tienes que cumplirlo tú mismo, y ese detalle es exactamente el primer error común de esta lección.

Las tres señales de que la sesión entró en un bucle improductivo

Los límites duros de la sección anterior son el respaldo: eventualmente cortan, pase lo que pase. Pero esperar a que se cumpla el número completo —diez turnos, $4, 25 minutos— antes de actuar deja pasar información que ya estaba disponible desde antes. Mientras la sesión corre, hay tres señales que indican que el enfoque actual no va a converger, mucho antes de que el límite numérico se dispare.

La misma corrección se repite dos veces. El agente aplica un cambio, la falla persiste, y en un turno posterior aplica —con otras palabras, en otro archivo, con otra forma— esencialmente el mismo cambio que ya había hecho. Es la señal de que no está incorporando la evidencia del intento anterior: no vio que ya lo había intentado, o no entendió por qué no funcionó.

El diff crece y el problema no se mueve. Cada turno toca más líneas y más archivos, pero el indicador real de progreso —cuántas pruebas fallan, si el síntoma original sigue reproduciéndose— se mantiene exactamente igual. Un diff que pasa de 20 a 200 líneas sin que el número de fallas cambie no es "más trabajo hecho": es más superficie tocada sin acercarse al resultado.

Cambia de estrategia sin resolver ninguna. El agente abandona un enfoque a medio camino y arranca uno distinto, sin haber llevado el primero hasta una conclusión verificada. Saltar de "el problema es el manejo de reintentos" a "el problema es el pool de conexiones" a "el problema es la configuración del balanceador de carga", todo dentro de la misma sesión y sin que ninguno de los tres se haya confirmado o descartado con evidencia, es exhibir movimiento sin exhibir avance.

Sigamos el caso de inventory_sync.py para ver cómo se ven las tres juntas, con evidencia concreta y no con una sensación:

  • Turno 2: el agente agrega reintentos con backoff exponencial alrededor de la llamada HTTP al proveedor, en sync_inventory(). Corre el job 15 veces contra un entorno simulado: falla 1 vez, el mismo ritmo que antes del cambio.
  • Turno 4: todavía falla. El agente agrega el mismo mecanismo de reintentos —prácticamente idéntico, con otro nombre de variable— dentro de fetch_supplier_catalog(), una función distinta que llama a la misma API. No hay ninguna señal en el diagnóstico de que haya notado que el primer intento ya cubría ese código. (Señal 1: misma corrección, dos veces.)
  • Turno 6: sigue fallando 1 de 15. El agente abandona el enfoque de reintentos sin haberlo descartado con evidencia —nunca llegó a confirmar si el timeout ocurre antes o después de que el reintento entra en juego— y decide que el problema real es el pool de conexiones a la base de datos. Empieza a reescribir la clase ConnectionPool completa. (Señal 3: cambio de estrategia sin resolver la anterior.)
  • Turno 8: el diff pasó de 20 líneas en un archivo a 210 líneas en seis archivos. El job todavía falla 1 de 15 corridas, el mismo ritmo del turno 2. (Señal 2: el diff creció diez veces, el indicador real de progreso no se movió nada.)

Ninguna de las tres señales, por separado, prueba que el agente "es malo" en un sentido general — de hecho, en la lección 4 de este módulo viste que hasta el modelo más capaz produce callejones sin salida en tareas de causa ambigua. Lo que las tres juntas prueban es que este intento puntual, con este enfoque puntual, dejó de converger, y seguir dándole más turnos al mismo camino no es continuar el trabajo: es seguir pagando por la misma búsqueda a ciegas. Es la misma trampa de decisión que ya viste en la lección 7 del Módulo 4 —cada paso individual se siente razonable, la suma no lo es—, pero un turno más temprano: ahí evaluabas un diff ya terminado con hallazgos documentados; aquí estás mirando una sesión que todavía está corriendo, antes de que exista ningún diff completo que revisar.

Qué hacer cuando salta el corte

Ya sea que el corte lo disparó un límite duro (se acabaron los turnos, el presupuesto o el tiempo) o que lo disparaste tú al reconocer una de las tres señales antes de que el número se cumpliera, la pregunta es la misma: ¿qué haces con la sesión cortada? Cuatro salidas, y ninguna es automáticamente la correcta — depende de cuál señal viste.

  • Reducir el alcance. Si la tarea que le diste al agente era en realidad dos tareas encimadas —"encuentra la causa y arregla el job" cuando el diagnóstico solo todavía no está confirmado—, córtala en una tarea más chica: solo el diagnóstico, verificable por separado, antes de pedir ningún fix. Es la salida natural cuando viste la señal 1 —misma corrección repetida—: suele indicar que al agente le falta un dato puntual (un archivo, un log, una restricción) que una tarea más acotada, con ese dato explícito en el prompt, sí puede resolver.
  • Cambiar de modelo. Si ya escalaste el alcance y el problema persiste, y lo que viste fue la señal 3 —cambio de estrategia sin resolver ninguna—, es la señal de que la tarea excede lo que el nivel de modelo actual puede sostener con este grado de ambigüedad. El criterio de escalada de la lección 4 de este módulo aplica igual acá: si ya van dos intentos fallidos con el mismo modelo sobre el mismo enfoque, escala, en vez de darle un tercer intento al mismo nivel esperando un resultado distinto.
  • Rehacer la especificación. Si lo que viste fue la señal 2 —el diff crece, el indicador real no se mueve—, muchas veces el problema no es de ejecución: es que la tarea original no traía la restricción que hacía falta para acotar la búsqueda. En el caso de inventory_sync.py, por ejemplo, el prompt nunca mencionó que el proveedor externo tiene un límite de tasa de solicitudes que se activa bajo ciertas condiciones de carga — un dato que, escrito explícitamente en la tarea, le habría ahorrado al agente los turnos 2 a 8 completos. Volver a la especificación y agregar esa restricción, con las herramientas del Módulo 2, suele valer más que otro intento sin ese dato.
  • Hacerlo a mano. Cuando el corte ya se cumplió y ninguna de las tres anteriores aplica con claridad, o cuando los turnos que sí corrieron ya te dieron, como subproducto, suficiente información para terminar la tarea tú mismo más rápido de lo que tomaría reiniciar una sesión nueva. En el ejemplo, después del turno 8 ya sabes que no es el manejo de reintentos ni el pool de conexiones — eso ya se descartó con evidencia real, aunque a un costo alto—, así que terminar el diagnóstico con esa información en la mano, en vez de abrir otra sesión desde cero, puede ser la opción más barata de las cuatro.

Como referencia rápida, así se relacionan las tres señales con la acción más probable:

Lo que visteQué suele significarAcción típica
Misma corrección, dos vecesAl agente le falta un dato puntual del contextoReducir el alcance, incluir ese dato explícito
El diff crece, el indicador no se mueveEl síntoma no era la causa; falta una restricción en la especificaciónRehacer la especificación con el caso real que faltaba
Cambia de estrategia sin resolver ningunaLa ambigüedad excede lo que este nivel de modelo puede sostenerCambiar de modelo (escalar)
Se cumplió el límite duro y ninguna señal fue claraYa tienes suficiente diagnóstico de los intentos que sí corrieronTerminarlo a mano con lo ya aprendido

Errores comunes

Fijar el número y después negociarlo contigo mismo en el momento (conceptual). Definiste diez turnos antes de empezar, pero al llegar al turno diez el agente "está cerca" —encontró algo, propuso un cambio, falta correr las pruebas una vez más— y decides darle dos turnos de más. Por qué pasa: todo el valor de fijar el límite antes de empezar viene de que en ese momento no hay ninguna presión para estirarlo; en el turno diez esa presión ya existe, y es exactamente la misma que hace que un límite decidido en caliente no sirva de nada. Cómo detectarlo: si te sorprendes pensando "dos turnos más y lo tengo" después de haber definido un número distinto antes de empezar, ya estás negociando el límite en vez de cumplirlo. Cómo corregirlo: trata el número fijado antes como una decisión ya tomada, no como una sugerencia — si dos turnos más de verdad valen la pena, esa es información nueva para la próxima sesión con un límite nuevo, no una excepción para la actual.

Poner límites tan holgados que nunca se cumplen (práctico). Configuras --max-turns 50 y --max-budget-usd 100 "por las dudas", y en la práctica el límite nunca se activa porque ninguna sesión real llega tan lejos sin que la abortes antes por otras razones. Por qué pasa: un número generoso se siente más seguro que uno ajustado, porque reduce el riesgo de cortar una tarea legítima demasiado pronto. Cómo detectarlo: revisa tu historial de sesiones — si ningún límite se activó nunca, no tienes un límite, tienes una formalidad decorativa. Cómo corregirlo: calibra el número con la tabla de costo por tipo de tarea que construiste en la lección 2 — si una tarea de ese tipo típicamente toma 4 turnos y cuesta $0.30, un límite de 8 turnos y $1.00 sigue siendo generoso y, a la vez, sí se activa cuando algo salió mal de verdad.

Tratar cada corte como si hubiera que descartar toda la sesión (práctico). Se cumplió el límite, y la reacción automática es cerrar todo y empezar de cero sin aprovechar nada de lo que la sesión cortada ya produjo. Por qué pasa: un límite que se dispara con un código de salida por error se siente como un fracaso total, y la reacción natural es tratarlo como tal. Cómo detectarlo: si al reiniciar una tarea le das al agente exactamente el mismo prompt que la vez anterior, sin mencionar nada de lo que la sesión cortada ya descartó, estás pagando de nuevo por información que ya tenías. Cómo corregirlo: antes de reiniciar, revisa qué descartó la sesión cortada con evidencia real —en el ejemplo, "no es el manejo de reintentos, no es el pool de conexiones"— y arranca la siguiente sesión con esa información ya incluida en el prompt, en vez de con una hoja en blanco.

Ejercicios

Ejercicio 1. Un agente investiga por qué POST /api/webhooks/stripe procesa el mismo webhook dos veces cuando Stripe reintenta la entrega. Este es el registro de la sesión:

  • Turno 1: agrega una tabla processed_webhook_ids y un chequeo de idempotencia antes de procesar, en handle_webhook(). Corre las pruebas de integración: 1 de 4 sigue fallando — el caso donde dos reintentos llegan casi simultáneos.
  • Turno 3: agrega el mismo chequeo de idempotencia, esta vez dentro de webhook_middleware(), sin mencionar que ya existe uno en handle_webhook(). El mismo caso sigue fallando.
  • Turno 5: decide que el problema es el load balancer y empieza a proponer cambios de configuración de infraestructura fuera del código de la aplicación.
  • Turno 7: el diff pasó de 15 a 90 líneas en cuatro archivos. El mismo caso de reintentos simultáneos sigue fallando.

Identifica en qué turno aparece cada una de las tres señales de bucle improductivo, y qué acción de la tabla de esta lección aplicarías antes de llegar al turno 7.

Ver solución

Turno 3: señal 1, misma corrección repetida (el mismo chequeo de idempotencia, en otro archivo, sin reconocer que ya existía). Turno 5: señal 3, cambio de estrategia sin resolver la anterior (salta del código de la aplicación a infraestructura, sin haber confirmado ni descartado con evidencia si la idempotencia por sí sola alcanzaba). Turno 7: señal 2, el diff creció seis veces y el mismo caso puntual sigue fallando.

La acción más ajustada aparece ya en el turno 3, no en el 7: la señal 1 apunta a que al agente le falta un dato del contexto, no a que el enfoque esté mal. El caso que sigue fallando —dos reintentos casi simultáneos— es la pista: un chequeo de "verificar si existe, si no, insertar" tiene una ventana de carrera si dos solicitudes llegan casi al mismo tiempo, a menos que la tabla tenga una restricción única a nivel de base de datos que rechace el segundo insert. Reducir el alcance a una tarea puntual —"agrega una restricción única en processed_webhook_ids.event_id y maneja el error de violación de esa restricción como éxito silencioso"— con ese dato explícito en el prompt, en vez de dejar que el agente siga buscando a ciegas, es más barato que esperar hasta el turno 7.

Por qué funciona: la señal 1 aparece antes que las otras dos, y actuar en el momento en que aparece —en vez de esperar al límite duro— es exactamente la diferencia entre usar las señales como alerta temprana y usarlas solo como explicación de por qué se cortó la sesión.

Ejercicio 2. Tienes dos tareas para delegar: (C) actualizar la versión de una dependencia en package.json y correr la suite completa para confirmar que nada se rompió; (D) reducir el tiempo de respuesta p95 del endpoint de búsqueda sin cambiar el contrato de la API, sabiendo que no hay ningún perfilador corriendo en producción todavía. Propone un número razonable de turnos, tiempo de reloj y gasto en dólares para cada una, con una línea de justificación por tarea.

Ver solución

Tarea C: 3 turnos, 5 minutos, $0.50. Es una tarea mecánica de criterio cerrado —la suite pasa o no pasa—; si a los 3 turnos no está resuelta, algo salió mal de verdad (un conflicto de versiones que el agente no puede resolver solo), no una investigación legítima que necesite más tiempo.

Tarea D: 12 turnos, 40 minutos, $6.00. Es una tarea de causa ambigua sin instrumentación previa —sin perfilador, cada hipótesis sobre dónde está el cuello de botella hay que confirmarla corriendo algo—, el mismo perfil que la Tarea B de la lección 4 de este módulo. Los límites tienen que ser generosos frente a la Tarea C, pero siguen siendo finitos: si a los 12 turnos el agente todavía está probando hipótesis sin haber aislado ni un candidato con evidencia (por ejemplo, un query lento identificado con un EXPLAIN), eso ya es la señal 3 de esta lección, y conviene cortar y rehacer la especificación agregando la instrumentación que falta, en vez de seguir dándole turnos a una búsqueda sin instrumentos.

Por qué funciona: el número de límites no sale de una tabla fija — sale de dónde cae la tarea en el mismo espectro de "criterio cerrado, error barato de detectar" contra "causa ambigua, verificación lenta" que ya usaste para elegir modelo en la lección 4. Una tarea mecánica necesita límites ajustados porque diez turnos de más ya son una señal de algo raro; una tarea ambigua necesita límites generosos porque la exploración legítima toma más — pero generosos no es lo mismo que ilimitados.

Ejercicio 3. Escribe el comando completo, con timeout, --max-turns y --max-budget-usd, para delegar esta tarea con los siguientes límites: máximo 5 turnos, máximo $1.50, máximo 10 minutos de reloj. La tarea: "Corrige el typo en el mensaje de error de validate_email() en src/utils/validators.py, que dice 'imput' en vez de 'input'."

Ver solución
timeout 10m claude -p --max-turns 5 --max-budget-usd 1.50 \
  "Corrige el typo en el mensaje de error de validate_email() \
   en src/utils/validators.py, que dice 'imput' en vez de 'input'. \
   No toques nada más en ese archivo." \
  > session.log
echo "Código de salida: $?"

Por qué funciona: los tres límites están deliberadamente ajustados —5 turnos, $1.50, 10 minutos— porque la tarea es tan mecánica y cerrada como la Tarea A de la lección 4: cambiar una palabra en un string. Si esta sesión llegara a agotar alguno de los tres números, eso no sería evidencia de que la tarea necesitaba más presupuesto — sería la señal más clara posible de que algo se salió del alcance esperado, y valdría la pena revisar session.log antes que nada más.

Resumen y siguiente paso

Ya tienes las dos mitades de esta lección funcionando juntas: los tres límites duros —turnos, tiempo, gasto— que defines antes de empezar y que se cumplen solos sin depender de tu juicio a mitad de la tarea, y las tres señales —misma corrección repetida, diff que crece sin que el problema se mueva, cambio de estrategia sin resolver ninguna— que te permiten actuar antes de que el número se cumpla, cuando actuar todavía sale más barato. Y viste que ninguno de los dos reemplaza al otro: el límite es el respaldo que corta pase lo que pase, las señales son la alerta temprana para no necesitar llegar hasta ahí.

Antes de avanzar deberías poder: fijar los tres límites duros para una tarea nueva antes de delegarla, justificando el número con el perfil de la tarea y no con una cifra arbitraria; reconocer al menos una de las tres señales de bucle improductivo mirando un registro de turnos, aunque el límite numérico todavía no se haya cumplido; y elegir, entre las cuatro salidas de esta lección, la que corresponde a la señal que viste, en vez de reiniciar siempre de la misma forma sin importar qué pasó.

Ya sabes cuándo cortar. Lo que falta es juntar todos los números que vienes registrando desde la lección 2 —costo, iteraciones, tiempo, y ahora también cuántas sesiones terminaron cortadas antes de llegar a un resultado— en una sola cifra: el costo real hasta tener código integrado, y por qué esa cifra casi nunca coincide con la sensación de qué tan rápido se sintió el trabajo. Esa es la siguiente lección.

Recursos

  • Manage costs effectively — referencia oficial de Claude Code sobre /usage y el seguimiento de gasto, para el caso de sesiones interactivas donde los límites se cumplen a mano.
  • CLI reference — Claude Code — documentación completa de --max-turns y --max-budget-usd, incluida la aclaración de que ambos flags son exclusivos del modo print (claude -p).
  • Building effective agents — Anthropic — la guía de ingeniería de Anthropic sobre diseño de agentes, que nombra explícitamente las condiciones de parada (como un máximo de iteraciones) como parte del control necesario en cualquier sistema agéntico, no solo en tareas de código.
  • timeout invocation — GNU Coreutils Manual — el comando de Unix que impone el límite de tiempo de reloj cuando no existe un flag nativo para eso, con el código de salida 124 que señala que fue el tiempo, y no la tarea, el que cortó la sesión.