BrainyBeeBrainyBee
ExploreBlogStart Studying
HomeDeveloping AI Apps and Agents on Azure (AI-103)Implement filters to classify unsafe or disallowed visual content
Lesson2,760 words

Implement filters to classify unsafe or disallowed visual content

AI-103 › Unit 3: Implement computer vision solutions › Implement responsible AI for multimodal content › Implement filters to classify unsafe or disallowed visual content

Implement filters to classify unsafe or disallowed visual content

Visual content moderation inherits the text filtering model and changes three things: the severity scale is coarser for images, the per-request override does not apply, and blocklists — being text — cannot see pixels at all. Knowing which of those bites in a given scenario is most of this objective.

Why This Matters

Image severities are trimmed. Image analysis "only returns severities 0, 2, 4, and 6", while image with text supports the full 0–7. Thresholding logic written for text breaks silently.

x-policy-id stops working. The per-request filter override "is not available for image input (chat with images) scenarios" — so per-caller variation must move to separate deployments.

Blocklists are a text control. They match terms. A prohibited symbol in an image is not a term, which is why that requirement needs a different instrument entirely.

What carries over and what does not

Carries over: the four harm categories, the safe/low/medium/high levels, the medium default on prompts and completions, resource-level filters associated with deployments, and annotate only. Does not: the x-policy-id override, the full 0–7 scale for image-only analysis, and blocklists as a means of catching visual content.

Prerequisites

  • The four harm categories and the four severity levels.
  • That filters are created at the resource level and associated with deployments.
  • Annotate-only as a measurement mode, and the approval rule on completions.
  • That image generation moderates the prompt and the output.

Learning Objectives

By the end of this lesson you will be able to:

  1. Apply the severity scale correct to each modality.
  2. Configure filtering for image input and image output.
  3. Explain why x-policy-id cannot be used and what replaces it.
  4. Use annotate only to measure before enforcing.
  5. Recognise requirements no built-in filter satisfies.

Building Blocks

The categories. Content Safety "recognizes four distinct categories of objectionable content": Hate and Fairness, Sexual, Violence, Self-Harm, and "classification can be multi-labeled".

The severity scales by modality.

ModalityScale
TextFull 0–7; can return trimmed 0/2/4/6 if requested
ImageTrimmed only — 0, 2, 4, 6
Image with text (multimodal)Full 0–7

The filtering system. Four levels — safe, low, medium, high — with the default configuration filtering at the medium threshold for all four categories on both prompts and completions. Safe-level content "is labeled in annotation output but isn't subject to filtering and isn't configurable".

Annotate only. "Runs the respective model and returns annotations via API response, but it will not filter content." Available for prompts; for completions if approved, since turning filters "partially or fully off on completions" requires approval.

Scope. Filters are configured at the resource level and "associated with one or more deployments". The x-policy-id request override exists for text but "is not available for image input (chat with images) scenarios".

Generation moderation. Image and video generation moderate the prompt and the output. Sora 2 additionally "blocks all IP and photorealistic content", rejects copyrighted characters and music, cannot generate real people including public figures, rejects input images with faces of humans, and produces only content suitable for audiences under 18.

In Content Understanding. Filter results are surfaced "directly from the Foundry model deployment it uses", included as a content_filters array, and tuned on the Guardrails instance of that deployment — including switching "from blocking to annotating mode".

Where the filter sits

Attribute
Configured on

The deployment's filter

The deployment's filter

The Guardrails instance of your model deployment

Per-request override

Not available

Not applicable

Not applicable

Result surfaced as

A block or annotations

No image returned

content_filters array

Vary per caller by

Separate deployments

Separate deployments

Separate deployments

Deep Dive

The scale that changes, and why it is not a downgrade

Text supports the full 0–7 and can optionally return a trimmed 0/2/4/6 where "each two adjacent levels are mapped to a single level". Image supports only the trimmed scale. Image with text supports the full 0–7.

The reasoning trap is assuming the ceiling was lowered for images. It was not — multimodal returns 7, so nothing is being reserved. The image classifier reports at coarser resolution, which is a different statement.

The practical consequence is in code. A pipeline that routes on severity >= 5 works on text and never fires on images, because 5 is not a value the image classifier returns. Thresholds must be expressed against the values the modality actually produces — and a system handling both should not share one numeric threshold across them.

Note also that the filtering system's four named levels (safe, low, medium, high) are a separate vocabulary from the API's numbers. You set thresholds in the named levels; you receive numbers from the API. Conflating them produces confidently wrong answers.

Configuring visual content filtering

  1. 1

    Start from the defaults

    Four categories at the medium threshold on both prompts and completions — no configuration required.

