Skip to content

Policy decisions

Every request through the Arbitex Gateway is evaluated against your organization’s policy chain before it reaches an upstream provider. This page documents how those decisions are returned to your application on the data plane: the response headers that carry the terminal action, the error body emitted on a block, and how content-security inspection (prompt guard, content filters, DLP) manifests at request time.

For configuring policy packs, rules, and chains, see the Policy Engine Admin Guide.


After policy evaluation, the gateway attaches decision metadata to every response — including 403 error responses. Two headers are always present (or absent as noted):

Header Values When present
X-Policy-Action ALLOW, BLOCK, CANCEL, REDACT, ROUTE_TO Every response
X-Matched-Rule rule ID string Present when X-Policy-Action is not ALLOW

X-Matched-Rule is intentionally omitted on ALLOW responses to avoid leaking policy structure to callers. When the action is anything other than ALLOW, the header is set so your application can programmatically detect and handle enforcement events.

Action HTTP status What happened
ALLOW 200 (or provider status) No rule matched, or the first terminal match was an explicit ALLOW. The request was forwarded to the upstream provider.
BLOCK 403 A rule matched and its action was BLOCK. The request was not forwarded. See 403 policy_block below.
CANCEL 200 (truncated stream) The policy engine detected a violation in the output stream and halted it mid-response. The partial response is delivered; no retry is possible for the same request.
REDACT 200 Detected entities were replaced with placeholder tokens in the prompt before forwarding to the provider. The upstream model received a sanitized version of the request.
ROUTE_TO 200 (or provider status) The request was redirected to an alternate provider or model as specified by the matching rule.

CANCEL applies when a rule’s applies_to is output or both and a violation is detected in the model’s streamed response. The gateway emits a final output_blocked event in the SSE stream and closes the connection. The partially delivered content precedes the cancellation event. Because the provider round-trip already occurred, this action cannot be retried — the gateway logs the request with X-Policy-Action: CANCEL and records it in the audit log.


When X-Policy-Action is BLOCK, the gateway returns HTTP 403 with the following JSON body:

{
"error": {
"code": "policy_block",
"message": "OpenAI access is not permitted for your group.",
"type": "policy_error",
"rule_id": "rule_01HZ_BLOCK_OPENAI"
}
}
Field Type Description
code string Always "policy_block" for this error type
message string The optional message configured on the matched rule. If the rule has no custom message, a generic default is used.
type string Always "policy_error"
rule_id string The ID of the rule that produced the BLOCK action

A 403 policy_block response is deterministic: the same request will receive the same decision until the policy configuration changes. Do not implement automatic retry logic for this status code. Log the rule_id for diagnostics and surface a user-facing message from the message field.

The rule_id in the error body matches the matched_rule_id field in the audit log entry for the same request. Use this to cross-reference enforcement events with the audit log when investigating a block that your application or users did not expect.


Content-security inspection at request time

Section titled “Content-security inspection at request time”

Before policy chain evaluation, the gateway runs the request through two content-security stages that can independently produce enforcement actions.

Prompt guard (system prompt injection detection)

Section titled “Prompt guard (system prompt injection detection)”

The gateway inspects the full message array — including the system role — for prompt injection attempts before forwarding to the upstream model. Injection patterns that are detected result in a BLOCK action with X-Policy-Action: BLOCK and a 403 policy_block response. The matched rule ID in this case refers to the injection-detection rule configured in the active policy chain.

Prompt injection detection is part of Tier 1 (Regex) and Tier 2 (NER) of the 5-tier DLP pipeline. It runs on the assembled message text, not per-message.

Content filters are administrator-configured rules that operate at a lower layer than the policy chain:

Filter type Enforcement Response
keyword_block Prompt contains a prohibited keyword (case-insensitive substring match) 403 with the filter’s configured message
topic_block Prompt addresses a prohibited topic 403 with the filter’s configured message
custom_instruction Filter scope matches the requesting user The filter’s instruction is prepended to the system message; the request continues normally

Content filters are evaluated in ascending priority order (lower priority value = evaluated first). A keyword_block or topic_block match short-circuits all subsequent filter evaluation and the policy chain — the request is blocked immediately.

From the perspective of your application, a content filter block is indistinguishable from a policy chain block: you receive 403, X-Policy-Action: BLOCK, and a JSON error body with code: "policy_block". The rule_id field identifies the content filter that triggered.

The 5-tier DLP pipeline (Tier 0: TF-IDF, Tier 1: Regex, Tier 2: NER, Tier 3: DeBERTa, Tier 4: CredInt) inspects both prompt input and model output. DLP findings are passed to the policy engine as entity match signals; the policy chain then decides the enforcement action based on which entities were detected and which rules match.

The DLP pipeline does not independently choose an action — it feeds signals to the policy chain. The X-Policy-Action header reflects the policy chain’s terminal decision, not a DLP-layer decision.


Terminal window
curl -i https://api.arbitex.ai/v1/chat/completions \
-H "Authorization: Bearer $ARBITEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-4o",
"messages": [{"role": "user", "content": "Summarize our Q1 results."}]
}'

Allowed response (excerpt):

HTTP/2 200
x-policy-action: ALLOW

Blocked response:

HTTP/2 403
x-policy-action: BLOCK
x-matched-rule: rule_01HZ_BLOCK_OPENAI
content-type: application/json
{
"error": {
"code": "policy_block",
"message": "OpenAI access is not permitted for your group.",
"type": "policy_error",
"rule_id": "rule_01HZ_BLOCK_OPENAI"
}
}

Redacted response (excerpt):

HTTP/2 200
x-policy-action: REDACT
x-matched-rule: rule_01HZ_REDACT_CC

The response body in a REDACT case is the model’s completion based on the sanitized prompt — the model never saw the original sensitive content.


  • Policy Engine Admin Guide — configuring policy packs, rules, chains, and the combining algorithm
  • Audit logmatched_rule_id and the full audit record schema
  • Chat completionsoutput_blocked and dlp_correction SSE events for streaming responses