Phase 14 - Lesson 03

Reflexion: Aprendizaje por Refuerzo Verbal

This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.

El RL basado en gradientes necesita miles de intentos y un cluster de GPUs para corregir un modo de falla. Reflexion (Shinn et al., NeurIPS 2023) lo hace en lenguaje natural: después de cada intento fallido, el agente escribe una reflexión, la almacena en la memoria episódica y condiciona el siguiente intento a esa memoria. Este es el patrón detrás del sleep-time compute de Letta, los aprendizajes en CLAUDE.md de Claude Code y el learn-rule de pro-workflow.

Tipo: Build Lenguajes: Python (stdlib) Prerrequisitos: Fase 14 · 01 (Agent Loop), Fase 14 · 02 (ReWOO) Tiempo: ~60 minutos

Objetivos de Aprendizaje

  • Nombrar los tres componentes de Reflexion (Actor, Evaluator, Self-Reflector) y el papel de la memoria episódica.
  • Implementar un bucle de Reflexion con la biblioteca estándar (stdlib) que contenga un evaluador binario, un buffer de reflexión y nuevos intentos.
  • Elegir entre fuentes de retroalimentación escalar, heurística y autoevaluada para una tarea determinada.
  • Explicar por qué el refuerzo verbal detecta errores que el RL basado en gradientes necesitaría miles de intentos para corregir.

El Problema

Un agente falla en una tarea. En el RL estándar, ejecutarías miles de intentos más, calcularías gradientes y actualizarías pesos. Es costoso, lento y la mayoría de los agentes en producción no tienen un presupuesto de entrenamiento para cada fallo.

Reflexion (Shinn et al., arXiv:2303.11366) plantea una pregunta diferente: ¿qué pasaría si el agente simplemente pensara sobre por qué falló e intentara de nuevo con ese pensamiento en su prompt? Sin actualizaciones de pesos. Sin gradientes. Solo lenguaje natural almacenado entre intentos.

El resultado: en ALFWorld, supera a ReAct y otras líneas de base (baselines) sin ajuste fino (fine-tuning). En HotpotQA, mejora con respecto a ReAct. En generación de código (HumanEval/MBPP), estableció el estado del arte en su momento. Todo sin un solo paso de gradiente.

El Concepto

Los tres componentes

Actor         : generates a trajectory (ReAct-style loop)
Evaluator     : scores the trajectory — binary, heuristic, or self-eval
Self-Reflector: writes a natural-language reflection on the failure

Más una estructura de datos:

Episodic memory: list of prior reflections, prepended to the next trial's prompt

Un intento ejecuta al Actor. El Evaluator lo puntúa. Si la puntuación es baja, el Self-Reflector produce una reflexión ("Elegí la herramienta equivocada porque malinterpreté la pregunta pensando que preguntaba sobre X cuando preguntaba sobre Y"). La reflexión va a la memoria episódica. El siguiente intento comienza desde cero, pero ve la reflexión.

Tres tipos de evaluadores

  1. Escalar — una señal binaria externa. ALFWorld tiene éxito o falla. Las pruebas de HumanEval pasan o fallan. Es la señal más simple y de mayor calidad.
  2. Heurístico — firmas de fallas predefinidas. "Si el agente produjo la misma acción dos veces seguidas, márcalo como atascado." "Si la trayectoria supera los 50 pasos, márcalo como ineficiente."
  3. Autoevaluado — el LLM califica su propia trayectoria. Necesario cuando no hay una verdad fundamental (ground truth) disponible. Es una señal más débil; funciona bien combinada con verificación basada en herramientas (Lección 05 — CRITIC).

El estándar en 2026 es una mezcla: escalar cuando está disponible, autoevaluado cuando no, y heurísticas como medidas de seguridad.

Por que esto se generaliza

Reflexion no es tanto un algoritmo nuevo, sino un patrón con nombre. Casi todos los agentes de "autocorrección" en producción ejecutan alguna variante:

  • Sleep-time compute de Letta (Lección 08): un agente independiente reflexiona sobre conversaciones pasadas y escribe en bloques de memoria.
  • Patrón de Claude Code con CLAUDE.md / "save memory": reflexiones capturadas como aprendizajes, incluidas al inicio de futuras sesiones.
  • Comando /learn-rule de pro-workflow: correcciones capturadas como reglas explícitas.
  • Nodos de reflexión de LangGraph: un nodo que califica la salida y la redirige para refinarla si es necesario.

Todos se derivan de la misma idea: el lenguaje natural es un medio lo suficientemente rico como para transmitir "lo que aprendí del fallo" entre ejecuciones.

Cuándo funciona y cuándo no

