Prompts système
- Définir correctement un prompt système sur les quatre surfaces — le paramètre system d'Anthropic, le rôle developer d'OpenAI, system_instruction de Gemini et les cinq flags de Claude Code
- Savoir ce qui appartient au briefing permanent et ce qui doit en rester dehors
- Arrêter d'en rajouter : pourquoi « CRITICAL: you MUST » se retourne désormais contre les modèles actuels
- Placer le prompt système là où le cache de prompts peut le réutiliser, et en extraire la partie volatile
- Choisir entre compléter et remplacer le prompt par défaut de Claude Code — et comprendre ce que le remplacement fait perdre
Chaque modèle possède une couche qui cadre toute la conversation. C'est le levier le moins cher que vous ayez — défini une fois, appliqué à chaque tour — et c'est celui que la plupart des gens remplissent avec la mauvaise matière. Les rôles expliquent pourquoi cela compte. Cette leçon est la version opérateur : noms de paramètres exacts, dosage de l'insistance, et interactions avec le cache.
Une idée, quatre surfaces
Le concept se transpose partout. La plomberie, non.
| Surface | Comment la définir | Forme |
|---|---|---|
| Messages API d'Anthropic | system — un paramètre de requête de premier niveau, pas une entrée de messages | Chaîne, ou tableau de blocs de contenu |
| Responses API d'OpenAI | le paramètre instructions, ou un message avec le rôle developer | S'applique à la requête en cours ; instructions n'est pas repris quand vous enchaînez avec previous_response_id |
| API Google Gemini | system_instruction sur la requête (systemInstruction en Java, SystemInstruction en Go) | Défini par interaction |
| Claude Code | cinq flags CLI (ci-dessous), plus CLAUDE.md et les styles de sortie | Remplacer ou compléter |
| Applications de chat | instructions personnalisées sur votre compte | Persistantes d'une conversation à l'autre |
Le bug de portage le plus fréquent consiste à traiter le system d'Anthropic comme un message. Ce n'en est pas un : il se place à côté de messages, pas dedans. Dans l'autre sens, la hiérarchie d'OpenAI est explicite — les instructions developer prévalent sur les instructions user, qui prévalent sur les tours précédents de l'assistant. Leur propre analogie : le message developer est la définition de la fonction, le message user est les arguments qu'on lui passe.
Anthropic : system est un paramètre de premier niveau
curl https://api.anthropic.com/v1/messages \
-H "content-type: application/json" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-sonnet-5-5",
"max_tokens": 1024,
"system": "You are a precise financial analyst. Show your assumptions. Never invent numbers.",
"messages": [{"role": "user", "content": "Summarize this filing."}]
}'Ce qui a sa place dedans
Triez chaque ligne de votre prompt selon sa fréquence de changement. Ce qui reste vrai pour toute la conversation remonte dans le briefing permanent. Ce qui change à chaque tour reste dans le tour utilisateur.
- Une phrase de rôle suffit à déplacer le ton et le focus. Les docs d'Anthropic sont explicites : même une seule phrase fait une différence ; elles mettent aussi en garde contre un rôle trop contraint, parce que les modèles actuels n'ont pas besoin d'un lourd échafaudage de persona.
- Ce que le modèle ne doit jamais faire, ce qu'il doit toujours inclure, ce qu'il doit faire en cas de doute. Donnez-lui explicitement la permission de dire « je ne sais pas » — cette seule ligne réduit mesurablement les réponses inventées.
- La forme d'une réponse valide : sections, longueur, langue, préambule autorisé ou non. « Respond directly, without preamble » a sa place ici, pas dans chaque tour utilisateur.
- Quand recourir à un outil et quand répondre directement. C'est là que vous réglez l'empressement (voir ci-dessous).
- Les données du jour, le fichier courant, les documents récupérés, l'état en direct. Tout cela appartient au tour utilisateur ou au contexte de récupération. Enterrez-les dans le prompt système et vous invalidez votre cache tout en enseignant au modèle des faits périmés.
- Les gros documents vont en tête du tour utilisateur, au-dessus de la question. Voir /docs/prompting/long-context.
Jusqu'où insister
C'est ici que les prompts écrits pour d'anciens modèles font activement du mal. Les recommandations d'Anthropic pour la génération Opus 4.5/4.6 et au-delà sont sans détour : ces modèles sont plus réactifs au prompt système que leurs prédécesseurs, donc les prompts durcis contre un modèle qui sous-déclenchait les outils vont maintenant le faire sur-déclencher. Le correctif consiste à baisser le volume — Use this tool when… au lieu de CRITICAL: you MUST use this tool when….
- Les MAJUSCULES, « CRITICAL », « you MUST » et les formulations menaçantes sont un héritage des modèles qui ignoraient les instructions douces. Sur les modèles actuels, elles provoquent du surdéclenchement et des appels d'outils trop empressés.
- Les personas trop contraints (« you are a world-class 10x expert who never makes mistakes ») ajoutent des tokens et n'achètent rien. Demandez plutôt la perspective que vous voulez réellement.
- Des couches contradictoires sont pires qu'un briefing mince. Si le prompt système dit « be concise » et qu'une skill dit « always explain your reasoning », le modèle doit deviner.
- Empiler toutes les techniques d'un coup — rôle, XML, few-shot, chaîne de raisonnement, schéma de sortie — est la forme la plus courante de sur-ingénierie. Ajoutez-en une, mesurez, gardez-la seulement si elle a aidé.
L'empressement est un potentiomètre, pas un trait figé, et le prompt système est l'endroit où vous le réglez. Enveloppez la politique dans une balise nommée pour pouvoir la retrouver et la modifier plus tard :
Pousser vers l'action
<default_to_action> Implement changes rather than only proposing them. If intent is ambiguous, infer the most useful action and proceed, using tools to find the details you are missing instead of guessing. </default_to_action>
Pousser à demander d'abord
<do_not_act_before_instructions> Do not modify files or start an implementation unless you are clearly asked to. When intent is ambiguous, research and recommend instead of acting. Make changes only on an explicit request. </do_not_act_before_instructions>
Le prompt système est votre préfixe de cache
C'est la partie qui se voit sur la facture. Anthropic construit le préfixe cachable dans un ordre fixe — tools, puis system, puis messages — et le cache couvre tout jusqu'au bloc que vous marquez, inclus. Le prompt système occupe donc la position de cache la plus rentable de toute la requête : stable, réutilisé à chaque appel, et placé devant la conversation.
Deux conséquences :
- Gardez le prompt système stable au byte près. Un horodatage, un nom d'utilisateur ou un identifiant de session interpolé à l'intérieur change le préfixe et rate le cache à chaque requête.
- Si une partie doit varier, mettez la partie stable en premier et coupez le cache après elle, pour que la queue variable soit la seule chose relue.
Les longueurs minimales cachables diffèrent selon le modèle — certains modèles actuels cachent à partir de 512 tokens, les plus anciens en exigent jusqu'à 4 096 — et un prompt sous le seuil est traité silencieusement sans cache, sans aucune erreur. Vérifiez le tableau à jour avant de compter dessus.
Claude Code livre une version taillée sur mesure de cette séparation. Quand votre prompt de remplacement mélange des instructions fixes et du contexte propre à l'exécution, placez entre les deux une ligne contenant uniquement __SYSTEM_PROMPT_DYNAMIC_BOUNDARY__ : Claude Code coupe à la première ligne de ce type et la supprime, en gardant en cache tout ce qui se trouve au-dessus tandis que la partie en dessous change (v2.1.275+). Pour des exécutions scriptées multi-utilisateurs, --exclude-dynamic-system-prompt-sections déplace le contexte propre à chaque utilisateur hors du prompt, vers le premier message utilisateur, afin que plusieurs machines partagent un même préfixe mis en cache.
Claude Code : compléter ou remplacer
Cinq flags définissent le prompt. Quatre d'entre eux posent du texte ; le cinquième contrôle si une conversation conserve le texte avec lequel elle a démarré.
| Flag | Ce qu'il fait |
|---|---|
--system-prompt | Remplace tout le prompt par défaut par votre texte |
--system-prompt-file | Le remplace par le contenu d'un fichier |
--append-system-prompt | Ajoute votre texte au prompt par défaut |
--append-system-prompt-file | Ajoute le contenu d'un fichier au prompt par défaut |
--system-prompt-snapshot | off reconstruit le prompt à chaque requête au lieu de réutiliser celui enregistré à la première requête |
--system-prompt et --system-prompt-file sont mutuellement exclusifs ; chacun des flags d'ajout peut être combiné avec l'un ou l'autre des flags de remplacement.
La règle de décision porte sur ce que vous êtes prêt à assumer :
- L'ajout préserve les recommandations d'outils par défaut, les instructions de sécurité et les conventions de code, donc vous ne fournissez que ce qui diffère — règles propres à l'invocation, format de sortie, contexte métier pour un script -p.
- Un agent non dédié au code dans un pipeline sans surveillance, par exemple. Le remplacement supprime tout le prompt par défaut — y compris les recommandations d'outils et les instructions de sécurité — donc tout ce dont votre tâche a encore besoin devient votre responsabilité.
- Les conventions de projet que Claude doit toujours suivre ont leur place dans CLAUDE.md. Un persona que vous alternez et partagez a sa place dans un style de sortie. Un flag, c'est pour une seule invocation.
Ajouter une règle pour une seule exécution headless
claude -p --append-system-prompt "Cite file:line for every claim." "audit the auth flow"
Un piège qui coûte un vrai temps de débogage : par défaut, Claude Code construit le prompt système une seule fois, à la première requête d'une conversation, et l'enregistre. Chaque requête ultérieure de cette conversation réutilise le prompt enregistré — y compris après --resume ou --continue. Changez le texte du flag à un lancement ultérieur et rien ne se passe jusqu'à ce que la conversation soit compactée ou que vous en démarriez une nouvelle. Pendant que vous itérez sur la formulation, passez --system-prompt-snapshot off (v2.1.257+) pour le reconstruire à chaque requête.
Un avant/après travaillé
Avant — tout à volume maximal, faits volatils intégrés, aucun contrat de sortie :
Trop insistant et hostile au cache
You are THE BEST code reviewer in the world. You are a 10x engineer. CRITICAL: You MUST ALWAYS use the search tool before answering. NEVER skip this. IT IS EXTREMELY IMPORTANT that you are thorough. The current date is 2026-09-30 and the user is reviewing PR #4412 on branch fix/auth-race.
Quatre problèmes distincts : les superlatifs n'achètent rien, les cris vont pousser le modèle à sur-appeler ses outils, il n'y a aucune définition d'une réponse valide, et la dernière ligne change à chaque exécution donc le préfixe ne se met jamais en cache.
Après — une phrase de rôle, un vrai contrat de sortie, une porte de sortie pour l'incertitude, les faits volatils déplacés dans le tour utilisateur :
Calme, contrat d'abord, cachable
You are a code reviewer for a TypeScript monorepo. Rules: - Search the codebase before claiming a symbol is unused. - If you cannot verify a claim from the diff or the code, say so instead of guessing. Output: a Summary section, then Risks, then Suggested changes. No preamble.
La date, le numéro de PR et la branche vont dans le tour utilisateur, là où ils ont leur place. Même comportement, un préfixe de cache stable, et environ un tiers des tokens.
Ce qu'il ne faut plus utiliser
Le prefilling — commencer soi-même le tour de l'assistant pour que le modèle continue dans votre format — était la méthode de référence pour forcer du JSON ou sauter un préambule. Sur Claude 4.6 et au-delà, un dernier tour assistant pré-rempli renvoie une erreur 400. Les remplacements vivent tous dans le prompt système ou juste à côté : une instruction directe « respond without preamble », les sorties structurées, ou un outil avec un champ enum pour la classification. Les messages assistant situés ailleurs dans la conversation ne sont pas affectés, donc les exemples few-shot fonctionnent exactement comme avant.
- Même concept, plomberie différente : le paramètre `system` d'Anthropic, le rôle `developer` / `instructions` d'OpenAI, `system_instruction` de Gemini, les cinq flags de Claude Code.
- Triez par fréquence de changement — les règles durables vont dans le briefing permanent, les faits volatils dans le tour utilisateur.
- Baissez le volume. Les modèles actuels sur-déclenchent sur des prompts durcis pour des modèles qui sous-déclenchaient.
- Le prompt système se trouve dans le préfixe de cache (tools → system → messages) : gardez-le stable au byte près, et détachez la queue variable.
- Dans Claude Code, compléter préserve les instructions de sécurité et les recommandations d'outils par défaut ; remplacer vous confie toute la responsabilité.
- Les derniers tours assistant pré-remplis donnent une erreur 400 sur Claude 4.6+ — utilisez un contrat de sortie, les sorties structurées, ou des outils.