Losing the per-request override

For text, x-policy-id names a custom filter configuration and "will override the deployment-level content filtering configuration for the specific API call". It is how a multi-tenant service applies stricter settings for one customer without duplicating deployments.

That mechanism disappears with images: it "is not available for image input (chat with images) scenarios", and the default deployment filter is used instead.

Two consequences follow.

Per-caller variation becomes a deployment concern. If customers genuinely require different thresholds and images are in scope, you need separate deployments, each with its own associated filter configuration, and routing logic in front.

A working text design can break on adding images. The failure is quiet — the header is accepted, the call succeeds, and the stricter policy simply did not apply. Any scenario that describes per-tenant filtering working "until we added image upload" is describing this.

Annotate only, as a measurement tool

Enforcement decisions are better made with data, and annotate-only is how you get it.

It "runs the respective model and returns annotations via API response, but it will not filter content". Running a representative sample through it shows the severity distribution — which categories appear, at what levels, and how much traffic a stricter threshold would block.

Two details matter. Safe-level content is annotated but not filtered and "isn't configurable", so annotations exist even where nothing would be blocked — making this a distribution signal rather than a block log. And annotate-only on completions requires approval, since it is a form of turning filtering off there; tightening thresholds afterwards is self-service.

The same idea appears inside Content Understanding: the Guardrails instance can be switched "from blocking to annotating mode", so the analyze response carries a content_filters array your workflow can act on rather than the platform refusing outright.

Blocklists cannot see an image

A blocklist matches terms — it is a text control, applied as an input filter, an output filter, or both. A prohibited symbol, a competitor's logo, or an unapproved visual mark is not a term, so no blocklist configuration will catch it. Requirements of that shape need a classifier — a trained detection or classification model, or a Content Understanding classify field — not a filter setting.

What the built-in filters do not cover

The four harm categories are fixed, and this is the boundary most scenarios probe.

They cannot be extended. There is no way to add "our prohibited symbol list" as a fifth category. Partner-specific, brand-specific, and regulatory-specific visual rules sit outside the harm taxonomy entirely.

Protected material is a different question. It detects known copyrighted content in output — text and code, both GA and on by default. It is not a brand-compliance control and not a provenance control.

Provenance is separate again. Content Credentials, implementing C2PA, record that content was AI-generated and by which model, embedded so they travel with the file.

Generation-side policy is model-level. Sora 2's restrictions — no real people including public figures, input images with faces rejected, no copyrighted characters or music, under-18-suitable only, blocks all IP and photorealistic content — are properties of the model, not settings you configure. A scenario asking to relax them is describing something outside the configuration surface.

Worked Examples

Example 1 — a threshold that never fires. A moderation pipeline routes anything with severity 5 or above to human review. It works for text; images never trigger it.

The image classifier returns only 0, 2, 4, and 6, so 5 is never produced. Express thresholds against values the modality actually returns. Text supports the full 0–7, and image with text does too — so nothing is reserved for multimodal; the image model simply reports at coarser resolution.

Example 2 — per-tenant strictness, then images. A service applies stricter filtering for one customer using x-policy-id, then adds image upload and the stricter policy stops applying.

x-policy-id "is not available for image input (chat with images) scenarios", so the deployment's filter governs. The call still succeeds, which is why it fails quietly. Move the variation to separate deployments with different associated filter configurations.

Example 3 — a prohibited symbol list. A partner requires that a defined set of symbols never appears in generated images.

Not a filter configuration. The harm categories cannot be extended, and a blocklist matches terms, not pixels. This needs a classifier over the output — an Azure ML AutoML detection model, or a Content Understanding classify field — plus review. Pair with Content Credentials if provenance is also required.

Visual Explanations

The three scales:

Loading Diagram...
Figure 1 — Mermaid diagram

What applies where:

Loading Diagram...
Figure 2 — Mermaid diagram

Common Mistakes

Sharing one numeric threshold across text and image. Image returns only 0/2/4/6.

Reading the image trim as a lowered ceiling. Multimodal returns 7.

Confusing the four named levels with the API's numbers.

Assuming x-policy-id works with image input. It does not, and it fails quietly.

Expecting a blocklist to catch a symbol or logo. Blocklists match terms.

Trying to add a fifth harm category. The taxonomy is fixed.

Confusing protected material with brand compliance or provenance.

Forgetting that annotate-only on completions needs approval.

Retrying a refused generation unchanged. The same prompt gives the same result.

