← volver Ilustración técnica de engranajes e tuberías interconectadas formando un ciclo cerrado con un manómetro y válvula de escape.

Ralph Loops en Claude Code: Verificadores, presupuestos y condiciones de parada

Un Ralph loop son tres cosas: una tarea, un verificador y un presupuesto. Ese es el patrón completo. Geoffrey Huntley lo nombró así por el personaje de Los Simpson que sigue adelante sin importar si algo funciona o no, y la analogía es precisa. El riesgo no es que Claude se detenga demasiado pronto. El riesgo es que declare éxito en un estado roto, queme tu presupuesto de tokens, o ambas cosas. Este artículo cubre cómo definir cada uno de los tres elementos con precisión, elegir la implementación correcta para tu situación y detener el loop de forma segura cuando esté realmente terminado. El flujo de trabajo de desarrollo agentico es una preocupación separada; este artículo se limita estrictamente a la iteración hasta que se cumpla una condición.

Define el objetivo, el verificador y el presupuesto

Antes de escribir un solo comando, escribe tres oraciones. ¿Cómo se ve "terminado"? ¿Cómo lo comprobarás de forma mecánica? ¿Y cuántas iteraciones estás dispuesto a pagar?

El objetivo debe ser verificable por máquina. "El código es bueno" no es un objetivo. "Todas las pruebas en npm test pasan y git status está limpio" es un objetivo. La diferencia importa porque un verificador solo puede evaluar lo que puede observar. Si tu condición de finalización depende de que un humano mire algo, no tienes un verificador; tienes un paso de revisión, y estas dos cosas no deberían estar dentro del mismo loop.

El verificador no es la propia opinión de Claude. Esta es la parte que la mayoría de la gente se equivoca. Como lo dijo un comentarista de Hacker News: "si la IA cree que las cosas funcionan, dirá COMPLETE aunque tú no creyeras que está completo". Un DONE generado por el modelo es una señal, no un verificador. Un verificador real es un proceso externo: tu corredor de pruebas, tu linter, un curl contra un endpoint en vivo que devuelve el código de estado esperado. Se ejecuta después de cada iteración y produce un true/false determinista. Construye eso primero.

El presupuesto es tu válvula de seguridad. Elige un número que realmente estés dispuesto a gastar. La implementación comunitaria frankbria/ralph-claude-code requiere indicadores de finalización heurística (dos o más) y un EXIT_SIGNAL: true explícito en el bloque RALPH_STATUS del modelo antes de que salga. Ese diseño de doble condición existe precisamente porque las señales individuales no son fiables. Tu --max-iterations debe ser conservador en la primera ejecución. Puedes aumentarlo una vez que hayas visto cuán lejos llega el loop en realidad.

Para ser claros, tu configuración antes de ejecutar cualquier cosa debería responder:

  • ¿Qué comando de shell devuelve código de salida 0 solo cuando la tarea está genuinamente completa?
  • ¿Cuál es el número máximo de iteraciones que permitiré?
  • ¿Qué archivo o log registrará los resultados de iteración para que pueda inspeccionarlos más tarde?

Elige la implementación del Loop

Claude Code 2.1 incluye tres primitivos integrados que cubren la mayoría de casos de uso de Ralph sin ningún plugin. La guía Awesome Claude documenta los tres:

Ilustración técnica de una tubería bifurcada con dos caminos, uno abierto y otro con una válvula de corte, representando las opciones de implementación del loop.
  1. /goal continúa funcionando entre turnos hasta que se verifica una condición. Usa un modelo más pequeño separado (Haiku por defecto, según el artículo de Ranjan Kumar) para leer la transcripción de la sesión después de cada turno y responder una pregunta: ¿se cumplió el objetivo? Si no, Claude toma otro turno. Si sí, el bucle se limpia.
  2. /loop re-ejecuta un prompt en un intervalo fijo o autoajustable. Esc para detener. Útil para tareas de sondeo.
  3. /batch distribuye un cambio grande entre 5 a 30 agentes worktree paralelos. Es otra cosa; no es lo que quieres para una tarea única acotada.

Luego está la ruta del plugin y el bucle bash crudo. Aquí es donde difieren de forma que realmente importa para tu trabajo.

El plugin (ralph-wiggum@claude-plugins-official o el fork de la comunidad) se ejecuta dentro de una única sesión usando un stop hook. Cuando Claude intenta salir, el hook lo intercepta y devuelve el prompt. El contexto se acumula entre iteraciones. Es conveniente, pero significa que en la iteración 15 la ventana de contexto lleva el residuo de cada intento anterior, lo que puede degradar la calidad de cada nuevo turno.

El enfoque bash crudo, canalizando PROMPT.md en claude -p dentro de un bucle while, genera un proceso completamente nuevo cada vez. Como señala Steve Kinney, "Cada invocación de claude -p obtiene una ventana de contexto completamente limpia. Este es el punto completo de la técnica, evitar la degradación del contexto comenzando deliberadamente desde cero." El trueque: pierdes la memoria implícita de lo que se intentó, así que tu PROMPT.md y los archivos de estado de tareas deben llevar todo el contexto explícitamente entre iteraciones.

