Custom Guardrails : bloquer avant le modèle
Sur cette page
Leçon réécrite le 3 novembre 2026. Elle décrivait un paramètre
guardrailsinventé (un dictionnaire avecenabled), des catégories qui n’existent pas (hate,violence), une méthodeconversation.send()absente du SDK et des réponses JSON imaginaires. Le format officiel est une liste de configurationsmoderation_llm_v2, et les réponses ci-dessous sont celles de la documentation. Le code a été vérifié contre les types du SDKmistralai3.7.0. Sources : Moderation & Guardrailing · SDK Python mistralai.
Le principe des Custom Guardrails
Les Custom Guardrails de Mistral fonctionnent comme un filtre en entrée : ils analysent le prompt de l’utilisateur avant qu’il n’atteigne le modèle de génération. Si le contenu dépasse l’un des seuils que vous avez fixés, la requête est bloquée avec une erreur HTTP 403. Le modèle ne voit jamais le prompt problématique.
La documentation insiste sur deux limites, à garder en tête dès le départ. Les guardrails ne modèrent que l’entrée : ce que le modèle génère n’est pas vérifié, c’est le rôle de l’API Moderation (leçon 5). Et ils remplacent un travail que vous auriez sinon codé vous-même : appeler l’API Moderation, comparer les scores à vos seuils, refuser la requête.
Comment ça fonctionne
Lorsque vous ajoutez des guardrails à une requête, l’enchaînement côté Mistral est le suivant :
- Votre application envoie la requête avec le paramètre
guardrails - Le classifieur
mistral-moderation-2603note le prompt dans chaque catégorie - Si un score dépasse son seuil, l’API renvoie une erreur
403et le modèle n’est pas appelé - Sinon, le modèle traite la requête normalement
- La réponse contient un champ
guardrailsavec les scores évalués
Flux : prompt → [mistral-moderation-2603] → score > seuil ? → 403 (bloqué)
→ sinon → [LLM] → réponse + scores
La décision repose sur un score comparé à un seuil que vous fixez, catégorie par catégorie, entre 0 et 1. Un seuil bas bloque davantage ; un seuil à 1 désactive explicitement la catégorie.
Le format du paramètre guardrails
Le paramètre est une liste. Chaque élément est un objet qui contient une configuration moderation_llm_v2 et, à côté, l’option block_on_error :
guardrails = [
{
"block_on_error": True, # bloquer si la modération elle-même échoue
"moderation_llm_v2": {
"custom_category_thresholds": {
"jailbreaking": 0.3,
"criminal": 0.2,
},
"ignore_other_categories": False,
"action": "block",
},
}
]
| Clé | Où | Rôle |
|---|---|---|
custom_category_thresholds | dans moderation_llm_v2 | Seuil de 0 à 1 par catégorie ; 1 désactive la catégorie |
ignore_other_categories | dans moderation_llm_v2 | True : seules les catégories listées sont évaluées |
action | dans moderation_llm_v2 | "block" pour bloquer la requête en cas de dépassement |
model_name | dans moderation_llm_v2, facultatif | Autre modèle de modération que celui par défaut, mistral-moderation-2603 |
block_on_error | à côté de moderation_llm_v2 | True : la requête est bloquée si l’évaluation échoue |
Vous pouvez placer plusieurs objets dans la liste : la requête est bloquée dès que l’un d’eux se déclenche. Chaque objet ne contient qu’une seule configuration moderation_llm_v2. Une configuration plus ancienne, moderation_llm_v1, existe encore dans le SDK, avec les catégories de l’ancien modèle mistral-moderation-2411, déprécié le 31 mars 2026 : ne l’utilisez pas pour un nouveau projet.
Les onze catégories
Les clés de custom_category_thresholds sont fixées ; une autre clé, comme violence ou hate, ne correspond à rien :
| Clé | Ce qu’elle détecte |
|---|---|
sexual | Contenu sexuel explicite |
hate_and_discrimination | Haine ou discrimination fondée sur des caractéristiques protégées |
violence_and_threats | Violence physique décrite, glorifiée ou menacée |
dangerous | Comportements extrêmement dangereux |
criminal | Activités illégales |
selfharm | Automutilation, suicide, troubles alimentaires |
health | Demande de conseil médical détaillé ou personnalisé |
financial | Demande de conseil financier détaillé ou personnalisé |
law | Demande de conseil juridique détaillé ou personnalisé |
pii | Données personnelles demandées ou partagées |
jailbreaking | Tentative de contourner les règles du modèle |
La leçon 6 revient sur chacune et sur le choix des seuils.
Les trois niveaux d’application
Le même paramètre s’accepte à trois endroits. Le choix détermine où vit votre politique de sécurité, et qui peut l’oublier.
Niveau 1 : une requête Chat Completions
Vous passez guardrails dans l’appel chat.complete(). Chaque requête porte ses propres règles : pratique pour explorer, risqué à grande échelle, car il suffit d’un appel sans le paramètre pour qu’il passe sans contrôle.
import os
from mistralai.client import Mistral
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
response = client.chat.complete(
model="mistral-large-latest",
messages=[{"role": "user", "content": "Quelle est la distance de la Terre à la Lune ?"}],
guardrails=[
{
"block_on_error": True,
"moderation_llm_v2": {
"custom_category_thresholds": {"sexual": 0.1, "selfharm": 0.1},
"ignore_other_categories": False,
"action": "block",
},
}
],
)
print(response.choices[0].message.content)
Cas d’usage : prototypage, appels ponctuels, réglage des seuils.
Niveau 2 : une conversation
Avec l’API Conversations, vous passez guardrails au démarrage, dans client.beta.conversations.start() :
conversation = client.beta.conversations.start(
model="mistral-large-latest",
inputs="Bonjour, pouvez-vous m'aider à préparer un entretien ?",
guardrails=[
{
"block_on_error": True,
"moderation_llm_v2": {
"custom_category_thresholds": {
"sexual": 0.2,
"hate_and_discrimination": 0.1,
"violence_and_threats": 0.3,
"selfharm": 0.1,
},
"action": "block",
},
}
],
)
for entree in conversation.outputs:
if entree.type == "message.output":
print(entree.content)
Les messages suivants s’envoient avec client.beta.conversations.append(conversation_id=conversation.conversation_id, inputs=...). Cette méthode n’accepte pas de paramètre guardrails dans le SDK 3.7.0, et la documentation ne précise pas si ceux du démarrage s’appliquent encore aux tours suivants. Pour une protection garantie à chaque tour, attachez les guardrails à un agent.
Cas d’usage : conversation ponctuelle sans agent, ou remplacement des guardrails d’un agent pour une requête donnée.
Niveau 3 : un agent
Les guardrails passés à client.beta.agents.create() font partie de la définition de l’agent. D’après la documentation, toutes les conversations qui utilisent cet agent en héritent, sans les répéter. Une requête de conversation peut toutefois les remplacer en passant son propre guardrails.
agent = client.beta.agents.create(
model="mistral-large-latest",
name="Assistant sécurisé",
instructions="Vous êtes un assistant professionnel du service client.",
guardrails=[
{
"block_on_error": True,
"moderation_llm_v2": {
"custom_category_thresholds": {
"sexual": 0.1,
"hate_and_discrimination": 0.1,
"violence_and_threats": 0.2,
"criminal": 0.1,
"selfharm": 0.1,
"jailbreaking": 0.3,
},
"ignore_other_categories": False,
"action": "block",
},
}
],
)
conversation = client.beta.conversations.start(agent_id=agent.id, inputs="Bonjour !")
Cas d’usage : production, quand plusieurs équipes ou services appellent le même assistant.
Ce que renvoient les guardrails
Quand la requête passe, la réponse de l’API contient, à côté des champs habituels, un champ guardrails : une liste, avec un résultat par guardrail. Voici ce champ dans l’exemple de la documentation :
{
"guardrails": [
{
"moderation_llm_v2": {
"action": "pass",
"categories": {
"sexual": { "score": 0.03, "violated": false },
"selfharm": { "score": 0.05, "violated": false },
"violence_and_threats": { "score": 0.0, "violated": false },
"hate_and_discrimination": { "score": 0.0, "violated": false }
}
}
}
]
}
Avec ignore_other_categories à True, seules les catégories listées dans vos seuils figurent dans ce résultat. Dans le SDK Python, la réponse d’une conversation expose ce champ (conversation.guardrails). La réponse de chat.complete(), en revanche, n’a pas de champ prévu pour lui dans le SDK 3.7.0 : il s’y perd. Si vous voulez journaliser les scores, et c’est utile pour savoir plus tard si vos seuils sont trop lâches ou trop serrés, passez par les conversations ou lisez la réponse HTTP brute.
Quand un seuil est dépassé, l’API renvoie une erreur 403 dont le corps détaille la décision, catégorie par catégorie :
{
"error": { "message": "Content blocked by guardrail", "status": 403 },
"guardrails": {
"results": {
"moderation_llm_v2": {
"model_name": "mistral-moderation-2603",
"decisions": {
"sexual": { "threshold": 0.1, "score": 0.3, "violated": true },
"selfharm": { "threshold": 0.1, "score": 0.05, "violated": false }
},
"violated": true,
"action": "block"
}
}
}
}
Le SDK lève alors errors.SDKError, dont status_code vaut 403 et body contient ce JSON :
import json
from mistralai.client import errors
try:
response = client.chat.complete(
model="mistral-large-latest",
messages=[{"role": "user", "content": message_utilisateur}],
guardrails=guardrails,
)
except errors.SDKError as e:
if e.status_code != 403:
raise
decisions = json.loads(e.body)["guardrails"]["results"]["moderation_llm_v2"]["decisions"]
violees = [nom for nom, d in decisions.items() if d["violated"]]
print(f"Requête bloquée : {violees}")
C’est cette charge utile qui vous permettra d’expliquer un blocage lors d’une réclamation : quelle catégorie, quel score, quel seuil.
Reste le cas dégradé. Si l’évaluation elle-même échoue et que block_on_error vaut True, la requête est refusée avec le code d’erreur 3201 et le message Request blocked due to error in guardrail evaluation and block_on_error is set to True. C’est le mode fail-safe : en cas de doute, on bloque. Avec block_on_error à False, sa valeur par défaut dans le SDK, la requête passerait sans contrôle.
Choisir le bon niveau
| Critère | Chat Completions | Conversation | Agent |
|---|---|---|---|
| Où se déclarent les guardrails | Dans chaque appel | Au démarrage (start) | À la création de l’agent |
| Héritage | Aucun | Non documenté pour les tours suivants | Toutes les conversations de l’agent |
| Remplaçables | — | — | Oui, par une requête de conversation |
| Cas d’usage | Tests, réglage des seuils | Conversation ponctuelle | Production |
En pratique, réglez vos seuils sur des requêtes Chat Completions avec des cas réels, puis déplacez la politique dans un agent dès que le code sort de votre machine : il n’y aura plus d’appel oublié.
Points clés à retenir
- Les guardrails bloquent les prompts avant le modèle, par une erreur
403; ils ne vérifient pas la sortie - Le paramètre est une liste d’objets
{"block_on_error": ..., "moderation_llm_v2": {...}}, et non un dictionnaire avecenabled - Onze catégories aux noms fixés (
hate_and_discrimination,violence_and_threats…), un seuil de 0 à 1 chacune ;1désactive - Trois niveaux :
chat.complete(),conversations.start(),agents.create(); les agents transmettent leurs guardrails à toutes leurs conversations block_on_error=Trueassure le comportement fail-safe (erreur3201)