# Request policy

> Block phrases, replace text and add context in every request an account makes, restore replaced wording in responses, and review what the policy did.

Source: https://0.0.0.0:3000/docs/privacy/request-policy
Documentation index: https://0.0.0.0:3000/docs/llms.txt

A request policy changes what reaches models for a whole account without changing any client. It applies to requests made with any of the account's API keys and to [chat](/chat), for every member. Configure it on the [Security](/dashboard/security) page. It has three independent parts:

| Part | What it does |
| --- | --- |
| **Blocked phrases** | Rejects a request before any provider receives it when its input contains a listed phrase. |
| **Replacements** | Replaces listed text in the request before it's sent, and can restore the original wording where the model repeats a replacement. |
| **Context** | Adds your text once, before the first user message of every chat request. |

Blocking applies only to input. A response is never blocked because of what it says.

## Who can change it

| | Personal account | Organization account |
| --- | --- | --- |
| Edit the policy and see its rules | You | Owners and administrators |
| See which parts are on | You | Every member |
| See the event log | You | Owners and administrators: all keys. Others: requests made with keys they created |

The policy belongs to the account, so your personal rules never apply in an organization. Members can't turn it off for their own keys, and no request header bypasses it. A saved change applies to requests that start after it, including later turns of an ongoing conversation.

Each change on the Security page is saved as you make it. Adding the first rule or context turns that part on, and removing the last turns it off; you can also turn a part off without losing its rules. If someone else changed the policy since you loaded it, reload before making more changes.

## End-to-end encrypted models

[End-to-end encrypted models](/docs/inference/encrypted) can't be inspected, so the policy can't apply to them. While any part of the policy is on, Security shows which applies:

- **Allowed** (the default): E2EE requests skip blocking, replacement and context, and the event log lists them as **Allowed without inspection**. Every other model keeps applying the policy.
- **Blocked**: an owner or administrator chose **Block E2EE models**, so E2EE requests are rejected while the policy is on. **Allow E2EE models** undoes it.

With every part off, E2EE models work either way, and the saved choice applies the next time a part is turned on.

## What it inspects

The policy processes all the text a request sends to a provider. In a chat request, that's the whole conversation, including earlier turns your client sends back:

| Text | Blocked phrases | Replacements |
| --- | --- | --- |
| Every message, including its `name`: system, developer, user, assistant and tool results | Checked | Applied |
| String values in tool-call arguments | Checked | Applied |
| Tool descriptions | Checked | Applied |
| `stop` sequences | Checked | Applied |
| Keys and numbers in tool-call arguments, and tool-call names | Checked | Block the request |
| Reasoning in earlier assistant messages (`reasoning`, `reasoning_details`) | Checked | Block the request |
| Tool names and parameter schemas, hosted-tool settings, and `response_format` | Checked | Block the request |

Some text can't be changed without breaking the request: reasoning can be signed, and changing a key, a name or a schema changes what the model is allowed to return. A replacement that matches there blocks the request instead, so the original text never reaches a provider. To keep such requests working, make sure your replacement rules don't match your schemas, tool names or keys.

Watch for these cases in particular, because agents send their tools and earlier turns with every request, so one match blocks every later turn of the conversation:

- a `description` nested inside a tool's parameter schema or inside `response_format`
- `enum` values and property names in a schema; a blocked phrase such as `password` also matches a `password` property
- keys and numbers in earlier tool-call arguments, and reasoning from earlier turns

Narrow the rule, for example with **Whole words** and **Match case**, or reword the schema. A tool's top-level `description` can be replaced.

Replacements must fit the policy's aggregate resource limits and preserve valid JSON. Provider-specific limits on `stop` sequences are checked upstream.

When a policy is active, opaque conversation or generation extensions that the policy cannot inspect fail before dispatch. This includes unfamiliar top-level reasoning controls, a `temperature`, `top_p`, `top_k` or `seed` that isn't a number or `null`, and a `tool_choice` that names a function missing from `tools`. Without an active policy, these extensions pass through to compatible endpoints.

The [embeddings](/docs/api-reference/embeddings/create-embedding), [image](/docs/api-reference/media/create-image) and [speech](/docs/api-reference/media/create-speech) endpoints apply blocked phrases and replacements to their text input: each embeddings input, the image `prompt` and the speech `input`. They never receive context, and nothing in their output is restored. A replacement can't leave that text empty or longer than the endpoint accepts; the request fails with `interception_failed` or `interception_limit_exceeded` instead.

The policy doesn't inspect images, audio, PDF files, pre-tokenized embeddings input or encrypted reasoning, and it doesn't apply to [audio transcription](/docs/api-reference/media/create-transcription). IDs, such as tool-call IDs, and typed settings, such as the image `resolution` and `aspect_ratio` or the speech `voice`, aren't inspected either. Don't rely on the policy to protect content in those places.

Matches never span different messages, tool calls, tools or values. Text split across several parts of one message is matched as one piece of text.

## How matching works

Rules are literal text, not regular expressions.