¿Cuál deberías elegir? Si tu tarea es corta (se esperan menos de 10 iteraciones) y el contexto se mantiene manejable, /goal con un límite de turnos es la opción de menor fricción. Si la tarea es larga o la calidad del contexto es una preocupación, el bucle bash de contexto fresco es más confiable. El artículo sobre tests y herramientas de IA cubre cómo estructurar tu suite de pruebas para que el verificador pueda ejecutarse limpiamente de cualquier forma.

Ejecuta Una Tarea con Iteraciones Acotadas

Aquí hay una configuración ilustrativa para una tarea acotada usando la primitiva /goal:

/goal Todas las pruebas en npm test pasan y git status está limpio, o detente después de 20 turnos

Esa única línea le da a Claude una condición de salida verificable y un límite duro. El evaluador Haiku lee la transcripción después de cada turno y verifica ambas condiciones. La cláusula or stop after 20 turns es tu barrera de presupuesto.

Para un enfoque de bucle bash, la estructura del equipo de Geocodio es un buen modelo a seguir. Usan un archivo JSON (un simple prd.json) donde cada tarea tiene un campo "passes": false. Cada iteración encuentra la historia de mayor prioridad con passes: false, la implementa, ejecuta el verificador e invierte la bandera a true en caso de éxito. El bucle while se cierra cuando cada historia tiene passes: true. Su artículo vale la pena leer solo por la estructura de criterios de aceptación.

El flujo numerado para un bucle bash de contexto fresco se ve así:

  1. Escribe PROMPT.md con la tarea actual, el comando del verificador y la ruta del log de éxito/fracaso.
  2. Inicia el bucle while, canalizando PROMPT.md en claude -p.
  3. Claude lee las instrucciones, hace una unidad de trabajo, hace commit a git.
  4. El verificador se ejecuta. Código de salida 0 significa éxito; cualquier otra cosa significa fracaso.
  5. Registra el resultado (número de iteración, éxito/fracaso, costo de tokens si está disponible) en un archivo.
  6. Si todas las tareas pasan, escribe la señal de parada y sal. De lo contrario, vuelve al paso 2.

Mantén cada iteración a una unidad de trabajo. Intentar hacer demasiado por bucle es cómo terminas con un estado a medio terminar que el verificador no puede evaluar limpiamente.

Detecta Falta de Progreso y Finalización Falsa

Dos modos de fallo son mucho más comunes que los bucles infinitos: el bucle no avanza entre iteraciones, y el modelo declara éxito en un estado roto.

La detección de no-progreso requiere comparar algo concreto entre la iteración N e iteración N+1. Un git diff es la señal más simple. Si git diff HEAD~1 está vacío después de una iteración que no produjo un verificador exitoso, el bucle está girando. Deberías exponerlo inmediatamente en lugar de quemar tres iteraciones más esperando que algo cambie.

La finalización falsa es más complicada. El modelo producirá DONE, COMPLETE, o EXIT_SIGNAL: true en circunstancias donde tu verificador real devolvería un código de salida distinto de cero. La verificación de doble condición de la implementación de frankbria (dos o más indicadores heurísticos y la señal explícita) es una mitigación razonable. Pero la solución más afilada es: nunca dejes que el bucle salga basándose únicamente en la salida del modelo. El script verificador se ejecuta sin importar lo que diga el modelo, y el bucle continúa si el verificador falla, punto.

Ten cuidado con una trampa relacionada: el verificador mismo devolviendo un falso positivo. Si tu suite de pruebas tiene pruebas inestables que a veces pasan sin que el error subyacente se haya corregido, obtendrás una finalización falsa que el modelo ni siquiera causó. Eso es la siguiente sección.

Maneja Pruebas Inestables y Verificadores Fallidos

Las pruebas inestables son el enemigo de cualquier bucle automatizado. Una prueba que pasa el 80% de las veces eventualmente disparará una salida de bucle en el 20% donde no debería. Y porque cada iteración cuesta tokens, una salida falsa seguida de una re-ejecución es cara.

La mitigación no es complicada, pero requiere algo de trabajo previo:

  • Ejecuta tu comando verificador tres veces seguidas antes de confiar en un pase. Si falla una de tres, trátalo como un fallo.
  • Separa tus pruebas de "está el trabajo hecho" de tus pruebas de "funciona el entorno". Las pruebas dependientes de red, las aserciones sensibles al tiempo, y cualquier cosa que requiera estado externo no deberían estar en el verificador que controla la salida del bucle.
  • Registra cada ejecución del verificador con su salida. Si el bucle se detiene y algo se ve mal, quieres la salida completa del verificador de la iteración final, no solo el código de salida.

Si el verificador mismo falla (se bloquea, agota el tiempo de espera, o devuelve un código de error inesperado que no es un fallo de prueba), trátalo como una detención del bucle, no una continuación del bucle. Intentar iterar a través de un verificador roto solo producirá iteraciones que no pueden ser evaluadas.

