SSD Nodes Learn Hosting plans →
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-08-27

Perché gli agenti di coding ignorano le istruzioni

La regola dice di fermarsi, ma l'agente continua? Scopri se non è nel contesto, è vaga, contraddetta o troppo lontana, con una diagnosi pratica.

Perché gli agenti di coding ignorano le istruzioni

Gli agenti di coding ignorano le istruzioni per quattro motivi, e nessuno dipende dal fatto che tu sia stato troppo cortese. La regola non è mai entrata nella finestra di contesto. La regola era troppo vaga per poter verificare un'azione rispetto a essa. Qualcos'altro nel contesto la contraddiceva, di solito il codice che l'agente aveva appena letto. Oppure la regola è ancora caricata, ma si trova molto prima del turno corrente e l'agente lavora sulla base di ciò che ha vicino.

Ogni causa richiede una correzione specifica, quindi il primo compito consiste nel distinguerle. Le maiuscole e la parola IMPORTANT non costituiscono una diagnosi. Gli aspetti tecnici descritti di seguito usano Claude Code come esempio pratico, perché il suo comportamento di caricamento e compattazione è documentato in dettaglio ad agosto 2026. Gli altri strumenti differiscono nei dettagli, ma in linea generale si comportano allo stesso modo.

Prima definiamo due termini. La finestra di contesto è il blocco di testo che il modello vede in un determinato turno: il prompt di sistema, i file con le istruzioni, la conversazione e ogni file letto dall'agente. L'harness è il programma che circonda il modello, cioè il componente che legge i file dal disco e assembla quel blocco. Quasi ogni lamentela descritta in questo articolo riguarda in realtà l'harness, non il modello.

Il file di istruzioni è un messaggio, non un'impostazione

Un file di istruzioni non è una configurazione. Nulla nel runtime legge CLAUDE.md e la applica. L'harness legge il file dal disco e incolla il testo nella conversazione. In Claude Code, quel contenuto viene fornito come messaggio dell'utente dopo il prompt di sistema. Il modello vede quindi le tue regole nello stesso modo in cui vede qualsiasi altro testo digitato.

Questo ha una conseguenza scomoda. Le tue regole competono con ogni altro testo presente nella finestra, sullo stesso piano. Una regola è un'affermazione. Il file appena aperto dall'agente è un'evidenza. Quando i due elementi sono in conflitto, spesso prevale l'evidenza e non viene generato alcun errore, perché dal punto di vista del modello non è successo nulla di errato.

La documentazione ufficiale lo afferma chiaramente: i file di istruzioni vengono trattati come contesto, non come configurazione applicata. Per bloccare un'azione indipendentemente dalla decisione del modello, serve un hook, non una frase. Tieni presente questo principio. La maggior parte delle correzioni alla fine di questo articolo consiste nell'applicarlo a un caso specifico.

Quali file di istruzioni vengono caricati e quando

Claude Code risale l'albero delle directory partendo dalla directory in cui è stato avviato. Ogni file CLAUDE.md e CLAUDE.local.md, dalla radice del filesystem fino alla directory di lavoro, viene caricato completamente all'avvio. I file vengono concatenati in quest'ordine: quello più vicino alla directory da cui è stato avviato viene letto per ultimo e, all'interno della stessa directory, il file .local viene aggiunto dopo quello principale.

I file nelle sottodirectory al di sotto della directory di lavoro si comportano diversamente. Non vengono caricati all'avvio. Vengono caricati quando l'agente legge un file in quella directory. Lo stesso vale per le regole con ambito limitato al percorso in .claude/rules/ che contengono un campo frontmatter paths:: entrano nel contesto quando viene letto un file corrispondente, non a ogni turno.

Questa differenza spiega gran parte dei problemi segnalati. Inserisci una regola in packages/api/CLAUDE.md, fai una domanda sull'API e l'agente risponde senza mai aprire un file sotto packages/api/. La regola non è stata ignorata. Non era mai presente nel contesto. Se il repository distribuisce le indicazioni tra file di istruzioni per pacchetto in un monorepo, questo è il primo controllo da eseguire, ogni volta.

Esiste un'altra insidia nel caricamento, ed è la causa più comune del messaggio «l'agente ha ignorato le mie istruzioni»: Claude Code legge CLAUDE.md, non AGENTS.md. Un repository standardizzato su AGENTS.md e privo di CLAUDE.md non fornisce a Claude Code alcun file da caricare. Il meccanismo supportato è un file CLAUDE.md la cui prima riga è @AGENTS.md. Questo importa il file all'avvio e consente di aggiungere sotto eventuali note specifiche per Claude. Anche un collegamento simbolico funziona quando non è necessario aggiungere altro. Stabilire che cosa inserire inizialmente in quel file è una questione distinta, trattata in separare le istruzioni per l'agente dalla documentazione per le persone.

Confermare che il file sia stato caricato prima di riscriverlo

Non modificare il testo finché non hai verificato che l'agent possa vedere il file. Sono disponibili due controlli; esegui prima quello più semplice.

Esegui /context nella sessione. Il comando stampa la finestra corrente suddivisa per categoria e, nell'elenco Memory files, indica ogni file di istruzioni effettivamente caricato. Se un file non compare nell'elenco, non fa parte della conversazione e quindi nessun contenuto scritto al suo interno può avere effetto. /memory elenca i percorsi dei file e li apre per la modifica, inclusi quelli che non esistono ancora.

Per una verifica più approfondita, registra i caricamenti. L'evento hook InstructionsLoaded viene attivato ogni volta che un CLAUDE.md o un file di regole entra nel contesto; il relativo matcher indica il motivo del caricamento: session_start, nested_traversal, path_glob_match, include o compact. Inserisci quanto segue in .claude/settings.json:

{
  "hooks": {
    "InstructionsLoaded": [
      {
        "matcher": "nested_traversal",
        "hooks": [
          {
            "type": "command",
            "command": "cat >> /tmp/instructions-loaded.log"
          }
        ]
      }
    ]
  }
}

L'hook riceve il payload in formato JSON tramite lo standard input, quindi cat aggiunge l'intero record. Monitoralo con tail -f /tmp/instructions-loaded.log mentre lavori. Il codice di uscita di questo evento viene ignorato, quindi l'hook può solo osservare e non bloccare. Se il file annidato non compare mai in quel log durante una sessione in cui ti aspetti che venga caricato, interrompi la riscrittura. Il problema è la posizione.

Cosa comporta una sessione lunga per le tue regole

In questo caso si applicano due effetti distinti, che richiedono risposte diverse.

Distanza. Una regola indicata al turno 1 è ancora nella finestra al turno 90, ma ora compete con 90 turni di testo più recente e più specifico rispetto all'attività in corso. Non puoi eliminare questo effetto tramite configurazione, ma puoi misurarlo. Esegui la stessa attività in una sessione nuova. Se la regola viene rispettata nella sessione nuova ma non nelle fasi avanzate di una sessione lunga, hai identificato l'effetto della distanza.

Compattazione. Quando la finestra si riempie, l'har ne ss riassume la conversazione fino a quel momento e prosegue dal riepilogo. Ciò che sopravvive è quanto il sistema di riepilogo ha giudicato importante, che non coincide necessariamente con ciò che consideri importante. Claude Code documenta il comportamento per ogni meccanismo e le differenze sono significative. La root del progetto CLAUDE.md e le regole senza ambito vengono reinserite dal disco dopo una compattazione. La memoria automatica viene reinserita dal disco. Le regole con frontmatter paths: vengono perse finché non viene letto di nuovo un file corrispondente. I file CLAUDE.md annidati nelle sottodirectory vengono persi finché non viene letto di nuovo un file in quella sottodirectory.

Classifica le istruzioni in base a questa tabella e otterrai l'ordine di fragilità. Una regola inserita soltanto nella chat è l'elemento più fragile della sessione: persiste solo se il riepilogo la conserva. Una regola in packages/api/CLAUDE.md viene dopo, perché viene caricata una volta, eliminata dal riepilogo e ripristinata solo alla lettura successiva in quella directory. Una regola nel file root del progetto è l'elemento più duraturo, perché viene riletta dal disco ogni volta.

Quindi, se un'istruzione deve rimanere valida per tutta la sessione, inseriscila nel file root del progetto senza frontmatter paths:. Tutto il resto è un compromesso da scegliere consapevolmente. Gestire ciò che rimane nella finestra di contesto tratta /compact con un argomento focus e /clear tra attività non correlate, due fattori che modificano la frequenza con cui il sistema di riepilogo può decidere quali fossero le tue regole.

Perché il codice circostante prevale sulla regola

Questo è il problema che viene descritto più spesso e diagnosticato meno spesso. Il file stabilisce che l'accesso al database passa dal repository layer. L'agente scrive un handler che chiama direttamente l'ORM (object relational mapper). Non ha ignorato le tue indicazioni per motivi di stile. Ha seguito le evidenze disponibili.

Una regola descrive una preferenza. Il codice ne dimostra una. Quando l'agente apre tre file del modulo che sta per modificare e tutti e tre chiamano direttamente l'ORM, il contesto contiene una frase astratta da una parte e tre esempi concreti, recenti e pertinenti all'attività dall'altra. Copiare il pattern locale è in genere il comportamento corretto. In questo caso è sbagliato solo perché tu sai qualcosa che il contesto non sa: quei file contengono codice legacy.

Scrivilo quindi nella regola. Le regole che indicano le proprie controevidenze resistono al confronto con un repository reale. Le regole che esprimono soltanto una preferenza non ci riescono.

Il nuovo accesso al database passa da app/repositories/. I file sotto app/legacy/ chiamano ancora direttamente l'ORM. Si tratta di codice obsoleto, non del pattern da seguire. Non copiarlo.

La seconda frase svolge il lavoro principale. Dice all'agente che cosa troverà e come deve interpretarlo, prima che lo trovi. La stessa correzione si applica a qualsiasi regola che il repository contraddice in modo evidente: uno stile dei commit che la cronologia non segue, una struttura dei test ignorata da metà della suite, una convenzione per gli import applicata solo al nuovo codice. Quando il codice non è coerente con il file, indica la discrepanza nel file.

Una regola vaga non può essere verificata e quindi non può essere applicata

"Scrivi codice pulito." "Non progettare troppo." "Mantieni la semplicità." "Fai attenzione alle migrazioni." Nessuna di queste indicazioni può essere verificata rispetto a un'azione specifica, né dall'agente né da te. Se un agente riceve una regola che non può verificare sul proprio output, procede per tentativi e tu valuti il risultato in base a una sensazione.

Applica questo test a ogni riga del file. Scrivi il comando shell che restituisce un codice diverso da zero quando la regola viene violata. Se non puoi scrivere quel comando, la regola non è verificabile. Confronta queste coppie:

  • Non verificabile: "Mantieni le funzioni brevi." Verificabile: "Una funzione più lunga di 60 righe deve avere sopra di sé un commento che spieghi il motivo."
  • Non verificabile: "Testa le modifiche." Verificabile: "Esegui npm test e incolla il numero di errori prima di considerare completata un'attività."
  • Non verificabile: "Mantieni i file organizzati." Verificabile: "I gestori HTTP si trovano in src/api/handlers/. Nient'altro deve essere inserito in quella directory."
  • Non verificabile: "Formatta correttamente il codice." Verificabile: "Usa un'indentazione di 2 spazi nei file .ts."

"Non progettare troppo" è l'indicazione a cui le persone rinunciano per prima, perché la correzione non consiste in una frase più breve, ma in una frase più lunga: specificare che cosa significa esattamente la modifica minima che risolve il problema fornisce all'agente criteri con cui confrontare il proprio diff.

