Agent Mentor Learn
Memoria y estado del agente · Lección 3 de 6

Lección 3: Memoria externa: archivos y recuperación

Objetivos de aprendizaje:

  • Explicar por qué la memoria que debe sobrevivir a través de las sesiones tiene que escribirse fuera de la ventana, en archivos
  • Distinguir los archivos de memoria escritos por humanos, como CLAUDE.md, de los escritos por el modelo, como Auto memory
  • Enunciar el equilibrio entre «recuperar bajo demanda» y «cargar todo por adelantado»
  • Añadir una comprobación segura de límites de ruta a una herramienta que lee y escribe archivos de memoria

Requisitos: terminada la Lección 2, entiendes la diferencia entre compactación y borrado de resultados de herramientas | Anterior: Lección 2 << | Siguiente: Lección 4 >>

Cuando la sesión termina, todo lo que hay en la ventana desaparece

La Lección 2 cerró con un problema sin resolver: un asistente de agenda al que un usuario le dijo la semana pasada «no como picante», y luego esta semana el usuario abre una conversación nueva con una ventana vacía, y el agente no tiene ni idea de que esa oración se dijo alguna vez.

El truncado, la compactación y el borrado de resultados de herramientas no pueden arreglar esto. Los tres lidian con «nos quedamos sin espacio dentro de esta única conversación». El problema aquí es distinto: esta conversación no tenía nada del contenido de la semana pasada desde el primer turno. El Cookbook oficial traza la línea sin rodeos: el borrado y la compactación operan ambos sobre el contexto actual; ninguno ayuda cuando arranca una sesión nueva y la ventana está vacía. La memoria resuelve ese problema1. La ventana, como contenedor, solo vive lo que dura esta única sesión. Cierra la sesión, y todo lo que había en la ventana que no se movió a otro lado desaparece de verdad.

La única forma de mantener viva la información más allá de esta sesión es escribirla, antes de que la sesión termine, en algún lugar fuera de la ventana: en la memoria externa, un almacenamiento que no está atado al ciclo de vida de esta conversación, normalmente solo un archivo en disco. Cuando arranca la siguiente sesión, lees ese archivo de vuelta y cargas su contenido en la nueva ventana de contexto.

CLAUDE.md: escrito por humanos, cargado completo cada vez

El patrón más directo de memoria externa es que un humano mantenga un archivo de memoria, guardado en el proyecto y leído completo al inicio de cada sesión. CLAUDE.md en Claude Code es el caso representativo: la documentación oficial dice que un archivo CLAUDE.md se carga en la ventana de contexto al inicio de cada sesión, gastando tokens junto a la conversación misma, y el tamaño recomendado como objetivo es mantener cada archivo por debajo de 200 líneas: cuanto más largo el archivo, más contexto consume y menor es la adherencia del agente a las instrucciones.2 Nota que 200 líneas es una recomendación blanda; el límite duro real es 4 MiB: un CLAUDE.md más grande que eso se omite por completo.2

Un detalle de este archivo vale la pena notar: la documentación oficial explica que los comentarios HTML a nivel de bloque en CLAUDE.md se eliminan antes de que el contenido se inyecte en el contexto del agente.2 En otras palabras, lo que sea que escribas dentro de <!-- --> es visible cuando un humano abre el archivo, pero la versión que lee el agente no incluye ese comentario, lo que le da a un humano una forma de «dejarme una nota sin gastar el presupuesto de tokens del agente».

CLAUDE.md tiene otra propiedad que conecta directamente con la compactación de la Lección 2: la documentación señala que un CLAUDE.md en la raíz del proyecto sobrevive a la compactación; después de /compact, Claude lo relee desde disco y lo vuelve a inyectar en la sesión.2 Dicho de otro modo, un archivo así no es «preservado de forma incidental» por la compactación; se relee y se reinyecta por separado, no depende en absoluto de si esa compactación conservó su contenido en el resumen.

Auto memory: escrita por el modelo, recuperada bajo demanda

CLAUDE.md lo escribe un humano y se carga completo cada vez. Hay un patrón complementario: dejar que el modelo anote lo que vale la pena recordar a medida que avanza la conversación, guardándolo en sus propios archivos de memoria. Claude Code llama a este mecanismo Auto memory. Su reparto de tareas con CLAUDE.md es complementario, y una tabla comparativa expone la diferencia con claridad: CLAUDE.md lo escribes tú, Auto memory la escribe Claude.2

La memoria que el modelo escribe por sí mismo suele dividirse en dos capas: un archivo índice (digamos, MEMORY.md) más un montón de archivos de memoria específicos desglosados por tema. El archivo índice tampoco se carga sin límite: la regla que da la documentación es que, al inicio de cada conversación, solo se cargan las primeras 200 líneas de MEMORY.md, o los primeros 25KB, lo que ocurra primero; el contenido más allá de ese umbral no se carga al inicio de la sesión.2

Eso es recuperación bajo demanda: al inicio de una sesión el agente ve solo los resúmenes de las entradas del índice (algo así como «las notas detalladas de este tema viven en tal archivo»), no el contenido completo de cada archivo de memoria específico. La documentación es directa al respecto: los archivos de tema no se cargan al arranque; Claude los lee bajo demanda con sus herramientas de archivo estándar cuando necesita la información2. Solo cuando la tarea actual de verdad requiere un tema dado, el contenido de ese archivo de memoria específico se trae a la ventana de contexto de esta ronda.

