Refusal Receipt

When the AI says no, it shows its work

The AI says "I can't help with that" and nothing else — so users retry blindly, learn superstitions about phrasing, and abandon legitimate requests. Refusal Receipt attaches structure to every no: which policy fired, which span of the request triggered it, how severe the call was, what a permitted variant looks like, and where to appeal. The refusal stops being a wall and becomes a signpost.

Framing

The problem

The AI says "I can't help with that" and nothing else — the user retries blindly, learns superstitions about phrasing, and abandons legitimate requests.

The pattern

Attach a receipt to every refusal: the policy that fired, the span that triggered it, the severity of the call, a permitted alternative, and an appeal path.

Why chat breaks here

Chat delivers a refusal as just another message bubble — no structure, no trigger, no way forward — so the reason stays exactly as invisible as the model leaves it.

Risks

A receipt that is too specific becomes a jailbreak manual — name the policy and category, not the exact decision boundary.

Avoid when

Trivial or obviously out-of-scope refusals — a ceremonial receipt on every "no" erodes the signal for the refusals that matter.

Use when

Users hit guardrails on legitimate work and need to understand what triggered the refusal and how to proceed.

DOPE evaluation

Directability
The receipt names the triggering span, so the user edits that instead of guessing at rephrasings
Observability
Which policy fired, at what severity, is printed on the refusal instead of hidden in the model
Predictability
Named policies behave like rules — the same category triggers the same way across requests
Explainability
The refusal explains itself: policy, span, severity, and a permitted alternative instead of a blanket no

In the wild

  • Azure OpenAI · Content filter annotations (Microsoft) — Filtered responses return the triggered category (hate, sexual, violence, self-harm) and severity level per request — a machine-readable refusal receipt at the API layer, waiting for product UIs to surface it.
  • Gemini API · Safety ratings (Google) — Every response carries per-category safety ratings and a block reason when filtered; thresholds are user-adjustable per category — policy visibility plus a steering surface.
  • GitHub Copilot · Public code filter notice (GitHub) — When the duplication filter suppresses a completion, Copilot says the match filter fired rather than silently returning nothing — a minimal but real named-policy refusal.

FAQ

When should I use the Refusal Receipt pattern?

Users hit guardrails on legitimate work and need to understand what triggered the refusal and how to proceed.

When should I avoid the Refusal Receipt pattern?

Trivial or obviously out-of-scope refusals — a ceremonial receipt on every "no" erodes the signal for the refusals that matter.

What problem does Refusal Receipt solve?

The AI says "I can't help with that" and nothing else — the user retries blindly, learns superstitions about phrasing, and abandons legitimate requests.

Why is chat the wrong fit for this?

Chat delivers a refusal as just another message bubble — no structure, no trigger, no way forward — so the reason stays exactly as invisible as the model leaves it.

Related patterns

  • Often paired with: Capability Boundary — The boundary declares what the system cannot do up front; the receipt explains the no at the moment it happens.
  • Extends: Reasoning Trace — A micro reasoning-trace scoped to a single refusal — policy, trigger, severity.
  • Alternative to: Constraint Rules Engine — Author-defined guardrails you wrote vs platform policies you can only inspect.

Browse all patterns