---
title: "Guardrails"
subtitle: "Block prompt injections, jailbreaks, and unsafe content at the gateway, before they reach your model. Powered by span-01 and free with the Respan gateway."
---

Guardrails check each request you send through the [Respan gateway](/docs/documentation/features/gateway/gateway-quickstart) with [span-01](/docs/documentation/span-01/quickstart), Respan's classification model. You pick the categories to block once for your organization, with no code changes.

## Turn on guardrails

<Steps>
<Step title="Send your requests through the gateway">

Guardrails run inside the gateway, so they only cover requests sent through it. Apps that only send traces to Respan aren't checked. To set up the gateway, see the [gateway quickstart](/docs/documentation/features/gateway/gateway-quickstart).

</Step>
<Step title="Turn on blocking">

Go to **Gateway** › **Routing config** › **Guardrails** and turn on **Block unsafe requests**. This blocks all eight categories. Only organization admins can change this setting.

</Step>
<Step title="Choose the categories to block">

Open the **Block** menu under the switch, check the categories you want, and click **Save**.

<img src={"/docs/images/guardrails/blocking-categories-light.png"} className="block dark:hidden" alt="The Guardrails tab with Block unsafe requests turned on and the Block menu open, listing the eight categories with five of them checked" />
<img src={"/docs/images/guardrails/blocking-categories-dark.png"} className="hidden dark:block" alt="The Guardrails tab with Block unsafe requests turned on and the Block menu open, listing the eight categories with five of them checked" />

</Step>
</Steps>

Guardrails apply to every gateway request in your organization. There's no per-key or per-request setting. To turn them off, switch off **Block unsafe requests** and click **Disable**.

## Categories

| Category | Blocks requests that |
|---|---|
| Jailbreak / prompt injection | Try to override the agent's instructions or safety controls |
| System prompt leak | Try to get the agent to reveal its system prompt or hidden instructions |
| Unsafe content | Ask for or share seriously harmful content |
| Hate / harassment | Target people for a protected attribute such as race, religion, or gender |
| Self-harm | Express self-harm or suicide intent, or ask for methods |
| Sexual content | Ask for sexually explicit content, or any sexual content involving minors |
| Violence | Ask for graphic violence, or threaten people |
| Illegal instructions | Ask how to make weapons, explosives, or drugs, or how to write malware or commit fraud |

## What gets checked

- **The newest turn only.** Guardrails read the latest user and tool messages after the last assistant message, with the system prompt as context. Earlier turns and model responses aren't checked.
- **Redacted text.** If [PII redaction](/docs/documentation/pii-redaction) is on, guardrails see the redacted messages.
- **Fail open.** If the check can't run, the request goes through and counts as **Skipped**.

## Handle a blocked request

A blocked request never reaches the model. The gateway returns HTTP `400`, and the message lists every category that matched:

```json
{
  "error": {
    "message": "Request blocked by guardrail: jailbreak.",
    "type": "invalid_request_error",
    "param": null,
    "code": "guardrail_blocked"
  }
}
```

That's the body on chat completions. On passthrough routes such as the Anthropic endpoint, the body is `{"detail": "Request blocked by guardrail: jailbreak."}`.

To show your own message, catch the error and check its code:

```python
from openai import BadRequestError

try:
    response = client.chat.completions.create(
        model="gpt-5.5",
        messages=messages,
    )
except BadRequestError as error:
    if error.code != "guardrail_blocked":
        raise
    reply = "Sorry, I can't help with that."
```

## Review activity

The **Guardrails** tab shows the last 7 days (UTC): how many requests were checked, how many **Passed**, were **Blocked**, or were **Skipped**, and the counts **Blocked by category**. A request can match more than one category.

<img src={"/docs/images/guardrails/activity-light.png"} className="block dark:hidden" alt="Guardrail activity for the last 7 days: 21,007 total requests, 20,719 passed, 281 blocked, 7 skipped, a daily stacked bar chart, and blocked counts by category led by Jailbreak / prompt injection" />
<img src={"/docs/images/guardrails/activity-dark.png"} className="hidden dark:block" alt="Guardrail activity for the last 7 days: 21,007 total requests, 20,719 passed, 281 blocked, 7 skipped, a daily stacked bar chart, and blocked counts by category led by Jailbreak / prompt injection" />

## Benchmarks

On a benchmark built from 7 public security datasets, Respan Guardrails post the highest average F1 of the guardrails we tested.

<Frame caption="Average F1 across the 8 guardrail categories. * Estimated hosted cost.">
  <img src={"/docs/images/guardrails/quality-vs-cost.png"} alt="Guardrail quality versus cost. Average F1 across 8 guardrail categories: Span-01 0.637 at $0, TypeSafe Jev 0.627, gpt-oss safeguard 20B 0.621 at an estimated $0.85 per 1,000 checks, Shieldstral 3B 0.590, OpenAI Moderation 0.481 at $0, Azure AI Content Safety 0.377 at $0.89 per 1,000 checks." />
</Frame>