Lado a lado, CLAUDE.md y Auto memory manejan dos dimensiones distintas de la memoria:

  • CLAUDE.md: reglas y convenciones curadas por humanos, disciplinadas en tamaño, que aplican cada vez; encaja con información estable del estilo «así es como se supone que funciona el proyecto», cargada completa por adelantado.
  • Auto memory: detalles específicos que pueden ser numerosos y que solo importan para tareas particulares; encaja con la recuperación bajo demanda, para que no se desperdicie presupuesto de ventana en memoria que esta tarea no necesita.

Ambas son memoria externa. Las únicas diferencias son «quién la escribe» y «cuándo se carga», lo que hace eco del modelo mental de la Lección 2: el punto de la memoria es mover la información fuera de la ventana para que sobreviva a través de las sesiones, y que esa información se cargue completa por adelantado o se recupere bajo demanda depende de qué tan estable es y con qué frecuencia se usa.

Añadir un límite seguro a la lectura y escritura de archivos de memoria

Ya sea un archivo escrito por humanos como CLAUDE.md o uno escrito por el modelo como Auto memory, en cuanto un agente tiene una herramienta para leer y escribir archivos de memoria, hay una pregunta concreta de ingeniería que enfrentar: ¿se puede convencer a esa herramienta de leer o escribir archivos fuera del directorio del proyecto?

Una comprobación de ruta que solo hace una coincidencia de prefijo de cadena parece que bloquea las peticiones de «escapar del directorio de memoria», pero tiene un agujero clásico. Si la raíz de memoria es /project/memory, una comprobación ingenua de startsWith("/project/memory") también dejará pasar una ruta como /project/memory-evil, porque sí empieza con esa cadena, aunque ese sea un directorio completamente distinto que está fuera de la raíz de memoria. La forma segura es exigir que la ruta o bien sea exactamente igual a la raíz, o bien empiece con «la raíz más un separador de ruta»:

La combinación abs === MEMORY_ROOT || abs.startsWith(MEMORY_ROOT + path.sep) es lo que de verdad garantiza que solo pase una ruta «igual a la raíz misma» o «que empiece con la raíz más un separador»: /project/memory-evil no se confundirá con una ruta dentro de /project/memory, porque no satisface ninguna de las dos condiciones. Este patrón se reutiliza directamente en la Lección 6 cuando construimos las herramientas de lectura/escritura para una capa de memoria persistente, y la Lección 5 dejará claro en qué clase de objetivo de ataque se convierte un archivo de memoria si esta comprobación de límites no tiene dientes.

Resumen

  • Cuando una sesión termina, todo lo que hay en la ventana que no se movió fuera se pierde para siempre; para conservar información a través de las sesiones, tienes que escribirla en memoria externa fuera de la ventana antes de que la sesión termine
  • CLAUDE.md lo escribe un humano, se carga completo en el contexto cada sesión, con un objetivo de tamaño oficial de 200 líneas (límite duro 4 MiB, archivos más grandes se omiten por completo); los comentarios HTML a nivel de bloque se eliminan antes de la inyección, y un CLAUDE.md en la raíz del proyecto se relee y se reinyecta después de /compact2
  • Auto memory la escribe el modelo, dividida en un archivo índice más archivos de tema específicos; el índice carga solo sus primeras 200 líneas o 25KB, y los archivos de tema no se cargan al arranque, se leen bajo demanda cuando hacen falta2, así que no se desperdicia presupuesto de ventana en memoria que no se va a usar
  • Las dos son complementarias: CLAUDE.md encaja con reglas estables útiles cada vez; Auto memory encaja con detalles de gran volumen necesarios solo para tareas particulares
  • La herramienta de lectura/escritura de un archivo de memoria debe hacer una comprobación segura de límites de ruta; la condición combinada abs === ROOT || abs.startsWith(ROOT + path.sep) necesita ambas mitades, ya que una comprobación de startsWith sola tiene un agujero de sorteo por mismo prefijo

>> Lección 4: Estado estructurado: cómo un agente recuerda en qué punto está una tarea

Footnotes

  1. Context engineering: memory, compaction, and tool clearing — https://platform.claude.com/cookbook/tool-use-context-engineering-context-engineering-tools

  2. How Claude remembers your project — https://code.claude.com/docs/en/memory 2 3 4 5 6 7 8 9

Ejercicios

01

Para cada una de las cuatro piezas de información de abajo, decide si encaja mejor en CLAUDE.md o en uno de los archivos de tema de Auto memory, y di por qué.

Nivel 1: Elegir el hogar de memoria correcto para una nota
  1. «Este proyecto indenta con 4 espacios, nunca tabulaciones»: sin cambios desde el día en que se creó el proyecto.
  2. «El miércoles pasado rastreamos un timeout en producción; la causa raíz fue que el pool de conexiones a la base de datos estaba configurado demasiado pequeño, y en su momento lo subimos a 50»: un registro puntual de un evento pasado que podría venir bien para un problema parecido más adelante.
  3. «En una conversación anterior el usuario mencionó que el proceso de revisión de código de su equipo es primero lint, luego una revisión humana»: solo relevante en sesiones que interactúan con este usuario.
  4. «En esta conversación el usuario hizo una petición puntual de cambiar cierta función a una implementación síncrona»: solo relevante para esta única tarea; casi con seguridad no volverá a surgir la próxima sesión.
Criterios de finalización · marcado local
02

El código de abajo intenta restringir una herramienta de lectura de memoria a archivos dentro del directorio MEMORY_ROOT:

Nivel 2: Diagnosticar una comprobación de ruta con error

Encuentra el agujero de seguridad en este código, da un ejemplo concreto de ruta que sortee la comprobación y lea un archivo fuera de MEMORY_ROOT, y escribe la condición de comprobación corregida.

Criterios de finalización · marcado local