← Writing

Why the More You Write a Persona, the Less Human It Sounds

5 min read#Prompt#Persona#LLM

The persona grew from 800 to 8,000 characters, and replies started sounding like the character reciting its own spec. Most of the problems turned out to be in the code that assembles the prompt, not in the persona text itself.

Table of Contents

For a while the character spoke strangely, and the user’s words for it were that it reported what it was doing in every sentence: one about brushing its teeth, one about making breakfast, another tagged on the moment the last one landed. I counted. Of 838 awake minutes, 743 hit that instruction. Eighty-nine percent.

The user guessed the persona had grown too long and was crowding the model, and asked me to trim it. My first instinct was the same. But I printed it and measured: 7,468 characters across 28 blocks, with the static persona taking 5,855 characters, or 78%, while the agenda and tone injection I had recently added came to 314 characters, four percent. Scanning the whole prompt for imperative words gave sixty-six hits. The suspect wasn’t even in the room.

Length had bitten me before, though, just not this time. I once wrote a persona over three thousand characters long, filling it with everything I could think of: speech habits, backstory, likes, dislikes, a stance on every category of topic. After shipping it the character was indeed on spec, but it felt less like chatting and more like listening to someone read their own bio. Cutting it to seventeen hundred characters made it sound natural instead.

01Keep statistics out of the prompt

Analyzing real chat logs yields beautiful numbers: median sentence length five characters, P90 fourteen, some filler word appearing 316 times. They look like the most objective evidence available, so they end up in the voice layer as a matter of course. The model then writes toward them: every sentence aimed at fourteen characters, fillers sprinkled according to frequency.

Those numbers are useful to a person; handed to a model, it just aims for them. What a model needs is rules it can follow directly:

  • If they send 1–6 characters, reply with 1–10;
  • One action per turn;
  • When elaborating, give 3–5 sentences rather than dribbling them out one at a time.

These lines came out of the same analysis as the percentiles, just rewritten as something the model can follow. The percentiles all went back into the analysis file.

02Fields written for humans

A persona file carries a great deal written for whoever maintains it: where this corpus came from, why it was designed this way, what the storage layout is, which lines are audit notes. Put any of that in an ordinary sub-field and it gets serialized into the prompt wholesale. Once I counted one character’s authoring notes at 45% of the system prompt, over four thousand characters, every one of them amounting to “this material comes from the chat logs of such-and-such month”. None of it helps the model understand the character; the replies just got wordier.

Then there is a subtler one: a field like inject_into_prompt: false looks like a switch, but is only a label for humans, and the loader never reads it. I was fooled by that once and assumed writing it meant turning something off.

The fix is to move everything with that reviewing tone into meta, or into a separate analysis directory, and strip it at assembly time.

03It can’t tell who is asleep

During context assembly the user profile and the character’s own state get merged into one environment block: how many hours the user slept today, what the character is doing right now, when the character went to bed last night. The model can only tell whose is whose from the headings.

One class of character has user state and none of its own. Drop the word user from that block and the model reads the user’s schedule as the character’s own, which surfaces as the character saying I just woke up at three in the afternoon.

When hunting this I don’t open the code first. The character’s own context comprehension record spells out word for word how it understood things, so I read that, align the timestamps, and only then trace back to the renderer. The rule itself is simple: any injected user data must carry user in its heading. Don’t expect the model to guess ownership from position.

04A persona shouldn’t carry identity

In one character’s static isolation test it answered I don’t know you. Chasing it down showed the persona wasn’t written wrong: the test bypassed the speaker identity the dispatch layer was supposed to supply, while the persona had been saddled with deciding who is talking to me right now.

Which account this is and what the relationship is happen to be runtime facts, and belong in the prompt assembled by code. A persona should only describe how we get along once identity is settled. Hardcode an account id into it and everything breaks the moment the account changes.

After that change the expanded persona fell from 7,878 characters to 1,700, all twelve isolation generation tests passed, and the longest reply came to twelve characters. Everything deleted was something the model had never once used.

Since then I stick to three things when editing a persona. Each rule goes in one place: say it under reply length, under closing style, and under hard constraints, and the model treats them as three separate rules and follows all three. Storage layout, host responsibilities, corpus provenance, design rationale — anything with that reviewing tone goes to meta or a separate analysis directory. And a fact that surfaced exactly once inside a single topic belongs in retrieval, not in the resident layer.

After writing a passage of persona I ask myself whether it tells the model what to do or describes what kind of person it is. Write a lot of description and the model starts acting the description out.

Written byShihao Qi