Skip to main content

Input & Output Controls

External Moderation

external-moderation asks a moderation service, such as OpenAI Moderation, Azure AI Content Safety, or an AWS Bedrock guardrail, to classify the request, and blocks it when the service flags it. If the service cannot answer, the request is blocked too.

The service receives the full request text, and the call adds latency before the model request. Choose a service that is approved for that data.

Configuration​

policy-config.yaml
pack:
  name: external-moderation-example
  version: 1.0.0
  enabled: true
policies:
  chain:
    - external-moderation
policy:
  external-moderation:
    provider: openai-moderation
    secret_key_ref:
      env: OPENAI_API_KEY
    categories:
      - violence
      - self-harm
    threshold: 0.5
    timeout_ms: 3000

Use the OpenAI adapter​

  1. Save the example as policy-config.yaml.
  2. Export OPENAI_API_KEY, your provider key, in the terminal that runs the gateway.
  3. Run verdictan policy lint --file policy-config.yaml.
  4. Apply it to a test agent with the config-first workflow.
  5. Send a harmless request such as Hello. Its runtime event shows external-moderation.ok.

The failure path is easy to see offline: without the key in the environment, verdictan policy test blocks a case with policy.external_moderation_unavailable. On a test gateway, a wrong key gives the same result. A successful model response does not tell you which categories ran.

Fields​

FieldTypeDefaultDescription
providerstringopenai-moderationAdapter. See Providers.
secret_key_refobjectenv names the variable with the provider credential. store is rejected.
endpointstringProvider URL. Required by some providers.
categorieslist of strings[]Categories that count. Empty counts every category.
thresholdnumber0.5Category score that flags the text. Lint rejects 0 and 1.
timeout_msinteger3000Timeout of the provider request
fail_closedbooleantrueIgnored. A provider failure always blocks.
aws_regionstringRegion for bedrock-apply-guardrail
aws_access_key_envstringAWS_ACCESS_KEY_IDVariable with the AWS access key, for bedrock-apply-guardrail
aws_secret_key_envstringAWS_SECRET_ACCESS_KEYVariable with the AWS secret key, for bedrock-apply-guardrail
aws_session_token_envstringVariable with the AWS session token, for bedrock-apply-guardrail
guardrail_idstringGuardrail ID, for bedrock-apply-guardrail
guardrail_versionstringDRAFTGuardrail version, for bedrock-apply-guardrail
embedding_modelstringembedModel name, for embedding-endpoint
reference_textslist of strings[]Reference texts, for embedding-endpoint. Scores take the names in categories, in order, or reference_<n>.
presidio_languagestringenLanguage code, for presidio
presidio_entitieslist of strings[]Entity types, for presidio. Empty requests all.
guard_namestringdefaultGuard name in the path, for guardrails-ai
policy_idstringPolicy ID, for dynamo-ai
lakera_categorieslist of strings[]Category filter, for lakera

Providers​

Use one of the four providers that lint accepts:

ProviderRequired fieldsOptional fields
openai-moderationsecret_key_ref.envendpoint (default https://api.openai.com/v1/moderations)
azure-content-safetysecret_key_ref.env, endpoint
bedrock-apply-guardrailaws_region, guardrail_idguardrail_version, endpoint, aws_access_key_env, aws_secret_key_env, aws_session_token_env
embedding-endpointendpoint, reference_textsembedding_model, secret_key_ref.env, categories

The runtime also has adapters for presidio, guardrails-ai, dynamo-ai, and lakera, but lint rejects them. Do not bypass validation to use them. An unknown value, such as webhook, silently selects openai-moderation.

How it works​

  1. The gateway joins the request messages into one string.
  2. The control sends it to the adapter with the timeout_ms limit.
  3. The adapter turns the provider answer into category scores and a flagged result. For score-based providers, a category flags the text at threshold or above. categories limits which categories count.
  4. No valid answer: block with policy.external_moderation_unavailable.
  5. Flagged: block with external-moderation.flagged.
  6. Not flagged: allow with external-moderation.ok.

The details contain flagged, scores, reason, unavailable, provider, and threshold.

Phase and verdicts​

ItemValue
Stagespre-request (default), pre-response
Request familiesChat Completions, Completions, Responses, Messages
Verdictsallow, block
Reason codesexternal-moderation.ok, external-moderation.flagged, policy.external_moderation_unavailable

Examples​

Azure AI Content Safety:

Inside policy-config.yaml
policy:
  external-moderation:
    provider: azure-content-safety
    secret_key_ref:
      env: VERDICTAN_AZURE_CONTENT_SAFETY_KEY
    endpoint: https://replace-with-resource.cognitiveservices.azure.com
    threshold: 0.5

An AWS Bedrock guardrail, with the AWS credentials of the gateway process:

Inside policy-config.yaml
policy:
  external-moderation:
    provider: bedrock-apply-guardrail
    aws_region: eu-central-1
    guardrail_id: replace-with-guardrail-id
    guardrail_version: "1"

Moderate the model response instead of the request:

Inside policy-config.yaml
policies:
  chain:
    - external-moderation:
        stage: pre-response

Limits and failure behavior​

  • A block returns HTTP 400 with error code content_policy_violation.
  • A missing credential, a timeout, a network error, a non-2xx status, or an invalid answer blocks with policy.external_moderation_unavailable. The control never fails open, and fail_closed: false does not change that.
  • Each request waits for one provider call, up to timeout_ms.
  • The full request text goes to the provider.
  • For bedrock-apply-guardrail, the request is signed with SigV4 from the named variables. If a value is missing, the request is blocked as unavailable.
  • categories filters the answer. It does not change what the provider checks. Use the provider's category names.

Next steps​