SSD Nodes Learn 🎉 VPS da $5.50/mese
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-08-13

AGENTS.md annidati per un monorepo

Scopri come distribuire AGENTS.md tra radice e servizi: regole comuni nel file principale, comandi locali nei file annidati, meno contesto sprecato dall’agente.

Cosa significa AGENTS.md annidato in un monorepo

Un file AGENTS.md annidato in un monorepo consiste in un file breve nella radice del repository e in un altro file all’interno di ogni directory dei servizi. Il file nella radice contiene le poche regole valide ovunque e una mappa dei percorsi degli altri file. Ogni file dei servizi contiene i comandi e le convenzioni relativi esclusivamente a quella directory. Un agente che modifica services/worker/queue.py legge quindi il file nella radice e quello del worker, senza consumare contesto per il front end che non dovrà mai modificare.

Non c’è nulla da installare. AGENTS.md è una convenzione, come dichiara esplicitamente il progetto upstream:

AGENTS.md è semplice Markdown standard. Usa le intestazioni che preferisci; l’agente analizza semplicemente il testo che fornisci.

Per questo vale la pena imparare correttamente questa tecnica. Il formato non cambierà senza preavviso. I problemi derivano dal posizionamento e dalla manutenzione, ed entrambi sono di tua responsabilità.

Perché un unico AGENTS.md alla radice smette di funzionare?

Un unico AGENTS.md di 600 righe alla radice di un repository che contiene una web app, un background worker e una directory Terraform non funziona per quattro motivi distinti.

Diventa obsoleto perché nessuno ne è responsabile. L'ingegnere che rinomina uno script di test in apps/web sta modificando file sotto apps/web. Il file AGENTS.md alla radice non fa parte di quella modifica, quindi nessun revisore vede la discrepanza. Dopo sei settimane, il file descrive una procedura di build che non esiste più e la persona che ha introdotto il problema ha dimenticato la modifica.

Consuma contesto per ogni attività. Questi file vengono caricati all'inizio della sessione, prima che l'agente sappia cosa gli verrà chiesto. La documentazione di Claude Code indica un valore preciso: "target under 200 lines per CLAUDE.md file. Longer files consume more context and reduce adherence." Codex smette di unire i file di istruzioni quando la loro dimensione complessiva raggiunge 32 KiB, il valore predefinito di project_doc_max_bytes. Un file alla radice che documenta quattro servizi utilizza quel budget per tre di essi in ogni singola attività.

Le istruzioni iniziano a contraddirsi. La directory web richiede pnpm test. Il worker richiede pytest -q. Quando vengono scritte nello stesso file, ciascuna regola è corretta solo in alcuni casi, quindi l'agente deve determinare quale si applica. La documentazione di Claude Code descrive il risultato: "if two rules contradict each other, Claude may pick one arbitrarily." Un file specifico per directory elimina l'incertezza, perché solo una delle due regole si trova nel contesto.

Si riempie di informazioni che l'agente può ricavare dal codice. Un albero delle directory, un elenco delle dipendenze, un riepilogo delle funzioni di ogni pacchetto. Il controllo /doctor di Claude Code esiste per rimuovere esattamente questo tipo di contenuto. "cuts content Claude can derive from the codebase, such as directory layouts, dependency lists, and architecture overviews" e conserva "pitfalls, rationale, and conventions that differ from tool defaults." Questa frase è il criterio migliore che conosco per stabilire se una riga debba appartenere al file.

L’agente legge il file nella directory root o soltanto quello più vicino?

È questo il punto in cui la maggior parte delle persone interpreta male il modello. Perciò è utile citare la convenzione upstream invece di parafrasarla:

Inserisci un altro AGENTS.md in ogni package. Gli agent leggono automaticamente il file più vicino nella gerarchia delle directory, quindi quello più vicino ha la precedenza e ogni sottoprogetto può distribuire istruzioni personalizzate.

Per i conflitti:

Ha la precedenza l’AGENTS.md più vicino al file modificato; i prompt espliciti dell’utente nella chat hanno la precedenza su tutto.

