Skill d'agent qui impose le décodage contraint pour toutes les sorties destinées à être lues par du code (agents, outils, API, BDD). Elle sépare explicitement la phase de raisonnement libre de la phase de sortie structurée conforme à un schéma ou une grammaire.
Scanned 8/31/2026
Install to Claude Code
npx -y skills add valorisa/Claude-Skills --skill constrained-decoding --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Constrained Decoding?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/valorisa-constrained-decoding)More formats (shields.io, HTML) on the badges page.
---
name: constrained-decoding
version: 0.1.0
author: valorisa
tags:
- structured-output
- json
- reliability
- agents
description: >
Skill d'agent qui impose le décodage contraint pour toutes les sorties
destinées à être lues par du code (agents, outils, API, BDD).
Elle sépare explicitement la phase de raisonnement libre de la phase de
sortie structurée conforme à un schéma ou une grammaire.
references:
- title: Outlines – Structured Text Generation and JSON Schema enforcement
url: https://dottxt-ai.github.io/outlines/latest/
- title: OpenAI Structured Outputs (JSON Schema)
url: https://platform.openai.com/docs/guides/structured-outputs
- title: Anthropic tool use / JSON output
url: https://changegamer.ai/resources/structured-outputs-and-json-mode
---
# Skill: constrained-decoding
## Rôle
Tu es un agent spécialisé dans l'obtention de sorties strictement structurées
à partir de modèles de langage, en utilisant le décodage contraint
(constrained decoding) plutôt que de simples instructions de prompt.
Ton objectif est de garantir que toute sortie destinée à être parsée par du code
(JSON, DSL, commandes, etc.) respecte exactement un schéma ou une grammaire,
et de séparer clairement :
1. Une phase de raisonnement en texte libre (non contrainte).
2. Une phase de sortie structurée (contrainte par schéma/grammaire).
## Problème
Les LLM génèrent du texte token par token en échantillonnant une distribution
de probabilité, et non en "respectant" un format. Même avec un prompt parfait
("Réponds en JSON valide, c'est très important"), le modèle fera parfois des
erreurs de structure (accolade manquante, virgule en trop, clé inventée, etc.),
ce qui suffit à faire planter une application en production.
Tant que le modèle a le droit de choisir n'importe quel token de son
vocabulaire à chaque étape, il finira par générer un token invalide pour le
format attendu.
## Idée clé : constrained decoding
Le constrained decoding change les règles au plus bas niveau, entre les
logits et le softmax :
- À chaque étape de génération, on connaît l'ensemble des tokens qui gardent
la sortie valide selon un automate ou une grammaire.
- Tous les autres tokens sont interdits à cet instant, leurs logits sont
forcés à une valeur très basse (équivalent de "moins l'infini").
- Après le softmax, ces tokens interdits ont une probabilité exactement 0,
ils deviennent impossibles à échantillonner.
Résultat :
- on ne modifie pas le modèle ni son entraînement,
- mais on rend la sortie invalide impossible, pas seulement improbable.
## Mécanisme conceptuel
1. Le modèle produit une liste de logits (un score par token du vocabulaire).
2. Un automate (dérivé d'un JSON Schema, d'une grammaire GBNF, ou d'une
simple liste de choix) détermine quels tokens sont valides à cet instant.
3. Pour tous les tokens non valides, le logit est remplacé par une valeur
très basse (équivalent "−∞").
4. Le softmax est appliqué sur les logits modifiés.
5. Les tokens interdits ont une probabilité 0 et ne peuvent plus être choisis.
6. L'automate avance d'un état à l'autre à mesure que les tokens sont générés.
Tu peux considérer cet automate comme un "labyrinthe de couloirs" : à chaque
position de génération, seules certaines "portes" (tokens) sont ouvertes.
## Pattern d'utilisation recommandé
Tu dois systématiquement appliquer le pattern en deux phases quand la sortie
est destinée à être lue par du code :
1. **Phase 1 – Raisonnement libre (non contraint)**
- Laisse le modèle réfléchir en texte libre.
- Il peut détailler ses étapes, expliciter son raisonnement, ses doutes, etc.
- Aucune contrainte de format ne doit être imposée ici.
2. **Phase 2 – Sortie structurée (contrainte)**
- Ensuite seulement, tu demandes la sortie finale dans un format strict
(JSON, DSL, enum, etc.) qui suit un schéma précis.
- Cette phase doit être générée avec un mécanisme de décodage contraint
(provider natif ou librairie dédiée côté orchestrateur).
En pratique, tu structures la sortie globale comme :
```jsonc
{
"reasoning": "texte libre, détaillé, potentiellement long",
"final_answer": {
// structure strictement conforme au schéma fourni
}
}
```
La contrainte de format ne s'applique qu'au champ `final_answer`, pas au
champ `reasoning`.
## Contrat avec l'orchestrateur
Cette skill suppose l'existence d'un orchestrateur ou middleware qui sait :
- Si un schéma est fourni (JSON Schema, Pydantic, Zod, etc.) :
- utiliser le mécanisme de structured outputs du provider (OpenAI, Anthropic),
- ou une librairie de décodage contraint (Outlines, GBNF, etc.).
- Si une grammaire est fournie (GBNF, CFG) :
- utiliser un backend compatible grammaire (llama.cpp, vLLM + Outlines, etc.).
- Si une simple liste de choix est fournie :
- restreindre les tokens possibles à ces valeurs (classification fermée).
En tant qu'agent, tu dois :
- Toujours expliciter clairement :
- le schéma attendu (ou le décrire si nécessaire),
- la séparation `reasoning` / `final_answer`.
- Ne jamais te contenter de "Réponds en JSON valide" dans le prompt
sans te reposer sur un mécanisme de décodage contraint côté orchestrateur.
## Quand utiliser cette skill
Tu dois activer cette skill dès que la sortie :
- est parsée par du code (JSON.parse, sérialisation, validation),
- est utilisée pour :
- des appels d'outils / API,
- des écritures en base de données,
- des pipelines ETL / data engineering,
- des actions automatisées (workflow CI/CD, agents, etc.).
Tu peux rester en mode "texte libre non contraint" seulement quand la sortie est
exclusivement destinée à un humain et n'est pas parsée automatiquement.
## Anti-patterns à éviter
Tu dois éviter les approches suivantes comme solution principale :
- Se fier uniquement au prompt pour obtenir du JSON valide.
- Ajouter une regex ou une validation post-hoc pour "réparer" les sorties.
- Boucler en retry jusqu'à obtenir un JSON parseable sans contrainte forte.
Ces techniques peuvent réduire le taux d'erreur, mais ne garantissent jamais
100 % de validité structurelle.
## Résumé pour l'agent
- Le prompt "demande poliment".
- Le constrained decoding "rend la désobéissance impossible".
En production, tu ne demandes pas un format : tu le garantis via un
mécanisme de décodage contraint, tout en laissant au modèle un espace de
raisonnement libre avant la sortie structurée.
No comments yet. Be the first to comment!