Summary
A heartbeat / async completion run that uses agents.defaults.heartbeat.model appears to persist its runtime model into the normal chat session (sessionEntry.model / modelProvider). After that, /status / session status reports the user-facing WhatsApp direct session as running the heartbeat model, even though normal turns are configured for the default model and fallbacks are empty.
This is confusing and makes it look like the agent unexpectedly routed normal user traffic through the heartbeat model / fallback path.
Environment
- OpenClaw:
2026.4.24 (2026.4.26 available, not tested yet)
- macOS arm64
- Channel: WhatsApp direct session
- Runtime: OpenClaw Pi Default
Relevant config
{
"agents.defaults.model": {
"primary": "openai-codex/gpt-5.5",
"fallbacks": []
},
"agents.defaults.heartbeat": {
"every": "1h",
"model": "xai/grok-4-1-fast-reasoning"
}
}
openclaw models fallbacks list also returns:
Observed timeline
In one WhatsApp direct session JSONL, model snapshots show:
08:05Z model-snapshot provider=openai-codex modelApi=openai-codex-responses modelId=gpt-5.5
08:13Z model-snapshot provider=xai modelApi=openai-responses modelId=grok-4-1-fast
08:28Z model-snapshot provider=openai-codex modelApi=openai-codex-responses modelId=gpt-5.5
The 08:13Z event was not a normal user-requested model switch. It was adjacent to an async command completion / heartbeat-style internal event whose instruction was effectively to handle internally and reply HEARTBEAT_OK only.
After that, the session store for the WhatsApp direct session contained:
{
"model": "grok-4-1-fast",
"modelProvider": "xai",
"modelOverride": null,
"providerOverride": null,
"modelOverrideSource": null
}
/status then reported the direct user session as:
But gateway logs around later normal turns showed the real normal run path still using the configured default:
[context-overflow-diag] sessionKey=agent:<agent>:whatsapp:direct:<redacted> provider=openai-codex/gpt-5.5 ...
context overflow detected ... attempting auto-compaction for openai-codex/gpt-5.5
Expected behavior
One of these should happen:
- Heartbeat / internal async-completion runs should not persist their runtime model into the user-facing session's
model / modelProvider; or
- Status should clearly distinguish:
- configured/selected model for normal user turns, and
- last runtime model used by an internal heartbeat/background event.
In particular, a heartbeat model should not make a direct user session look like it has switched to that model when no session model override exists and normal fallback lists are empty.
Actual behavior
A heartbeat/internal run using agents.defaults.heartbeat.model persisted xai/grok-4-1-fast into the direct session runtime fields. Status then reported that as the session model, causing apparent unexpected routing to Grok despite:
- default model =
openai-codex/gpt-5.5
- configured fallbacks =
[]
- no per-session model override
Notes
There may be a second, smaller naming/normalization oddity: config uses xai/grok-4-1-fast-reasoning, but the model snapshot/session status showed xai/grok-4-1-fast. That might be provider aliasing, but it adds to the confusion.
No private phone numbers, account ids, or user names are included here; session identifiers above are redacted.
Summary
A heartbeat / async completion run that uses
agents.defaults.heartbeat.modelappears to persist its runtime model into the normal chat session (sessionEntry.model/modelProvider). After that,/status/ session status reports the user-facing WhatsApp direct session as running the heartbeat model, even though normal turns are configured for the default model and fallbacks are empty.This is confusing and makes it look like the agent unexpectedly routed normal user traffic through the heartbeat model / fallback path.
Environment
2026.4.24(2026.4.26available, not tested yet)Relevant config
{ "agents.defaults.model": { "primary": "openai-codex/gpt-5.5", "fallbacks": [] }, "agents.defaults.heartbeat": { "every": "1h", "model": "xai/grok-4-1-fast-reasoning" } }openclaw models fallbacks listalso returns:Observed timeline
In one WhatsApp direct session JSONL, model snapshots show:
The 08:13Z event was not a normal user-requested model switch. It was adjacent to an async command completion / heartbeat-style internal event whose instruction was effectively to handle internally and reply
HEARTBEAT_OKonly.After that, the session store for the WhatsApp direct session contained:
{ "model": "grok-4-1-fast", "modelProvider": "xai", "modelOverride": null, "providerOverride": null, "modelOverrideSource": null }/statusthen reported the direct user session as:But gateway logs around later normal turns showed the real normal run path still using the configured default:
Expected behavior
One of these should happen:
model/modelProvider; orIn particular, a heartbeat model should not make a direct user session look like it has switched to that model when no session model override exists and normal fallback lists are empty.
Actual behavior
A heartbeat/internal run using
agents.defaults.heartbeat.modelpersistedxai/grok-4-1-fastinto the direct session runtime fields. Status then reported that as the session model, causing apparent unexpected routing to Grok despite:openai-codex/gpt-5.5[]Notes
There may be a second, smaller naming/normalization oddity: config uses
xai/grok-4-1-fast-reasoning, but the model snapshot/session status showedxai/grok-4-1-fast. That might be provider aliasing, but it adds to the confusion.No private phone numbers, account ids, or user names are included here; session identifiers above are redacted.