Before you configure: the OpenAI key
This policy calls OpenAI with a credential of your own, so you need a key before it can do anything. That is the whole prerequisite — there is no resource to create, no template to build and no permission to grant, which is what makes this the quickest of the guardrails to stand up. Two things worth knowing before you pick a key. The Moderations API is billed separately from your model usage, and this policy calls it on every inspected leg in its scope. And a key you save here never comes back to your browser, so you cannot read it off the policy afterwards — give it a key scoped to moderation rather than one that can also spend on completions, and keep your own copy wherever you keep your other credentials.Configure the policy
Open Policies → Library → OpenAI Moderation.
Three fields, and only API Key is required. See
Making it block for what this policy does with nothing
else touched.
Saving validates more than “is it filled in.” The gateway rejects the
write with
422 validation_failed for an unknown Model — unless it is
exactly the model already stored on this policy. A model already stored
under older rules stays editable; only a newly introduced bad value is
refused.The key, once saved
A key you save is never sent back to the browser. Reopen the policy and the field tells you only that a key is set; it does not show you the key. You can replace it, and you cannot read it. Rotating means pasting the new key over that marker, which is also the only way to correct a key you typed wrongly.Inspecting the response too
The request is always inspected — that is not a setting, and it is one call to OpenAI on every turn. Inspect model responses, the toggle directly below API Key, is off by default. Turn it on and the model’s answer is sent to the Moderations API too, checked exactly like the request: a second call to OpenAI on every turn. There is no way to inspect the response only — the request is always inspected first. Measure what the request alone costs you before you turn this on; it is the call that can stop something before it reaches the model, and it is the one this policy always makes.With Inspect model responses on, a streamed response is inspected as it is
generated, and a failure of that check lets the stream continue.
Mode and scope
Start in Observe and read the recorded per-category scores before you switch to Enforce — this policy already blocks anything OpenAI flags by default, so Observe is where you see what that would catch before it starts refusing calls.Making it block
In Enforce, this policy refuses any text OpenAI itself flags. That is true the moment you save it, with nothing else to touch: every category OpenAI scores for the chosen model, with no number of yours involved and no extra step to take. Observe records the same verdict without refusing anything, which is why it is worth switching to first — see Mode and scope.How the decision is made
1
The text is flattened and sent in one call
On the request leg, the system prompt and the content of every message are joined
with newlines into a single string. On the response leg, the assistant’s content
alone. One call, one string.
2
Scores are aggregated across the returned results
The highest score per category wins, and a category flagged in any result counts
as flagged.
3
A flagged category is a violation
Out of the box, any category OpenAI itself marks as flagged is a violation —
every category it returns for the chosen model.
4
A violation in Enforce refuses the call
The caller gets
403, and the response lists every category that was flagged,
with the score OpenAI returned for it. The wording is
This content violates our usage policy.Modes and failures
Those decision names are what you read on the request’s Policies tab in
Activity:
allowed, reported, block, and — when the call to OpenAI
itself failed — failed_open, in Enforce and Observe alike, and failed_closed
when the content caused the failure and Enforce refused it. Expect
failed_open on a first run: a key that is wrong, revoked or out of quota
looks from here exactly like an outage at OpenAI. The event’s failure_reason
field says which: transport (the call failed or timed out), verdict_incomplete
(OpenAI answered without a usable result), config_invalid (the stored
settings could not be used), or decode_failed (the gateway’s own request or
response body could not be decoded before OpenAI was ever called).
Limits
- It cannot mask. There is no anonymise action; the call is blocked or it is not. For redaction use TrustGuard or Regex Replace.
- Inspect model responses is off by default. The model’s answer is not scored until you turn it on.
- A streamed response is inspected as it is generated, with Inspect model responses on. If the check itself fails, the stream is not cut.
- Text only, and structure is lost. Roles, tool calls, tool definitions and attachments are not sent — the request leg becomes one newline-joined blob. A detector that would care which participant said something cannot.
- Your own system prompt is scored. It is the first thing in that blob, and a security-related system prompt can score high enough to matter. Check it in Observe before enforcing.
- LLM traffic only. The policy does not apply to MCP (Model Context Protocol) tool calls.
Verify the policy
Open the Playground, pick an application the policy applies to, and work through these in order. Steps 2 and 3 are one loop: observe, then enforce.1
Control — the path works at all
allowed. If this fails, the
problem is the application, the model or the key. Fix it before going on.2
Observe — learn what your traffic scores
Leave the policy in Observe and send real prompts, including ones you expect
to be borderline. Then open Activity, open each request, and read the
per-category scores and the flagged verdict on its Policies tab — this is
what decides whether Enforce would have refused it.
3
Enforce — confirm a violation is refused
Switch the policy to Enforce and resend a prompt from step 2 that OpenAI
flagged.Expect the decision
block and a 403 naming the category and the score.
Then confirm the model was never called: open the request in Activity, go to
its Policies tab, and read Aggregated Latency. The Provider row
should show no time at all. That the provider leg is empty is the evidence that
matters.Troubleshooting
Related
- Guardrails — the other guardrail policies, and how to choose between them
- TrustGuard — the guardrail that also covers MCP, and can mask
- Policies overview — scope, modes and policy chains
- Event schema — the fields each decision records