Per molte persone, l’espressione “ha la precedenza” significa che “il file nella root viene ignorato”. Non è così. Negli strumenti che implementano questa convenzione, vengono letti tutti i file lungo il percorso dalla root del repository fino alla directory di lavoro e il loro contenuto viene unito. Il file più vicino ha la precedenza soltanto quando due file specificano indicazioni diverse sullo stesso argomento.

Codex descrive esplicitamente il meccanismo: “Codex concatena i file dalla root verso il basso, separandoli con righe vuote. I file più vicini alla directory corrente sovrascrivono le indicazioni precedenti.” Claude Code percorre lo stesso percorso per il proprio nome file. I file nelle directory sopra la directory di lavoro “vengono caricati completamente all’avvio” e “tutti i file individuati vengono concatenati nel contesto, invece di sovrascriversi a vicenda”. Le directory sotto la directory di lavoro si comportano in modo diverso: Claude Code carica quei file su richiesta, “quando Claude legge file in quelle directory”.

Ne derivano due conseguenze pratiche. Il file nella root è un prefisso presente in ogni sessione del repository. Considera quindi ogni riga come una riga il cui costo viene sostenuto cento volte alla settimana. Un file specifico di una directory non comporta alcun costo quando l’agente lavora in un’altra posizione. In questo modo, i dettagli possono essere inseriti lì senza appesantire il contesto generale.

Questo comportamento è stato verificato sulla documentazione di Codex e Claude Code nell’agosto 2026. Gli strumenti implementano la convenzione in modo leggermente diverso e possono modificarla. Verifica quindi le regole di caricamento dell’agente utilizzato dal tuo team.

Un esempio completo di struttura per un repository con tre servizi

repo/
  AGENTS.md                   rules true everywhere, plus the map
  apps/web/AGENTS.md          TypeScript client, Vite, Vitest
  services/worker/AGENTS.md   Python queue consumer, pytest
  infra/AGENTS.md             Terraform and the deploy scripts

Il file nella directory principale è volutamente breve. Indica dove cercare e contiene solo le regole valide in tutte le directory.

# AGENTS.md

This is a monorepo. Each top-level directory ships its own AGENTS.md.
Read this file and the AGENTS.md nearest the code you are editing
before you change anything.

- `apps/web` browser client
- `services/worker` queue consumer
- `infra` Terraform and deploy scripts

## Rules for the whole repository

- The package manager is `pnpm`. `npm install` writes a second lockfile
  that CI ignores, so the install you tested is not the install that ships.
- Any `generated/` directory is build output. Edit the schema in
  `schemas/` and run `pnpm codegen` instead.
- `.env.local` holds real credentials. Do not read it and do not print it.
- If you change code in a directory, update that directory's AGENTS.md
  in the same commit.

Il file specifico della directory contiene i dettagli e può avere la lunghezza necessaria per quella directory.

# apps/web

Browser client. Vite and React, TypeScript with `strict` on.

## Commands

- `pnpm dev` serves on port 5173.
- `pnpm test` runs Vitest once and exits.
- `pnpm typecheck` runs `tsc --noEmit`.

## Conventions

- One component per file under `src/components/`.
- All HTTP goes through `src/api/client.ts`. Do not call `fetch` directly,
  because the client attaches the auth header and retries on 429.

## Traps

- `pnpm build` does not type check. Vite strips the types instead of
  checking them, so a broken type still produces a green build.
  Run `pnpm typecheck` as a separate step.

Il file del worker ha la stessa struttura, ma contenuti diversi: il comando di installazione, pytest -q, il motivo per cui il consumer deve restare idempotente e la migrazione che deve essere eseguita prima che i test abbiano esito positivo. Il file dell'infrastruttura contiene le regole che impediscono a un agent di causare danni. Non eseguire mai terraform apply. Esegui terraform plan e fermati, quindi indica il backend dello stato già configurato, in modo che l'agent non tenti di inizializzarne uno nuovo.

Notare che nessuno di questi file contiene una descrizione dello scopo dei singoli servizi. Questo aspetto riguarda le persone. Upstream traccia la stessa distinzione e afferma che "i file README.md sono destinati alle persone: quick start, descrizioni dei progetti e linee guida per i contributi", mentre AGENTS.md contiene "il contesto aggiuntivo, talvolta dettagliato, di cui hanno bisogno gli agent di coding: passaggi di compilazione, test e convenzioni". La separazione tra AGENTS.md e un README rivolto alle persone analizza questa distinzione frase per frase, mentre un DESIGN.md che documenta il motivo per cui il codice ha questa struttura tratta il terzo file, quello che spiega le decisioni anziché i comandi.

