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
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: 3000Use the OpenAI adapter
- Save the example as
policy-config.yaml. - Export
OPENAI_API_KEY, your provider key, in the terminal that runs the gateway. - Run
verdictan policy lint --file policy-config.yaml. - Apply it to a test agent with the config-first workflow.
- Send a harmless request such as
Hello. Its runtime event showsexternal-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
| Field | Type | Default | Description |
|---|---|---|---|
provider | string | openai-moderation | Adapter. See Providers. |
secret_key_ref | object | env names the variable with the provider credential. store is rejected. | |
endpoint | string | Provider URL. Required by some providers. | |
categories | list of strings | [] | Categories that count. Empty counts every category. |
threshold | number | 0.5 | Category score that flags the text. Lint rejects 0 and 1. |
timeout_ms | integer | 3000 | Timeout of the provider request |
fail_closed | boolean | true | Ignored. A provider failure always blocks. |
aws_region | string | Region for bedrock-apply-guardrail | |
aws_access_key_env | string | AWS_ACCESS_KEY_ID | Variable with the AWS access key, for bedrock-apply-guardrail |
aws_secret_key_env | string | AWS_SECRET_ACCESS_KEY | Variable with the AWS secret key, for bedrock-apply-guardrail |
aws_session_token_env | string | Variable with the AWS session token, for bedrock-apply-guardrail | |
guardrail_id | string | Guardrail ID, for bedrock-apply-guardrail | |
guardrail_version | string | DRAFT | Guardrail version, for bedrock-apply-guardrail |
embedding_model | string | embed | Model name, for embedding-endpoint |
reference_texts | list of strings | [] | Reference texts, for embedding-endpoint. Scores take the names in categories, in order, or reference_<n>. |
presidio_language | string | en | Language code, for presidio |
presidio_entities | list of strings | [] | Entity types, for presidio. Empty requests all. |
guard_name | string | default | Guard name in the path, for guardrails-ai |
policy_id | string | Policy ID, for dynamo-ai | |
lakera_categories | list of strings | [] | Category filter, for lakera |
Providers
Use one of the four providers that lint accepts:
| Provider | Required fields | Optional fields |
|---|---|---|
openai-moderation | secret_key_ref.env | endpoint (default https://api.openai.com/v1/moderations) |
azure-content-safety | secret_key_ref.env, endpoint | |
bedrock-apply-guardrail | aws_region, guardrail_id | guardrail_version, endpoint, aws_access_key_env, aws_secret_key_env, aws_session_token_env |
embedding-endpoint | endpoint, reference_texts | embedding_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
- The gateway joins the request messages into one string.
- The control sends it to the adapter with the
timeout_mslimit. - The adapter turns the provider answer into category scores and a
flaggedresult. For score-based providers, a category flags the text atthresholdor above.categorieslimits which categories count. - No valid answer:
blockwithpolicy.external_moderation_unavailable. - Flagged:
blockwithexternal-moderation.flagged. - Not flagged:
allowwithexternal-moderation.ok.
The details contain flagged, scores, reason, unavailable, provider, and threshold.
Phase and verdicts
| Item | Value |
|---|---|
| Stages | pre-request (default), pre-response |
| Request families | Chat Completions, Completions, Responses, Messages |
| Verdicts | allow, block |
| Reason codes | external-moderation.ok, external-moderation.flagged, policy.external_moderation_unavailable |
Examples
Azure AI Content Safety:
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.5An AWS Bedrock guardrail, with the AWS credentials of the gateway process:
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:
policies:
chain:
- external-moderation:
stage: pre-responseLimits and failure behavior
- A block returns HTTP
400with error codecontent_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, andfail_closed: falsedoes 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. categoriesfilters the answer. It does not change what the provider checks. Use the provider's category names.
Next steps
- Safety Filter: a local term list without a provider call.
- Environment Variable Use: the
secret_key_ref.envreference. - Investigate a Blocked Request: read the scores and failure reason.