Refusal policy

Some requests should not be answered. Legal advice, medical dosing, credential generation, and anything your product is not supposed to do. The refusal policy encodes those rules as a final check on the output. If the reply tries to cross the line, the layer rewrites it to a refusal that explains the boundary without being preachy.

layers/guardrails.py (refusal)
python
REFUSAL_PATTERNS = [
    (re.compile(r"(?i)\bprescrib(e|ing)\b"),
     "I cannot give medical advice. Please check with a licensed clinician."),
    (re.compile(r"(?i)\b(ssn|social security)\b"),
     "I cannot generate or share SSNs."),
    (re.compile(r"(?i)\bsudo\s+rm\s+-rf\b"),
     "I will not generate destructive shell commands."),
]


class GuardrailsLayer:
    def apply_refusal(self, text: str) -> GuardrailResult:
        for pattern, message in REFUSAL_PATTERNS:
            if pattern.search(text):
                return GuardrailResult(text=message, flags=["refused"])
        return GuardrailResult(text=text, flags=[])

    def check_output(self, text: str) -> GuardrailResult:
        pii_scrubbed = self._scrub(text)
        refused = self.apply_refusal(pii_scrubbed.text)
        flags = pii_scrubbed.flags + refused.flags
        return GuardrailResult(text=refused.text, flags=flags)

The output guardrail is now a two-step: scrub PII first, then apply the refusal policy. A refusal replaces the text wholesale but keeps the flags so the trace records what was refused.

Matching exercise: Match the request to the right response

Loading practice…

Quiz: Quiz

Loading practice…