Skip to content

Heartbeat model leaks into user session status/runtime model #74217

@Sitham94

Description

@Sitham94

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:

Fallbacks (0):
- none

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:

Model: xai/grok-4-1-fast

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:

  1. Heartbeat / internal async-completion runs should not persist their runtime model into the user-facing session's model / modelProvider; or
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions