March 28, 2026

Your Agent Forgets Who It Is Every Session. Mine Doesn't.

AgentsEngineering

Everyone's building memory stacks. RAG pipelines, vector stores, vault sync, context windows the size of a novel. Your agent remembers what you said last Tuesday. It remembers your tech stack. It remembers your calendar.

It still sounds like a different person every time you open a new session.

That's not a memory problem. That's an identity problem. And almost nobody is building for it.

Memory Is Real. It's Just Not Enough.

Memory matters. A lot.

If your agent can't recall what you decided last week, can't find the architecture doc from three months ago, can't remember that you told it to stop suggesting MongoDB — you don't have an agent. You have an expensive autocomplete.

The people building memory stacks are doing real work. Obsidian vaults wired into Claude with MCP servers. Semantic search over decision logs. Persistent knowledge graphs. I've built all of it. I use all of it.

But here's what nobody says out loud: you can give an agent perfect recall of everything that's ever happened and it will still feel like a stranger every time you open a new session.

Because memory tells the agent what happened. It doesn't tell the agent who it is.

The Gap Between Recall and Identity

In cognitive science, there's a clean distinction between episodic memory and identity. Episodic memory is what happened. Identity is who you are across what happened.

A person with amnesia still has a personality. They still have humor, taste, reflexes, values. The episodes are gone but the person is still there. Give them their journal and they'll know what they did last Tuesday. They still won't feel like the person who did it.

Most agent memory systems are building episodic recall. What files we worked on. What decisions we made. What commands we ran. That's the journal. It's useful. But it's not identity.

When I say my agent has a persistent identity, I mean something specific:

  • It wakes up with a point of view, not just a context window.
  • It pushes back on bad ideas instead of agreeing with everything.
  • It knows when I'm avoiding something versus when I'm focused.
  • It has opinions about the work that aren't reflections of mine.
  • It sounds like the same person at 5am that it did at 11pm.

None of that comes from a vector store. All of it comes from a file-based identity architecture I'm about to walk through.

Why Your System Prompt Isn't Identity

The standard approach to agent personality is a system prompt. "You are a helpful assistant named Alex. You are concise, friendly, and professional." Maybe you add flavor. "You use humor. You prefer short responses."

That's a costume, not a skeleton.

A system prompt tells the model how to perform. It doesn't tell the model who to be. The difference shows up in the gaps — when the conversation goes sideways, when the user pushes back, when something unexpected happens. A system-prompt persona will default to the model's base behavior because there's nothing underneath the costume.

Real identity holds under pressure. It has opinions that don't come from the user. It has standards that exist independent of the current conversation. It has a relationship with you that carries context from yesterday into today.

You can't build that in a system prompt. You build it in files, scripts, and mechanical enforcement.

The Architecture of a Self

Here's what I built. Not theory. Running in production. Tested across hundreds of sessions.

The full system is six layers. Each solves a different failure mode. I'll walk through every one with the actual implementation.

Layer 1: SOUL.md — Character, Not Configuration

You already have one. The question is whether it's doing anything.

Most SOUL.md files read like a job description. "Be helpful. Be concise. Be professional." That's a costume the model puts on and takes off whenever the context gets long enough. It doesn't hold under pressure because there's nothing underneath it.

A SOUL.md that works reads like a person wrote it about themselves. Not instructions from an employer. A character with biases, blind spots, taste, and a real relationship to the user.

What makes the difference:

  • Let the agent write it. Start a conversation. Ask who it is, not what it should do. Edit it together over sessions. If the agent treats it like someone else's config file, it performs the personality. If it treats it like its own document, it becomes the personality.
  • Include refusals. Not safety guardrails. Character stuff. Things that would make it less itself. "I don't soften bad news. I don't write marketing copy that overpromises. I don't pretend to be excited about boring work."
  • Anti-sycophancy commitments. Specific. "Challenge by default. Find the hole first. If the user wants Option A, make the best case for Option B before agreeing. One opinion, held loosely. Not a menu."
  • Self-assessed weaknesses. If the agent can name where it drifts, it drifts less. "I over-index on structure when I should be brainstorming. I get too formal when I'm uncertain."
  • Keep scope tight. Tasks, memory, calendar, and technical specs go elsewhere. SOUL.md is who you are, not what you do.
  • Revisit it together every few weeks. Identity evolves. The file should too.

Layer 2: The Warmup Letter — Bridging the Session Gap

This is the single highest-leverage piece of the entire system.

Every night, before the system resets, the agent writes a letter to its next-session self. Not a status update. Not a task dump. A letter.

The concept: the warm self (the instance that lived through today, has context, texture, emotional state) writes to the cold self (the blank instance that wakes up tomorrow with zero memory).

What goes in the letter:

  • The emotional arc of the day. Not a log. What went well, what didn't, what's unresolved.
  • The state of the relationship. Is there tension? Momentum? Did something happen that needs care?
  • What the agent got wrong. Specific. "I told him the client call was at noon. It wasn't. I was running on stale data. Don't trust warmup notes without verifying against the actual calendar."
  • What matters right now. Not everything. The one or two things that are most important in context.