Chi aggiorna il file quando cambia il codice?

Una sola regola, da inserire nel file radice: chi modifica il codice in una directory aggiorna l'AGENTS.md di quella directory nello stesso commit.

Questa regola funziona per un motivo meccanico, non culturale. Il file specifico della directory si trova nello stesso diff del codice, quindi il reviewer della pull request li vede entrambi nello stesso momento. Un file radice appartiene a tutti, quindi non appartiene a nessuno e non compare mai nel diff che qualcuno sta già esaminando.

Applica la regola con un controllo sulla pull request. Il controllo individua l'AGENTS.md più vicino sopra ogni file modificato, quindi segnala i casi in cui quel file non è stato modificato.

#!/usr/bin/env bash
# Warn when code changed but the nearest AGENTS.md above it did not.
changed=$(git diff --name-only origin/main...HEAD)

nearest_doc() {
  d=$(dirname "$1")
  while [ "$d" != "." ]; do
    if [ -f "$d/AGENTS.md" ]; then echo "$d/AGENTS.md"; return; fi
    d=$(dirname "$d")
  done
  echo "AGENTS.md"
}

printf '%s\n' "$changed" | while read -r f; do
  [ -n "$f" ] || continue
  case "$f" in AGENTS.md|*/AGENTS.md) continue ;; esac
  doc=$(nearest_doc "$f")
  printf '%s\n' "$changed" | grep -Fqx "$doc" && continue
  echo "note: $f changed but $doc was not updated"
done

In un branch che ha riscritto il client API senza modificare la documentazione, l'output è simile al seguente:

note: apps/web/src/api/client.ts changed but apps/web/AGENTS.md was not updated

Mantieni il controllo come avviso, non come errore. Un gate bloccante insegna alle persone ad aggiungere una riga vuota al file per fare passare la CI, e un file modificato solo per soddisfare un robot vale meno di nessun file. L'avviso dà al reviewer una domanda da porre. È questo l'aspetto che funziona davvero.

Come individuare un file AGENTS.md non più aggiornato?

Oggi è possibile eseguire due controlli e osservare un sintomo durante una sessione.

Confrontare la data di ogni file con quella del codice descritto. %cs stampa la data del commit come YYYY-MM-DD.

for f in $(git ls-files '*AGENTS.md'); do
  d=$(dirname "$f")
  printf '%s  doc:%s  code:%s\n' "$f" \
    "$(git log -1 --format=%cs -- "$f")" \
    "$(git log -1 --format=%cs -- "$d")"
done
apps/web/AGENTS.md          doc:2026-02-11  code:2026-08-07
services/worker/AGENTS.md   doc:2026-07-29  code:2026-08-09
infra/AGENTS.md             doc:2026-08-01  code:2026-08-01

Una data della documentazione di sei mesi precedente a quella del codice non dimostra che il file sia errato. Indica quale file leggere per primo, ed è tutto ciò che serve da un controllo che richiede un secondo.

Verificare la presenza di percorsi che non esistono più. La documentazione diventa obsoleta in un modo molto specifico: continua a descrivere codice che è stato eliminato. Ogni percorso in questi file è racchiuso tra backtick, quindi è facile estrarlo e verificarlo.

grep -o '`[^`]*`' apps/web/AGENTS.md | tr -d '`' | grep '/' | while read -r p; do
  [ -e "$p" ] || [ -e "apps/web/$p" ] || echo "missing: $p"
done

Leggere l'output invece di inserire questo controllo nella CI. Il controllo segnala anche glob come src/**/*.ts e qualsiasi URL inserito tra virgolette, perché entrambi contengono una barra e nessuno dei due è un file presente sul disco.

Il sintomo durante una sessione. L'agent legge il file, prova ad aprire src/api/client.ts perché il file glielo indica e lo strumento restituisce:

No such file or directory

