Lección 04 — Dividí las instrucciones entre archivos
Lección 04 — Dividí las instrucciones entre archivos
Te tomaste en serio el harness engineering. Creaste un AGENTS.md y metiste adentro todas las reglas, restricciones y lecciones aprendidas que se te ocurrieron. Un mes después el archivo tenía 300 líneas; dos meses después, 450; tres meses después, 600. Y entonces notás que el rendimiento del agente está empeorando: para corregir un bug simple consume contexto procesando instrucciones de despliegue irrelevantes; una restricción de seguridad crítica enterrada en la línea 300 se ignora por completo; tres reglas contradictorias de estilo hacen que elija una al azar cada vez.
Esta es la trampa del archivo gigante de instrucciones. Es como sobrecargar una valija: todo parece útil, así que lo metés hasta que el cierre está por reventar. Para encontrar una remera limpia tenés que vaciar todo.
El ciclo vicioso de fondo
flowchart LR
E["El agente comete<br/>un error"] --> R["«Agreguemos una<br/>regla para evitarlo»"]
R --> A["Se agrega a AGENTS.md"]
A --> T["Funciona<br/>temporalmente"]
T --> E2["El agente comete<br/>otro error"]
E2 --> R
A --> B["El archivo crece<br/>sin control"]
B --> D["Baja el SNR<br/>Sube el costo de contexto<br/>Aparecen contradicciones"]
No es culpa tuya. Agregar una regla cada vez que algo sale mal parece razonable. Pero el efecto acumulado es desastroso. Veamos qué se rompe exactamente.
El presupuesto de contexto se consume vivo. La ventana del agente es finita. Un archivo de instrucciones inflado puede consumir 10-20K tokens. ¿Parece que queda mucho espacio? Pero una tarea compleja requiere leer decenas de archivos fuente, la salida de herramientas también ocupa contexto y el historial de conversación se acumula. Para cuando el agente necesita entender el código, el presupuesto ya está apretado.
Perdido en el medio. El artículo Lost in the Middle (Liu et al., 2023) demostró que los LLM usan la información situada en el medio de textos largos con mucha menos eficacia que la del principio o el final. Tu AGENTS.md tiene 600 líneas y en la línea 300 dice “todas las consultas de base de datos deben usar consultas parametrizadas”: es una restricción fuerte de seguridad, pero está enterrada en el medio y el agente casi seguro la va a ignorar.
Conflictos de prioridad. El archivo mezcla restricciones no negociables (“nunca uses eval()”), guías de diseño importantes (“preferí estilo funcional”) y una lección histórica concreta (“la semana pasada se corrigió una fuga de memoria en WebSocket, vigilar patrones similares”). Las tres tienen niveles de importancia completamente distintos, pero se ven iguales en el archivo.
Deterioro de mantenimiento. Las instrucciones obsoletas rara vez se eliminan, porque las consecuencias de borrarlas son inciertas, mientras que agregar instrucciones nuevas parece gratis. Resultado: el archivo solo crece, nunca se reduce, y la relación señal-ruido cae continuamente.
Acumulación de contradicciones. Instrucciones agregadas en momentos distintos empiezan a contradecirse: una dice “usar TypeScript strict mode”, otra dice “algunos archivos legacy permiten any”. El agente elige al azar cuál seguir cada vez.
Conceptos clave
- Instruction Bloat: cuando un archivo de instrucciones ocupa más del 10-15% de la ventana de contexto, empieza a desplazar presupuesto que debería usarse para leer código y razonar. Un
AGENTS.mdde 600 líneas puede consumir 10.000-20.000 tokens: 8-15% de una ventana de 128K antes de que el agente empiece. - Efecto Lost in the Middle: los LLM usan la información del medio de textos largos mucho peor que la de los extremos. Una restricción crítica en la línea 300 de un archivo de 600 tiene alta probabilidad de ser ignorada.
- Relación señal-ruido de instrucciones (SNR): la proporción de instrucciones del archivo que son relevantes para la tarea actual. Leer 50 líneas de instrucciones de despliegue durante un arreglo de bug es bajo SNR.
- Routing File: un archivo de entrada corto cuya función principal es dirigir al agente hacia documentación más detallada, no contenerlo todo. 50-200 líneas alcanzan.
- Progressive Disclosure: dar primero la información general y los detalles cuando hacen falta. Un buen diseño de harness se parece a un buen diseño de UI.
- Priority Ambiguity: cuando todas las instrucciones aparecen con el mismo formato y en el mismo lugar, el agente no puede distinguir restricciones duras no negociables de guías blandas.
La arquitectura de instrucciones que sí funciona
flowchart TD
A["AGENTS.md<br/>50-200 líneas<br/>ROUTER"] --> B["docs/api-patterns.md<br/>120 líneas"]
A --> C["docs/database-rules.md<br/>60 líneas"]
A --> D["docs/testing-standards.md<br/>80 líneas"]
A --> E["docs/deploy.md<br/>90 líneas"]
A -.contiene.-> F["Resumen del proyecto<br/>Comandos de arranque<br/>≤15 restricciones duras<br/>Índice de docs temáticos"]
B -.se lee.-> G["Solo cuando<br/>se agregan endpoints"]
C -.se lee.-> H["Solo cuando<br/>se toca la BD"]
El principio central: mantené a mano la información que se necesita con frecuencia, guardá aparte la que se necesita ocasionalmente y eliminá lo que no vas a usar.
El archivo de entrada debe mantenerse en 50-200 líneas y contener solo lo que se usa más: resumen del proyecto en una o dos frases, comandos de primera ejecución, restricciones globales duras (no más de 15 reglas no negociables) y enlaces a documentos temáticos con una descripción de una línea y su condición de aplicabilidad.
# AGENTS.md
## Resumen del proyecto
Backend Python 3.11 con FastAPI, base de datos PostgreSQL 15.
## Arranque rápido
- Instalar: `make setup`
- Testear: `make test`
- Verificación completa: `make check`
## Restricciones duras
- Todas las APIs deben usar autenticación OAuth 2.0
- Todas las consultas deben usar sintaxis SQLAlchemy 2.0
- Toda PR debe pasar pytest + mypy --strict + ruff check
## Documentos temáticos
- Patrones de API (`docs/api-patterns.md`) — lectura obligatoria al agregar endpoints
- Reglas de base de datos (`docs/database-rules.md`) — obligatorio al modificar operaciones de BD
- Estándares de testing (`docs/testing-standards.md`) — referencia al escribir tests
Cada documento temático debería tener 50-150 líneas, organizado por tema en docs/ o junto al módulo correspondiente. El agente solo lo lee cuando hace falta.
Parte de la información conviene ponerla directamente en el código: definiciones de tipos, comentarios de interfaz, explicaciones en archivos de configuración. El agente la ve naturalmente al leer el código, así que no hace falta duplicarla.
El ciclo de vida de una instrucción
Cada instrucción debería tener:
| Atributo | Pregunta que responde | Ejemplo |
|---|---|---|
| Fuente | ¿Por qué se agregó esta regla? | ”Incidente de SQL injection en 2026-03” |
| Aplicabilidad | ¿Cuándo hace falta? | ”Al escribir cualquier query” |
| Caducidad | ¿En qué circunstancias se puede eliminar? | ”Cuando el linter la detecte automáticamente” |
Auditá con regularidad y eliminá entradas obsoletas, redundantes o contradictorias. Gestioná tus instrucciones como gestionás dependencias de código.
Si una instrucción debe estar en el archivo de entrada, ponela arriba o abajo, nunca en el medio. Pero el mejor enfoque es moverla a un documento temático que se cargue bajo demanda.
OpenAI dice que los archivos de entrada deben ser “cortos y orientados al enrutamiento”; Anthropic dice que la información de control para agentes de larga duración debe ser “concisa y de alta prioridad”. Ambos dicen lo mismo: no metas todo en un solo archivo.
Ejemplo real
El AGENTS.md de un equipo SaaS creció de 50 a 600 líneas. Mezclaba versiones del stack, estándares de código, notas históricas de bugs, guías de uso de API, procedimientos de despliegue y preferencias personales de miembros del equipo.
El rendimiento del agente empezó a caer de forma visible. El equipo ejecutó una reorganización:
AGENTS.mdse redujo a 80 líneas: solo resumen, comandos de ejecución y 15 restricciones globales duras.- Se crearon documentos temáticos:
docs/api-patterns.md(120 líneas),docs/database-rules.md(60),docs/testing-standards.md(80). - Se agregaron enlaces a esos documentos en el archivo de enrutamiento.
- Las notas históricas se convirtieron en tests o se eliminaron.
| Métrica | Antes | Después |
|---|---|---|
| Tasa de éxito del mismo conjunto de tareas | 45% | 72% |
| Cumplimiento de la restricción de seguridad | 60% | 95% |
El salto en cumplimiento vino de mover la restricción del medio del archivo a la parte superior del router: dejó de perderse en el medio.
Ideas clave
- “Agregar una regla” alivia el dolor a corto plazo y envenena a largo plazo. Antes de agregar una, preguntate si no estaría mejor en un documento temático.
- El archivo de entrada es un router, no una enciclopedia. 50-200 líneas con resumen, restricciones duras y enlaces.
- Aprovechá el efecto lost in the middle: la información importante va arriba o abajo; la menos importante se mueve a documentos temáticos.
- Gestioná el crecimiento de instrucciones como deuda técnica. Cada instrucción necesita fuente, condición de aplicabilidad y condición de caducidad.
- Después de dividir, mejora el SNR y el agente gasta más presupuesto de contexto en la tarea real.
Ejercicios
- Auditoría de SNR: listá todas las instrucciones de tu archivo de entrada. Elegí 5 tipos comunes de tareas y marcá si cada instrucción es relevante para cada una. Calculá el SNR por tipo de tarea. Las que son ruido para la mayoría deben moverse.
- Refactor de progressive disclosure: si tenés un archivo de más de 300 líneas, dividilo en un router de menos de 100 líneas más 3-5 documentos temáticos. Corré el mismo conjunto de tareas (al menos 5) antes y después.
- Verificación de lost in the middle: colocá una restricción crítica arriba, en el medio y abajo, ejecutando el mismo conjunto de tareas cada vez (al menos 5 ejecuciones por posición). Mirá si cambia la tasa de cumplimiento.
Lecturas adicionales
- OpenAI: Harness Engineering
- Anthropic: Effective Harnesses for Long-Running Agents
- Lost in the Middle: How Language Models Use Long Contexts
- Nielsen Norman Group: Progressive Disclosure
Anterior: Lección 03 — El repositorio como fuente única de verdad · Siguiente: Lección 05 — Mantené vivo el contexto entre sesiones