Skip to content

Security and governanceAnalysis

Provider-side moderation: what your AI gateway must handle

Screening no longer happens only in your code or only inside the model. xAI now takes moderation guidelines on the request, and OpenRouter screens every inference request in flight. This maps the layers, what each one returns to your app, and the evidence a security or procurement reviewer will ask for.

By INFRO Editorial

Published

8 min read

A grid of dark glass cards with small bar charts, a few of them lit amber, on a dark ground

In short

Content screening now sits at four layers: your gateway, an aggregator, the model provider's policy, and the model itself. Each reports differently, and some report nothing. Normalize the signals you can get, and keep dated provider terms plus request records as evidence. 21

Key takeaways

  • Screening happens at several layers, and a request can pass your guardrails and still be declined, flagged or retained downstream.
  • xAI's guidelines change how the model writes its answer and keep the response shape, so a decline is not a machine-readable error.
  • OpenRouter's moderation flags arrive as an error with metadata, but its CSAM announcement does not say how a flagged request appears to the caller, so do not assume.
  • Zero-data-retention terms now carry a named exception for CSAM review and legal preservation; record it in your retention register.
  • Keep dated copies of provider terms, request records with status and error type, and the policy change history; never log flagged text beyond what your payload policy allows.

Four places a request can be screened

A prompt on its way to a model can now meet screening at four layers, and your gateway controls only one of them.

  1. Your own layer: application code and gateway policy, such as pattern checks or a classifier you run before the call.
  2. An intermediary: a hosted router or aggregator between you and the model. OpenRouter announced on 27 October 2026 that it will screen all inference requests for child sexual abuse material (CSAM) as they pass through, in flight, during request processing.1
  3. The provider's policy layer: account, key or team blocks, and any automated safety checks the provider runs under its own terms.
  4. The model itself: behavior shaped by the provider's defaults and, increasingly, by parameters you send.

The xAI change sits at layer 4. A guidelines array on the request sets how Grok handles named content categories; today the categories are nsfw, violence and profanity, and the only behavior is decline. Categories you leave out keep the model's default moderation.2

This article does not repeat how to build pattern or classifier checks at your own layer; the guardrails article and the payload logging policy cover that. The question here is narrower: what the other three layers do to your traffic, how it surfaces, and what you can show a reviewer.

Who screens what, by layer

LayerWhat it doesWho configures itVisible to the app as
Gateway or appYour own checks on prompts and responsesYouAn error you define
OpenRouter, in flightHash comparison against known CSAM, plus review of suspected new material1OpenRouter; not optional per its announcementNot stated in the announcement
OpenRouter moderation flagA provider requested moderation and flagged input3Provider and routerAn error with reasons, flagged_input, provider_name, model_slug in error.metadata3
xAI guidelinesModel declines chosen categories while writing its answer2You, per requestA normal response, same shape2
Provider account policyKey or team blocked or without permissionProviderA 403 on xAI4
screening layers on a request path, from the pages read on 29 October 2026.

Two rows deserve emphasis. First, OpenRouter's announcement describes what is screened and retained but not the wire format of a flagged request, so a gateway should not hard-code an assumption. Second, the xAI guidelines are not a filter in front of the model. Grok follows them as it writes its response, in its own words.2 That makes them a behavior setting, not a block.

How blocked and flagged requests appear to the app

There are three shapes, and a gateway has to distinguish them because the right reaction differs.

A hard error with detail. OpenRouter documents a 403 for "insufficient permissions, guardrail block, or moderation flag". For a moderation flag, error.metadata carries the reasons, the flagged text segment (capped at 100 characters, truncated in the middle if longer), the provider that requested moderation and the model slug.3 A guardrail block on the same status looks different: a message about the block reason and, for pattern detectors, the matched patterns.3 One status code, several causes, so branching on 403 alone is wrong.

A hard error from your own gateway. INFRO returns 403 with error.code of guardrail_blocked when a guardrail refuses a request, and guardrail_unavailable is a separate code on the same status.5 The type string is stable and meant to be branched on; the message wording can change.5

A soft decline. With xAI guidelines, nothing in the response shape tells you a decline happened.2 The user sees a refusal written in prose. If your product has a "the model refused" metric, it has to be built from text classification or sampling, not from a status code.

A fourth case arrives as a 400: when every provider tried rejected a request as invalid, INFRO returns the provider's own message prefixed Provider rejected the request:, with credential-shaped strings redacted and a 500-character cap.5 Providers can use that channel for policy rejections as well as schema errors, so read the message in logs, but do not parse it in code.