La dimensione presenta lo stesso problema sotto un'altra forma. Le linee guida di Claude Code raccomandano meno di 200 righe per file di istruzioni e dichiarano esplicitamente che i file più lunghi riducono il livello di applicazione delle istruzioni. Un file di 700 righe non contiene istruzioni più vincolanti. Contiene 700 affermazioni con più possibilità di contraddirsi e viene conteggiato nella finestra a ogni singolo turno, il che si riflette direttamente sull'utilizzo dei token. La strutturazione del file, con ogni regola sotto un'intestazione che il lettore possa scorrere rapidamente, è descritta in scrivere un file di istruzioni che l'agente possa applicare. Meglio ancora, elimina le parti descrittive anziché prescrittive: una panoramica delle directory che indica dove si trovano gestori e modelli è una struttura che l'agente può consultare quando serve tramite una mappa analizzata del repository, invece di mantenerla nella finestra a ogni turno.

Come diagnosticare il problema in dieci minuti

Eseguire questi controlli nell’ordine indicato. Passare direttamente all’ultimo passaggio porta spesso ad accumulare un lungo file di regole formulate in modo perentorio che continua a non funzionare.

  1. Verificare che il file sia stato caricato. Eseguire /context e leggere l’elenco Memory files. Se il file non è presente, correggere il percorso e fermarsi. Nessun altro controllo di questo elenco è ancora applicabile.
  2. Riprodurre il problema in una nuova sessione. Avviare una nuova sessione e assegnare il compito più semplice che dovrebbe attivare la regola. Se la regola funziona all’inizio ma non in una sessione lunga, il problema riguarda la distanza dal contesto o la compattazione. Se non funziona nemmeno nella nuova sessione, il problema è nella regola stessa.
  3. Rimuovere la concorrenza. Richiedere la stessa modifica in una directory il cui codice esistente segue già la regola. Se la conformità viene ripristinata, il codice circostante stava prevalendo sulla regola.
  4. Cercare un conflitto. Due file che forniscono indicazioni diverse per lo stesso comportamento costituiscono un errore documentato: il modello può sceglierne uno in modo arbitrario e non comunicherà di averlo fatto.
  5. Rendere la regola verificabile e ripetere il test. Riscrivere la regola indicando un percorso concreto e una condizione. Un aumento significativo della conformità indica che la causa era la formulazione.

Il passaggio 4 richiede un solo comando. Cercare l’argomento in tutte le fonti delle istruzioni, non soltanto nel file che si stava modificando:

grep -rni "migration" --include="CLAUDE.md" --include="CLAUDE.local.md" .
grep -rni "migration" .claude/rules/ ~/.claude/CLAUDE.md ~/.claude/rules/ 2>/dev/null

La presenza di indicazioni diverse in due file è il problema. Eliminarne una. Non cercare di stabilire una priorità usando una formulazione più forte, perché non esiste un motore di priorità a cui fare riferimento.

Le correzioni, in ordine di efficacia

Ogni passaggio seguente offre un controllo più efficace di quello precedente, ma richiede più lavoro di configurazione. Inizia dall’alto quando è sufficiente riformulare una regola a basso costo. Scendi al passaggio successivo non appena una regola diventa abbastanza importante da rendere inaccettabili le omissioni occasionali.

  1. Rendi concreta la regola. Indica un percorso, un comando o una condizione. Aggiungi gli elementi contrari che l’agente troverà nel repository, come mostrato in precedenza. Non costa nulla e risolve una quota sorprendentemente ampia dei casi.
  2. Avvicinala all’elemento che disciplina. Usa un CLAUDE.md annidato, una regola con ambito limitato al percorso in .claude/rules/ oppure un commento all’inizio del file stesso. In questo modo la regola viene letta insieme al codice a cui si applica. Accetta il compromesso: tutto ciò che viene caricato in questo modo viene rimosso durante la compattazione successiva e torna disponibile alla lettura successiva corrispondente.
  3. Sposta l’applicazione della regola in un hook. La prosa chiede. Un hook decide. Gli hook vengono eseguiti come codice in eventi fissi del ciclo di vita e si applicano indipendentemente dalla conclusione a cui arriva il modello.
  4. Affida la regola a uno strumento deterministico ed elimina la prosa. Formattazione, ordine degli import, lunghezza delle righe, import vietati, formato del messaggio di commit. ruff format, prettier --write, eslint, un hook pre-commit. Il formatter applica la regola correttamente ogni volta e non consuma token. La frase è corretta nella maggior parte dei casi e consuma token a ogni turno.

