You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,6 +21,7 @@ Docs: https://docs.openclaw.ai
21
21
- Channels/Discord: split long CJK replies at punctuation and code-point-safe fallback boundaries so Discord chunking stays readable without corrupting astral characters. Fixes #38597; repairs #71384. Thanks @p3nchan.
22
22
- Browser/gateway: ignore Playwright dialog-close races from `Page.handleJavaScriptDialog` so browser automation no longer crashes the Gateway when a dialog disappears before Playwright accepts it. (#40067) Thanks @randyjtw.
23
23
- Cron/Gateway: defer missed isolated agent-turn catch-up out of the channel startup window, so overdue cron work cannot starve Discord or Telegram while providers connect after a restart. Thanks @vincentkoc.
24
+
- Heartbeat/cron: defer heartbeat turns while cron work is active or queued, add opt-in `heartbeat.skipWhenBusy` for subagent/nested lane pressure, and retry busy skips without advancing the schedule so local Ollama hosts do not run heartbeat and cron prompts concurrently. Fixes #50773. Thanks @scottgl9.
24
25
- Plugins/runtime-deps: prune stale `openclaw-unknown-*` bundled runtime dependency roots during Gateway startup while keeping recent or locked roots, so old staging debris cannot keep growing across restarts. Thanks @vincentkoc.
25
26
- Ollama: compose caller abort signals with guarded-fetch timeouts for native `/api/chat` streams, so `/stop` and early cancellation still interrupt local Ollama requests that also carry provider timeout budgets. Refs #74133. Thanks @obviyus.
26
27
- Doctor/TTS: migrate legacy `messages.tts.enabled`, agent TTS, channel TTS, and voice-call plugin TTS toggles to `auto` mode during `openclaw doctor --fix`, matching the documented TTS config contract. Thanks @vincentkoc.
Copy file name to clipboardExpand all lines: docs/automation/index.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -93,7 +93,7 @@ See [Hooks](/automation/hooks).
93
93
94
94
### Heartbeat
95
95
96
-
Heartbeat is a periodic main-session turn (default every 30 minutes). It batches multiple checks (inbox, calendar, notifications) in one agent turn with full session context. Heartbeat turns do not create task records and do not extend daily/idle session reset freshness. Use `HEARTBEAT.md` for a small checklist, or a `tasks:` block when you want due-only periodic checks inside heartbeat itself. Empty heartbeat files skip as `empty-heartbeat-file`; due-only task mode skips as `no-tasks-due`.
96
+
Heartbeat is a periodic main-session turn (default every 30 minutes). It batches multiple checks (inbox, calendar, notifications) in one agent turn with full session context. Heartbeat turns do not create task records and do not extend daily/idle session reset freshness. Use `HEARTBEAT.md` for a small checklist, or a `tasks:` block when you want due-only periodic checks inside heartbeat itself. Empty heartbeat files skip as `empty-heartbeat-file`; due-only task mode skips as `no-tasks-due`. Heartbeats defer while cron work is active or queued, and `heartbeat.skipWhenBusy` can also defer them while subagent or nested lanes are busy.
-`lightContext`: when true, heartbeat runs use lightweight bootstrap context and keep only `HEARTBEAT.md` from workspace bootstrap files.
539
540
-`isolatedSession`: when true, each heartbeat runs in a fresh session with no prior conversation history. Same isolation pattern as cron `sessionTarget: "isolated"`. Reduces per-heartbeat token cost from ~100K to ~2-5K tokens.
541
+
-`skipWhenBusy`: when true, heartbeat runs defer on extra busy lanes: subagent or nested command work. Cron lanes always defer heartbeats, even without this flag.
540
542
- Per-agent: set `agents.list[].heartbeat`. When any agent defines `heartbeat`, **only those agents** run heartbeats.
541
543
- Heartbeats run full agent turns — shorter intervals burn more tokens.
Copy file name to clipboardExpand all lines: docs/gateway/heartbeat.md
+8-1Lines changed: 8 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -50,6 +50,7 @@ Example config:
50
50
directPolicy:"allow", // default: allow direct/DM targets; set "block" to suppress
51
51
lightContext:true, // optional: only inject HEARTBEAT.md from bootstrap files
52
52
isolatedSession:true, // optional: fresh session each run (no conversation history)
53
+
skipWhenBusy:true, // optional: also defer when subagent or nested lanes are busy
53
54
// activeHours: { start: "08:00", end: "24:00" },
54
55
// includeReasoning: true, // optional: send separate `Reasoning:` message too
55
56
},
@@ -65,6 +66,7 @@ Example config:
65
66
- The heartbeat prompt is sent **verbatim** as the user message. The system prompt includes a "Heartbeat" section only when heartbeats are enabled for the default agent, and the run is flagged internally.
66
67
- When heartbeats are disabled with `0m`, normal runs also omit `HEARTBEAT.md` from bootstrap context so the model does not see heartbeat-only instructions.
67
68
- Active hours (`heartbeat.activeHours`) are checked in the configured timezone. Outside the window, heartbeats are skipped until the next tick inside the window.
69
+
- Heartbeats automatically defer while cron work is active or queued. Set `heartbeat.skipWhenBusy: true` to defer on extra busy lanes (subagent or nested command work) as well; this is useful for local Ollama and other constrained single-runtime hosts.
68
70
69
71
## What the heartbeat prompt is for
70
72
@@ -98,6 +100,7 @@ Outside heartbeats, stray `HEARTBEAT_OK` at the start/end of a message is stripp
98
100
includeReasoning:false, // default: false (deliver separate Reasoning: message when available)
99
101
lightContext:false, // default: false; true keeps only HEARTBEAT.md from workspace bootstrap files
100
102
isolatedSession:false, // default: false; true runs each heartbeat in a fresh session (no conversation history)
103
+
skipWhenBusy:false, // default: false; true also waits for subagent/nested lanes
101
104
target:"last", // default: none | options: last | none | <channel id> (core or plugin, e.g. "bluebubbles")
When true, each heartbeat runs in a fresh session with no prior conversation history. Uses the same isolation pattern as cron `sessionTarget: "isolated"`. Dramatically reduces per-heartbeat token cost. Combine with `lightContext: true` for maximum savings. Delivery routing still uses the main session context.
When true, heartbeat runs defer on extra busy lanes: subagent or nested command work. Cron lanes always defer heartbeats, even without this flag, so local-model hosts do not run cron and heartbeat prompts at the same time.
238
+
</ParamField>
233
239
<ParamFieldpath="session"type="string">
234
240
Optional session key for heartbeat runs.
235
241
@@ -287,7 +293,8 @@ Use `accountId` to target a specific account on multi-account channels like Tele
287
293
- `session` only affects the run context; delivery is controlled by `target` and `to`.
288
294
- To deliver to a specific channel/recipient, set `target` + `to`. With `target: "last"`, delivery uses the last external channel for that session.
289
295
- Heartbeat deliveries allow direct/DM targets by default. Set `directPolicy: "block"` to suppress direct-target sends while still running the heartbeat turn.
290
-
- If the main queue is busy, the heartbeat is skipped and retried later.
296
+
- If the main queue, target session lane, cron lane, or an active cron job is busy, the heartbeat is skipped and retried later.
297
+
- If `skipWhenBusy: true`, subagent and nested lanes also defer heartbeat runs.
291
298
- If `target` resolves to no external destination, the run still happens but no outbound message is sent.
help: "Per-agent maximum time in seconds allowed for a heartbeat agent turn before it is aborted. Leave unset to inherit the merged heartbeat/default agent timeout.",
28420
28442
tags: ["performance", "automation"],
28421
28443
},
28444
+
"agents.list[].heartbeat.skipWhenBusy": {
28445
+
label: "Agent Heartbeat Skip When Busy",
28446
+
help: "Per-agent override that defers heartbeat turns on extra busy lanes: subagent or nested command work. Cron lanes always defer heartbeat turns.",
28447
+
tags: ["automation"],
28448
+
},
28422
28449
"agents.list[].sandbox.browser.network": {
28423
28450
label: "Agent Sandbox Browser Network",
28424
28451
help: "Per-agent override for sandbox browser Docker network.",
"Maximum time in seconds allowed for a heartbeat agent turn before it is aborted. Leave unset to use agents.defaults.timeoutSeconds.",
257
257
"agents.list[].heartbeat.timeoutSeconds":
258
258
"Per-agent maximum time in seconds allowed for a heartbeat agent turn before it is aborted. Leave unset to inherit the merged heartbeat/default agent timeout.",
259
+
"agents.defaults.heartbeat.skipWhenBusy":
260
+
"When true, defer heartbeat turns on extra busy lanes: subagent or nested command work. Cron lanes always defer heartbeat turns.",
261
+
"agents.list[].heartbeat.skipWhenBusy":
262
+
"Per-agent override that defers heartbeat turns on extra busy lanes: subagent or nested command work. Cron lanes always defer heartbeat turns.",
259
263
browser:
260
264
"Browser runtime controls for local or remote CDP attachment, profile routing, and screenshot/snapshot behavior. Keep defaults unless your automation workflow requires custom browser transport settings.",
0 commit comments