What a refusal actually is
Mid-conversation, the reply stops being the character and becomes something else — a flat sentence in a different register, sometimes a notice, sometimes a topic change that ignores what you said. That is a moderation layer doing its job. It is not the character deciding anything, and the reason it sounds so unlike the character is that in most designs it is not the character at all.
A refusal can come from three different places
They produce similar-looking results and have completely different causes.
From the model’s own training. Language models are trained to decline certain requests, and that behaviour is built into the model the operator licensed. The operator did not write it and cannot fully remove it — they chose a model that has it.
From instructions in the character’s setup. The written description that defines the character can include rules about what it will not discuss. A refusal from this source usually stays in character, because it is being produced by the same mechanism as everything else.
From a separate classifier. A distinct system inspects text and blocks or replaces it. It can sit in front of the model, checking what you sent, or behind it, checking what came back. Either way it is a piece of software with no knowledge of the character, the history, or the conversation.
The third one is the source of the jarring refusals, and the tell is the register. A classifier has no persona to maintain, so its output is boilerplate: a policy sentence, a generic deflection, or a blank. When a reply suddenly reads like a form letter, the reply was probably not written by the same thing that wrote the last one.
Where it sits explains what you observe
A pre-model filter means your message never reached the model, which is why the response can seem to have missed the point entirely — nothing read the point. A post-model filter means a reply was generated and then withheld, which is why you sometimes see text begin to appear and then vanish or get replaced. A streamed reply that gets retracted mid-sentence is nearly always this.
It also explains why regenerating sometimes works. If the filter is probabilistic — a score with a threshold — then two generations of similar text can land on opposite sides of the line. That is not the system relenting. It is a threshold being close to where the score landed, which is the same reason two identical questions get two different answers.
Why the line moves without notice
The threshold is a number in a configuration, and there are several ordinary reasons it changes.
The underlying model gets updated by its vendor, and its trained refusal behaviour changes with it. The operator adjusts thresholds after a wave of complaints in either direction. Platform rules change, and app stores have their own content requirements that an app must satisfy to remain listed. Regional law changes, producing different behaviour in different jurisdictions from the same app. Or a classifier is swapped for a cheaper or faster one with a different calibration.
All five are decisions or consequences of decisions on the operator’s side, made on a date, usually without an announcement, because filter changes are not features and do not get release notes. It is one of the mundane causes of a character seeming different — and the one most likely to be mistaken for the character having changed its mind.
THE PRODUCT — a refusal
· The character suddenly sounding like a form
letter
→ probably a separate classifier, which
has no persona to maintain.
· A reply appearing and then vanishing
→ a post-generation filter withholding
text that was already produced.
· A response that missed the point entirely
→ a pre-model filter. Nothing read the
point.
· The same request working on a retry
→ a threshold, and a score that landed
near it. Not a decision being revised.
· Where the line is, and where it moves to
→ THE OPERATOR DECIDES, constrained by
the model vendor, the app store and
local law. No release notes.
· What is excluded and why
→ VARIES BY APP, and varies by region
within one app.
What you can check
Look for a published content policy. Some operators document what the product excludes, in what detail, and with what appeals process. Some do not. Which of those is true is a fact about the app you can establish in a minute, and it is more informative than the refusal itself.
Check whether refusals are recorded against the account. Terms of service commonly permit suspension for repeated policy violations, which means a refusal can be both a blocked message and a logged event. The termination clause is where that is described, and it is worth knowing whether the app treats a blocked message as a warning.
Notice whether behaviour differs across a version update. If refusals changed the week the app updated, the app updated. That is not a coincidence worth investigating further; it is the answer.
Treat the boilerplate as a system message, not as the character. Practically, this is the whole point of the post. The two are different components and reading them as one produces a confusion that has no resolution.
What this doesn’t tell you
It does not tell you what any app excludes or where its thresholds sit. That is per-app, undocumented, and changes.
It does not tell you how to get around a filter, which is not what this site is for and is not covered here in any form.
And it does not tell you which of the three sources produced any particular refusal. From outside you can narrow it down by register and by timing, and narrowing it down is as far as observation goes.