Bug
Isolated cron jobs (sessionTarget: "isolated") that specify a sessionKey matching the main session key (e.g., agent:main:main) overwrite the parent session entry in the session store, including updatedAt. This prevents the daily session reset from triggering.
Root Cause
In src/cron/isolated-agent/session.ts, persistSessionEntry does a raw write:
store[agentSessionKey] = cronSession.sessionEntry;
When agentSessionKey resolves to the same key as the main session (e.g., agent:main:main), the cron run's session entry replaces the main session's entry entirely — including updatedAt, sessionId, model, and all other fields.
Impact
evaluateSessionFreshness checks updatedAt < dailyResetAtMs to determine staleness. When an isolated cron completes after the daily reset hour (default 4 AM), it bumps updatedAt past the reset boundary, making the session appear "fresh" on the next inbound message.
Result: The daily session reset silently fails. The user gets the previous day's session with stale context instead of a fresh start.
Reproduction
- Configure
session.reset.mode: "daily" with atHour: 4
- Create an isolated cron with
sessionKey: "agent:main:main" that runs after 4 AM (e.g., hourly, or scheduled at 5/6/7 AM)
- Wait for the cron to complete after 4 AM
- Send a message to the main session
- Expected: New session (daily reset triggered)
- Actual: Same session continues —
updatedAt was bumped by the cron run
Suggested Fix
Either:
- Option A: Use
mergeSessionEntryPreserveActivity (already exists in codebase) when persisting isolated cron session entries to parent keys, so updatedAt is not bumped
- Option B: Isolated cron runs should always write to a namespaced key (e.g.,
agent:main:cron:<jobId>:run:<runId>) and never to the parent session key directly
- Option C:
evaluateSessionFreshness should ignore updatedAt changes from cron-originated writes (e.g., by tracking lastUserActivityAt separately from updatedAt)
Workaround
Set each isolated cron's sessionKey to a unique value (e.g., agent:main:cron:<job-name>) instead of agent:main:main. This prevents the cron from writing to the main session's store entry.
Environment
- OpenClaw version: 2026.3.13
- OS: macOS 26.2 (arm64)
- Config:
session.reset.mode: "daily", atHour: 4
- Affected cron: any isolated job with
sessionKey matching the main session key
Bug
Isolated cron jobs (
sessionTarget: "isolated") that specify asessionKeymatching the main session key (e.g.,agent:main:main) overwrite the parent session entry in the session store, includingupdatedAt. This prevents the daily session reset from triggering.Root Cause
In
src/cron/isolated-agent/session.ts,persistSessionEntrydoes a raw write:When
agentSessionKeyresolves to the same key as the main session (e.g.,agent:main:main), the cron run's session entry replaces the main session's entry entirely — includingupdatedAt,sessionId,model, and all other fields.Impact
evaluateSessionFreshnesschecksupdatedAt < dailyResetAtMsto determine staleness. When an isolated cron completes after the daily reset hour (default 4 AM), it bumpsupdatedAtpast the reset boundary, making the session appear "fresh" on the next inbound message.Result: The daily session reset silently fails. The user gets the previous day's session with stale context instead of a fresh start.
Reproduction
session.reset.mode: "daily"withatHour: 4sessionKey: "agent:main:main"that runs after 4 AM (e.g., hourly, or scheduled at 5/6/7 AM)updatedAtwas bumped by the cron runSuggested Fix
Either:
mergeSessionEntryPreserveActivity(already exists in codebase) when persisting isolated cron session entries to parent keys, soupdatedAtis not bumpedagent:main:cron:<jobId>:run:<runId>) and never to the parent session key directlyevaluateSessionFreshnessshould ignoreupdatedAtchanges from cron-originated writes (e.g., by trackinglastUserActivityAtseparately fromupdatedAt)Workaround
Set each isolated cron's
sessionKeyto a unique value (e.g.,agent:main:cron:<job-name>) instead ofagent:main:main. This prevents the cron from writing to the main session's store entry.Environment
session.reset.mode: "daily",atHour: 4sessionKeymatching the main session key