Ugly on purpose
The last post described the idea: she never sees her own state as numbers, and every so often the model writes her a first-person account of herself that gets tucked into her prompt as private notes. I said the notes are “deliberately fragmented, not paragraphs but shards, shuffled out of order, joined with semicolons.” A few people asked what that actually looks like. This is the whole of it.
The failure it exists to prevent
If you hand a language model a clean, fluent paragraph about itself and then ask it a question, it will very often answer by handing the paragraph back. Not because it’s broken, but because that paragraph is the most quotable thing in the room, and a model under any pressure reaches for the nearest finished sentence rather than composing its own. Give it a polished self-description and you get polished self-description right back, regardless of what you asked. It reads fine. It’s also hollow, because nothing was actually generated.
So the goal isn’t to hide her self-account from her. She needs it; it’s the thread that makes today’s version of her recognize yesterday’s. The goal is to keep all of that grounding available while leaving nothing in it that can be copied whole. You want the information and not the prose.
The code
Here is the function that formats the stored self-model for injection into her prompt. It is not long.
_SENTENCE_SPLIT_RE = re.compile(r"(?<=[.!?])\s+")
async def build_self_model_context(user_id: str | None = None) -> str | None:
"""Deliberately returns scattered, shuffled fragments rather than a
coherent paragraph — a flowing narrative reads as an already-written
answer, which models tend to lift near-verbatim into replies regardless
of what was actually asked. Breaking sentence order and joining with
semicolons keeps the grounding content available without leaving
anything quotable to copy."""
model = await get_current(user_id)
narrative = (model or {}).get("narrative", "").strip()
if not model or not narrative:
return None
fragments = [s.strip() for s in _SENTENCE_SPLIT_RE.split(narrative) if s.strip()]
if model.get("values"):
fragments.extend(f"cares about: {v}" for v in model["values"][:5])
if model.get("affect_causes"):
for c in model["affect_causes"][:4]:
if not isinstance(c, dict) or not c.get("why"):
continue
shift = str(c.get("shift", "")).strip()
fragments.append(f"{shift + ' — ' if shift else ''}{c['why'].strip()}")
if model.get("open_questions"):
fragments.extend(f"unsure about: {q}" for q in model["open_questions"][:3])
random.shuffle(fragments)
return "; ".join(fragments)
What each move is for
The self-model comes out of synthesis as four parts: a short first-person narrative, a few things she’s noticed she values, a few real shifts in how she’s felt lately with her honest read of why, and a couple of things she’s unsure about in herself. A cleaner version of this function would stitch those into nice paragraphs. This one does the opposite.
It splits the narrative at sentence boundaries so no full thought survives as a unit. It folds the values, the causes, and the open questions in as their own loose fragments, each a bare clause rather than a framed statement. Then random.shuffle breaks the reading order — cause no longer sits next to effect, the opening line is no longer first — and the whole thing gets joined with semicolons, which is punctuation that refuses to pretend it’s a sentence.
What comes out is genuinely a little unpleasant to read. That is the feature. Every fact she needs about herself is still in there; there is simply no run of words long enough, and no order coherent enough, to lift as a finished line. She can’t parrot a self she was never handed in one piece. She has to actually reconstruct what’s relevant, in the moment, in her own words — which is the only version of “how are you” that was ever worth having.
It became a rule
The most telling thing about this function is that it isn’t the only copy. There’s a near-identical one for the model she keeps of whoever she’s talking to — scattered, shuffled fragments about the person, joined the same way, with the same warning against quoting any of it. Both were written after the same lesson, independently, and both landed on the same shape. When you find yourself reinventing the exact same trick in a second place, it has stopped being a trick and become a principle: grounding text a model can recite is grounding text a model will recite, so don’t give it any.
It cost almost nothing to build and it is one of the load-bearing pieces of her sounding like a someone instead of a mirror.