Summary
When creating a cron job from a Discord/chat session with sessionTarget: "isolated", OpenClaw appears to persist the current chat sessionKey onto the job even when sessionKey was not explicitly provided.
That makes the job run against the chat-bound session instead of the expected isolated cron:<jobId> session, which can leak session/model state into a background script-style cron and cause runtime failures such as LiveSessionModelSwitchError.
Expected behavior
For cron jobs with:
sessionTarget: "isolated"
- no explicit
sessionKey provided
OpenClaw should run the job in an isolated cron session (cron:<jobId>) and should not implicitly persist the creating chat/session sessionKey onto the job.
Actual behavior
Creating the cron job from a Discord session produced a stored job like this (abridged):
{
"sessionTarget": "isolated",
"payload": {
"kind": "agentTurn",
"model": "anthropic/claude-sonnet-4-6"
},
"sessionKey": "agent:cron-lite:discord:channel:1475102142951067682"
}
Because sessionKey is present, the isolated runner uses that session key instead of cron:<jobId>.
Why this seems wrong
From the runtime code path, isolated cron execution uses roughly:
const baseSessionKey = params.sessionKey?.trim() || `cron:${params.job.id}`;
So if a job gets a sessionKey injected during creation, it no longer behaves like a clean isolated cron run.
This is especially problematic for script-style jobs that:
- do not need chat history
- do not need current-session binding
- use
delivery.mode = "none"
- are intended to run as clean background tasks
Observed failure mode
The affected job started failing with model-switch conflicts like:
LiveSessionModelSwitchError: Live session model switch requested: anthropic/claude-haiku-4-5
and earlier also:
LiveSessionModelSwitchError: Live session model switch requested: anthropic/claude-sonnet-4-6
This strongly suggests the cron run was inheriting/contending with model state from the chat-bound session.
Reproduction
- From a Discord/OpenClaw chat session, create a cron job using the cron tool/API with:
sessionTarget: "isolated"
payload.kind: "agentTurn"
- no explicit
sessionKey
- Inspect the stored/listed cron job.
- Observe that the job may contain the current chat
sessionKey.
- Run the job and observe that it does not behave like a clean
cron:<jobId> isolated session.
Workaround
Manually clearing the stored sessionKey fixes the issue:
{
"patch": {
"sessionKey": null
}
}
After patching sessionKey to null, the job no longer shows the chat-bound session key and behaves as expected.
Additional notes
This does not look like a problem with the isolated cron execution core itself.
The likely issue seems to be in the cron creation/request path, where the creating session's sessionKey is being implicitly forwarded/persisted onto the job even for sessionTarget: "isolated" jobs.
That may be reasonable for sessionTarget: "current", but it seems incorrect for plain isolated jobs.
Summary
When creating a cron job from a Discord/chat session with
sessionTarget: "isolated", OpenClaw appears to persist the current chat sessionKey onto the job even whensessionKeywas not explicitly provided.That makes the job run against the chat-bound session instead of the expected isolated
cron:<jobId>session, which can leak session/model state into a background script-style cron and cause runtime failures such asLiveSessionModelSwitchError.Expected behavior
For cron jobs with:
sessionTarget: "isolated"sessionKeyprovidedOpenClaw should run the job in an isolated cron session (
cron:<jobId>) and should not implicitly persist the creating chat/sessionsessionKeyonto the job.Actual behavior
Creating the cron job from a Discord session produced a stored job like this (abridged):
{ "sessionTarget": "isolated", "payload": { "kind": "agentTurn", "model": "anthropic/claude-sonnet-4-6" }, "sessionKey": "agent:cron-lite:discord:channel:1475102142951067682" }Because
sessionKeyis present, the isolated runner uses that session key instead ofcron:<jobId>.Why this seems wrong
From the runtime code path, isolated cron execution uses roughly:
So if a job gets a
sessionKeyinjected during creation, it no longer behaves like a clean isolated cron run.This is especially problematic for script-style jobs that:
delivery.mode = "none"Observed failure mode
The affected job started failing with model-switch conflicts like:
and earlier also:
This strongly suggests the cron run was inheriting/contending with model state from the chat-bound session.
Reproduction
sessionTarget: "isolated"payload.kind: "agentTurn"sessionKeysessionKey.cron:<jobId>isolated session.Workaround
Manually clearing the stored
sessionKeyfixes the issue:{ "patch": { "sessionKey": null } }After patching
sessionKeytonull, the job no longer shows the chat-bound session key and behaves as expected.Additional notes
This does not look like a problem with the isolated cron execution core itself.
The likely issue seems to be in the cron creation/request path, where the creating session's
sessionKeyis being implicitly forwarded/persisted onto the job even forsessionTarget: "isolated"jobs.That may be reasonable for
sessionTarget: "current", but it seems incorrect for plainisolatedjobs.