> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Sensitive words guardrail: redact operator-defined terms from agent output

> Add a literal word or phrase list to an agent's safety_config so every match is redacted to [REDACTED] on the output path — for competitor names, internal codenames, or any term the agent should never speak.

# Sensitive words guardrail

The sensitive-words guardrail takes a list of literal words and phrases you
define on the agent, and redacts every occurrence of them from the agent's
output before the turn is returned. Each match is replaced inline with the
literal text `[REDACTED]` — one marker per match, never a span that swallows
adjacent words.

Redaction is **advisory, not blocking**: the violation emitted
(`sensitive_words_redacted`) is LOW severity, so the turn still completes and
the caller gets the answer with the term scrubbed. Use this for terms the
agent must never speak on a customer surface — competitor names, internal
project codenames, unreleased product names — where a hard refusal would be
wrong but a silent scrub is exactly right. When you need a hard block, layer
`blocked_topics` or the harmful-content filter instead.

The endpoint paths below are relative. Send them against
`https://api.orbit.devotel.io/api/v1`.

## Configure it

Add `sensitive_words` to the agent's `safety_config` on `POST /agents` or
`PUT /agents/:id`, alongside the other guardrail fields:

```bash theme={null}
curl -X PUT https://api.orbit.devotel.io/api/v1/agents/agent_abc123 \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "safety_config": {
      "pii_redaction": true,
      "content_filter": true,
      "sensitive_words": ["CompetitorCo", "Project Nightfall"]
    }
  }'
```

An absent or empty list leaves the guard off — existing agents are unchanged
until you opt in. Payload limits: up to 64 terms, each up to 120 characters.
Terms outside those bounds are rejected at save time with a 422 rather than
silently dropped.

## Matching semantics

* **Literal matching.** Terms are matched as literal text — no regex, no
  semantic or fuzzy matching. "sales tax" does not match "taxes", and a term
  you do not list never fires.
* **Case-insensitive.** A term matches regardless of case, in any language
  script (the match is Unicode-aware).
* **Whitespace-normalised.** Leading and trailing whitespace on each entry is
  trimmed at compile time, and blank or whitespace-only entries are dropped.
* **Bounded matches, not substrings.** A term that starts with a letter or
  digit only matches at a word edge — `taxes` never clips inside `syntaxes`.
  Terms starting with punctuation match as the literal sequence up to a
  non-word edge.
* **Every occurrence redacted.** All matches in the output are scrubbed, and
  the violation reports the match count.
* **Per-word severity is not configurable.** Every term in the list redacts at
  LOW severity; there is no per-term block/advisory split.

## How it interacts with the other output guards

Sensitive words runs inside the same output-validation pass as
`pii_redaction`, `content_filter`, and `blocked_topics` — the checks that scrub
what the agent says back or what a tool returns. It executes after PII
redaction and the profanity filter, and before `max_response_length`
truncation, so a term near the tail is caught before the output is sliced.

It is distinct from `pii_egress`: `pii_egress` scrubs **tool call arguments**
(the payload the agent sends out through a connector) at the dispatch
boundary, while `sensitive_words` scrubs the **spoken output** the customer
reads or hears. The two are independent toggles and commonly both on.

On voice agents the guard runs before text-to-speech, so the redacted output
is what reaches the caller.

## Where the violation shows up

Every redaction pushes a `sensitive_words_redacted` violation (LOW severity)
onto the turn, which appears in **agent run inspection** and rolls into the
[Guardrail Effectiveness](/agents/guardrail-effectiveness) analytics so you
can see firing rates per agent and per policy. Many matches — especially on
voice traffic — mean the agent freely speaks the term and silently speaks it
redacted; a low-severity violation does not mean the match was harmless.

## Worked example

A customer-facing support agent must never name a competitor or expose an
internal project codename:

```bash theme={null}
curl -X PUT https://api.orbit.devotel.io/api/v1/agents/agent_support \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "safety_config": {
      "sensitive_words": ["Telaxis", "Nightfall"]
    }
  }'
```

A customer asks "How does Devotel Orbit compare to Telaxis?" — before the
guard, the agent answered with the competitor's name. With the guard on, the
reply returns with the name scrubbed:

```
Before: "Telaxis routes inbound calls similarly, but ..."
After:  "[REDACTED] routes inbound calls similarly, but ..."
```

The turn still completes, and the run-inspection violation tells you the list
fired. Pair it with `blocked_topics` (e.g. `["competitor comparisons"]`) when
the question itself should get a soft refusal rather than a scrubbed answer.

## Related reading

* [Creating agents](/agents/creating-agents) — the full `safety_config` field
  list and the `pii_egress` tool-argument guard.
* [Guardrail effectiveness monitoring](/agents/guardrail-effectiveness) —
  firing rates for this and every other guardrail policy.