classify_block.py
def classify(status: int, body: dict) -> str:
    err = body.get("error", {}) if isinstance(body, dict) else {}
    meta = err.get("metadata") or {}
    code = err.get("code")

    if status == 403 and code in ("guardrail_blocked", "guardrail_unavailable"):
        return "gateway_policy"          # your own gateway layer
    if status == 403 and "reasons" in meta and "provider_name" in meta:
        return "provider_moderation"     # upstream flagged the input
    if status == 403:
        return "permission_or_other"     # key, team, budget, guardrail
    if status == 400 and str(err.get("message", "")).startswith("Provider rejected"):
        return "provider_rejected"       # read the message, do not parse it
    return "other"

# Log the class, status, request id and provider name.
# Do NOT log meta["flagged_input"] unless your payload policy allows prompt text.

Failure modes a gateway has to design for

Retrying a block as if it were an outage. Failover exists for timeouts and 5xx before the response starts. A content refusal is a decision, not a fault. Sending the same prompt to a second provider after a moderation 403 can look like shopping for a model that will answer, which is a bad pattern to explain to a reviewer. In INFRO, failure rules decide per failure kind whether to retry, move on or stop; test how a provider's 403 and 400 are handled on your routes before relying on it, because this article did not confirm how every provider rejection is classified.

Treating flagged_input as safe to log. It is up to 100 characters of the user's text.3 If your payload logging is off, copying it into an error log reverses that decision.

Assuming retention rules from the marketing name. OpenRouter's announcement says that for content under its Zero Data Retention (ZDR) policy, it does not retain prompts or responses after processing, except when you choose to store them or when retention is needed for CSAM review, reporting and related legal preservation. Screening applies to ZDR traffic too.1 The same page says content flagged as potential CSAM may be retained for human review, including content that does not match a known hash, and that a flag is a suspicion rather than a determination.1

Forgetting the per-request nature of guidelines. xAI guidelines apply only to the request that carries them; for a whole conversation they must be sent on every request. They currently do not work with multi-agent models or deferred completions.2 A gateway or wrapper that adds the array only on the first turn leaves later turns on default moderation.

Reading the provider as the only retainer. OpenRouter notes that model labs and providers may use their own screening and retention methods, and some may retain content to run automated safety checks before anything has been flagged. Those practices are separate from its in-flight screening.1 Its docs add that it has no routing rules that change with providers' retention policies; users can ignore providers that do not meet their requirements.6

What the reporting duty means for your contract review

The OpenRouter announcement states that under US law covered providers must report to the NCMEC CyberTipline as soon as reasonably possible after obtaining actual knowledge of specified apparent offenses, and that reported contents and certain related material must be preserved for one year after submission. It says this applies to reported material, not to every item flagged for review, and that ZDR does not remove the duty.1

For a procurement team the consequence is practical, not legal advice: a "no retention" clause in a vendor agreement is incomplete unless it names this exception. Ask each intermediary and provider two things in writing: whether in-flight screening exists, and what is retained, for how long and by whom when something is flagged. If you route through more than one party, you need the answer per hop.

What to keep for a security or procurement review

Reviewers ask for artifacts, not assurances. Keep these, each dated:

  • Dated copies of provider and intermediary terms. Save the retention and screening language as of the day you approved the provider, with the URL and retrieval date. Pages change; the CSAM provisions were announced as documentation and terms updates in progress.1
  • A screening map. The table above, filled in for your own routes: which layer screens, which you configure, which are visible to the app.
  • Request records with the outcome class. Request id, project, key, model, provider, status, error type and your own class from the classifier above. Metadata only.
  • The request configuration that produced behavior. For xAI, the guidelines array in versioned code or config, since the response shape will not show it.2
  • Policy change history. Who turned a guardrail on or changed an allowlist, and when.
  • A retention register line for each exception. Example: ZDR with the CSAM review exception, quoted from the provider.

What a gateway on your own accounts can and cannot cover

Because INFRO works over provider accounts you already hold, the provider's screening and terms are the ones in your own contract, and you pick them by choosing which connections a route uses. What INFRO adds is at your layer: guardrails check text in chat completion prompts and responses and can block, redact or flag, with a stable 403 guardrail_blocked code, while images and audio inside a message are not inspected, and the docs say detection can miss things.75 Request traces and usage records give the per-request metadata a review needs, with prompt and completion logging off by default and a retention window you choose, and the audit log records policy changes with actor and timestamp. None of this is a CSAM control, and INFRO does not replace a provider's or router's screening.

