Por qué los agentes de código ignoran tus instrucciones
Descubre por qué un agente ignora una regla de parada: contexto ausente, ambigüedad, contradicciones o compactación, y cómo diagnosticar cada caso antes de reescribirla.
Por qué los agentes de programación ignoran sus instrucciones
Los agentes de programación ignoran sus instrucciones por cuatro motivos, y ninguno es que usted haya sido demasiado educado. La regla nunca estuvo en la ventana de contexto. La regla era demasiado imprecisa para comprobar una acción con ella. Otro elemento del contexto la contradecía, normalmente el código que el agente acababa de leer. O la regla sigue cargada, pero está muy atrás en el turno actual, y el agente trabaja con lo que tiene más cerca.
Cada causa tiene su propia solución, así que el primer trabajo consiste en distinguirlas. Las mayúsculas y la palabra IMPORTANT no sirven para diagnosticar el problema. Los mecanismos siguientes usan Claude Code como ejemplo práctico, porque su comportamiento de carga y compactación está documentado en detalle a fecha de August 2026. Otras herramientas difieren en los detalles, pero siguen el mismo esquema general.
Primero, dos términos. La ventana de contexto es el bloque de texto que el modelo ve en un turno determinado: el prompt del sistema, los archivos de instrucciones, la conversación y cada archivo que el agente ha leído. El harness es el programa que rodea al modelo, es decir, el componente que lee archivos del disco y ensambla ese bloque. Casi todas las quejas de este artículo se refieren realmente al harness, no al modelo.
Tu archivo de instrucciones es un mensaje, no una configuración
Un archivo de instrucciones no es una configuración. Nada en el entorno de ejecución lee CLAUDE.md y lo aplica. El arnés lee el archivo del disco y pega el texto en la conversación. En Claude Code, ese contenido se entrega como un mensaje de usuario situado después del mensaje del sistema. Por tanto, el modelo ve tus reglas igual que cualquier otro texto que hayas escrito.
Esto tiene una consecuencia incómoda. Tus reglas compiten con cualquier otro texto de la ventana en igualdad de condiciones. Una regla es una afirmación. El archivo que el agente acaba de abrir es una evidencia. Cuando ambos discrepan, la evidencia suele imponerse y no se genera ningún error, porque desde el punto de vista del modelo no ha ocurrido nada incorrecto.
La documentación oficial lo dice claramente: los archivos de instrucciones se tratan como contexto, no como una configuración aplicada. Para bloquear una acción independientemente de lo que decida el modelo, necesitas un hook, no una frase. Conserva esta idea. La mayoría de las correcciones del final de esta publicación consisten en aplicar esa idea a un caso concreto.
Qué archivos de instrucciones se cargan y cuándo
Claude Code sube por el árbol de directorios desde el directorio en el que lo inició. Cada CLAUDE.md y CLAUDE.local.md desde la raíz del sistema de archivos hasta el directorio de trabajo se carga completo al iniciar. Los archivos se concatenan en ese orden, por lo que el archivo más cercano al directorio desde el que inició se lee en último lugar. Dentro de un mismo directorio, el archivo .local se añade después del archivo principal.
Los archivos de los subdirectorios por debajo del directorio de trabajo se comportan de otra forma. No se cargan al iniciar. Se cargan cuando el agente lee un archivo de ese directorio. Lo mismo ocurre con las reglas restringidas por ruta en .claude/rules/ que incluyen un campo de frontmatter paths:: entran en el contexto cuando se lee un archivo coincidente, no en cada turno.
Esta diferencia explica una parte importante de los fallos registrados. Coloca una regla en packages/api/CLAUDE.md, hace una pregunta sobre la API y el agente responde sin abrir ningún archivo de packages/api/. La regla no se ignoró. Nunca estuvo presente. Si el repositorio distribuye las instrucciones en archivos de instrucciones por paquete en un monorepo, esto es lo primero que debe comprobar, siempre.
Hay otra trampa de carga, y es la causa más común de que «el agente ignore mis instrucciones»: Claude Code lee CLAUDE.md, no AGENTS.md. Un repositorio que se ha estandarizado en AGENTS.md y no tiene CLAUDE.md no proporciona nada que Claude Code pueda cargar. El mecanismo compatible es un archivo CLAUDE.md cuya primera línea sea @AGENTS.md. Esto importa el archivo al iniciar y permite añadir debajo notas específicas de Claude. Un enlace simbólico también funciona cuando no necesita añadir nada más. Decidir qué debe incluir ese archivo es otra cuestión, que se trata en separar las instrucciones del agente de la documentación para personas.
Confirme que el archivo se ha cargado antes de reescribirlo
No cambie el texto hasta tener pruebas de que el agente puede ver el archivo. Hay dos comprobaciones, y la más sencilla va primero.
Ejecute /context dentro de la sesión. Muestra la ventana actual desglosada por categoría, y la lista Archivos de memoria incluye el nombre de cada archivo de instrucciones que se ha cargado realmente. Si un archivo no aparece en esa lista, no forma parte de la conversación, por lo que nada de lo que escriba en él puede tener efecto. /memory muestra las ubicaciones de los archivos y los abre para editarlos, incluidos los que todavía no existen.
Para obtener una respuesta más concluyente, registre las cargas. El evento de hook InstructionsLoaded se ejecuta cada vez que un CLAUDE.md o un archivo de reglas entra en el contexto, y su matcher indica por qué se produjo la carga: session_start, nested_traversal, path_glob_match, include o compact. Coloque esto en .claude/settings.json:
{
"hooks": {
"InstructionsLoaded": [
{
"matcher": "nested_traversal",
"hooks": [
{
"type": "command",
"command": "cat >> /tmp/instructions-loaded.log"
}
]
}
]
}
}El hook recibe la carga útil como JSON en la entrada estándar, por lo que cat añade el registro completo. Supervíselo con tail -f /tmp/instructions-loaded.log mientras trabaja. El estado de salida de este evento se ignora, por lo que el hook sólo puede observar, no bloquear. Si el archivo anidado nunca aparece en ese registro durante una sesión en la que esperaba que se cargara, deje de reescribirlo. El problema está en la ubicación.
Qué efecto tiene una sesión larga en las reglas
Aquí se aplican dos efectos distintos. Cada uno requiere una respuesta diferente.
Distancia. Una regla indicada en el turno 1 sigue dentro de la ventana en el turno 90, pero ahora compite con 90 turnos de texto más reciente y más específico de la tarea que está realizando. No puede eliminar este efecto mediante configuración, pero sí puede medirlo. Ejecute la misma tarea en una sesión nueva. Si la regla se cumple allí y deja de cumplirse después de avanzar mucho en una sesión larga, la distancia es la causa.
Compactación. Cuando la ventana se llena, el sistema resume la conversación hasta ese momento y continúa a partir de ese resumen. Lo que sobrevive es lo que el sistema de resumen considera importante, que no siempre coincide con lo que usted considera importante. Claude Code documenta el resultado de cada mecanismo, y las diferencias son grandes. La raíz del proyecto CLAUDE.md y las reglas sin ámbito se vuelven a inyectar desde el disco después de una compactación. La memoria automática se vuelve a inyectar desde el disco. Las reglas con paths: en el frontmatter se pierden hasta que se vuelve a leer un archivo coincidente. Los archivos CLAUDE.md anidados en subdirectorios se pierden hasta que se vuelve a leer un archivo de ese subdirectorio.
Ordene las instrucciones según esa tabla y el orden de fragilidad será evidente. Una regla que sólo escribió en el chat es el elemento más frágil de la sesión: sólo persiste si el resumen la conserva. Una regla en packages/api/CLAUDE.md es la siguiente, porque se cargó una vez, se eliminó al resumir y sólo vuelve a aparecer en la siguiente lectura de ese directorio. Una regla en el archivo de la raíz del proyecto es la más duradera, porque se vuelve a leer del disco cada vez.
Por tanto, si una instrucción debe mantenerse durante toda la sesión, debe estar en el archivo de la raíz del proyecto sin frontmatter paths:. Todo lo demás implica una decisión que debe tomar de forma consciente. Administrar lo que permanece en la ventana de contexto cubre /compact con un argumento de enfoque y /clear entre tareas no relacionadas; ambos factores cambian la frecuencia con la que el sistema de resumen puede decidir qué reglas suyas conservar.
Por qué el código circundante prevalece sobre la regla
Este es el fallo que más se describe y el que menos se diagnostica. El archivo indica que el acceso a la base de datos pasa por la capa de repositorios. El agente escribe un controlador que llama directamente al ORM (mapeador objeto-relacional). No ignoró la indicación por motivos de estilo. La evidencia pesó más.
Una regla describe una preferencia. El código demuestra una. Cuando el agente abre tres archivos del módulo que está a punto de editar y los tres llaman directamente al ORM, el contexto contiene una frase abstracta a un lado y tres ejemplos concretos, recientes y relacionados con la tarea al otro. Copiar el patrón local suele ser el comportamiento correcto. Aquí es incorrecto sólo porque usted sabe algo que el contexto desconoce: esos archivos son código heredado.
Por tanto, escriba esa información en la regla. Las reglas que mencionan sus propias contradicciones sobreviven al uso en un repositorio real. Las reglas que expresan sólo una preferencia no.
El acceso nuevo a la base de datos pasa porapp/repositories/. Los archivos bajoapp/legacy/todavía llaman directamente al ORM. Es código antiguo, no el patrón que se debe seguir. No lo copie.
La segunda frase es la que hace el trabajo. Indica al agente qué está a punto de encontrar y cómo debe interpretarlo, antes de que lo encuentre. La misma corrección se aplica a cualquier regla que el repositorio contradiga de forma visible: un estilo de commits que no sigue el historial, una estructura de pruebas que la mitad de la suite ignora o una convención de imports que sólo se aplica al código nuevo. Cuando el código no coincide con el archivo, describa la discrepancia en el archivo.
Una regla imprecisa no se puede comprobar, por lo que tampoco se puede seguir
"Escriba código limpio." "No sobrediseñe." "Manténgalo simple." "Tenga cuidado con las migraciones." Ninguna de estas reglas se puede comprobar mediante una acción específica, ni por parte del agente ni por su parte. Un agente que recibe una regla que no puede comprobar en su propia salida está adivinando, y usted evalúa esa suposición según sus impresiones.
Aplique esta prueba a cada línea del archivo. Escriba el comando de shell que terminaría con un estado distinto de cero cuando se incumpla la regla. Si no puede escribir ese comando, la regla no se puede comprobar. Compare estos pares:
- No se puede comprobar: "Mantenga las funciones pequeñas." Se puede comprobar: "Una función de más de 60 líneas necesita un comentario encima que explique el motivo."
- No se puede comprobar: "Pruebe los cambios." Se puede comprobar: "Ejecute
npm testy pegue el número de fallos antes de marcar una tarea como terminada." - No se puede comprobar: "Mantenga los archivos organizados." Se puede comprobar: "Los controladores HTTP están en
src/api/handlers/. No coloque nada más en ese directorio." - No se puede comprobar: "Formatee correctamente el código." Se puede comprobar: "Use una indentación de 2 espacios en los archivos
.ts."
"No sobrediseñe" es la regla que la gente abandona primero, porque la solución no es una frase más corta, sino una más larga: explicar con precisión qué significa el cambio mínimo que funciona proporciona al agente criterios con los que puede comparar su propio diff.
El tamaño plantea el mismo problema con otra apariencia. Las directrices de Claude Code recomiendan menos de 200 líneas por archivo de instrucciones y afirman directamente que los archivos más largos reducen el cumplimiento. Un archivo de 700 líneas no contiene instrucciones más firmes. Contiene 700 líneas de afirmaciones, con más posibilidades de contradecirse entre sí, y consume espacio de contexto en cada turno, lo que se refleja directamente en el uso de tokens. La estructuración del archivo para que cada regla aparezca bajo un encabezado que el lector pueda revisar está cubierta en cómo escribir un archivo de instrucciones que un agente pueda ejecutar.
Cómo diagnosticarlo en diez minutos
Ejecute estos pasos en orden. Saltar directamente al último paso es la razón por la que se terminan acumulando reglas extensas y enfáticas que siguen sin funcionar.
- Confirme que se cargó. Ejecute
/contexty revise la lista de archivos de Memory. Si el archivo no aparece, corrija su ubicación y deténgase. Ningún otro punto de esta lista se aplica todavía. - Reproduzca el problema en una sesión nueva. Inicie una sesión nueva y proporcione la tarea mínima que debería activar la regla. Si funciona al principio pero falla en una sesión larga, el problema apunta a la distancia o a la compactación. Si también falla aquí, el problema está en la propia regla.
- Elimine la competencia. Solicite el mismo cambio en un directorio cuyo código existente ya siga la regla. Si el cumplimiento vuelve a funcionar, el código circundante estaba imponiéndose a su frase.
- Busque un conflicto. Que dos archivos proporcionen instrucciones diferentes para el mismo comportamiento es un fallo documentado: el modelo puede elegir uno de forma arbitraria y no le informará de ello.
- Haga que se pueda comprobar y vuelva a probar. Reescriba la regla con una ruta concreta y una condición. Un aumento importante del cumplimiento indica que la causa era la redacción.
El paso 4 requiere un solo comando. Busque el tema en todas las fuentes de instrucciones, no sólo en el archivo que estaba editando:
grep -rni "migration" --include="CLAUDE.md" --include="CLAUDE.local.md" .
grep -rni "migration" .claude/rules/ ~/.claude/CLAUDE.md ~/.claude/rules/ 2>/dev/nullEncontrar resultados en dos archivos que indican cosas diferentes es el problema. Elimine uno. No intente establecer una prioridad con una redacción más contundente, porque no existe ningún motor de prioridades al que pueda recurrir.
Las correcciones, en orden de eficacia
Cada paso siguiente ofrece más eficacia que el anterior y requiere más trabajo de configuración. Empiece por arriba cuando sea barato reformular una regla. Baje al siguiente nivel en cuanto una regla sea lo bastante importante como para que no sean aceptables los incumplimientos ocasionales.
- Concretar la regla. Indique una ruta, un comando o una condición. Añada las pruebas en contra que el agente encontrará en el repositorio, como se mostró antes. Esto no tiene coste y resuelve una cantidad sorprendente de casos.
- Acercarla a aquello que regula. Puede ser un
CLAUDE.mdanidado, una regla limitada a una ruta en.claude/rules/o un comentario al principio del propio archivo. Así, la regla se carga en la misma lectura que el código al que se aplica. Acepte la contrapartida: todo lo que se cargue de esta forma se pierde en la siguiente compactación y vuelve a cargarse en la siguiente lectura coincidente. - Trasladar la aplicación a un hook. La prosa solicita. Un hook decide. Los hooks se ejecutan como código en eventos fijos del ciclo de vida y se aplican independientemente de la conclusión del modelo.
- Asignar la regla a una herramienta determinista y eliminar la prosa. Formato, orden de imports, longitud de línea, imports prohibidos, estructura del mensaje de commit.
ruff format,prettier --write,eslint, un hook depre-commit. El formateador acierta siempre y no consume tokens. La frase acierta la mayoría de las veces y consume tokens en cada turno.
Paso 3 completo. Suponga que el agente nunca debe editar los archivos de migración. Coloque esto en .claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/guard-migrations.sh"
}
]
}
]
}
}Y esto en .claude/hooks/guard-migrations.sh:
#!/usr/bin/env bash
set -euo pipefail
path=$(jq -r '.tool_input.file_path // empty')
case "$path" in
*/migrations/*)
echo "Files under migrations/ are written by hand. Stop and ask first." >&2
exit 2
;;
esac
exit 0Ejecute chmod +x .claude/hooks/guard-migrations.sh, inicie una sesión nueva y pida al agente que edite un archivo bajo migrations/. La edición se rechaza y el mensaje se devuelve como motivo. El código de salida 2 en PreToolUse bloquea la llamada a la herramienta antes de que se ejecute, y el texto de stderr se entrega al modelo como mensaje de bloqueo. ${CLAUDE_PROJECT_DIR} se resuelve en la raíz del proyecto, por lo que el hook funciona independientemente del directorio en el que se encuentre el agente. El agente no tiene que aceptar la regla, recordarla ni conservarla en el contexto. La edición no se realiza.
Para una prohibición simple sin lógica, permissions.deny en la configuración hace lo mismo sin necesidad de mantener un script, y los modos de permisos determinan qué se ejecuta sin pedirle permiso primero. Si una instrucción debe estar realmente en el nivel del system prompt y no en un mensaje de usuario, --append-system-prompt la coloca allí, aunque debe pasarse en cada invocación, por lo que resulta más adecuada para scripts que para el trabajo interactivo.
Lo que no se puede conseguir con instrucciones
Deje claro qué parte le corresponde. La ubicación, la redacción, los conflictos entre archivos y el tamaño del archivo son problemas del autor, con soluciones que corresponden al autor. El resto es comportamiento del modelo, y una redacción mejor no lo eliminará.
Aceptar no es cumplir. Un agente reconocerá una regla, se la repetirá correctamente y la incumplirá dos llamadas de herramientas después. El reconocimiento no cuesta nada ni permite predecir nada. No lo interprete como una corrección ni lo cuente como una prueba.
Algunos hábitos persisten. Añadir comentarios, incorporar gestión defensiva de errores, escribir un resumen final y ejecutar el siguiente comando obvio. Estos comportamientos reaparecen cuando una regla los prohíbe, aunque con una frecuencia menor que cero. Puede medir su propia tasa: ejecute la misma tarea diez veces en sesiones nuevas y cuente las infracciones. Cuando ese número deba ser cero, la regla debe salir del prompt.
Su propia sesión se convierte en un ejemplo. Si el agente incumple la regla en el turno 12 y usted lo deja pasar, esa infracción queda en el contexto como demostración y es mucho más reciente que la regla. Corrija una infracción en cuanto la detecte. Una infracción sin corregir enseña al resto de la sesión.
Un archivo de instrucciones no es un límite de seguridad. Modifica el comportamiento, pero no lo impone. Todo aquello cuyo incumplimiento sea costoso, como las credenciales o los comandos destructivos, debe gestionarse mediante permisos o un hook. Mantener los secretos fuera del alcance de un agente aplica el mismo principio a los datos: no pida a un agente que no lea un archivo; haga que el archivo no sea legible.
La versión breve: demuestre que el archivo se ha cargado, haga que la regla se pueda comprobar, colóquela junto al elemento que gobierna y, cuando la tasa de incumplimiento siga siendo importante, sáquela de la prosa. Una regla que un agente no puede ignorar es una regla que nunca se le pidió al agente.
FAQ
¿Por qué Claude Code ignora mi CLAUDE.md?
Compruebe que el archivo se haya cargado antes de asumir que se ignoró. Ejecute /context y revise la lista Memory files; si un archivo no aparece allí, no forma parte de la conversación. Los archivos de instrucciones se envían como un mensaje de usuario después del mensaje del sistema y se tratan como contexto, no como configuración obligatoria. Por tanto, no existe una garantía estricta de cumplimiento. En la mayoría de los casos, se trata de uno de estos cuatro problemas: el archivo está en un subdirectorio que el agente nunca leyó, dos archivos discrepan y el modelo eligió uno arbitrariamente, la regla es demasiado vaga para comprobar una acción, o el código existente muestra lo contrario de lo que indica la regla.
¿Editar el archivo de instrucciones durante la sesión cambia algo?
No para la copia que ya forma parte de la conversación. Los archivos situados por encima del directorio de trabajo se cargan completos al iniciar la sesión, por lo que el texto que conserva el modelo es el de ese momento. Para incorporar una edición, inicie una sesión nueva o pida al agente que lea el archivo con sus herramientas normales de archivos. De este modo, la versión actual se incorpora a la conversación como un mensaje nuevo. Después de una compactación, el archivo de la raíz del proyecto se vuelve a leer desde el disco, por lo que la nueva versión también se incorpora en ese momento.
¿Qué archivo prevalece si un CLAUDE.md raíz y otro anidado discrepan?
Ninguno de forma fiable. Los archivos descubiertos se concatenan en el contexto en lugar de sobrescribirse. Se ordenan desde la raíz del sistema de archivos hasta el directorio de trabajo, por lo que el archivo más cercano simplemente se lee al final. No existe un motor de precedencia que resuelva las contradicciones, y la documentación de Claude Code indica que las reglas contradictorias pueden resolverse arbitrariamente. Escriba los archivos anidados como adiciones que indiquen la ruta que regulan y elimine la contradicción en lugar de intentar darle prioridad.
¿Mis instrucciones sobreviven a /compact?
Depende de cómo se hayan cargado. El archivo raíz del proyecto CLAUDE.md, las reglas sin ámbito y la memoria automática se vuelven a inyectar desde el disco después de una compactación. Las reglas con frontmatter paths: y los archivos CLAUDE.md anidados en subdirectorios se pierden hasta que se vuelve a leer un archivo correspondiente. Todo lo que haya escrito únicamente en el chat sobrevive sólo si el resumidor decidió conservarlo. Si una regla debe mantenerse durante toda la sesión, colóquela en el archivo raíz del proyecto sin frontmatter paths:.
¿Cuándo debe convertirse una regla en un hook en lugar de mantenerse como texto?
Cuando la comprobación sea determinista y el coste de omitirla sea mayor que el de escribir un script pequeño. Las restricciones de rutas de archivos, los comandos obligatorios antes de un commit y las llamadas a herramientas prohibidas cumplen este criterio. Un hook PreToolUse que termina con el estado 2 bloquea directamente la llamada a la herramienta y devuelve el texto de stderr al modelo como motivo. Por tanto, la regla se aplica aunque ya no figure en el contexto. Todo lo que pueda decidir un formateador o un linter debe quedar bajo el control de esa herramienta y eliminarse por completo del archivo de instrucciones.