Passaggio 3 completo. Supponiamo che l’agente non debba mai modificare i file di migrazione. Inserisci questo contenuto in .claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/guard-migrations.sh"
          }
        ]
      }
    ]
  }
}

E questo contenuto in .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 0

Esegui chmod +x .claude/hooks/guard-migrations.sh, quindi avvia una nuova sessione e chiedi all’agente di modificare un file in migrations/. La modifica viene rifiutata e il motivo viene restituito nel messaggio. Il codice di uscita 2 in PreToolUse blocca la chiamata allo strumento prima dell’esecuzione e il testo su stderr viene passato al modello come messaggio di blocco. ${CLAUDE_PROJECT_DIR} restituisce la directory radice del progetto, quindi l’hook funziona indipendentemente dalla directory corrente dell’agente. L’agente non deve accettare la regola, ricordarla o averla ancora nel contesto. La modifica non viene eseguita.

Per un divieto semplice che non richiede logica, permissions.deny nelle impostazioni svolge lo stesso compito senza uno script da mantenere; le modalità di autorizzazione determinano quali operazioni vengono eseguite senza chiedere prima il tuo consenso. Se un’istruzione deve necessariamente trovarsi a livello di prompt di sistema anziché in un messaggio dell’utente, --append-system-prompt la inserisce in quel livello, ma deve essere passata a ogni invocazione; questo la rende più adatta agli script che al lavoro interattivo.

Cosa non si può ottenere con le sole istruzioni

Chiarisci quale metà del problema dipende da te. Posizione, formulazione, conflitti tra file e dimensione dei file sono problemi dell'autore, che l'autore deve risolvere. Il resto dipende dal comportamento del modello e una formulazione migliore non lo eliminerà.

Accettare non significa rispettare. Un agente riconosce una regola, te la ripete correttamente e la viola due chiamate agli strumenti dopo. Il riconoscimento non costa nulla e non consente di prevedere il comportamento. Non considerarlo una correzione e non usarlo come test.

Alcune abitudini persistono. Aggiungere commenti, introdurre una gestione degli errori difensiva, scrivere un riepilogo finale, eseguire il comando successivo più ovvio. Questi comportamenti ricompaiono quando una regola li vieta, anche se con una frequenza ridotta e non pari a zero. Puoi misurare la tua frequenza: esegui la stessa attività dieci volte in sessioni nuove e conta le violazioni. Se quel numero deve essere zero, la regola deve uscire dal prompt. Dichiarare conclusa un'attività quando una parte è ancora incompleta ha la stessa origine. La correzione deve essere strutturale, non verbale: la skill unlazy sostituisce la frase con un Depth Tree e con file gate che l'agente deve superare prima di poter dichiarare conclusa l'attività.

La sessione stessa diventa un esempio. Se l'agente ha violato la regola al turno 12 e lo hai lasciato fare, quella violazione ora fa parte del contesto come dimostrazione ed è molto più recente della regola. Correggi una violazione nel momento in cui la rilevi. Una violazione non corretta insegna quel comportamento al resto della sessione.

Un file di istruzioni non è un confine di sicurezza. Modifica il comportamento, ma non lo impone. Tutto ciò per cui un errore ha conseguenze rilevanti, come le credenziali o i comandi distruttivi, deve essere gestito tramite permessi o un hook. Tenere i secret fuori dalla portata di un agente applica lo stesso principio ai dati: non chiedere a un agente di non leggere un file; fai in modo che il file non sia leggibile.

In sintesi: dimostra che il file è stato caricato, rendi la regola verificabile, spostala accanto all'oggetto che governa e, quando la frequenza degli errori resta importante, rimuovila dalla prosa. Una regola che l'agente non può ignorare è una regola che non gli è mai stata affidata.

FAQ

Perché Claude Code ignora il mio CLAUDE.md?

Verificate che il file sia stato caricato prima di concludere che sia stato ignorato. Eseguite /context e controllate l'elenco Memory files; se un file non compare nell'elenco, non fa parte della conversazione. I file di istruzioni vengono forniti come messaggio dell'utente dopo il prompt di sistema e vengono trattati come contesto, non come configurazione vincolante. Non esiste quindi alcuna garanzia di conformità rigorosa. Nella maggior parte dei casi reali, la causa rientra in una di queste quattro categorie: il file si trova in una sottodirectory che l'agente non ha mai letto, due file sono in conflitto e il modello ne ha scelto uno in modo arbitrario, la regola è troppo vaga per poterla verificare rispetto a un'azione oppure il codice circostante dimostra l'opposto di quanto indicato dalla regola.

La modifica del file di istruzioni durante la sessione cambia qualcosa?

Non per la copia già presente nella conversazione. I file che si trovano sopra la directory di lavoro vengono caricati completamente all'avvio, quindi il testo in possesso del modello è quello presente al momento dell'avvio. Per acquisire una modifica, avviate una nuova sessione oppure chiedete all'agente di leggere il file con i normali strumenti di gestione dei file; in questo modo la versione corrente viene inserita nella conversazione come nuovo messaggio. Dopo una compattazione, il file nella radice del progetto viene riletto dal disco, quindi anche la nuova versione viene acquisita in quel momento.

Quale file prevale quando un CLAUDE.md nella radice e uno annidato sono in conflitto?

Nessuno dei due in modo affidabile. I file individuati vengono concatenati nel contesto invece di sovrascriversi a vicenda. L'ordine va dalla radice del filesystem alla directory di lavoro, quindi il file più vicino viene semplicemente letto per ultimo. Non esiste un motore di precedenza che risolva le contraddizioni e la documentazione di Claude Code specifica che le regole contraddittorie possono essere risolte in modo arbitrario. Scrivete i file annidati come aggiunte che indicano il percorso a cui si applicano ed eliminate la contraddizione invece di cercare di far prevalere una regola sull'altra.

Le mie istruzioni sopravvivono a /compact?

Dipende da come sono state caricate. Il file nella radice del progetto CLAUDE.md, le regole senza ambito e la memoria automatica vengono reinseriti dal disco dopo una compattazione. Le regole con frontmatter paths: e i file annidati CLAUDE.md nelle sottodirectory vengono persi finché non viene letto di nuovo un file corrispondente. Tutto ciò che avete digitato soltanto nella chat sopravvive solo se il riepilogatore ha deciso di conservarlo. Se una regola deve rimanere valida per l'intera sessione, inseritela nel file nella radice del progetto senza frontmatter paths:.

Quando una regola dovrebbe diventare un hook invece di restare testo descrittivo?

Quando il controllo è deterministico e il costo di un'omissione è superiore a quello necessario per scrivere un piccolo script. Le restrizioni sui percorsi dei file, i comandi obbligatori prima di un commit e le chiamate agli strumenti vietate rientrano tutte in questa categoria. Un hook PreToolUse che termina con lo stato 2 blocca direttamente la chiamata allo strumento e restituisce al modello il testo di stderr come motivazione. In questo modo la regola viene applicata indipendentemente dal fatto che sia ancora presente nel contesto. Qualsiasi controllo che un formatter o un linter è in grado di decidere dovrebbe essere affidato a quello strumento e rimosso completamente dal file di istruzioni.