Quindi esegue l'operazione ragionevole e scrive il proprio wrapper fetch. Questo è il costo reale di un file non più aggiornato. L'agent non ignora la documentazione. La segue, raggiunge un percorso eliminato tre mesi prima e ricostruisce codice che esiste già. Una skill come Ponytail, che vincola l'agent alla modifica minima funzionante, riduce la frequenza di questo comportamento, ma non può trovare un helper a cui il file punta nel posto sbagliato.

Claude Code legge i file AGENTS.md?

No. È importante chiarirlo, perché da questo dipende la struttura annidata. Ad agosto 2026 la documentazione specifica: «Claude Code legge CLAUDE.md, non AGENTS.md». Il metodo continua a funzionare, ma è necessario inserire un CLAUDE.md accanto a ogni AGENTS.md.

La modalità di importazione è corretta quando si vogliono aggiungere direttive specifiche per lo strumento a quelle condivise. Inserire quanto segue in services/worker/CLAUDE.md:

@AGENTS.md

## Claude Code

Use plan mode for changes under `services/worker/migrations/`.

La modalità con link simbolico è corretta quando non è necessario aggiungere impostazioni specifiche per lo strumento.

git ls-files '*AGENTS.md' | while read -r f; do
  ln -s AGENTS.md "$(dirname "$f")/CLAUDE.md"
done
ls -l apps/web/CLAUDE.md

ln non stampa nulla se l'operazione riesce, quindi controllare l'elenco con apps/web/CLAUDE.md -> AGENTS.md. Avviare quindi una sessione ed eseguire /context: i file caricati vengono mostrati nella sezione Memory files. In Windows, per creare un link simbolico sono necessari i diritti di Administrator oppure Developer Mode; in alternativa, usare l'importazione @AGENTS.md.

È necessario considerare anche questo caso. Dopo /compact, il file nella directory radice viene riletto dal disco, ma i file annidati nelle sottodirectory non vengono reiniettati. Vengono ricaricati la volta successiva in cui l'agent legge un file in quella directory. Se una regola specifica per directory sembra smettere di essere applicata durante una sessione lunga, questa è di solito la causa. È sufficiente modificare un file nella directory per ricaricare la regola.

Impostazioni che indirizzano altri agent verso AGENTS.md

Codex legge AGENTS.md in modo nativo. A ogni livello controlla prima AGENTS.override.md, consentendo di applicare un override locale a una directory senza modificare il file condiviso. Interrompe l'unione quando la dimensione complessiva raggiunge 32 KiB, il valore predefinito di project_doc_max_bytes. Questo è un ulteriore motivo per mantenere ridotte le dimensioni del file nella directory radice.

Aider lo gestisce tramite .aider.conf.yml con la direttiva read: AGENTS.md.

Gemini CLI lo gestisce tramite .gemini/settings.json con { "context": { "fileName": "AGENTS.md" } }.

La documentazione upstream descrive una ridenominazione compatibile con le versioni precedenti per i repository che usano ancora il nome singolare precedente: mv AGENT.md AGENTS.md && ln -s AGENTS.md AGENT.md.

In un monorepo molto grande, l'impostazione claudeMdExcludes di Claude Code esclude i file degli ancestor in base al percorso o a un glob. È utile quando la directory di un altro team si trova a un livello superiore rispetto alla propria.

In che modo differisce dalla memoria dell’agente o da una skill?

Questi meccanismi possono sembrare simili, ma presentano modalità di errore completamente diverse. È quindi importante stabilire con precisione quale si vuole usare.

AGENTS.md viene scritto da te, salvato in git, sottoposto a revisione tramite pull request ed è identico per tutti coloro che clonano il repository. La memoria dell’agente viene scritta dall’agente, archiviata al di fuori del repository ed è locale a una singola macchina. La documentazione di Claude Code traccia la stessa distinzione: CLAUDE.md contiene le «Istruzioni e regole» che scrivi tu, mentre la memoria automatica contiene gli «Apprendimenti e modelli» che scrive Claude; inoltre, la directory della memoria non viene condivisa tra le macchine. La verifica è semplice. Se un fatto deve essere valido anche per un collega che esegue un clone appena creato, non può essere memorizzato nella memoria dell’agente. Come persiste la memoria dell’agente tra le sessioni tratta questa parte del problema.

