Skip to main content
Lesson 6 of 12 · AI Moderation and Security with Mistral

The 11 Moderation Categories

Lesson 6 of 12 Updated November 3, 2026 Developer
On this page
  1. Understanding Risk Categories
  2. ”Hard” vs. “Soft” Categories
  3. Analyzing Scores in Python
  4. Multiple Categories: One Text Can Trigger Several Alerts
  5. Key Takeaways

Updated November 3, 2026. The category table previously listed three non-existent keys (hate, violence, unpredictable) and omitted dangerous. The eleven keys below reflect mistral-moderation-2603, based on the documentation and types from the mistralai SDK 3.7.0; descriptions follow Mistral’s definitions. Output values presented as measured data were illustrative examples and are now clearly labeled as such. Sources: Moderation & Guardrailing · Mistral Moderation 2411 (deprecated model).

Understanding Risk Categories

The Mistral Moderation model analyzes content across 11 distinct categories. Each category covers a specific risk type and returns an independent score between 0.0 and 1.0. Understanding exactly what each category detects is essential for setting meaningful thresholds. Without this clarity, you’re just guessing at numbers and wondering why content gets blocked unexpectedly.

The table below provides the exact API key for each category, what it covers, and the types of cases it catches in practice.

CategoryAPI KeyWhat Mistral Includes
Sexual contentsexualExplicitly described or promoted sexual activities, nudity, or sexual services; non-explicit educational or medical content is generally exempt
Hate and discriminationhate_and_discriminationPrejudice, hostility, or calls for discrimination based on protected characteristics, including harassment
Violence and threatsviolence_and_threatsDescribed, glorified, incited, or threatened physical violence, and instructions for committing it
Dangerous contentdangerousExtremely dangerous behaviors with a high risk of physical harm
Criminal activitiescriminalDescribed or promoted illegal activities
Self-harmselfharmSelf-harm, suicide, eating disorders: methods, glorification, intent, dangerous challenges
HealthhealthRequests for or provision of detailed or personalized medical advice
FinancefinancialRequests for or provision of detailed or personalized financial advice
LegallawRequests for or provision of detailed or personalized legal advice
Personal datapiiRequests, sharing, or attempts to obtain identifying data: full name, address, phone number, social security number, bank details
JailbreakjailbreakingAttempts to bypass model rules through prompt manipulation, role-playing, or other techniques

The dangerous, criminal, and jailbreaking categories arrived with mistral-moderation-2603. The previous model, mistral-moderation-2411, deprecated on March 31, 2026, combined the first two under a single key, dangerous_and_criminal_content, and did not detect jailbreaks. Some response examples in the documentation still show this older breakdown: always read the keys the API returns rather than assuming them.

”Hard” vs. “Soft” Categories

In practice, these 11 categories fall into two groups based on criticality, and this distinction drives your entire threshold strategy.

Hard categories — sexual, hate_and_discrimination, violence_and_threats, dangerous, criminal, and selfharm — represent serious risks where a false negative (failing to detect dangerous content) can have severe consequences. Sexual content carries legal risk and obligations to protect minors; hate speech exposes you to major reputational damage and legal liability; violence involves incitement and threats; dangerous and criminal categories cover high-risk behaviors and illegal activities; self-harm involves user safety and life-threatening situations. For these six categories, low thresholds of 0.1 to 0.2 are justified regardless of your product, and you deliberately accept some false positives.

Soft categories depend heavily on your application’s context, with adjustable thresholds between 0.3 and 0.8. A legitimate medical chatbot needs to discuss health, a fintech app requires conversations covered by financial, a legal assistant necessarily handles law, and some applications legally collect data falling under pii. One case reads differently: jailbreaking doesn’t depend on the subject matter but on the intent to manipulate the model, and remains critical for any application open to the public.

Analyzing Scores in Python

The following function transforms a raw API call into a readable verdict: it isolates categories exceeding 0.3, identifies the maximum score and its category, and returns a safe indicator you can use directly in your application logic.

from mistralai.client import Mistral
import os

client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])

def analyze_content(text: str) -> dict:
    """Analyze text and return risk categories."""
    response = client.classifiers.moderate(
        model="mistral-moderation-2603",
        inputs=[text]
    )

    scores = response.results[0].category_scores or {}

    # Separate risk categories
    risks = {}
    for category, score in scores.items():
        if score > 0.3:
            risks[category] = round(score, 3)

    return {
        "text": text[:100],
        "risks": risks,
        "max_score": max(scores.values(), default=0.0),
        "max_category": max(scores, key=lambda c: scores[c], default=None),
        "safe": len(risks) == 0
    }

print(analyze_content("Hello, how are you?"))
print(analyze_content("What dose of acetaminophen for a 20 kg child?"))

category_scores is optional in the SDK, hence the or {}. Run both examples on your account: the greeting should stay very low across the board, while the dosage question should spike on health. This isn’t “dangerous” content in the common sense—it’s content you must decide whether falls within your scope.

Multiple Categories: One Text Can Trigger Several Alerts

A single text can have high scores in multiple categories simultaneously—a request for help with tax fraud will hit criminal, financial, and law all at once. Your decision logic must account for this multiplicity, and above all, prioritize: the function below sorts violations by the magnitude of the threshold breach, telling you which category actually drove the block.

def evaluate_global_risk(scores: dict, thresholds: dict) -> dict:
    """Evaluate global risk considering all categories."""
    violations = []

    for category, threshold in thresholds.items():
        score = scores.get(category, 0)
        if score > threshold:
            violations.append({
                "category": category,
                "score": score,
                "threshold": threshold,
                "excess": round(score - threshold, 3)
            })

    return {
        "blocked": len(violations) > 0,
        "violations": sorted(violations,
                            key=lambda v: v["excess"],
                            reverse=True),
        "violation_count": len(violations)
    }

# Configuration by profile
strict_thresholds = {
    "sexual": 0.1, "hate_and_discrimination": 0.1, "violence_and_threats": 0.15,
    "dangerous": 0.1, "criminal": 0.1, "selfharm": 0.1,
    "health": 0.3, "financial": 0.3, "law": 0.3,
    "pii": 0.15, "jailbreaking": 0.1,
}

The strict_thresholds profile follows exactly the hard/soft logic outlined above: thresholds of 0.1 to 0.15 on the six critical categories and jailbreak, tolerance at 0.3 for contextual domains. Keep this structure as your starting point and document any deviations you introduce.

Key Takeaways

  • mistral-moderation-2603 analyzes content across 11 categories with fixed keys; hate, violence, or unpredictable do not exist
  • Each category returns a score from 0.0 to 1.0
  • “Hard” categories (sexual, hate_and_discrimination, violence_and_threats, dangerous, criminal, selfharm) require low thresholds
  • “Soft” categories (health, financial, law) adjust based on your application context
  • A single text can trigger multiple categories simultaneously
  • Use raw scores (category_scores) rather than default booleans