Reflexion funciona cuando:

  • Hay una señal de fallo clara (fallo en pruebas, error de herramienta, respuesta incorrecta).
  • La clase de tarea es reproducible (se puede hacer el mismo tipo de pregunta de nuevo).
  • La reflexión tiene espacio para mejorar la trayectoria (presupuesto de acciones suficiente).

Reflexion no ayuda cuando:

  • El agente ya tiene éxito en el primer intento.
  • El fallo es externo (red caída, herramienta rota) — reflexionar sobre "la red estaba caída" no ayuda en ejecuciones futuras.
  • La reflexión se convierte en superstición — almacenar una narrativa sobre una ejecución inestable aislada.

Trampa de 2026: deterioro de la memoria (memory rot). Las reflexiones se acumulan; algunas quedan obsoletas o son incorrectas; las reejecuciones se vuelven más lentas a medida que crece el buffer episódico. Mitigación: compactación periódica (Lección 06), TTL en reflexiones o un agente de limpieza independiente en tiempo de sueño (Letta).

Build It

El archivo code/main.py implementa Reflexion en un rompecabezas simple: producir una lista de 3 elementos que sumen un valor objetivo. El Actor emite listas candidatas; el Evaluator verifica la suma; el Self-Reflector escribe una línea sobre lo que salió mal. La reflexión va a la memoria episódica para el siguiente intento.

Componentes:

  • Actor — una política basada en scripts que mejora cuando ve reflexiones.
  • Evaluator.binary() — éxito/fallo según la suma objetivo.
  • SelfReflector — genera un diagnóstico de una línea sobre el fallo.
  • EpisodicMemory — una lista acotada con semántica de TTL.

Ejecútalo:

python3 code/main.py

El rastreo (trace) muestra tres intentos. El intento 1 falla, se almacena una reflexión, el intento 2 ve la reflexión y mejora pero aún falla, el intento 3 tiene éxito. Compara esto con una ejecución de referencia (baseline, sin reflexión): se queda atascado en la respuesta del intento 1.

Use It

LangGraph entrega la reflexión como un patrón de nodo. El comando /memory de Claude Code y /learn-rule de pro-workflow externalizan el buffer episódico como un archivo markdown. El sleep-time compute de Letta ejecuta el Self-Reflector en segundo plano para que el agente principal no se vea limitado por la latencia. OpenAI Agents SDK no incluye Reflexion directamente; lo construyes con un Guardrail personalizado que rechaza trayectorias por puntuación y una sesión (Session) de memoria que sobrevive entre ejecuciones.

Ship It

El archivo outputs/skill-reflexion-buffer.md crea y mantiene un buffer episódico con captura de reflexión, TTL y deduplicación. Dada una clase de tarea y un fallo, emite una reflexión que realmente ayuda al siguiente intento (no un genérico "ten más cuidado").

Ejercicios

  1. Cambia de un evaluador binario a un evaluador escalar que devuelva una métrica de distancia (qué tan lejos está del objetivo). ¿Converge más rápido?
  2. Añade un TTL de 10 intentos a las reflexiones. ¿Las reflexiones más antiguas perjudican o ayudan después de ese punto?
  3. Implementa un evaluador heurístico: marca el intento como atascado si se repite la misma acción. ¿Cómo interactúa esto con Self-Reflector?
  4. Ejecuta Reflexion con un Actor adversario que ignore las reflexiones. ¿Cuál es el diseño de prompt (prompt engineering) mínimo para la reflexión que obliga al Actor a prestarles atención?
  5. Lee la Sección 4 del artículo de Reflexion sobre AlfWorld. Reproduce conceptualmente la mejora del 130% en la tasa de éxito: ¿cuál es la diferencia clave frente a ReAct estándar?

Key Terms

Término Lo que la gente dice Lo que realmente significa
Reflexion "Autocorrección" Shinn et al. 2023 — Actor, Evaluator, Self-Reflector más memoria episódica
Verbal reinforcement "Aprendizaje sin gradientes" Reflexión en lenguaje natural antepuesta al prompt del siguiente intento
Episodic memory "Reflexiones por tarea" Buffer acotado de reflexiones anteriores para una clase de tarea
Scalar evaluator "Señal de éxito binaria" Éxito/fallo o puntuación numérica a partir de la verdad fundamental
Heuristic evaluator "Detector basado en patrones" Firmas de fallos predefinidas (por ejemplo, bucle atascado, demasiados pasos)
Self-evaluator "LLM como juez en su propio rastreo" Alternativa con señal más débil cuando no hay una verdad fundamental — combínala con verificación basada en herramientas
Memory rot "Reflexiones obsoletas" El buffer episódico se llena con entradas obsoletas; se soluciona con compactación/TTL
Sleep-time reflection "Autorreflexión asíncrona" Ejecuta Self-Reflector fuera del camino crítico para que el agente principal permanezca rápido

Further Reading

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).