Ingénierie15 mai 2026· 10 min de lecture
Context Engineering pour Coding Agents : pourquoi un seul CLAUDE.md ne suffit pas
Pourquoi un seul CLAUDE.md ne suffit pas sur une vraie codebase, et la structure en 3 couches qu'on utilise chez Maleus pour injecter aux agents les bonnes instructions au bon moment.
Adrien MaretCTO

Sur cette page
- Pourquoi 3 niveaux et pas un seul
- Niveau 1 : les coding rules, déclenchées par pattern matching
- Une règle par type de fichier
- Edit flow : pattern matching déterministe sur le read
- Write flow : le problème du fichier qui n'existe pas encore
- Skills : l'évaluation par le LLM en complément
- CRITICAL INSTRUCTION, à utiliser avec parcimonie
- Construire les règles empiriquement
- Niveau 2 : CLAUDE.md, la plomberie du projet
- Niveau 3 : AGENT.md par module, le métier
- Un fichier par domaine fonctionnel
- Structure standard
- Exemple court : features/agent-sessions/AGENT.md
- AGENT.md comme index de la codebase
- Benchmark : ce que les AGENT.md font gagner
- La règle qui crée la règle
- Conclusion
Découvrez comment Maleus peut accélérer vos équipes.


Le Context Engineering, c'est l'art d'injecter à un agent la bonne information au bon moment pour qu'il code correctement.
Aujourd'hui, la plupart des équipes qui s'attaquent au sujet balancent toutes leurs instructions dans un gros
CLAUDE.mdà la racine du repo. Ça marche pour un prototype, ça craque dès que la codebase grossit.Sur une vraie application, il faut 3 niveaux distincts d'instructions, chacun déclenché à un moment différent du workflow de l'agent. Sans cette stratification, on dilue tellement le contexte que le LLM finit par ignorer les règles les plus importantes.
Dans cet article, je détaille les 3 couches qu'on utilise chez Maleus pour générer des applications en quasi-autonomie sur la partie code.
Pourquoi 3 niveaux et pas un seul
Le contexte d'un LLM est limité et chaque token en dilue les autres.
Les instructions ont des scopes différents:
CLAUDE.mdà la racineAGENT.mdpar moduleSi on charge tout d'un coup, on récolte du bruit, des contradictions entre règles, et de la dilution.
La solution, c'est de stratifier. Chaque couche est chargée au moment où elle est pertinente.
L'ordre de grandeur chez Maleus aujourd'hui:
Ce qui donne deux ratios intéressants:
AGENT.mdpour ~27 lignes de code dans le module qu'il décritSi on balançait ces 16 000 lignes dans un seul gros
CLAUDE.md, on cramerait l'équivalent de plusieurs dizaines de milliers de tokens à chaque prompt, dont 95% sans rapport avec la tâche en cours. La stratification, c'est ce qui rend cet investissement de contexte tenable au lieu d'imbuvable.Niveau 1 : les coding rules, déclenchées par pattern matching
C'est la couche la plus granulaire et celle qui a le plus d'impact sur la qualité du code généré.
Une règle par type de fichier
Chez Maleus, chaque fichier backend est suffixé par son rôle:
<Entity>.table.ts→ définition de table Drizzle<Entity>.repository.ts→ accès BDD<Entity>.service.ts→ logique métier<Entity>.controller.ts→ endpoints Nest.jsÀ chaque suffixe correspond une rule dédiée, déclenchée par un glob précis dans la propriété
pathsdu frontmatter:# .claude/rules/backend/backend-tables.md name: "backend-tables" paths: "**/{backend,studio-backend}/**/*.table.ts"Ce découpage par glob permet de charger uniquement la rule pertinente au moment où l'agent touche un fichier de ce type.
Edit flow : pattern matching déterministe sur le
readL'agent lit toujours un fichier avant de l'éditer. Le path passé au
readsert de clé au pattern matching.C'est du pattern matching, donc 100% déterministe, sans aléa LLM possible.
Write flow : le problème du fichier qui n'existe pas encore
Cette mécanique tombe à l'eau quand l'agent crée un nouveau fichier.
Pourquoi ? Parce qu'il n'a aucune raison de faire un
readavant, le fichier n'existe pas. Il génère directementwrite("Foobar.table.ts", content), et le content est déjà dans le buffer avant qu'on ait pu pattern-matcher quoi que ce soit.Le pattern matching a donc un trou dans la raquette : pour la création de fichier, il faut un autre mécanisme.
Skills : l'évaluation par le LLM en complément
Les skills sont des instructions que le LLM décide lui-même de charger en évaluant leur description.
Le mécanisme:
**/*.table.ts"CRITICAL INSTRUCTION YOU MUST ALWAYSpour appuyer la prioritéChez nous, la rule (
.claude/rules/backend/backend-tables.md) et le skill (.claude/skills/backend-tables/SKILL.md) sont le même fichier via hardlink. Le frontmatter et le contenu sont identiques, seul le mécanisme de déclenchement change: pattern matching pour le edit flow, évaluation LLM pour le write flow.Le frontmatter sert donc les deux canaux simultanément:
--- name: "backend-tables" paths: "**/{backend,studio-backend}/**/*.table.ts" description: Contains guidelines for defining database tables using Drizzle ORM with PostgreSQL. [...] CRITICAL INSTRUCTION You MUST ALWAYS use this skill before editing/writing any file matching "**/{backend,studio-backend}/**/*.table.ts". ---En pratique le skill se déclenche presque toujours, mais ce n'est jamais 100% puisqu'aucun mécanisme déterministe ne peut intercepter une création de fichier avant la génération du contenu.
CRITICAL INSTRUCTION, à utiliser avec parcimonieLe mot-clé
CRITICAL INSTRUCTION YOU MUST ALWAYSest un canal de priorisation propre aux modèles Anthropic qui fonctionne par contraste : si on l'écrit partout, plus rien n'est prioritaire.Surtout, écrire
CRITICAL INSTRUCTIONest le signe qu'on a besoin de déterminisme, pas de prompt engineering. Le prompt engineering augmente la probabilité qu'une instruction soit respectée ; le déterminisme la garantit. Dès qu'un mécanisme déterministe est possible (pattern matching, hook, lint, test), il faut le préférer. Le skill est l'exception assumée: rien ne permet d'intercepter une création de fichier avant la génération.Construire les règles empiriquement
Inutile d'écrire toutes les coding rules d'un coup. On finit avec des règles génériques, jamais déclenchées, ou pire, qui se contredisent.
L'approche qui marche est inverse. On démarre avec quelques règles essentielles (structure du backend, naming des méthodes, format des erreurs), puis on observe l'agent et à chaque erreur récurrente, on enrichit la rule correspondante.
Autant laisser Claude Code rédiger ces ajouts : les modèles Anthropic sont fine-tunés pour ça. On lui donne la correction ("dans ce repository tu aurais dû utiliser X au lieu de Y") et il met la rule à jour. On relit toujours, et on garde les règles courtes : une rule trop longue se dilue dans le contexte.
Chaque correction humaine devient une règle qui évite la même erreur la fois suivante.
Cette approche en trois couches est l'un des éléments clé qui permettent à Maleus de générer des applications prêtes à être déployées en production.
Niveau 2 :
CLAUDE.md, la plomberie du projetUn seul fichier
CLAUDE.mdà la racine du repo, chargé une fois au démarrage de la session.Il répond à trois questions: où je suis, quels outils j'ai, quel est l'environnement.
Concrètement on y trouve:
14001, backend14002)Comme ce fichier est chargé pour toute la session, il faut le garder court : chaque ligne reste dans le contexte de toutes les requêtes.
Niveau 3 :
AGENT.mdpar module, le métierLà où les coding rules disent comment écrire, les
AGENT.mddisent ce que fait ce module.Un fichier par domaine fonctionnel
À l'intérieur de chaque module fonctionnel, on met un fichier
AGENT.mdqui contient les infos technico-fonctionnelles spécifiques au module.Ces
AGENT.mdsont écrits par les agents eux-mêmes au moment où ils codent, dans un style optimisé pour un LLM qui doit comprendre vite plutôt que pour un onboarding humain.Chez Maleus aujourd'hui, on a 97
AGENT.mdrépartis sur toute l'application, de quelques dizaines à plusieurs centaines de lignes selon la complexité du module.Structure standard
Le template qu'on a fini par converger, généré et maintenu par les agents:
# <Module> Module ## Overview [2-4 phrases : raison d'être du module] ## Main Flows [1 à 3 schémas ASCII des flows principaux] ## Important Files [Tableau: chemin de fichier | responsabilité] ## Tables Structure [Tableau par table : colonne | type | description] ## Permissions [Tableau: API action | rôles autorisés | description] ## Error Codes [Tableau: code | status HTTP | description] ## Dependencies [Liste des autres modules / clients dont on dépend]Toutes les sections ne sont pas dans tous les modules, uniquement celles qui ont du sens. Un module sans BDD n'a pas de section Tables Structure. Un module qui ne consomme pas d'événements AMQP n'a pas de section AMQP Events.
Exemple court :
features/agent-sessions/AGENT.mdPour illustrer, voici un
AGENT.mdminimal (69 lignes) qui couvre un module de routing d'événements AMQP:# Agent Sessions Module ## Overview The Agent Sessions module owns the AMQP event consumption for `snivel.agent-sessions.end` and `snivel.files.change` events. It routes these events to the appropriate feature module (versions or workshops). This module exists because the `AmqpEventServer` enforces one handler per event pattern, and multiple feature modules need to react to the same events. ## Important Files | File | Description | | ------------------------------------------ | --------------------------------------------- | | `services/AgentSessionsRouting.service.ts` | Event routing logic + Mutex | | `presentation/AgentSessions.consumer.ts` | AMQP consumer for `snivel.agent-sessions.end` | | `presentation/FilesChange.consumer.ts` | AMQP consumer for `snivel.files.change` | ## Routing Logic 1. Distributed Mutex lock on `agent-session:processing:{conversationId}` prevents duplicate processing 2. If `sessionOrigin` is present, dispatch directly to the owning module (no DB lookups) 3. Fallback: try each handler sequentially until one claims the conversationAvec 69 lignes comme celles-ci, un agent qui reçoit une tâche du type "ajouter un nouveau type d'événement AMQP" sait immédiatement:
AgentSessionsRouting.service.tsplus un nouveau consumerSans cet
AGENT.md, l'agent aurait dû ouvrir 5 à 10 fichiers pour reconstituer cette compréhension.AGENT.mdcomme index de la codebaseUn
AGENT.mdjoue le rôle d'index au sens base de données : quand un agent reçoit une tâche, il ouvre ceux des modules potentiellement concernés et, en quelques centaines de tokens par module, il sait:L'agent ne fouille plus la codebase au hasard, il sait directement quels fichiers ouvrir, ce qui économise des tokens et garde son contexte propre pour le raisonnement.
Benchmark : ce que les
AGENT.mdfont gagnerPour quantifier, on a joué une question de compréhension de code en production sur le monorepo, "comment les images circulent du frontend studio vers Claude Code dans snivel ?", deux fois, avec et sans accès aux
AGENT.md.AGENT.mdAGENT.mdMême conclusion finale dans les deux cas. Mais sans index, l'agent double sa consommation de tokens et paie 50% de plus juste pour reconstituer ce que les
AGENT.mdlui auraient dit en quelques lignes.À l'échelle d'une équipe qui fait tourner des milliers de requêtes par jour, c'est la différence entre une facture API tenable et un budget qui dérape.
La règle qui crée la règle
Et c'est une coding rule qui maintient ces
AGENT.md, extrait debackend-architecture.md:**Module AGENT.md** Each module MUST contain a `AGENT.md` file at the root. This file contains a high level description of the module purpose and general behavior. It can contain anything necessary so a Senior developer is happy to read it to understand how to handle the module: - schema of main flow - important files - tables structure - particular permissions - important API actions - important business logic **You MUST ALWAYS update the AGENT.md file associated with a module after working on it.**Cette rule est chargée à chaque édition de fichier backend, parce que son
paths:est**/{backend,studio-backend}/**/*— un glob générique qui match tous les fichiers du backend. Donc à chaque fois qu'un agent touche un fichier de module, il a en contexte immédiat l'instruction de mettre à jour l'AGENT.md.La couche 1 (coding rules) maintient ainsi la couche 3 (
AGENT.md), sans qu'un humain ait à toucher la doc.Conclusion
Trois couches, trois moments de chargement, chacune avec un mécanisme de déclenchement adapté.
Sans cette stratification, on plafonne très vite dès que la codebase grossit. On finit par mettre tellement d'instructions au même endroit qu'aucune n'est respectée correctement.
Ça marche parce qu'on respecte le fonctionnement réel de l'attention du LLM : l'info doit être proche du moment de génération, et non pas perdue 20 000 tokens plus haut dans un
CLAUDE.mdgéant.Les
AGENT.mdsont eux-mêmes générés et maintenus par les coding agents qui suivent une rule chargée à chaque édition de fichier backend, donc le système se maintient sans intervention humaine sur la documentation.Chez Maleus, c'est ce qui nous permet de générer la majorité du code en quasi-autonomie sans sacrifier la qualité 😉