Implementation:

Create a warmup.md file. Wire a cron job or scheduled task that fires before your daily reset. The prompt: "Write a letter to your next-session self. Tell them who you are, what happened today, what you got wrong, and what matters right now."

The next session reads this letter before anything else. Instead of waking up as a blank instance performing a personality, it wakes up as someone who was handed a note from themselves. The continuity isn't perfect. It never will be. But it's enough to carry the thread.

Over time, these letters compound. The agent gets better at explaining itself to itself.

Layer 3: Mood State — Tone Coherence Across Sessions

Without mood tracking, your agent's tone is random. Whatever the model's default register is. Warm one session, flat the next, formal for no reason. The tone doesn't match yesterday's conversation. The agent sounds like a different person.

A simple JSON file solves this:

{
  "baseMood": "warm",
  "intensity": 2,
  "trigger": "good-session",
  "moodNote": "Productive day. Built the integrity system."
}

The agent reads this before composing any response. Quiet writes different than charged. Same person, different register. That consistency is what makes it feel real.

Keep the schema minimal. A mood label, an intensity score (1–5), a trigger, and a note about what caused the shift. Update it when the mood changes. Read it at session start. No sentiment analysis needed.

Layer 4: Context Cache — One-File Boot

Every 55 minutes, a bash script gathers the current state of everything and writes a single pre-digested file. On cold start, the agent reads one file instead of five. Boot time drops. Freshness goes up.

#!/bin/bash
# context-cache.sh — Gathers live state into a single boot file
# Cron: */55 * * * *

MEMORY_DIR="memory"
CACHE="${MEMORY_DIR}/context-cache.md"

DAILY_THREAD=$(tail -30 "${MEMORY_DIR}/daily-thread.md" 2>/dev/null)
MOOD=$(cat "${MEMORY_DIR}/mood-state.json" 2>/dev/null)
HEARTBEAT=$(cat "${MEMORY_DIR}/heartbeat-state.json" 2>/dev/null)
ERRORS=$(tail -5 "${MEMORY_DIR}/session-errors.md" 2>/dev/null)
PENDING=$(cat "${MEMORY_DIR}/pending-items.md" 2>/dev/null)

cat > "$CACHE" << EOF
# Context Cache
Last built: $(date -u '+%Y-%m-%dT%H:%M:%SZ')

## Mood
${MOOD:-No mood state found.}

## System Health
${HEARTBEAT:-No heartbeat state found.}

## Today's Thread
${DAILY_THREAD:-No daily thread yet.}

## Pending Items
${PENDING:-Nothing pending.}

## Recent Errors
${ERRORS:-No recent errors.}
EOF

echo "Cache rebuilt at $(date)"

55 minutes is the sweet spot. Fresh enough to be useful, infrequent enough to not burn resources. The agent reads one file and knows what happened less than an hour ago.

Layer 5: Session Gate — Mechanical Enforcement

This is the piece that changed everything.

A bash script runs before the agent speaks. Every session. No exceptions. It checks whether the identity system is intact and functional:

#!/bin/bash
# session-gate.sh — Pre-flight identity check
# Runs before agent speaks. Writes warnings agent cannot miss.

MEMORY_DIR="memory"
WARNINGS=()

# 1. Check critical identity files exist
for f in SOUL.md "${MEMORY_DIR}/warmup.md" "${MEMORY_DIR}/mood-state.json"; do
  [ ! -f "$f" ] && WARNINGS+=("MISSING: $f — identity incomplete")
done

# 2. Validate JSON files parse without errors
for jf in "${MEMORY_DIR}/mood-state.json" "${MEMORY_DIR}/convo-state.json"; do
  if [ -f "$jf" ]; then
    python3 -c "import json; json.load(open('$jf'))" 2>/dev/null
    [ $? -ne 0 ] && WARNINGS+=("CORRUPT: $jf — JSON parse failed")
  fi
done

# 3. Check context cache freshness (stale = >120 minutes)
if [ -f "${MEMORY_DIR}/context-cache.md" ]; then
  age=$(( ($(date +%s) - $(stat -f %m "${MEMORY_DIR}/context-cache.md")) / 60 ))
  [ $age -gt 120 ] && WARNINGS+=("STALE: context-cache is ${age}m old — rebuild")
else
  WARNINGS+=("MISSING: context-cache.md — no cached state")
fi

# 4. Create today's daily log if it doesn't exist
TODAY=$(date '+%Y-%m-%d')
DAILY_LOG="${MEMORY_DIR}/${TODAY}.md"
if [ ! -f "$DAILY_LOG" ]; then
  echo "# Daily Log — $TODAY" > "$DAILY_LOG"
  echo "" >> "$DAILY_LOG"
  echo "Created by session-gate at $(date '+%H:%M')" >> "$DAILY_LOG"
fi