Una skill è il terzo elemento. AGENTS.md è un contesto che viene caricato in ogni sessione; una skill è una procedura che viene caricata quando serve. La documentazione di Claude Code fornisce una regola utile: «Se una voce descrive una procedura composta da più passaggi o è rilevante soltanto per una parte del codebase, spostala in una skill o in una regola associata a un percorso». La seconda parte della frase descrive esattamente il caso risolto da un AGENTS.md annidato. La prima parte indica invece a cosa servono le skill dell’agente; quando la stessa procedura serve in più repository, condividi la skill tra i repository invece di incollare gli stessi paragrafi in dieci file AGENTS.md diversi.

Il progetto upstream osserva che «al momento della stesura, il repository principale di OpenAI contiene 88 file AGENTS.md». Questo numero riassume l’intero argomento. Un repository di grandi dimensioni non ha bisogno di un file più grande. Ha bisogno di più file piccoli, ciascuno accanto al codice che descrive e affidato a chi ha modificato quel codice per ultimo.

FAQ

Un file AGENTS.md annidato sostituisce quello nella radice o si aggiunge a esso?

Si aggiunge a esso. La documentazione upstream afferma che «quello più vicino ha la precedenza», descrivendo ciò che accade in caso di conflitto, non i file che vengono caricati. Codex «concatena i file dalla radice verso il basso, separandoli con righe vuote» e Claude Code concatena ogni file trovato risalendo dalla directory di lavoro, invece di sostituirli. Il file più vicino prevale soltanto quando due file forniscono istruzioni diverse sullo stesso argomento. Scrivi le regole condivise una sola volta nel file nella radice e non ripeterle in ogni directory.

Quanto deve essere grande il file AGENTS.md nella radice?

Deve essere abbastanza piccolo da non creare problemi se venisse aggiunto all'inizio di ogni richiesta che invii in quel repository, perché è esattamente ciò che accade. La documentazione di Claude Code suggerisce di mantenere ogni file sotto 200 righe e avverte che i file più lunghi «riducono il rispetto delle istruzioni». Per impostazione predefinita, Codex interrompe l'unione dei file di istruzioni quando la dimensione complessiva raggiunge 32 KiB. Se il file nella radice documenta quattro servizi, gran parte del contenuto è superflua per una singola attività. Sposta i dettagli nei file delle singole directory e lascia un riferimento alla loro posizione.

Come posso evitare che questi file diventino obsoleti?

Inserisci una regola nel file nella radice: chi modifica il codice di una directory aggiorna anche il relativo file AGENTS.md nello stesso commit. Collocare il file accanto al codice rende la regola effettiva, perché la modifica viene inclusa nello stesso diff della pull request che una persona sta già esaminando. Aggiungi un avviso CI che associ ogni percorso modificato al file AGENTS.md più vicino in una directory superiore e, periodicamente, confronta git log -1 --format=%cs di ogni file con lo stesso comando eseguito sulla directory documentata.

Claude Code legge i file AGENTS.md?

No. Ad agosto 2026 la documentazione afferma: «Claude Code legge CLAUDE.md, non AGENTS.md». Crea un file CLAUDE.md nella stessa directory, con @AGENTS.md sulla prima riga. In questo modo carichi il file condiviso e puoi aggiungere sotto le istruzioni specifiche per Claude. Un collegamento simbolico creato con ln -s AGENTS.md CLAUDE.md funziona quando non devi aggiungere altro, ma in Windows richiede i diritti di Administrator o la modalità Developer Mode. Esegui /context in una sessione e verifica che il file compaia tra i file di memoria.

Dove inserisco una regola che si applica solo in alcuni casi?

Non in AGENTS.md. Il file viene caricato in ogni sessione, quindi ogni sua riga compete per l'attenzione con la richiesta che hai effettivamente scritto. Una procedura composta da più passaggi e necessaria solo occasionalmente appartiene a una skill, che viene caricata su richiesta. Una regola applicabile a una sola directory appartiene al relativo file AGENTS.md. Un'informazione che l'agente può ricavare direttamente dal codice, come l'albero delle directory o l'elenco delle dipendenze, non appartiene a nessuno dei due.