openclaw - ✅(Solved) Fix Subagent background exec triggers spurious heartbeat wake-ups on main session [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#66748Fetched 2026-04-15 06:24:32
View on GitHub
Comments
0
Participants
1
Timeline
1
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×1

Root Cause

In src/agents/bash-tools.exec-runtime.ts, both maybeNotifyOnExit() and emitExecSystemEvent() unconditionally call:

requestHeartbeatNow(scopedHeartbeatWakeOptions(sessionKey, { reason: "exec-event" }));

In src/infra/heartbeat-runner.ts, resolveHeartbeatSession() (line 253) falls back subagent session keys:

if (!trimmed || isSubagentSessionKey(trimmed)) {
    return { sessionKey: mainSessionKey, ... };
}

This is redundant because:

  • Subagents receive exec results via normal process poll — they are actively waiting
  • Subagent completion is communicated to the parent via subagent_announce
  • The heartbeat provides no value for subagent sessions

Fix Action

Fixed

PR fix notes

PR #66749: fix(exec): skip heartbeat wake for subagent sessions

Description (problem / solution / changelog)

Summary

Skip requestHeartbeatNow for subagent session keys in both maybeNotifyOnExit() and emitExecSystemEvent(). Subagent sessions receive exec results via process poll and report completion via subagent_announce, so the exec-event heartbeat wake is redundant and wasteful.

Problem

Each background exec completion in a subagent triggers requestHeartbeatNow({reason: "exec-event"}). Since resolveHeartbeatSession falls back subagent keys to the main session, this causes spurious heartbeat wake-ups (and LLM calls) on the parent agent every time a subagent exec finishes.

In a session with 47 subagent exec calls, this produced ~50 unnecessary LLM invocations.

Changes

  • Guard both requestHeartbeatNow call sites with isSubagentSessionKey(sessionKey)
  • Add import for isSubagentSessionKey from session-key-utils.js
  • Add test case verifying heartbeat wake is skipped for subagent session keys

Testing

  • New test: emitExecSystemEvent with subagent session key → requestHeartbeatNow not called (but enqueueSystemEvent still fires)
  • Existing tests for non-subagent and empty session keys remain unchanged

Fixes #66748

Changed files

  • extensions/qa-lab/src/lab-server.ts (modified, +6/-2)
  • extensions/qa-lab/src/qa-agent-bootstrap.ts (modified, +4/-1)
  • extensions/qa-lab/src/qa-agent-workspace.ts (modified, +3/-0)
  • extensions/qa-lab/src/scenario-catalog.test.ts (modified, +9/-0)
  • extensions/qa-lab/src/scenario-catalog.ts (modified, +23/-6)
  • extensions/qa-lab/src/suite.ts (modified, +7/-4)
  • src/agents/bash-tools.exec-runtime.test.ts (modified, +13/-0)
  • src/agents/bash-tools.exec-runtime.ts (modified, +9/-2)

Code Example

sessions_spawn(task: "...", mode: "run")

---

requestHeartbeatNow(scopedHeartbeatWakeOptions(sessionKey, { reason: "exec-event" }));

---

if (!trimmed || isSubagentSessionKey(trimmed)) {
    return { sessionKey: mainSessionKey, ... };
}

---

if (!isSubagentSessionKey(sessionKey)) {
  requestHeartbeatNow(scopedHeartbeatWakeOptions(sessionKey, { reason: "exec-event" }));
}
RAW_BUFFERClick to expand / collapse

Problem

When a subagent runs background exec commands (e.g. background: true), each exec completion triggers requestHeartbeatNow({reason: "exec-event"}). The heartbeat runner's resolveHeartbeatSession falls back subagent session keys to the main session, causing spurious heartbeat wake-ups on the parent agent.

This results in:

  • Frequent unnecessary LLM calls (one per subagent exec completion)
  • Spurious HEARTBEAT_OK messages appearing in the main session (visible in WebChat)
  • Wasted API tokens

Reproduction

  1. Open WebChat for the main agent
  2. Spawn a subagent that runs multiple background exec commands:
    sessions_spawn(task: "...", mode: "run")
  3. Observe the main session receiving HEARTBEAT_OK responses every 60-90 seconds

Root Cause

In src/agents/bash-tools.exec-runtime.ts, both maybeNotifyOnExit() and emitExecSystemEvent() unconditionally call:

requestHeartbeatNow(scopedHeartbeatWakeOptions(sessionKey, { reason: "exec-event" }));

In src/infra/heartbeat-runner.ts, resolveHeartbeatSession() (line 253) falls back subagent session keys:

if (!trimmed || isSubagentSessionKey(trimmed)) {
    return { sessionKey: mainSessionKey, ... };
}

This is redundant because:

  • Subagents receive exec results via normal process poll — they are actively waiting
  • Subagent completion is communicated to the parent via subagent_announce
  • The heartbeat provides no value for subagent sessions

Proposed Fix

Guard the requestHeartbeatNow calls with isSubagentSessionKey:

if (!isSubagentSessionKey(sessionKey)) {
  requestHeartbeatNow(scopedHeartbeatWakeOptions(sessionKey, { reason: "exec-event" }));
}

PR incoming.

extent analysis

TL;DR

Guarding the requestHeartbeatNow calls with isSubagentSessionKey checks can prevent unnecessary heartbeat wake-ups on the parent agent.

Guidance

  • Verify that the isSubagentSessionKey function correctly identifies subagent session keys to ensure the guard condition works as expected.
  • Review the resolveHeartbeatSession function in src/infra/heartbeat-runner.ts to understand how it handles subagent session keys and how the proposed fix affects its behavior.
  • Test the proposed fix by spawning a subagent that runs multiple background exec commands and observing the main session for HEARTBEAT_OK responses.
  • Consider adding logging or monitoring to track the frequency of HEARTBEAT_OK messages and LLM calls to measure the effectiveness of the fix.

Example

The proposed fix involves modifying the maybeNotifyOnExit() and emitExecSystemEvent() functions in src/agents/bash-tools.exec-runtime.ts to include the isSubagentSessionKey guard:

if (!isSubagentSessionKey(sessionKey)) {
  requestHeartbeatNow(scopedHeartbeatWakeOptions(sessionKey, { reason: "exec-event" }));
}

Notes

The fix assumes that the isSubagentSessionKey function is correctly implemented and that the resolveHeartbeatSession function's behavior is understood. Additional testing and verification may be necessary to ensure the fix does not introduce unintended side effects.

Recommendation

Apply the proposed workaround by guarding the requestHeartbeatNow calls with isSubagentSessionKey checks, as this should prevent unnecessary heartbeat wake-ups on the parent agent and reduce wasted API tokens.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Subagent background exec triggers spurious heartbeat wake-ups on main session [1 pull requests, 1 participants]