Bug description
Isolated cron jobs (sessionTarget: "isolated", payload.kind: "agentTurn") ignore the payload.model field and always execute with the agent's primary model.
Expected behavior
Per the cron-jobs docs:
Resolution priority:
- Job payload override (highest)
- Hook-specific defaults
- Agent config default
Setting payload.model: "mistral/mistral-small-latest" on an isolated cron job should make the job run with that model.
Actual behavior
The job always runs with the agent's primary model (e.g. claude-haiku-4-5), regardless of the payload.model value.
Gateway logs show:
live session model switch detected before attempt for <sessionId>:
mistral/mistral-small-latest -> anthropic/claude-haiku-4-5
Root cause (code analysis)
The issue is a field name mismatch between the cron scheduler and the embedded runtime:
-
Cron scheduler (runCronIsolatedAgentTurn in gateway-cli-*.js) correctly resolves the payload model and writes it to:
cronSession.sessionEntry.model = model; // e.g. "mistral-small-latest"
cronSession.sessionEntry.modelProvider = provider; // e.g. "mistral"
-
Embedded runtime (resolveLiveSessionModelSelection in auth-profiles-*.js) reads from different fields:
const model = entry?.modelOverride?.trim() || defaultModelRef.model;
const provider = entry?.providerOverride?.trim() || defaultModelRef.provider;
-
Since modelOverride is never written by the cron scheduler, it's always undefined, so the runtime falls back to defaultModelRef.model (the agent's primary model).
-
The runtime then detects the difference between the session's model field and the resolved model as a "live session model switch" and switches to the agent default.
Suggested fix
Either:
Option A — Have the cron scheduler also write modelOverride/providerOverride:
cronSession.sessionEntry.providerOverride = provider;
cronSession.sessionEntry.modelOverride = model;
Option B — Have resolveLiveSessionModelSelection fall back to entry.model/entry.modelProvider before defaultModelRef:
const model = entry?.modelOverride?.trim() || entry?.model?.trim() || defaultModelRef.model;
Environment
- OpenClaw version: 2026.3.28
- OS: macOS 26.4 (arm64)
- Node: v25.6.1
- Models tested:
mistral/mistral-small-latest, kimi/k2p5, openai-codex/gpt-5.4
- All models are in the
agents.defaults.models allowlist
- Agent primary model:
anthropic/claude-haiku-4-5
Reproduction
- Configure an agent with primary model
haiku
- Add
mistral/mistral-small-latest to agents.defaults.models
- Create an isolated cron job with
payload.model: "mistral/mistral-small-latest"
- Run the job manually with
openclaw cron run <jobId>
- Check
openclaw cron runs --id <jobId> — model will show claude-haiku-4-5
- Check gateway logs — will show "live session model switch" from mistral to haiku
Bug description
Isolated cron jobs (
sessionTarget: "isolated",payload.kind: "agentTurn") ignore thepayload.modelfield and always execute with the agent's primary model.Expected behavior
Per the cron-jobs docs:
Setting
payload.model: "mistral/mistral-small-latest"on an isolated cron job should make the job run with that model.Actual behavior
The job always runs with the agent's primary model (e.g.
claude-haiku-4-5), regardless of thepayload.modelvalue.Gateway logs show:
Root cause (code analysis)
The issue is a field name mismatch between the cron scheduler and the embedded runtime:
Cron scheduler (
runCronIsolatedAgentTurningateway-cli-*.js) correctly resolves the payload model and writes it to:Embedded runtime (
resolveLiveSessionModelSelectioninauth-profiles-*.js) reads from different fields:Since
modelOverrideis never written by the cron scheduler, it's alwaysundefined, so the runtime falls back todefaultModelRef.model(the agent's primary model).The runtime then detects the difference between the session's
modelfield and the resolved model as a "live session model switch" and switches to the agent default.Suggested fix
Either:
Option A — Have the cron scheduler also write
modelOverride/providerOverride:Option B — Have
resolveLiveSessionModelSelectionfall back toentry.model/entry.modelProviderbeforedefaultModelRef:Environment
mistral/mistral-small-latest,kimi/k2p5,openai-codex/gpt-5.4agents.defaults.modelsallowlistanthropic/claude-haiku-4-5Reproduction
haikumistral/mistral-small-latesttoagents.defaults.modelspayload.model: "mistral/mistral-small-latest"openclaw cron run <jobId>openclaw cron runs --id <jobId>— model will showclaude-haiku-4-5