Practice Exercises

  1. Give the severity scale for each of the three modalities, and say what the image trim does not mean.
  2. Why does per-tenant filtering break when image input is added, and what is the fix?
  3. What does annotate-only do, and what approval does it need?
  4. A partner supplies a list of prohibited symbols. Why is no filter setting sufficient?
  5. Name three visual policy needs the built-in filters do not cover.
▶Answers
  1. Text — full 0–7, trimmed optional. Image — trimmed only: 0, 2, 4, 6. Image with text — full 0–7. The trim does not mean a lowered ceiling: multimodal returns 7, so nothing is reserved; the image classifier simply reports at coarser resolution.
  2. The x-policy-id per-request override "is not available for image input (chat with images) scenarios", so the deployment's filter governs and the call still succeeds — a quiet failure. Fix by using separate deployments, each with its own associated filter configuration, and routing in front.
  3. It "runs the respective model and returns annotations via API response, but it will not filter content" — used to measure the severity distribution before tightening a threshold, or to let the application decide. On completions it requires approval, since it is a form of turning filtering off there.
  4. Because the harm categories cannot be extended and a blocklist matches terms, not pixels. A prohibited symbol is visual, so it needs a classifier — an Azure ML AutoML detection model or a Content Understanding classify field — with review.
  5. Brand and partner-specific visual rules (symbols, logos, mark usage); provenance — which needs Content Credentials (C2PA); and model-level generation policy such as Sora 2's blocking of real people, faces in input images, copyrighted characters and music — properties of the model, not settings.

Summary & Concept Map

Visual filtering inherits the text model and diverges in three places. The four harm categories filter at the medium threshold on both prompts and completions by default, configured at the resource and associated with deployments — but the x-policy-id per-request override is not available for image input, so per-caller variation becomes separate deployments, and its absence fails quietly. Severity vocabularies must be kept straight: the filtering system uses safe/low/medium/high, while the API returns numbers where image is trimmed to 0/2/4/6 and image with text is full 0–7 — a coarser report, not a lower ceiling. Annotate only measures the distribution before enforcement, needing approval on completions, and appears inside Content Understanding as a Guardrails setting surfacing a content_filters array. And the boundary matters: blocklists match terms, not pixels, the taxonomy cannot be extended, and brand rules, provenance, and model-level generation policy all live outside it.

Loading Diagram...
Figure 3 — Mermaid diagram
Loading flashcards…

Sources and freshness

Written against current Microsoft Learn documentation for the AI-103 skills measured (16 April 2026), reviewed 2026-08-20. Microsoft Learn controls every changing product contract — availability, preview status, quotas, limits, regional support, naming, and retirement dates all move independently of this lesson. Where a scenario turns on a specific number or a GA/preview boundary, confirm it against the product's own page before relying on it.

All Developing AI Apps and Agents on Azure (AI-103) Study Resources

Related Notes

  • Choose an appropriate method for retrieval and indexing2,778 words
  • Quick Note — Choose an appropriate method for retrieval and indexing888 words
  • Choose an appropriate model for each task, including LLMs, small language models, multimodal models, and Foundry Tools3,097 words
  • Quick Note — Choose an appropriate model for each task, including LLMs, small language models, multimodal models, and Foundry Tools1,041 words
  • Choose appropriate memory, tool, and knowledge integration services for agent solutions2,815 words
  • Quick Note — Choose appropriate memory, tool, and knowledge integration services for agent solutions949 words
  • Choose the appropriate Foundry services for generative tasks, grounding, vector search, agent workflows, or multimodal processing2,733 words
  • Quick Note — Choose the appropriate Foundry services for generative tasks, grounding, vector search, agent workflows, or multimodal processing901 words
  • Apply responsible AI instrumentation, including evaluators, safety evaluations, and explanation tooling2,891 words
  • Configure safety filters, guardrails, risk detection, and content moderation2,795 words
  • Govern agent behavior with oversight modes, constraints, and tool-access controls2,863 words
  • Implement auditing through trace logging, provenance metadata, and approval workflows2,624 words

Ready to study Developing AI Apps and Agents on Azure (AI-103)?

Practice tests, flashcards, and all study notes — free, no sign-up.

Start Studying

Ready to study Developing AI Apps and Agents on Azure (AI-103)?

Practice tests, flashcards, and all study notes — free, no sign-up needed.

Start Studying — Free
Developing AI Apps and Agents on Azure (AI-103) ResourcesExplore All HivesBlogHome

© 2026 BrainyBee. Free AI-powered exam prep.