Los hooks de Claude Code te permiten adjuntar scripts en puntos específicos del ciclo de vida de la sesión. La guía de hooks de Claude Code cubre el mecanismo en detalle. Para bucles Ralph, el hook relevante es el que se dispara cuando Claude intenta salir: interceptarlo, ejecutar tu verificador, y solo permitir la salida si el verificador pasa. Si estás usando la ruta del plugin, esto ya está conectado. Si estás en el bucle bash, la decisión de salida ocurre en tu script de shell en lugar de un hook.

Registra Costo y Detente de Forma Segura

Deberías saber qué cuesta cada iteración antes de que el bucle termine. No necesitas números exactos en tiempo real, pero sí necesitas un archivo de registro que registre el número de iteración, resultado del verificador, e información de token suficiente para estimar el gasto después del hecho.

El post de la comunidad de Alibaba Cloud sobre bucles Ralph identifica tres condiciones de parada que vale la pena incorporar en cualquier implementación:

  • Éxito: el verificador devuelve 0 y todas las tareas tienen passes: true.
  • Detención sin progreso: dos o más iteraciones consecutivas sin git diff y sin mejora del verificador.
  • Agotamiento de presupuesto: el contador de iteración alcanza --max-iterations sin importar el estado del verificador.

El agotamiento de presupuesto no es un modo de fallo, es una parada diseñada. Cuando se dispara, el bucle debe escribir un resumen de qué pasó, qué no, y qué intentó la última iteración. Eso te da un traspaso limpio para una revisión manual o un bucle fresco con un mensaje revisado.

Una cosa a construir explícitamente: una distinción entre "bucle detenido porque tuvo éxito" y "bucle detenido porque alcanzó el límite". Si vuelves a una terminal y ves "bucle detenido en iteración 20", necesitas saber cuál de esos fue. Una única bandera en el archivo de registro, STOP_REASON: BUDGET_EXHAUSTED versus STOP_REASON: SUCCESS, es todo lo que se necesita.

Si estás haciendo este tipo de trabajo a escala o quieres una configuración administrada en lugar de scripts hechos a mano, el trabajo de ingeniería agentic cubre el aspecto de una configuración de bucle de grado producción con observabilidad adecuada.

FAQ

¿Es `/goal` realmente un bucle Ralph, o es algo diferente?

Comparten el mismo principio (iterar hasta que se cumpla una condición) pero difieren en arquitectura. /goal se ejecuta dentro de una sesión única persistente; un bucle bash Ralph clásico genera un nuevo proceso en cada iteración. Como documenta Ranjan Kumar, /goal usa un modelo Haiku separado para evaluar la transcripción después de cada turno. El bucle bash no evalúa nada, lo hace tu script de shell. Ambos son válidos; elige según si la acumulación de contexto es un problema para tu tarea.

¿Puedo usar la salida `DONE` del modelo como verificador?

No. La salida del modelo es una señal que puedes usar como una entrada, pero no puede ser la única condición de salida. Un modelo generará marcadores de finalización cuando crea que la tarea está completa, lo que no es lo mismo que cuando realmente lo está. Combina cualquier señal generada por el modelo con un comando externo que verifique el estado real del sistema.

¿Qué sucede con el bucle si Claude Code compacta el contexto durante la ejecución?

En un bucle de sesión persistente (plugin o /goal), la compactación ocurre automáticamente cuando el contexto crece, y la calidad de esa compactación es inconsistente. Un comentarista de Hacker News observó que "las compactaciones de Claude Code son de tan baja calidad que básicamente es lo mismo que limpiar el historial cada pocos turnos". El bucle bash de contexto fresco evita esto completamente porque cada iteración comienza limpia. Si estás usando el camino del plugin y ejecutando trabajos largos, vigila la disminución de la calidad de salida después de los puntos de compactación.

¿Cuán pequeña debe ser la unidad de trabajo de cada iteración?

Tan pequeña como puedas hacerla mientras siga siendo significativa. Una tarea por iteración es el modelo mental correcto. El enfoque de Geocodio (una historia de prd.json por bucle) y la descripción del comentarista de Hacker News ("elige la tarea más importante, la completa y termina su bucle") apuntan a la misma respuesta: los fragmentos pequeños y verificables son mucho más confiables que las iteraciones grandes y ambiciosas.

¿Necesito un plugin en absoluto?

Para la mayoría de tareas, no. El primitivo /goal integrado con un límite de turnos cubre el caso común. Recurre al plugin (ralph-wiggum@claude-plugins-official o frankbria/ralph-claude-code) cuando específicamente deseas el comportamiento de intercepción de stop-hook o la lógica de salida de doble condición que esas implementaciones proporcionan. No instales un plugin solo porque lo viste en un tutorial.

La advertencia más importante en todo este patrón: una señal de finalización generada por el modelo no es un verificador. Construye la verificación externa primero, antes que nada, y deja que todas las demás decisiones se deriven de eso.

← volver