Quand le format JSON strict change votre workflow
Le moment où arrêter de demander du texte libre et exiger un JSON validé. Une décision technique qui économise des semaines de glue code.
Publié le · revu le 11 mai 2026
- Étiquettes
- jsonschemavalidationengineering
Le jour où vous décidez que votre prompt sort du JSON strict plutôt que du texte libre, vous franchissez une étape. Avant : votre code parse, regex, devine, échoue. Après : votre code consomme un objet typé, valide avec un schéma, échoue clairement quand le contrat n'est pas tenu.
Cet article décrit quand prendre cette décision, comment l'implémenter, et les pièges qui restent quand vous l'avez prise.
Quand passer au JSON strict
Trois signaux indiquent que votre prompt doit basculer :
1. Vous écrivez du parsing à la main
Si vous extrayez le résultat avec du regex, du string.split, ou du « cherche le mot après ":" », c'est le signal. Vous payez le coût en bug et en complexité, pas en lisibilité.
2. Le résultat est consommé par un autre programme Un humain peut accommoder une variation de format. Un programme non. Si la sortie du prompt alimente une base de données, déclenche un workflow, ou nourrit un autre agent, le JSON strict est obligatoire.
3. Vous voulez tester la qualité du prompt
Avec du texte libre, mesurer la qualité demande un humain ou un autre LLM. Avec du JSON strict, vous écrivez un test : expect(result.intent).toBe("lead_qualifie"). Le coût d'évaluation chute.
Comment écrire un prompt JSON-first
Trois éléments incontournables :
Le schéma déclaré dans le prompt
Sortie JSON STRICT, sans texte avant ou après :
{
"intent": "pay" | "dispute" | "delay" | "info",
"invoice_reference": string | null,
"urgency": "low" | "normal" | "high",
"requires_human": boolean
}
Pas de schéma JSON dans une doc séparée. Dans le prompt, à la fin, immédiatement avant la consigne « pas de texte hors JSON ».
Les valeurs autorisées explicites
Préférez "low" | "normal" | "high" à string. Le modèle suit le pattern beaucoup plus fidèlement quand l'union est explicite.
La règle « pas de texte hors JSON »
À répéter trois fois dans le prompt, à des endroits différents. Sans ça, le modèle ajoute systématiquement « Voici votre JSON : » avant et « N'hésitez pas à me solliciter si... » après. Vous casserez votre JSON.parse().
Validation côté code
Le JSON sorti par le modèle peut être malformé (rare avec les modèles modernes, mais ça arrive). Validez-le :
import { z } from "zod";
const Schema = z.object({
intent: z.enum(["pay", "dispute", "delay", "info"]),
invoice_reference: z.string().nullable(),
urgency: z.enum(["low", "normal", "high"]),
requires_human: z.boolean(),
});
const parsed = Schema.safeParse(JSON.parse(modelOutput));
if (!parsed.success) {
// Retry, ou escalade humain, ou fallback documenté.
}
Validez à l'arrivée, pas à mi-pipeline. Le coût de validation est négligeable, le coût d'un mauvais routage en prod est élevé.
Les pièges qui restent
Le modèle invente des champs
Si votre schéma dit que intent peut être "pay" | "dispute" | "delay" | "info", le modèle peut sortir "refund" parce que ça lui semble plus précis. Validez avec Zod ou équivalent et rejetez.
Le modèle ajoute du markdown au JSON
```json au début, ``` à la fin. Trois solutions :
- Demander explicitement « pas de bloc de code markdown »
- Strip le markdown en post-processing avec une regex simple
- Utiliser le « JSON mode » du provider quand disponible (OpenAI, Anthropic)
Le modèle est trop confiant
Si vous demandez confidence: 0-1, le modèle aura tendance à mettre 0,9 partout. Forcez la calibration en demandant : « si tu hésites entre deux catégories, mets 0,5-0,6 ; si tu es certain, ≥0,9 ». Ajoutez un test qui vérifie que la distribution est saine sur un dataset.
Function calling vs prompt JSON
Si votre provider supporte le function calling (Claude tools, OpenAI tools), utilisez-le. Vous gagnez :
- La validation du schéma faite côté provider
- Une meilleure adhérence aux contraintes
- Pas besoin de strip le markdown
Quand l'utiliser : dès que vous avez plus d'un agent à orchestrer. Quand garder le JSON-in-prompt : pour les cas one-shot où l'overhead du tool spec n'en vaut pas la peine.
Pour aller plus loin
- Le pilier : Le guide des prompts pour opérateurs
- Le dossier complémentaire : Écrire un prompt système pour un agent
- L'entrée catalogue : Générer une description de fonction
- L'entrée catalogue : Extraire les engagements clés d'un contrat