Skip to content

fix: heartbeat model override ignored — 4 root causes (#56788)#1

Open
daniel-rudaev wants to merge 1 commit intomainfrom
fix/heartbeat-model-override
Open

fix: heartbeat model override ignored — 4 root causes (#56788)#1
daniel-rudaev wants to merge 1 commit intomainfrom
fix/heartbeat-model-override

Conversation

@daniel-rudaev
Copy link
Copy Markdown

Summary

Fixes agents.defaults.heartbeat.model config being ignored at runtime — heartbeat always falling back to the default model (e.g. Opus) regardless of what is configured.

Based on upstream openclaw/openclaw PRs #57094 and #57076, both currently open and unmerged.

Root causes (4 loss points in the model resolution chain)

  1. runtime-system.ts — heartbeat model field stripped when forwarding to runHeartbeatOnceInternal
  2. live-model-switch.tsresolveLiveSessionModelSelection() ignores caller-provided defaults, uses config default instead
  3. model-fallback.tsLiveSessionModelSwitchError swallowed as a candidate failure, inverts fallback order
  4. get-reply.ts — unconditionally overwrites heartbeat model after directive resolution

Changes

Applied via build-time patch script (patches/apply-heartbeat-model-fix.sh) in Dockerfile.base:

  • src/plugins/runtime/runtime-system.ts — pass model field through to runHeartbeatOnceInternal
  • src/plugins/runtime/types-core.ts — add model?: string to heartbeat type
  • src/agents/live-model-switch.ts — prefer caller-provided defaultProvider/defaultModel over config lookup
  • src/agents/model-fallback.ts — add isLiveSessionModelSwitchError() structural check + rethrowLiveSwitch param
  • src/auto-reply/reply/agent-runner-execution.ts — use structural check, pass rethrowLiveSwitch: true
  • src/auto-reply/reply/get-reply.ts — guard post-directive model overwrite with hasResolvedHeartbeatModelOverride

Testing

Patches verified against current openclaw/openclaw main (commit at clone time). Patch script exits non-zero if any substitution fails.

Upstream PRs pending — will remove patch and point directly to source once merged upstream.

References

Applies source-level fixes from upstream PRs #57094 and #57076 (both
unmerged) via a build-time patch script.

Root causes and fixes:
1. runtime-system.ts: plugin runtime API stripped heartbeat.model when
   forwarding to runHeartbeatOnceInternal — now passes it through
2. live-model-switch.ts: resolveLiveSessionModelSelection ignored caller-
   provided defaults when agentId was present, always using config default
   — now prefers caller defaults (the resolved heartbeat model)
3. model-fallback.ts: LiveSessionModelSwitchError was swallowed as a
   candidate failure, inverting the fallback order — now rethrown when
   rethrowLiveSwitch is set
4. get-reply.ts: post-directive resolution unconditionally overwrote the
   heartbeat model — now guarded by hasResolvedHeartbeatModelOverride

Also in agent-runner-execution.ts: uses structural isLiveSessionModelSwitchError
check (cross-module safe) and passes rethrowLiveSwitch: true.

Upstream refs: openclaw/openclaw#56788, PR #57094, PR #57076
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant