Skip to main content
Back to blog

Custom Guardrail DSL, Announced: Tenant-Authored Rules Beyond the Five Built-In Scanners

The Devotel Orbit safety stack now closes the tenant-specific gap the fixed scanners cannot express. Author literal `contains` or regex rules on `safety_config.custom_guardrail_rules` with block, redact, or warn actions, evaluated deterministically on every agent turn and shipped today.

Orbit Editorial Team

Devotel Orbit's safety stack ships five fixed scanners (prompt-injection classification, PII detection, harmful-content filtering, blocked topics, and sensitive words) that cover the universal violation classes every agent faces. But those scanners, by design, cannot express tenant-specific rules: things like "never mention competitor X", "redact reservation codes matching a carrier regex", or "scrub internal SKU prefixes before the reply reaches the customer."

The Custom Guardrail DSL closes that gap. You author rules as a JSON array on the same safety_config blob that already carries blocked_topics, sensitive_words, and locale_pii_patterns, and the platform evaluates them deterministically before every agent turn. This is a shipped capability, live today, not a roadmap item.

The gap fixed scanners leave

The five built-in scanners handle universal classes reliably. What they cannot do is tenant-specific policy, because no shipped scanner knows your business vocabulary. Three concrete examples the new DSL makes first-class:

  • "Never mention competitor X": a contains-match warn rule on input or output catches mentions of a named competitor without blocking the turn, so the team can measure how often it fires before flipping to block.
  • "Redact reservation codes matching a carrier regex": a regex rule like PNR [A-Z0-9]{6} on output scrubs carrier-format confirmation strings the model should never echo.
  • "Scrub internal SKU prefixes before reply": a regex rule like SKU-[0-9]+ on output replaces every match with [REDACTED] before the customer sees it.

These are the rules a tenant's support, legal, or compliance team actually asked for, and previously had no deterministic place to live.

The syntax: literal contains vs regex pattern, and three actions

The DSL has a small, deliberate surface. Each rule in custom_guardrail_rules is a JSON object with:

FieldValuesSemantics
directioninput or outputinput scans the user message before the model; output scans the model reply before it is returned.
matchcontains or regexcontains is a case-insensitive literal substring scan; regex compiles the pattern as a JavaScript RegExp with the i flag.
patternstring, 1–200 charsThe literal text (for contains) or regex source (for regex).
actionblock, redact, or warnblock hands the violation to the severity reducer; redact rewrites matches to [REDACTED]; warn records only.
id / nameoptional labelsStable identifiers for violation entries and analytics.
severitylow, medium, high, criticalDefaults: high for block/warn, low for redact.

Here is a verbatim worked example straight from the shipped guide, the complete safety_config shape:

{
  "safety_config": {
    "custom_guardrail_rules": [
      {
        "id": "competitor-mention",
        "name": "Competitor mention block",
        "direction": "input",
        "match": "contains",
        "pattern": "CompetitorCo",
        "action": "warn",
        "severity": "medium"
      }
    ]
  }
}

Validation runs at save time: a bad shape, an out-of-enum direction/match/action/severity, or a regex that does not compile returns custom_guardrail_rules[0].pattern is not a valid regex with a 422. Up to 25 rules per agent keeps the surface bounded.

Deterministic evaluation in the turn pipeline

Custom rules run at a defined point in the two guardrail legs, after the fixed scanners and text-length caps:

  • Input leg: after prompt-injection, PII detection, blocked topics, and encoding checks, before the passed decision. A contains rule sees the same post-cleanup text the fixed scanners see.
  • Output leg: after PII redaction, the content filter, and the citation check, before the passed decision. A term a PII redactor already masked will not re-fire a custom rule.

Evaluation is deterministic: the same text and the same rules produce the same violations every time. No LLM, no clock, no network in the matching path. A custom rule is reproducible in a unit test and identical in production. Both legs fold their violations into the normal pass/block reducer and the violation-log feed, alongside the fixed-scanner results. Rules are per-agent and opt-in: a rule you write applies to this agent only, separate from any central guardrail-policy preset you may also have attached.

Three use-case recipes

Each recipe names the rule shape and why it fits:

Retail: scrub internal SKU prefixes. Internal prefixes like SKU- followed by digits should never reach the customer:

{
  "id": "sku-prefix-scrub",
  "name": "Internal SKU prefix scrub",
  "direction": "output",
  "match": "regex",
  "pattern": "SKU-[0-9]+",
  "action": "redact"
}

Every occurrence becomes [REDACTED] before the reply returns, and a low-severity violation records that the scrub fired.

Healthcare: redact PHI-shaped phrases. A literal phrase like a procedure name the model must not echo becomes a contains rule on output with redact. The scrub fires deterministically, and the violation log shows the firing without ever carrying the redacted value. Counts and categories only.

B2B SaaS: competitor-mention warn-mode plus alert. Start in warn mode so the team measures firing rate without disrupting turns:

{
  "id": "competitor-telaxis",
  "name": "Competitor: Telaxis",
  "direction": "input",
  "match": "contains",
  "pattern": "Telaxis",
  "action": "warn",
  "severity": "medium"
}

When the firing rate looks right, flip action to block and severity to high so a mention stops the turn with a refusal. The whole rollout is observable before it ever blocks a turn.

Debugging redactions: cite the conversation-debug supplement

Rule edits land in the workspace audit log with severity, action, and attribution. A change from warn to block is a recordable event, not a management-only action. Per-turn, the debug view at /agents/<agent-id>/conversations/<conversation-id>/debug shows the violation entry against the turn, so you read redact firings as counts and categories, never the redacted value. For the full loop (allowed-versus-blocked outcomes, tuning one rule at a time, incident export to the audit log), the guardrail analytics tuning guide is the shipped surface, and the audit log guide is where edits and exports land.

Operational posture: tenant-owned config, versioned with the agent

Rules are tenant-authored configuration, not platform policy. Only the roles that can edit safety_config (owner, admin, developer) can write rules, and rule changes are recorded with the agent config that versions them. The same safety_config blob that already carries blocked_topics and sensitive_words now carries custom_guardrail_rules, one surface with one audit trail.

A checklist you can run in your own account

  1. Open the agent's Safety tab (or hit the API) and read the current safety_config blob.
  2. Pick one tenant-specific rule you have been handling manually.
  3. Set custom_guardrail_rules with that rule in warn mode first; save and note the violation-log entry.
  4. Watch firing in guardrail analytics for a day.
  5. Flip action to block or redact when the firing rate looks right. The change lands in the audit log.

Read the shipped docs

Custom Guardrail DSL, Announced: Tenant-Authored Rules Beyond the Five Built-In Scanners — Orbit by Devotel