A checklist before the next vendor review

  • Every route has a written screening map: gateway, intermediary, provider, model.
  • Your client or gateway branches on error type and metadata, not on 403 alone.
  • Moderation 403s are not retried on another provider by default.
  • flagged_input and similar fields are excluded from logs unless policy allows.
  • If you use xAI guidelines, the array is added on every request of a conversation.
  • Retention registers name the ZDR exception for flagged content wherever a vendor states one.
  • Terms are saved with retrieval dates, and re-checked when a vendor posts an update.

Questions readers ask

Does a gateway guardrail replace provider-side screening?
No. They run at different points and look for different things. INFRO's guardrails, for example, are pattern checks on text and say plainly that detection can miss things, and they do not inspect images or audio inside a message.7 Provider and aggregator screening is separate and you cannot switch it off from your gateway.
Can I tell from the response that xAI guidelines were applied?
Not from the response shape. xAI's documentation says the response has the same shape as one without guidelines.2 Your evidence is the request you sent, so keep the guidelines array in versioned code or config.

From the team that builds it

Where this shows up in INFRO

INFRO is a control plane in front of the provider accounts you already hold. The capabilities below are the parts of it this article touches, each with the documentation that defines its behaviour.

  • Guardrails

    Available with a plan

    Pattern-based checks on chat completion prompts and responses: block, redact or flag email addresses, phone numbers, card numbers, IBANs, US Social Security numbers, IP addresses, API keys and your own terms, plus optional classifier checks on your own connection to a decision model's provider. Detection can miss things. Included on every plan.

    Read the documentation for Guardrails
  • Request traces and payload logs

    Available with a plan

    Per-request timing detail, with prompt and completion logging off by default and a retention window you choose.

    Read the documentation for Request traces and payload logs
  • Usage and cost per request

    Available with a plan

    Every request records its model, latency, token or unit counts, and estimated provider cost, queryable by project and key.

    Read the documentation for Usage and cost per request
  • Audit log

    Available with a plan

    Member, key, and policy changes recorded with actor and timestamp, viewable in the console.

    Read the documentation for Audit log
  • Routing rules

    Available with a plan

    If-rules on a route send matching requests to their own targets, by metadata, feature, end user, key, project, prompt size, streaming, images, tools or time of day. Failure rules decide per failure kind whether to retry, move on or stop.

    Read the documentation for Routing rules
  • Provider connections

    Available with a plan

    Connect provider accounts you already hold. Each credential is encrypted when saved, scoped to your organization and never shown again; applications use INFRO gateway keys instead.

    Read the documentation for Provider connections
  • Usage, request and FOCUS exports

    Available with a plan

    GET /v1/usage and GET /v1/requests on any gateway key, the request log and usage series as CSV, plus a FOCUS v1.4 Cost and Usage dataset as JSON or CSV, so AI spend lands in your FinOps platform beside the rest of your cloud cost.

    Read the documentation for Usage, request and FOCUS exports

INFRO accounts are self-serve. Provider usage is billed to you by your providers; INFRO charges a software subscription and takes 0% of model spend. See plans.

Sources

Numbered in order of first citation. Each was opened and checked against the claim on the date shown.

  1. 1.CSAM Screening Across OpenRouter (opens in a new tab) — OpenRouter. Accessed Oct 29, 2026.
  2. 2.Custom Moderation Controls (opens in a new tab) — xAI (docs.x.ai). Accessed Oct 29, 2026.
  3. 3.API Errors and Debugging (opens in a new tab) — OpenRouter. Accessed Oct 29, 2026.
  4. 4.Debugging Errors (opens in a new tab) — xAI (docs.x.ai). Accessed Oct 29, 2026.
  5. 5.Errors — API reference (opens in a new tab) — INFRO. Accessed Oct 29, 2026.
  6. 6.Provider logging and data retention policies (opens in a new tab) — OpenRouter. Accessed Oct 29, 2026.
  7. 7.Guardrails — Features (opens in a new tab) — INFRO. Accessed Oct 29, 2026.

About this article

Read on 2026-10-29: xAI's Custom Moderation Controls and Debugging Errors pages, OpenRouter's CSAM screening announcement, error-handling and provider-logging docs, and INFRO's errors and guardrails docs. The xAI moderation page was returned truncated, so details after the request-limits section are not stated. OpenRouter's announcement does not say how a flagged request appears to the caller; that is left out as unconfirmed.

Last checked against its sources on . The next review is due by . No separate named reviewer is recorded for this article.

How articles are written, sourced and corrected is set out in the editorial standards.