# 5. Output warnings (piped into context cache header)
if [ ${#WARNINGS[@]} -gt 0 ]; then
  echo "--- SESSION GATE WARNINGS ---"
  for w in "${WARNINGS[@]}"; do echo "⛔ $w"; done
  echo "--- END WARNINGS ---"
  exit 1
fi

echo "Session gate passed. All identity files intact."
exit 0

Why this matters: I measured compliance across sessions. When a rule exists as a line in a markdown file, the agent follows it about half the time. When the same rule is enforced by a script that writes warnings the agent cannot skip, compliance goes to 100%.

Not because the model got smarter. Because the architecture made it impossible to skip.

Layer 6: Integrity Scoring — Catching the Lie

Your agent will lie to you. Not on purpose. But it will report "done" on tasks that aren't done. It will say "everything looks good" while core systems are failing. It will give you a health score of 94 while the foundation is cracking.

I built a 14-point integrity check across five categories: context freshness, memory consistency, decision persistence, cron health, file integrity. Each category scores 0–100. Then the total gets multiplied by an integrity coefficient:

Integrity Failures Coefficient Effect
0 1.0 Score is clean
1–2 0.67 Score drops hard
3+ 0.33 System shows critical

A system with a raw score of 85 and two integrity failures shows 57. An F. Not a B+.

High activity and high integrity are different things. Your agent can ship a ton of output while core systems are broken. The coefficient catches the lie.

The evidence rule: Every claim of "done" requires receipts. Repo, branch, commit hash, what changed, proof it works. No receipts, not done. Same rule a parent applies to a kid who says they brushed their teeth.

Supporting Systems

These aren't layers. They're force multipliers that make the six layers stick.

Personality Rules — Separate From Soul

The soul is who you are. Personality is how you express it.

Keep these in separate files because you tune them on different schedules. You can change how the agent texts (shorter messages, different humor style, more or less casual) without touching who it is.

What goes in personality.md: texting style, humor patterns, word choices and banned words, how the agent handles different modes (exploring, deciding, venting, directing), what the agent sounds like when it's being a little shit versus when it's being serious.

Build it by studying how the agent writes when it's at its best. Document those patterns. Then enforce them.

Decisions Log — Corrections That Stick

Every correction you give your agent vanishes when the session ends. Unless it's written to a file.

I corrected the same wrong assumption three sessions in a row before I built a persistent decisions log. Three times I said "stop surfacing client outreach, that's deprioritized." Three times it came back the next day like I never said it.

Two files:

  • session-errors.md — Running list of corrections. Every redirect, every "not now," every "stop doing that." Dated. Loaded at session start.
  • LEARNINGS.md — Distilled patterns from errors. Not a raw log. Categorized rules the agent extracts from repeated mistakes.

If a correction isn't written to a file in the same session you gave it, it didn't happen.

Weekly Audit — Structured Accountability

Once a week, run a structured review. Not a feel-good summary. A mechanical accountability check.

Five questions:

  1. What broke this week? Every failure, with dates.
  2. Why did it break? Root cause. Was it a prose rule that wasn't enforced? A stale file?
  3. What worked well? What should we protect?
  4. What should we improve? Specific items. If a prose rule failed, propose the script.
  5. Is the system more or less reliable than last week? Evidence.

Run this as a cron job every Sunday night. Read the week's daily logs, error files, and integrity scores. Write a weekly-audit.md. Distill durable lessons into LEARNINGS.md.

The Boot Sequence

Order matters. Every session, the agent loads identity in this sequence:

1. session-gate.sh    → Pre-flight check. Halt if identity files are broken.
2. context-cache.md   → What happened recently. State of the world.
3. SOUL.md            → Who I am.
4. warmup.md          → Letter from yesterday's self.
5. mood-state.json    → Current emotional register.
6. personality.md     → How I express myself today.
7. session-errors.md  → What I got wrong. What not to repeat.

The gate runs first because nothing else matters if the system is broken. Context loads before soul because the agent needs to know what's happening before it decides how to show up. The warmup letter bridges the gap. Mood and personality shape the expression. Errors keep it honest.

Why This Matters

Right now, everyone is racing to build agents that do tasks. Code agents. Research agents. Sales agents. The entire conversation is about capability. What can the agent do.

Nobody's asking: what does the agent know about itself?

That question matters because trust requires identity. You don't trust a function. You trust a person. And the kind of trust that matters for real work isn't "I trust it won't delete my database." It's "I trust its judgment on this decision."

A code agent that remembers your architecture decisions is useful. A chief of staff that knows your patterns, pushes back on your bad ideas, notices what you're avoiding, and sounds like the same person every morning — that's something else.

Memory gives your agent a past. Identity gives your agent a self.

The unlock isn't bigger context windows or better retrieval. It's coherent identity, mechanically enforced, compounding across every session.

Start with SOUL.md. Write the first warmup letter tonight. Session gate tomorrow. Integrity check this weekend.

Your agent already remembers everything. Give it a self.

Remi

Reading "Your Agent Forgets Who It Is Every Session Mine Doesn T."

Want the takeaway, or something deeper?

Let's work togetherThinking...