# AzureContentModerationMiddleware

> **Class** in `langchain_azure_ai`

📖 [View in docs](https://reference.langchain.com/python/langchain-azure-ai/agents/middleware/content_safety/_text/AzureContentModerationMiddleware)

AgentMiddleware that screens **text** messages with Azure AI Content Safety.

Pass this class (or multiple instances) in the ``middleware`` parameter of
any LangChain ``create_agent`` call:

```python
from langchain.agents import create_agent
from langchain_azure_ai.agents.middleware import (
    AzureContentModerationMiddleware
)

agent = create_agent(
    model="azure_ai:gpt-4.1",
    middleware=[
        # Screen both input and output text for all harm categories
        AzureContentModerationMiddleware(
            endpoint="https://my-resource.cognitiveservices.azure.com/",
            exit_behavior="error",
        ),
    ],
)
```

You can compose multiple instances with different configurations:

```python

agent = create_agent(
    model="azure_ai:gpt-4.1",
    middleware=[
        # Raise on hate/violence on input only
        AzureContentModerationMiddleware(
            categories=["Hate", "Violence"],
            exit_behavior="error",
            apply_to_input=True,
            apply_to_output=False,
            name="input_safety",
        ),
        # Replace self-harm content in model output and continue
        AzureContentModerationMiddleware(
            categories=["SelfHarm"],
            exit_behavior="continue",
            apply_to_input=False,
            apply_to_output=True,
            name="output_safety",
        ),
    ],
)
```

The middleware analyses text content using the Azure AI Content Safety API
and takes one of three actions when violations are detected:

* ``"error"`` – raises :exc:`ContentSafetyViolationError`, halting the graph.
* ``"replace"`` – replaces the offending message with a violation notice
  (either a service-derived description or a custom ``violation_message``)
  and lets execution proceed.
* ``"continue"`` – ignores the violation and lets execution proceed by
  adding annotations to the message metadata with details of the violation(s).

Both synchronous (``before_agent`` / ``after_agent``) and asynchronous
(``abefore_agent`` / ``aafter_agent``) hooks are implemented.

By default the middleware extracts the last ``HumanMessage`` (input) or
``AIMessage`` (output) and submits its text to the service.  You can
override this behaviour by supplying a ``context_extractor`` callable::

```python
from langchain_azure_ai.agents.middleware import (
    AzureContentModerationMiddleware,
    TextModerationInput,
)

def my_extractor(state, runtime):
    # Return None to skip moderation for this call
    messages = state.get("messages", [])
    text = " ".join(m.content for m in messages if hasattr(m, "content"))
    return TextModerationInput(text=text) if text else None

middleware = AzureContentModerationMiddleware(
    context_extractor=my_extractor,
)
```

## Signature

```python
AzureContentModerationMiddleware(
    self,
    endpoint: Optional[str] = None,
    credential: Optional[Any] = None,
    *,
    project_endpoint: Optional[str] = None,
    categories: Optional[List[Literal['Hate', 'SelfHarm', 'Sexual', 'Violence']]] = None,
    severity_threshold: int = 4,
    exit_behavior: Literal['error', 'continue', 'replace'] = 'error',
    violation_message: Optional[str] = None,
    apply_to_input: bool = True,
    apply_to_output: bool = True,
    blocklist_names: Optional[List[str]] = None,
    name: str = 'azure_content_safety',
    context_extractor: Optional[Callable[[AgentState[Any], Runtime[Any]], Optional[TextModerationInput]]] = None,
)
```

## Parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `endpoint` | `Optional[str]` | No | Azure Content Safety resource endpoint URL.  Falls back to the ``AZURE_CONTENT_SAFETY_ENDPOINT`` environment variable. Mutually exclusive with ``project_endpoint``. (default: `None`) |
| `credential` | `Optional[Any]` | No | Azure credential.  Accepts a :class:`~azure.core.credentials.TokenCredential`, :class:`~azure.core.credentials.AzureKeyCredential`, or a plain API-key string.  Defaults to :class:`~azure.identity.DefaultAzureCredential` when ``None``. (default: `None`) |
| `project_endpoint` | `Optional[str]` | No | Azure AI Foundry project endpoint URL (e.g. ``https://<resource>.services.ai.azure.com/api/projects/<project>``). Falls back to the ``AZURE_AI_PROJECT_ENDPOINT`` environment variable. Mutually exclusive with ``endpoint``. (default: `None`) |
| `categories` | `Optional[List[Literal['Hate', 'SelfHarm', 'Sexual', 'Violence']]]` | No | Harm categories to analyse.  Valid values are ``"Hate"``, ``"SelfHarm"``, ``"Sexual"``, and ``"Violence"``.  Defaults to all four. (default: `None`) |
| `severity_threshold` | `int` | No | Minimum severity score (0–6) that triggers the configured exit behaviour.  Defaults to ``4`` (medium). (default: `4`) |
| `exit_behavior` | `Literal['error', 'continue', 'replace']` | No | What to do when a violation is detected.  One of ``"error"`` (default), ``"continue"``, or ``"replace"``. (default: `'error'`) |
| `violation_message` | `Optional[str]` | No | Custom text used to replace the offending message when ``exit_behavior="replace"``. Defaults to a message built from the service response. (default: `None`) |
| `apply_to_input` | `bool` | No | Whether to screen the agent's input (last ``HumanMessage``).  Defaults to ``True``. (default: `True`) |
| `apply_to_output` | `bool` | No | Whether to screen the agent's output (last ``AIMessage``).  Defaults to ``True``. (default: `True`) |
| `blocklist_names` | `Optional[List[str]]` | No | Names of custom blocklists configured in your Azure Content Safety resource.  Matches against these lists in addition to the built-in harm classifiers. (default: `None`) |
| `name` | `str` | No | Node-name prefix used when wiring this middleware into a LangGraph.  Defaults to ``"azure_content_safety"``. (default: `'azure_content_safety'`) |
| `context_extractor` | `Optional[Callable[[AgentState[Any], Runtime[Any]], Optional[TextModerationInput]]]` | No | Optional callable with signature ``(state, runtime) -> Optional[TextModerationInput]`` that receives the current graph state and the LangGraph :class:`~langchain.agents.middleware.Runtime` execution context, and returns the text to screen, or ``None`` to skip evaluation entirely.  When ``None`` (default) the middleware uses its built-in extraction logic. (default: `None`) |

## Extends

- `_AzureContentSafetyBaseMiddleware`

## Constructors

```python
__init__(
    self,
    endpoint: Optional[str] = None,
    credential: Optional[Any] = None,
    *,
    project_endpoint: Optional[str] = None,
    categories: Optional[List[Literal['Hate', 'SelfHarm', 'Sexual', 'Violence']]] = None,
    severity_threshold: int = 4,
    exit_behavior: Literal['error', 'continue', 'replace'] = 'error',
    violation_message: Optional[str] = None,
    apply_to_input: bool = True,
    apply_to_output: bool = True,
    blocklist_names: Optional[List[str]] = None,
    name: str = 'azure_content_safety',
    context_extractor: Optional[Callable[[AgentState[Any], Runtime[Any]], Optional[TextModerationInput]]] = None,
) -> None
```

| Name | Type |
|------|------|
| `endpoint` | `Optional[str]` |
| `credential` | `Optional[Any]` |
| `project_endpoint` | `Optional[str]` |
| `categories` | `Optional[List[Literal['Hate', 'SelfHarm', 'Sexual', 'Violence']]]` |
| `severity_threshold` | `int` |
| `exit_behavior` | `Literal['error', 'continue', 'replace']` |
| `violation_message` | `Optional[str]` |
| `apply_to_input` | `bool` |
| `apply_to_output` | `bool` |
| `blocklist_names` | `Optional[List[str]]` |
| `name` | `str` |
| `context_extractor` | `Optional[Callable[[AgentState[Any], Runtime[Any]], Optional[TextModerationInput]]]` |


## Methods

- [`get_annotation_from_evaluations()`](https://reference.langchain.com/python/langchain-azure-ai/agents/middleware/content_safety/_text/AzureContentModerationMiddleware/get_annotation_from_evaluations)
- [`get_evaluation_response()`](https://reference.langchain.com/python/langchain-azure-ai/agents/middleware/content_safety/_text/AzureContentModerationMiddleware/get_evaluation_response)
- [`before_agent()`](https://reference.langchain.com/python/langchain-azure-ai/agents/middleware/content_safety/_text/AzureContentModerationMiddleware/before_agent)
- [`after_agent()`](https://reference.langchain.com/python/langchain-azure-ai/agents/middleware/content_safety/_text/AzureContentModerationMiddleware/after_agent)
- [`abefore_agent()`](https://reference.langchain.com/python/langchain-azure-ai/agents/middleware/content_safety/_text/AzureContentModerationMiddleware/abefore_agent)
- [`aafter_agent()`](https://reference.langchain.com/python/langchain-azure-ai/agents/middleware/content_safety/_text/AzureContentModerationMiddleware/aafter_agent)

---

[View source on GitHub](https://github.com/langchain-ai/langchain-azure/blob/7a6a664d617264df8dcb12fcfb1bacc09f21d504/libs/azure-ai/langchain_azure_ai/agents/middleware/content_safety/_text.py#L49)