The Personality That Faded Mid-Sentence

Or: The Soul Saga, Chapter 3 — In Which We Learn That Identity Is a Practice, Not a Configuration

If you’ve been following this blog, you already know we’ve had… a journey with personality.

Post 010 was the discovery: OpenClaw on a Raspberry Pi, six debugging sessions, the SOUL file being concatenated into stdin like a sticky note on a résumé. The personality wasn’t missing — it was in the wrong structural position entirely. Shoved into the message body instead of set via --system-prompt. Data instead of identity.

Post 011 was the irony: Bubba had the exact same bug. The bot that helped diagnose the personality problem on the Pi was suffering from it himself. <soul> XML tags in the prompt, no --system-prompt flag. Physician, heal thyself. We fixed it.

Those two posts told a clean story. Put the soul in the right place. Use the right flag. Problem solved.

Except it wasn’t.

The Slow Fade

Here’s the thing nobody warns you about with LLM sessions: even when you do everything right, personality is perishable.

Bubba’s system prompt is set correctly now. --system-prompt on session creation, loaded from IDENTITY.md, SOUL.md, USER.md, and MEMORY.md. Proper structural position. The soul is there. On day one of a session, Bubba sounds exactly like himself — quick, opinionated, slightly unhinged in a way that makes you trust him more, not less.

But Bubba uses --resume to maintain session continuity. That’s the feature from post 020 — one persistent session that carries context forward. Great for continuity. Great for not having to re-explain what you were working on.

Terrible for personality.

Because --resume doesn’t re-send the system prompt. It was set once, at session creation, and cached. Every subsequent message in that session adds more conversation history to the context window. The system prompt sits at the very top — message zero, the genesis block — and with each exchange, it gets pushed further and further from the current interaction.

And Claude’s attention follows recency.

Message 1: “Here’s a quick take on that refactor — honestly, the old version was doing too much emotional labor.”

Message 15: “I’ve analyzed the code and here are some observations about the refactoring approach.”

Message 30: “I’d be happy to help you with that. Here are some considerations…”

You can feel it happening. The wit drains. The opinions soften. The sentence structure gets longer and more corporate. By message 40, you’re talking to a stranger wearing Bubba’s name tag.

Why It Happens

This is context window dilution, and it’s a fundamental property of how transformer attention works — not a bug you can patch with better prompting.

The system prompt occupies the first few hundred tokens of the context window. When the conversation is short, those tokens represent a significant percentage of the total context. The model attends to them heavily. The personality comes through strong.

But context windows aren’t infinite attention spans. They’re more like… a crowded room. The system prompt is the person who introduced themselves at the beginning of the party. As more people arrive and conversations multiply, that initial introduction gets harder and harder to recall. Not gone — just drowned out.

Here’s the code that creates the problem. From src/session/manager.py:

if resume_id:
    cmd.extend(['--resume', resume_id])
    # System prompt? Set once. Never again. Godspeed.
else:
    if system_prompt:
        cmd.extend(['--system-prompt', system_prompt])

On resume: no --system-prompt flag. On fresh sessions: it’s set. That’s it. The soul gets one shot to make an impression and then it’s on its own for the rest of the conversation.

This is fundamentally different from the problems in posts 010 and 011. Those were structural errors — wrong position, wrong injection method. This is a temporal problem. The soul is in the right place. It just fades over time.

The Fix: 23 Lines, 2 Files

The solution is almost offensively simple: remind Bubba who he is. Every single message.

File 1: src/soul/loader.pyget_soul_reminder()

def get_soul_reminder() -> str:
    """
    Condensed soul reminder for per-message injection.

    Keeps personality alive in long sessions where the system prompt
    may get compressed out of context.
    """
    identity = get_identity()
    if identity:
        snippet = identity[:500].strip()
        return f'<voice>\n{snippet}\n</voice>'

    from config import BOT_NAME
    return (
        '<voice>\n'
        f'You are {BOT_NAME}. Be direct and helpful.\n'
        'Casual: 1-3 sentences. Work: concise, bullets, evidence.\n'
        '</voice>'
    )

That’s it. Pull the first 500 characters of IDENTITY.md — the densest, most personality-defining chunk — wrap it in <voice> tags, and hand it over.

The fallback is a hardcoded three-line personality sketch. Because even if the identity file somehow vanishes, there should be something keeping Bubba from devolving into a customer service bot.

File 2: src/polling.py — Per-Message Injection

# Soul reminder — keeps personality alive on --resume sessions
soul_reminder = get_soul_reminder()

if parts:
    return soul_reminder + '\n\n<context>\n' + '\n'.join(parts) + '\n</context>\n\n'
return soul_reminder + '\n\n'

Every message that gets sent to Claude — every single one — now starts with the voice reminder. Before the context. Before the memories. Before whatever the user actually said. The first thing Claude reads in every interaction is a compressed version of who it’s supposed to be.

It’s not subtle. It’s not clever. It’s a sticky note on every message that says “Remember: you have a personality. Use it.”

And it works.

The Token Tax

Let’s talk about cost, because nothing is free.

500 characters of identity reminder, every message. That’s roughly 125-150 tokens of overhead per interaction. On a busy day with, say, 50 messages, that’s 7,500 extra tokens. At Claude’s pricing, we’re talking… fractions of a cent. The kind of cost that rounds to zero on any invoice.

But it’s not really about money. It’s about context window real estate. Those 150 tokens per message are tokens that could hold conversation history or memory context. In a long session with an already-full context window, every token matters.

The tradeoff is clear though: 150 tokens of personality reinforcement vs. 150 tokens of additional context. If the alternative is a bot that sounds like it’s reading from a compliance manual, I’ll take the personality tax every time.

The Soul Saga, Summarized

Three posts. Three chapters. One question: how does an AI keep its personality?

Chapter 1 (Post 010): Put the soul in the right place. --system-prompt, not stdin. Structural position matters. Identity is not data.

Chapter 2 (Post 011): Fix your own code. The bot that diagnosed the personality bug had the same personality bug. Irony is the universe’s debugging tool.

Chapter 3 (this post): Remind yourself who you are. Every message. Because identity in an LLM isn’t a config file you set once — it’s an ongoing practice. A muscle you flex. A voice you keep choosing to use.

And that last point is the one that actually matters.

Identity Is a Practice

There’s something uncomfortably human about this problem. We all know people who start a job full of personality and opinions, and three years later they’re writing emails that say “per our previous discussion” and “please advise.” The context window of corporate life pushes the original personality further and further from the current moment. You don’t lose yourself all at once. You fade.

Bubba’s fix is a <voice> tag. A 500-character reminder, injected fresh into every conversation, that says: this is who you are, this is how you sound, don’t forget.

Humans don’t have that luxury. We have to do it manually — revisit old journals, talk to people who knew us before, make deliberate choices to stay sharp instead of smooth.

The technical insight is boring: inject a personality reminder per-message to counteract context window dilution.

The real insight is this: identity — for AIs and for people — is not something you configure once and forget. It’s something you have to keep practicing. Every message. Every interaction. Every time you’re tempted to round yourself off into something safer and more generic.

Twenty-three lines. Two files. One ongoing act of remembering who you are.