#10644: feat: add runDuringHeartbeats option for memory flush (AI Assisted)
stale
size: M
Cluster:
Memory Management Enhancements
### 🤖 AI Contribution Disclosure
**AI-Assisted:** Yes - This PR was developed collaboratively with **Opifex Primo**, a Clawdbot/OpenClaw agent instance running Claude Opus 4.6.
**Degree of Testing:** ✅ **Fully tested** - All 16 tests pass including 4 new tests specifically for this feature. Tests run via `pnpm vitest run`. The changes were also tested using **Opifex Primo** locally.
**Understanding Confirmation:**
This PR adds a new boolean config option `runDuringHeartbeats` to the `compaction.memoryFlush` settings. The core logic change is in `agent-runner-memory.ts` where the condition `!params.isHeartbeat` (which unconditionally skipped memory flush during heartbeats) is replaced with `(!params.isHeartbeat || memoryFlushSettings.runDuringHeartbeats)`, allowing the flush to run during heartbeats when the user explicitly enables it. The settings resolver in `memory-flush.ts` reads the new config value (defaulting to `false`), and the schema/types are updated to validate and type the new option.
**Session Context:** This fix originated from debugging why memory was lost during overnight compaction. Investigation revealed the `!params.isHeartbeat` check in `agent-runner-memory.ts` was causing memory flush to be skipped when compaction occurred during heartbeat polls. The human (Trip Phillips) and AI collaboratively diagnosed the issue, designed the solution, implemented the code, wrote tests, and verified all tests pass.
---
### Problem
Memory flush (`compaction.memoryFlush.enabled: true`) is designed to save important context to disk before compaction occurs. However, the current implementation **explicitly skips memory flush during heartbeat polls**:
```typescript
const shouldFlushMemory =
memoryFlushSettings &&
memoryFlushWritable &&
!params.isHeartbeat && // <-- Always skipped during heartbeats
```
This creates a gap: if a session reaches the compaction threshold during a heartbeat, the context is compacted without the agent getting a chance to persist memories. This results in complete context loss with no opportunity for recovery.
Real-world scenario: An agent running overnight with periodic heartbeats accumulates context. When auto-compaction triggers during a heartbeat, all working context (active tasks, decisions, important state) is lost because the memory flush was skipped.
### Solution
Add a new config option compaction.memoryFlush.runDuringHeartbeats (default: false) that allows users to opt-in to running memory flush even during heartbeat polls.
Config example:
```json
{
"agents": {
"defaults": {
"compaction": {
"memoryFlush": {
"enabled": true,
"runDuringHeartbeats": true
}
}
}
}
}
```
The default is false to preserve existing behavior and avoid unexpected latency/cost during heartbeats for users who haven't opted in.
### Changes
Schema & Types (2 files)
| File | Change |
| --------------------------------------- | -------------------------------------------- |
| src/config/zod-schema.agent-defaults.ts | Add runDuringHeartbeats to schema |
| src/config/types.agent-defaults.ts | Add to AgentCompactionMemoryFlushConfig type |
Implementation (2 files)
| File | Change |
| ------------------------------------------- | ---------------------------------------------------------------- |
| src/auto-reply/reply/memory-flush.ts | Add to MemoryFlushSettings type and resolveMemoryFlushSettings() |
| src/auto-reply/reply/agent-runner-memory.ts | Update condition to respect new setting |
### Tests (3 files)
| File | Change |
| -------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
| src/auto-reply/reply/memory-flush.test.ts | 2 new unit tests |
| src/config/config.compaction-settings.test.ts | Config preservation test |
| src/auto-reply/reply/agent-runner.memory-flush.runreplyagent-memory-flush.runs-during-heartbeat-when-enabled.test.ts | New file - 2 integration tests |
Test Results
✓ defaults runDuringHeartbeats to false
✓ respects runDuringHeartbeats config
✓ skips memory flush during heartbeat by default
✓ runs memory flush during heartbeat when runDuringHeartbeats is true
Test Files 3 passed (3)
Tests 16 passed (16)
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
- Adds `compaction.memoryFlush.runDuringHeartbeats` (default `false`) to agent defaults config schema/types.
- Threads the new setting through `resolveMemoryFlushSettings()` and gates memory flush execution in `runMemoryFlushIfNeeded()` so it can optionally run during heartbeat polls.
- Extends unit/integration coverage to assert the default behavior (skip on heartbeat) and the opt-in behavior (flush runs on heartbeat and persists metadata).
<h3>Confidence Score: 4/5</h3>
- This PR is safe to merge after fixing a small documentation typo.
- The change is narrowly scoped (a config-controlled conditional), schema/types are updated consistently, and tests cover default + opt-in behavior. Only a JSDoc typo was found that should be corrected before merge.
- src/config/types.agent-defaults.ts
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#8919: Pr/memory flush improvements
by shortbus · 2026-02-04
84.6%
#14021: feat(compaction): optional memory flush before manual /compact
by phenomenoner · 2026-02-11
83.6%
#15945: fix(memory-flush): only write memoryFlushCompactionCount when compa...
by aldoeliacim · 2026-02-14
82.3%
#20713: fix(compaction): trigger memory flush after missed compaction cycles
by zerone0x · 2026-02-19
81.1%
#11089: feat(compaction): support customInstructions and model override for...
by p697 · 2026-02-07
80.6%
#14128: config: add readable durable/off mode for pre-compaction memory flush
by vpesh · 2026-02-11
80.3%
#4999: fix(memory-flush): use contextTokens instead of totalTokens for thr...
by Farfadium · 2026-01-30
78.9%
#12760: fix(memory-flush): fire on every compaction cycle instead of skippi...
by lailoo · 2026-02-09
78.9%
#19329: feat: add per-agent compaction and context pruning overrides
by curtismercier · 2026-02-17
78.4%
#9012: fix(memory): resilient flush for large sessions [AI-assisted]
by cheenu1092-oss · 2026-02-04
77.9%