| Option | Default | Behavior |
| --- | --- | --- |
| **Where it matches** | **Whole words** | *Whole words* matches only where the text isn't part of a longer word. *Anywhere in text* also matches inside words. |
| **Match case** | Off | When off, `Acme`, `ACME` and `acme` all match. |
| **Close spellings** | Off | Also matches one typing slip (a missing, extra, changed or swapped character) for rules of 5–9 characters, and up to two for longer rules. |

- Rules need at least 2 characters, and 5 for close spellings. Short rules often match unintended text.
- Accented and unaccented letters (`e` and `é`) are different characters, and so are characters that only look alike.
- When rules overlap, the match that starts first wins; at the same start, the longest wins, then the rule higher in the list.
- Each replacement is applied once, and text it inserts isn't matched again. It inserts exactly what you configured, whatever spelling matched. Leave the replacement empty to delete the text.

## Order of processing

1. Blocked phrases, and replacements that can't be applied, are checked in the input you sent.
2. Replacements are applied.
3. The context is added before the first user message of a chat request.
4. Blocked phrases are checked again in the changed text, so a replacement or the context can also cause a block.

The changed request is then priced, routed and sent.

## Context

The context is wrapped in a tag at the start of the first user message:

```text
<context>
Answer in British English.
</context>

What is the capital of France?
```

`&`, `<` and `>` in your context are escaped. The tag doesn't give the context more authority than the user's own words, and models may still ignore it. It appears exactly once in every request, even though clients resend the whole conversation. While context is on, a request without a user message is rejected.

## Restore in responses

With **Restore in responses** on, a replacement that changed this request's messages or tool-call arguments is changed back wherever the model writes the exact replacement text, matching case, in response text and tool-call arguments. Rules that didn't match there don't affect the response, including rules that only changed a tool description or a `stop` sequence.

Replacement isn't anonymization:

- Restoring also changes any genuine use of the replacement text by the model.
- Case and close-spelling variants are restored to the spelling you configured, not the one the user typed.
- Model reasoning is never changed, so it can show replacement text.

Two restorable rules can't share a replacement, and restorable rules can't undo each other in a loop.

While restoring is active, a stream can pause briefly while it waits to see whether text is a replacement. JSON output (`response_format` of `json_object` or `json_schema`) and tool-call arguments are delivered whole once complete. Requests with nothing to restore stream as they would without a policy.

Restoring must not break your response schema or a tool's parameter schema. If the model's value fits the schema but the restored value wouldn't, the request fails with `interception_failed` before that value is delivered. Use replacements that keep values valid, or a schema that accepts the restored value without naming it: a schema that contains the original text blocks the request.

## Prompt caching

For the same rules and the same conversation, the text sent to the model is identical on every request, so [prompt caching](/docs/features/prompt-caching) keeps working across turns. Changing replacements or context changes that text, so earlier cache entries may stop applying.

## Billing

A request policy costs nothing to use.

- A blocked request isn't sent to any provider and is never charged. It still counts toward your rate limits.
- Otherwise you pay for the changed input that was sent and the output delivered to you after restoring, as described in [Usage accounting](/docs/account/usage-accounting). Your `max_completion_tokens` applies to the delivered text.

## Errors

Policy errors never say which phrase or rule matched. Use the `X-Request-Id` header and the event log to investigate.

| Status | Error type | Meaning |
| --- | --- | --- |
| `400` | `interception_limit_exceeded` | The conversation or policy is too large to process. Shorten the conversation or simplify the policy |
| `403` | `input_blocked` | A blocked phrase matched, a replacement matched text it can't change, or E2EE models are blocked |
| `500` | `interception_failed` | The policy couldn't process the request or its response |
| `503` | `interception_unavailable` | The policy is temporarily unavailable and the request wasn't processed. Retry with backoff |

See [Errors](/docs/api-reference/errors).

## Event log

The **Event log** on the Security page lists requests the policy acted on, newest first: when, which key, what it did and how the request ended. Expand a row to see each change to the input in order, with the rule, where it applied (a message, tool call, tool definition or endpoint input) and how many times, followed by how many times wording was restored in the response. Each row links to the request in [Logs](/dashboard/logs).

The log never contains prompt text, matched text, replacements or context. Requests the policy didn't change aren't listed. Restores are counted when the request completes, so a request that ends abnormally shows its input changes but not its restores.

## Limits

| Limit | Value |
| --- | --- |
| Rules turned on | 100 (200 stored) |
| Rule text or replacement | 256 characters |
| Context | 16 KiB |

Conversations or policies too large to process completely are rejected with `interception_limit_exceeded`; rules are never skipped. Restoring a long streamed response has a processing limit too: if it's exceeded, the request fails and only output delivered before that point remains.

## Next steps

:::cards
- {shield} [Account security](/docs/privacy/account-security) Protect the identities that can change the policy.
- {building} [Organizations](/docs/account/organizations) Roles that can edit the policy.
- {lock} [Encrypted inference](/docs/inference/encrypted) Models the policy can't inspect.
- {database} [Data retention and logging](/docs/privacy/data-retention) What the platform stores about your requests.
:::
