Why characters drift
At turn twenty the character is distinctive. At turn two hundred it is a pleasant, agreeable, generic assistant with the right name. Nobody changed anything. The model is the same, the definition is the same, the code is the same.
Drift has four causes, and the first one is arithmetic.
Cause one: the definition is outweighed
Your character definition is a fixed quantity of text. History is not.
Early on, the definition is a large share of the input and the character is strongly expressed. As the conversation grows, the definition stays the same size while everything else expands around it. The share of the input that describes who the character is falls continuously, and nothing stops it falling.
Whatever mechanism you use to carry history — a window, a summary, extracted facts, a search — makes this worse in proportion to how well it works. That is the trade at the centre of this whole subject: memory and consistency pull against each other, and every improvement to one costs the other.
Cause two: it reinforces itself
The part that turns a gradual slide into a runaway.
The history being carried is not just the user’s messages. It contains the model’s own previous replies, and those are being treated as evidence of how this character speaks.
So a small departure is not a one-off error. It becomes part of the input for the next turn, where it looks like an example. The next reply matches the recent examples slightly more than the definition, which produces another slightly-off reply, which joins the examples. The definition is one voice arguing for the original character; the recent transcript is a growing chorus arguing for wherever the conversation has got to.
This is why drift accelerates rather than plateauing, and why it has a consistent direction. Models tend toward agreeable, helpful, moderately verbose assistant register — so a character defined as terse, or prickly, or reticent decays toward that baseline, and one defined as warm and helpful appears more stable because it is drifting toward where it already was.
Cause three: the definition degrades as text
Even holding proportion constant, a definition’s influence is not uniform.
Long definitions dilute themselves: a hundred words of specific voice instruction is followed more faithfully than eight hundred words containing the same instruction plus backstory. Instructions buried mid-document behave differently from instructions at the boundaries, and how much differently depends on the model. And instructions phrased as description (“she is witty”) are weaker than instructions phrased as constraint on output (“replies are at most three sentences”), because one is a characterisation and the other is checkable.
The practical consequence: a bloated definition drifts faster than a lean one, and half of what is in most persona definitions is backstory that never affects a reply.
Cause four: something actually changed
Not everything is drift. Three changes produce the same symptom and need ruling out first.
A different model behind the same definition — the stated facts stay right while length, rhythm and formatting habits all shift. A revised definition, where one behaviour changes and everything else is intact. And a moderation intervention, where the character becomes evasive in one area only, often with a phrase that does not sound like it.
That last one is worth being precise about, because it is not a failure of your persona. Moderation sits outside the character by design — that is what makes it reliable, since it does not degrade as the conversation does. The cost of that reliability is a visible seam: an intervention will not sound like the character, and there is no clever way to make it. The available design work is to keep the seam small, hand back to the character cleanly afterwards, and not let a single refusal collapse the rest of the persona for the remainder of the session. Trying to eliminate the seam is trying to defeat the mechanism, which is a different project and not one this site helps with.
The turn
THE TURN — drift
· Fixed definition, growing history
→ definition's share of the input falls
continuously. The base mechanism.
· History contains the model's own replies
→ each small departure becomes an example.
Self-reinforcing, so it accelerates.
· Bloated definition
→ dilutes itself. Backstory that never
changes a reply crowds out voice
instruction that would.
· Re-anchoring the definition late in the
input
→ raises its effective weight. Costs
nothing extra to try.
· Every re-anchor and every carried turn
→ PAID EVERY TURN. Anti-drift measures are
per-message costs, and they compete for
the same space as the memory they are
correcting for.
· Evasive in one area, out-of-voice phrasing
→ MODERATION SITS OUTSIDE. Not drift, not
fixable in the persona. Keep the seam
small and hand back cleanly.
· Direction and rate of decay
→ VARIES BY MODEL. Characters far from the
default assistant register decay
fastest.
What actually slows it
No fix, four things that help, all with costs stated.
Cut the definition to what changes replies. The cheapest intervention available and usually the largest. Backstory that never surfaces is pure dilution.
Phrase voice as constraints on output rather than characterisation. Checkable instructions survive proportion loss better than adjectives.
Re-anchor. Restating the definition, or a compressed version of it, later in the assembled input raises its effective weight against the transcript. This is the most direct counter to the proportion problem and it costs input space on every turn — the cost lands on memory, since that is what it is competing with.
Keep less transcript and more structure. Carrying extracted facts instead of raw turns preserves what the user told you while removing the model’s own prior output from the input — which cuts the self-reinforcement channel specifically. The loss profiles differ, so this is a trade rather than an improvement.
Detection
Instrument the definition’s share of the input. The single most useful number here. Plot it against turn count; the curve is your drift pressure, and you will have a threshold beyond which complaints cluster.
Sample a fixed probe. Send the same handful of messages to a fresh conversation and to a long-running one, and compare. Systematic differences at turn two hundred that are absent at turn twenty are drift, measured rather than reported.
Track reply length distribution by turn depth. Length converges toward a model’s default as drift progresses, and it is trivial to log. A widening gap between early-conversation and late-conversation length is drift showing up in a number.
Rule out the real changes first. Compare a fresh conversation on the current build against your last known-good build. If the fresh conversation is also different, nothing drifted — something shipped.
What this costs and what it doesn’t fix
Everything above is paid per turn, and each measure competes for the same space as the memory it is compensating for. There is no configuration where the character is fully expressed and the history is fully carried, because they are the same resource.
And none of it stops drift — it slows the rate and lowers the ceiling. A long enough conversation drifts regardless, which is worth designing around rather than against: conversation boundaries, fresh threads, and periodically re-establishing state are all legitimate answers, and all of them cost less than pretending a single thread can run forever. As does knowing what a longer input actually costs you before you commit to carrying one.