Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Azure AI Content Safety SDK for Python. Use for detecting harmful content in text and images with multi-severity classification.
.claude/skills/azure-ai-contentsafety-py/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | — | — |
| case-09 | ✗→✓ | ▲ Improved | — | — |
| case-12 | ✗→✓ | ▲ Improved | — | — |
| case-03 | ✗→✓ | ▲ Improved | — | — |
| case-14 | ✗→✓ | ▲ Improved | — | — |
Detect harmful user-generated and AI-generated content in applications.
bashpip install azure-ai-contentsafety
bashCONTENT_SAFETY_ENDPOINT=https://<resource>.cognitiveservices.azure.com CONTENT_SAFETY_KEY=<your-api-key>
pythonfrom azure.ai.contentsafety import ContentSafetyClient from azure.core.credentials import AzureKeyCredential import os client = ContentSafetyClient( endpoint=os.environ["CONTENT_SAFETY_ENDPOINT"], credential=AzureKeyCredential(os.environ["CONTENT_SAFETY_KEY"]) )
pythonfrom azure.ai.contentsafety import ContentSafetyClient from azure.identity import DefaultAzureCredential client = ContentSafetyClient( endpoint=os.environ["CONTENT_SAFETY_ENDPOINT"], credential=DefaultAzureCredential() )
pythonfrom azure.ai.contentsafety import ContentSafetyClient from azure.ai.contentsafety.models import AnalyzeTextOptions, TextCategory from azure.core.credentials import AzureKeyCredential client = ContentSafetyClient(endpoint, AzureKeyCredential(key)) request = AnalyzeTextOptions(text="Your text content to analyze") response = client.analyze_text(request) # Check each category for category in [TextCategory.HATE, TextCategory.SELF_HARM, TextCategory.SEXUAL, TextCategory.VIOLENCE]: result = next((r for r in response.categories_analysis if r.category == category), None) if result: print(f"{category}: severity {result.severity}")
pythonfrom azure.ai.contentsafety import ContentSafetyClient from azure.ai.contentsafety.models import AnalyzeImageOptions, ImageData from azure.core.credentials import AzureKeyCredential import base64 client = ContentSafetyClient(endpoint, AzureKeyCredential(key)) # From file with open("image.jpg", "rb") as f: image_data = base64.b64encode(f.read()).decode("utf-8") request = AnalyzeImageOptions( image=ImageData(content=image_data) ) response = client.analyze_image(request) for result in response.categories_analysis: print(f"{result.category}: severity {result.severity}")
pythonfrom azure.ai.contentsafety.models import AnalyzeImageOptions, ImageData request = AnalyzeImageOptions( image=ImageData(blob_url="https://example.com/image.jpg") ) response = client.analyze_image(request)
pythonfrom azure.ai.contentsafety import BlocklistClient from azure.ai.contentsafety.models import TextBlocklist from azure.core.credentials import AzureKeyCredential blocklist_client = BlocklistClient(endpoint, AzureKeyCredential(key)) blocklist = TextBlocklist( blocklist_name="my-blocklist", description="Custom terms to block" ) result = blocklist_client.create_or_update_text_blocklist( blocklist_name="my-blocklist", options=blocklist )
pythonfrom azure.ai.contentsafety.models import AddOrUpdateTextBlocklistItemsOptions, TextBlocklistItem items = AddOrUpdateTextBlocklistItemsOptions( blocklist_items=[ TextBlocklistItem(text="blocked-term-1"), TextBlocklistItem(text="blocked-term-2") ] ) result = blocklist_client.add_or_update_blocklist_items( blocklist_name="my-blocklist", options=items )
pythonfrom azure.ai.contentsafety.models import AnalyzeTextOptions request = AnalyzeTextOptions( text="Text containing blocked-term-1", blocklist_names=["my-blocklist"], halt_on_blocklist_hit=True ) response = client.analyze_text(request) if response.blocklists_match: for match in response.blocklists_match: print(f"Blocked: {match.blocklist_item_text}")
Text analysis returns 4 severity levels (0, 2, 4, 6) by default. For 8 levels (0-7):
pythonfrom azure.ai.contentsafety.models import AnalyzeTextOptions, AnalyzeTextOutputType request = AnalyzeTextOptions( text="Your text", output_type=AnalyzeTextOutputType.EIGHT_SEVERITY_LEVELS )
| Category | Description | |----------|-------------| | Hate | Attacks based on identity (race, religion, gender, etc.) | | Sexual | Sexual content, relationships, anatomy | | Violence | Physical harm, weapons, injury | | SelfHarm | Self-injury, suicide, eating disorders |
| Level | Text Range | Image Range | Meaning | |-------|------------|-------------|---------| | 0 | Safe | Safe | No harmful content | | 2 | Low | Low | Mild references | | 4 | Medium | Medium | Moderate content | | 6 | High | High | Severe content |
| Client | Purpose | |--------|---------| | ContentSafetyClient | Analyze text and images | | BlocklistClient | Manage custom blocklists |
This skill is applicable to execute the workflow or actions described in the overview.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | pass→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +36 percentage points is the difference between those two pass rates over the 22 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.