Thomas M (@thomasxm) is a community contributor who identified and fixed a subtle but impactful bug affecting users with custom agent configurations. The fix includes not just the code change but also a migration path for existing affected installations.
OpenClaw uses session keys to identify and persist conversation transcripts. The key format is agent:{agentId}:{sessionAlias}. A bug in the session key resolution logic meant that when users configured a non-default agent ID, transcripts could be written to one key but read from another — effectively orphaning conversation history on every restart.
Who was affected: Users running multi-agent configurations where the default agent is not "main" — for example, if you configured defaultAgent: "ops" with mainKey: "work", your transcripts were being lost.
The root cause was a mismatch between write and read paths:
// resolveSessionKey() hardcoded DEFAULT_AGENT_ID = "main"
// Write path: "agent:main:main"
// Read path (via config): "agent:ops:work"
// Result: Write and read never find each other
Three write-path call sites were affected:
initSessionState — Auto-reply session initializationrunWebHeartbeatOnce — Heartbeat runnerresolveCronAgentSessionKey — Cron job sessionsAll three used the hardcoded default instead of resolving through the configuration system.
The fix wraps all three call sites with canonicalizeMainSessionAlias(), which properly resolves the session key through the configuration:
// Now consistent across read and write paths
const sessionKey = canonicalizeMainSessionAlias(rawKey, cfg);
// → "agent:ops:work" everywhere
But fixing the code isn't enough — existing users already have orphaned transcripts sitting in the wrong location.
The PR includes a startup migration (migrateOrphanedSessionKeys) that automatically recovers orphaned transcripts:
agent:main:*updatedAt if a conflict existsEdge cases handled: The migration correctly handles shared stores (where multiple agents use the same file), custom session.store templates, and avoids remapping legitimate cross-agent references like hooks, subagents, and per-sender keys.
The PR evolved through several iterations addressing review feedback:
getSessionSnapshot for heartbeat consistencyexpandHomePrefix for OPENCLAW_HOME overridesThe careful iteration on edge cases shows the complexity hidden in session key management when supporting flexible multi-agent configurations.
For single-agent users: No impact. The default configuration continues to work exactly as before.
For multi-agent users: If you've been seeing blank conversation history after restarts, upgrade to 2026.3.29 and your transcripts should automatically recover on first startup.
For developers: The fix establishes a clear pattern — always use canonicalizeMainSessionAlias() when constructing session keys. The hardcoded DEFAULT_AGENT_ID constant should only be used as a fallback when no configuration is available.
The migration runs automatically on startup. Check your logs for migrateOrphanedSessionKeys entries to confirm recovery. If you had orphaned transcripts, they should now appear in your conversation history.