API7 Docs

ai-content-moderation plugin for Apache APISIX

Skill for configuring APISIX AWS and Aliyun AI content moderation via the a6 CLI. Covers request and response checks, streaming, deny_code, and ai-proxy.

Overview

APISIX provides two content moderation plugins that filter harmful content in LLM requests and responses:

PluginProviderRequestResponseStreaming
ai-aws-content-moderationAWS Comprehend
ai-aliyun-content-moderationAliyun Moderation Plus

Both must be used alongside ai-proxy or ai-proxy-multi so the plugin can moderate decoded AI content. AWS response and streaming moderation, fail_mode, role selection, and the default deny_code of 200 apply from APISIX 3.18.0. For field tables and protocol details, see /hub/ai-aws-content-moderation and /hub/ai-aliyun-content-moderation.

When to Use

  • Block toxic, hateful, or sexual content before it reaches the LLM
  • Moderate harmful LLM responses. Non-streaming responses can be denied before delivery; streaming checks cannot retract chunks already sent
  • Enforce content policies with configurable thresholds
  • Comply with content safety regulations

Plugin Execution Order

ai-prompt-template           (priority 1071)
ai-prompt-decorator          (priority 1070)
ai-proxy                     (priority 1040)
ai-aws-content-moderation    (priority 1031) ← runs AFTER ai-proxy
ai-aliyun-content-moderation (priority 1029) ← runs AFTER ai-proxy

A larger priority number runs earlier. Both moderation plugins run after ai-proxy or ai-proxy-multi so they can read the decoded AI request. They still block a flagged request before the upstream LLM is called.


Plugin 1: ai-aws-content-moderation

Uses the AWS Comprehend DetectToxicContent API to score request and response content.

Configuration Reference

FieldTypeRequiredDefaultDescription
comprehend.access_key_idstringYesAWS access key ID
comprehend.secret_access_keystringYesAWS secret access key
comprehend.regionstringYesAWS region (e.g. us-east-1)
comprehend.endpointstringNoAutoCustom Comprehend endpoint
comprehend.ssl_verifybooleanNotrueVerify SSL certificate
check_requestbooleanNotrueEnable request moderation
check_responsebooleanNofalseEnable response moderation
request_check_rolesarrayNouser, tool, system, assistantRoles to moderate on the request
request_check_modestringNoallall or last (latest consecutive block). system is always checked when selected
request_check_length_limitintegerNo1000Maximum bytes per Comprehend request text segment
response_check_length_limitintegerNo1000Maximum bytes per Comprehend response text segment
stream_check_modestringNofinal_packetrealtime or final_packet when check_response is true
stream_check_cache_sizeintegerNo128Maximum characters per moderation batch in realtime mode
stream_check_intervalnumberNo3Seconds between moderation batches in realtime mode
fail_modestringNoskipskip, warn, or error for non-AI / unrecognized traffic
deny_codenumberNo200HTTP status for a denied request before headers are sent
deny_messagestringNoCustom denial message
moderation_categoriesobjectNoPer-category thresholds (0-1)
moderation_thresholdnumberNo0.5Overall toxicity threshold (0-1)

Moderation Categories

CategoryDescription
PROFANITYProfane language
HATE_SPEECHHateful content
INSULTInsulting language
HARASSMENT_OR_ABUSEHarassment or abusive content
SEXUALSexual content
VIOLENCE_OR_THREATViolent or threatening content

Each category accepts a score threshold from 0 (strictest, blocks nearly everything) to 1 (most permissive). If moderation_categories is set, each category is checked individually. Otherwise, the moderation_threshold is used as an overall toxicity check.

Step-by-Step: AWS Content Moderation

a6 route create -f - <<'EOF'
{
  "id": "moderated-chat",
  "uri": "/v1/chat/completions",
  "methods": ["POST"],
  "plugins": {
    "ai-aws-content-moderation": {
      "comprehend": {
        "access_key_id": "AKIAIOSFODNN7EXAMPLE",
        "secret_access_key": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
        "region": "us-east-1"
      },
      "moderation_categories": {
        "HATE_SPEECH": 0.3,
        "VIOLENCE_OR_THREAT": 0.2,
        "SEXUAL": 0.5
      }
    },
    "ai-proxy": {
      "provider": "openai",
      "auth": {
        "header": {
          "Authorization": "Bearer sk-your-key"
        }
      },
      "options": {
        "model": "gpt-4"
      }
    }
  }
}
EOF

By default, a flagged request is denied with HTTP 200 and a provider-compatible refusal so AI SDKs can parse the body. Set deny_code: 400 when clients must treat moderation as an HTTP error.

request body exceeds HATE_SPEECH threshold

Overall threshold (no per-category filtering)

{
  "plugins": {
    "ai-aws-content-moderation": {
      "comprehend": {
        "access_key_id": "AKIA...",
        "secret_access_key": "secret...",
        "region": "us-east-1"
      },
      "moderation_threshold": 0.7
    }
  }
}

Plugin 2: ai-aliyun-content-moderation

Uses Aliyun Machine-Assisted Moderation Plus. Supports request moderation, response moderation, and real-time streaming moderation.

Configuration Reference

