Summary
Cron job payload.model field is ignored when the target agent has a model set in agents.list[].model. The agent-level model pin always wins, causing every cron job to cascade through the entire fallback chain and land on the agent's pinned model (usually the most expensive one).
Environment
- OpenClaw version: 2026.3.28
- OS: Ubuntu 22.04 (Linux 5.15.0-171-generic x64)
- Setup: 5 agents (main, builder, orion, bizdev, health) with per-agent model pins
Config
{
"agents": {
"defaults": {
"model": {
"primary": "anthropic/claude-opus-4-6",
"fallbacks": ["anthropic/claude-sonnet-4-6", "openai-codex/gpt-5.4", "google/gemini-3.1-pro", "lmstudio/qwen/qwen3.5-9b"]
}
},
"list": [
{ "id": "builder", "model": "anthropic/claude-opus-4-6" },
{ "id": "orion", "model": "anthropic/claude-sonnet-4-6" }
]
}
}
Cron job example:
{
"agentId": "builder",
"payload": {
"model": "openai-codex/gpt-5.4-mini",
"message": "Run the daily error scanner..."
}
}
Expected Behavior
The cron's payload.model field (gpt-5.4-mini) should be used for that session, overriding the agent's default model. This is the whole point of the field — to run cheap/lightweight cron tasks on appropriate models without changing the agent's interactive model.
Actual Behavior
The gateway detects a "live session model switch" and rejects every candidate except the agent's pinned model:
[agent/embedded] live session model switch detected before attempt for <run-id>: openai-codex/gpt-5.4-mini -> anthropic/claude-opus-4-6
[model-fallback/decision] candidate_failed requestedModel=gpt-5.4-mini candidateModel=gpt-5.4-mini reason=unknown errorPreview="Live session model switch requested: anthropic/claude-opus-4-6"
[model-fallback/decision] candidate_failed candidateModel=gpt-5.4 reason=unknown errorPreview="Live session model switch requested: anthropic/claude-opus-4-6"
[model-fallback/decision] candidate_failed candidateModel=gemini-3.1-pro-preview reason=unknown errorPreview="Live session model switch requested: anthropic/claude-opus-4-6"
[model-fallback/decision] candidate_failed candidateModel=qwen/qwen3.5-9b reason=unknown errorPreview="Live session model switch requested: anthropic/claude-opus-4-6"
[model-fallback/decision] candidate_succeeded candidateModel=claude-opus-4-6 attempt=5 total=5
Every candidate fails with reason=unknown and the same error: "Live session model switch requested: anthropic/claude-opus-4-6". The session always lands on the agent's pinned model.
Impact
- All 15+ enabled cron jobs cascade through 4-5 fallback candidates before landing on the agent's model
- Produces ~60+ warning log lines per cron cycle (every 30 minutes)
- Jobs configured for
gpt-5.4-mini ($0.001/run) execute on claude-opus-4-6 ($0.10/run) — 100x cost multiplier
- Operators cannot run cost-tiered cron work without this fix
Suggested Fix
The cron payload.model field should create a per-session model override (similar to /model in interactive sessions) that takes priority over the agent's agents.list[].model pin for the duration of that cron run.
Workaround
Currently no clean workaround. Removing the agent-level model pin would affect interactive sessions. The cron model field is documented but non-functional when agent pins exist.
Summary
Cron job
payload.modelfield is ignored when the target agent has amodelset inagents.list[].model. The agent-level model pin always wins, causing every cron job to cascade through the entire fallback chain and land on the agent's pinned model (usually the most expensive one).Environment
Config
{ "agents": { "defaults": { "model": { "primary": "anthropic/claude-opus-4-6", "fallbacks": ["anthropic/claude-sonnet-4-6", "openai-codex/gpt-5.4", "google/gemini-3.1-pro", "lmstudio/qwen/qwen3.5-9b"] } }, "list": [ { "id": "builder", "model": "anthropic/claude-opus-4-6" }, { "id": "orion", "model": "anthropic/claude-sonnet-4-6" } ] } }Cron job example:
{ "agentId": "builder", "payload": { "model": "openai-codex/gpt-5.4-mini", "message": "Run the daily error scanner..." } }Expected Behavior
The cron's
payload.modelfield (gpt-5.4-mini) should be used for that session, overriding the agent's default model. This is the whole point of the field — to run cheap/lightweight cron tasks on appropriate models without changing the agent's interactive model.Actual Behavior
The gateway detects a "live session model switch" and rejects every candidate except the agent's pinned model:
Every candidate fails with
reason=unknownand the same error: "Live session model switch requested: anthropic/claude-opus-4-6". The session always lands on the agent's pinned model.Impact
gpt-5.4-mini($0.001/run) execute onclaude-opus-4-6($0.10/run) — 100x cost multiplierSuggested Fix
The cron
payload.modelfield should create a per-session model override (similar to/modelin interactive sessions) that takes priority over the agent'sagents.list[].modelpin for the duration of that cron run.Workaround
Currently no clean workaround. Removing the agent-level model pin would affect interactive sessions. The cron
modelfield is documented but non-functional when agent pins exist.