Loading Diagram...
Flowchart, top to bottom. Content Safety severity connects to Text: full 0-7<br/>trimmed optional. Content Safety severity] --> T[Text: full 0-7<br/>trimmed optional connects to Image: TRIMMED ONLY<br/>0, 2, 4, 6. Content Safety severity] --> T[Text: full 0-7<br/>trimmed optional connects to Image with text: full 0-7. I connects to Not a lowered ceiling -<br/>multimodal returns 7.<br/>Coarser reporting only. Filtering system - separate vocabulary connects to safe / low / medium / high<br/>thresholds set here.
Loading Diagram...
Flowchart, top to bottom. Requirement connects to A harm category?. H connects to Content filter:<br/>threshold per direction,<br/>default MEDIUM both ways (Yes). H connects to Enumerable TERMS? (No). K connects to Blocklist - text only,<br/>input, output, or both (Yes). K connects to CLASSIFIER:<br/>AutoML detection or<br/>Content Understanding classify (No, it is visual). Requirement] --> H{A harm category? connects to Provenance?. P connects to Content Credentials - C2PA (Yes). Requirement] --> H{A harm category? connects to Per-caller variation<br/>with image input?. 1 more statements.
Loading Diagram...
Flowchart, top to bottom. Visual filtering connects to Inherited. Visual filtering] --> INH[Inherited connects to Diverges. Visual filtering] --> INH[Inherited connects to Measurement. Visual filtering] --> INH[Inherited connects to Outside the filter. INH connects to Four harm categories. INH connects to safe / low / medium / high. INH connects to MEDIUM default, both directions. INH connects to Resource-level; ASSOCIATE to deployment. 11 more statements.

Visual content filtering — retrieval

Card 1 of 6

Front of flashcard 1 of 6

Severity scale by modality

hard

Text — full 0–7, trimmed optional. Image — trimmed only: 0, 2, 4, 6. Image with text (multimodal) — full 0–7. The image trim is coarser reporting, not a lowered ceiling.

severity

Visual content filtering — retrieval

Card 1

Front

Severity scale by modality

Back

Text — full 0–7, trimmed optional. Image — trimmed only: 0, 2, 4, 6. Image with text (multimodal) — full 0–7. The image trim is coarser reporting, not a lowered ceiling.

Card 2

Front

x-policy-id and image input

Back

The per-request filter override "is not available for image input (chat with images) scenarios" — the deployment's filter governs. The call still succeeds, so it fails quietly. Per-caller variation requires separate deployments.

Card 3

Front

Annotate only

Back

"Runs the respective model and returns annotations via API response, but it will not filter content." Use it to measure the severity distribution before tightening. On completions it requires approval.

Card 4

Front

Why a blocklist cannot catch a logo

Back

Blocklists match terms — they are a text control applied as an input filter, output filter, or both. A symbol, logo, or visual mark is not a term, so the requirement needs a classifier: AutoML detection or a Content Understanding classify field.

Card 5

Front

What the harm taxonomy cannot do

Back

It cannot be extended — there is no fifth category for partner or brand rules. Protected material detects known copyrighted content, not brand compliance. Provenance is Content Credentials (C2PA), separate again.

Card 6

Front

Sora 2 policy is model-level

Back

No real people including public figures, input images with faces rejected, no copyrighted characters or music, under-18-suitable only, and it blocks all IP and photorealistic content. These are model properties, not filter settings you can relax.

Visual content filtering — retrieval

Card 1

Front

Severity scale by modality

Back

Text — full 0–7, trimmed optional. Image — trimmed only: 0, 2, 4, 6. Image with text (multimodal) — full 0–7. The image trim is coarser reporting, not a lowered ceiling.

Card 2

Front

x-policy-id and image input

Back

The per-request filter override "is not available for image input (chat with images) scenarios" — the deployment's filter governs. The call still succeeds, so it fails quietly. Per-caller variation requires separate deployments.

Card 3

Front

Annotate only

Back

"Runs the respective model and returns annotations via API response, but it will not filter content." Use it to measure the severity distribution before tightening. On completions it requires approval.

Card 4

Front

Why a blocklist cannot catch a logo

Back

Blocklists match terms — they are a text control applied as an input filter, output filter, or both. A symbol, logo, or visual mark is not a term, so the requirement needs a classifier: AutoML detection or a Content Understanding classify field.

Card 5

Front

What the harm taxonomy cannot do

Back

It cannot be extended — there is no fifth category for partner or brand rules. Protected material detects known copyrighted content, not brand compliance. Provenance is Content Credentials (C2PA), separate again.

Card 6

Front

Sora 2 policy is model-level

Back

No real people including public figures, input images with faces rejected, no copyrighted characters or music, under-18-suitable only, and it blocks all IP and photorealistic content. These are model properties, not filter settings you can relax.