FieldTypeRequiredDefaultDescription
endpointstringYesAliyun service endpoint URL
region_idstringYesAliyun region (e.g. cn-shanghai)
access_key_idstringYesAliyun access key ID
access_key_secretstringYesAliyun access key secret
check_requestbooleanNotrueEnable request moderation
check_responsebooleanNofalseEnable response moderation
stream_check_modestringNofinal_packetrealtime or final_packet
stream_check_cache_sizeintegerNo128Max chars per batch (realtime)
stream_check_intervalnumberNo3Seconds between batch checks (realtime)
request_check_servicestringNollm_query_moderationAliyun service for request checks
request_check_length_limitnumberNo2000Max chars per request chunk
response_check_servicestringNollm_response_moderationAliyun service for response checks
response_check_length_limitnumberNo5000Max chars per response chunk
request_check_modestringNolastlast (latest consecutive selected turns) or all
request_check_rolesarrayNo["user"]user, tool, or system. Assistant history cannot be selected
fail_modestringNoskipskip, warn, or error for non-AI / unrecognized traffic
risk_level_barstringNohighThreshold: none, low, medium, high, max
deny_codenumberNo200HTTP status code for rejected content
deny_messagestringNoCustom rejection message
timeoutintegerNo10000Request timeout (ms)
ssl_verifybooleanNotrueVerify SSL certificate

Risk Level System

Content is blocked when its risk level meets or exceeds the risk_level_bar:

none (0) < low (1) < medium (2) < high (3) < max (4)

Setting risk_level_bar: "high" blocks content rated high or max. Setting risk_level_bar: "low" blocks everything rated low or above.

Streaming Modes

ModeBehavior
final_packetChecks the assembled response at the end and annotates the final stream packet with risk_level; it cannot retract earlier chunks
realtimeChecks content in batches during streaming and can replace the remainder of the stream after a violation; it cannot retract earlier chunks

Step-by-Step: Aliyun Request + Response Moderation

a6 route create -f - <<'EOF'
{
  "id": "aliyun-moderated-chat",
  "uri": "/v1/chat/completions",
  "methods": ["POST"],
  "plugins": {
    "ai-proxy": {
      "provider": "openai",
      "auth": {
        "header": {
          "Authorization": "Bearer sk-your-key"
        }
      },
      "options": {
        "model": "gpt-4"
      }
    },
    "ai-aliyun-content-moderation": {
      "endpoint": "https://green.cn-shanghai.aliyuncs.com",
      "region_id": "cn-shanghai",
      "access_key_id": "your-aliyun-key-id",
      "access_key_secret": "your-aliyun-key-secret",
      "check_request": true,
      "check_response": true,
      "risk_level_bar": "high",
      "deny_code": 400,
      "deny_message": "Content policy violation"
    }
  }
}
EOF

Realtime streaming moderation

{
  "plugins": {
    "ai-aliyun-content-moderation": {
      "endpoint": "https://green.cn-shanghai.aliyuncs.com",
      "region_id": "cn-shanghai",
      "access_key_id": "key-id",
      "access_key_secret": "key-secret",
      "check_request": true,
      "check_response": true,
      "stream_check_mode": "realtime",
      "stream_check_cache_size": 256,
      "stream_check_interval": 2,
      "risk_level_bar": "medium"
    }
  }
}

Integration Patterns

Pattern A: Request-only filtering (AWS)

Client → ai-proxy [sets context] → [AWS Comprehend blocks toxic] → LLM → Response → Client
plugins:
  ai-aws-content-moderation:
    comprehend:
      access_key_id: "${AWS_ACCESS_KEY_ID}"
      secret_access_key: "${AWS_SECRET_ACCESS_KEY}"
      region: us-east-1
    moderation_threshold: 0.5
  ai-proxy:
    provider: openai
    auth:
      header:
        Authorization: "Bearer ${OPENAI_API_KEY}"

Pattern B: Request + response filtering (Aliyun)

Client → ai-proxy [sets context] → [Aliyun checks request] → LLM
       → [Aliyun checks response] → Client
plugins:
  ai-proxy:
    provider: openai
    auth:
      header:
        Authorization: "Bearer ${OPENAI_API_KEY}"
  ai-aliyun-content-moderation:
    endpoint: "https://green.cn-shanghai.aliyuncs.com"
    region_id: cn-shanghai
    access_key_id: "${ALIYUN_KEY_ID}"
    access_key_secret: "${ALIYUN_KEY_SECRET}"
    check_request: true
    check_response: true
    risk_level_bar: high

Secret Management

Both plugins support APISIX secret management for credentials:

plugins:
  ai-aws-content-moderation:
    comprehend:
      access_key_id: "$secret://vault/aws_key_id"
      secret_access_key: "$secret://vault/aws_secret_key"
      region: us-east-1

Config Sync Example

version: "1"
routes:
  - id: moderated-chat
    uri: /v1/chat/completions
    methods:
      - POST
    plugins:
      ai-aws-content-moderation:
        comprehend:
          access_key_id: AKIAIOSFODNN7EXAMPLE
          secret_access_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
          region: us-east-1
        moderation_categories:
          HATE_SPEECH: 0.3
          VIOLENCE_OR_THREAT: 0.2
        moderation_threshold: 0.5
      ai-proxy:
        provider: openai
        auth:
          header:
            Authorization: Bearer sk-your-key
        options:
          model: gpt-4

Troubleshooting

SymptomCauseFix
"no ai instance picked"Moderation plugin used without ai-proxyAlways configure ai-proxy or ai-proxy-multi on the same route
AWS denial is HTTP 200Default deny_code is 200Set deny_code: 400 if clients expect an HTTP error
AWS plugin not blockingThreshold too permissive, or request_check_roles omitted the roleLower thresholds; AWS defaults to all roles with request_check_mode: all
Aliyun response moderation inactivecheck_response defaults to falseExplicitly set check_response: true
"Specified signature is not matched"Wrong Aliyun credentialsVerify access_key_id and access_key_secret
High latencyDouble moderation (both plugins)Use one moderation provider per route, not both
Streaming interrupted mid-responseA moderation plugin in realtime mode detected a violationExpected behavior; adjust the moderation threshold or use final_packet mode

This page is generated from a6-plugin-ai-content-moderation/SKILL.md in the api7/a6 repository. Browse all skills on the AI Agent Skills page.