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
Add trigger metadata to agent sessions (values: user, cron, subagent, hook) and exclude trigger: cron sessions from memory-core Dreaming ingestion by default, with opt-in override per cron job.
Problem to solve
memory-core's Dreaming pipeline ingests cron-triggered sessions (heartbeat pings, scheduled automation, email-watch jobs) into __dreaming_sessions__ identically to user-initiated conversations. On any deployment that uses openclaw cron non-trivially, this starves the REM and deep-promotion phases of real signal.
Concrete example from a fresh memory-core install, day 1, single-agent personal Donnie on Discord (OpenClaw 2026.4.14):
REM themes (confidence 1.00):
- heartbeat-ok 60 memories
- user 45
- assistant 44
- heartbeat.md 30
- home/hyamie 30
- openclaw/workspace/heartbeat.md 30
- read 30
Deep phase: zero promotions. "No strong candidate truths surfaced."
The corpus file memory/.dreams/session-corpus/2026-04-13.txt contains 60 lines of:
User: Read HEARTBEAT.md if it exists [...] reply HEARTBEAT_OK.
Assistant: HEARTBEAT_OK
Actual signal (family context, golf communications, project work) scores identically at confidence 0.58 per line, and gets buried. The deep phase's promotion gates (minScore 0.8 / minRecallCount 3 / minUniqueQueries 3) can never fire on real content because it's outweighed by cron repetition.
This is closely related to #63921 (transcript wrapper noise), but that issue's proposed fixes (stopword filter, wrapper stripping, role-token normalization) operate at the token level and don't address cron-content pollution. Heartbeat content is valid English prose that repeats — no stopword list can remove it without also removing legitimate user content.
Every session gets a trigger field set at creation, written to session state and available to plugins:
trigger value
When set
user
Default — DM, channel mention, direct agent invocation
cron
Originated from openclaw cron scheduled job
subagent
Spawned by parent agent via subagent delegation
hook
Gateway lifecycle hook invocation
The [cron:<id> <name>] preamble already emitted by openclaw cron is sufficient signal — formalize it as session metadata at session open time rather than as in-band text.
2. memory-core Dreaming opt-out for non-user triggers (new default)
memory-core config gains a dreaming.ingest.triggers array. Default:
Non-matching sessions are skipped during __dreaming_sessions__ enumeration. Operators who want a cron workload reflected on explicitly can set ["user", "cron"].
3. Per-cron-job override (fine-grained)
openclaw cron job definition gains dreamingIngest: boolean (default false if not set, same outcome as trigger filter). Lets someone whitelist a specific high-signal cron (e.g. a daily journaling prompt) without opening the floodgates.
4. Backward compatibility
Existing sessions without a trigger field default to user — matches current behavior, zero regression for users who don't run cron jobs.
Entropy/novelty gating (SimpleMem arxiv 2601.02553, entity novelty + semantic divergence threshold τ=0.35): principled but substantially more implementation work, requires embedding every exchange pre-ingestion, and gives fuzzy results when the right answer is a hard "skip." Good candidate for a Phase 2 layer on top of trigger filtering.
Min-token exchange gate: simple, catches heartbeat (4-6 tokens) but not longer cron runs like email-watch playbook invocations. Useful belt-and-suspenders but not sufficient alone.
Per-session importance weighting pre-TF-IDF (LangMem pattern — multiply phrase frequencies by a session weight before REM theme extraction): equivalent outcome to trigger filtering but more invasive change to the theme extractor. Trigger-based ingestion gating is simpler and affects fewer components.
Do nothing, rely on volume: wait for real user conversation to eventually outweigh cron noise. Doesn't work — cron runs on a fixed cadence, so the ratio stays roughly constant as real usage grows.
Impact
Affected: Anyone using openclaw cron with memory-core Dreaming enabled. As memory-core becomes the default memory plugin and cron gets used for automation (heartbeats, scheduled email checks, daily journaling prompts, periodic agent-driven tasks), this affects a growing share of users.
Severity: High for users who rely on Dreaming-promoted long-term memory. On my setup, deep phase produced zero promotions in week 1 despite real conversational content being present, because cron sessions dominated the corpus. Effectively breaks Dreaming's value proposition on any non-trivial cron deployment.
Frequency: Every Dreaming run. Daily for most users (default cron 0 3 * * *).
Consequence: Promoted "lasting truths" become noise or nothing. Operators lose trust in memory-core's consolidation layer and either disable Dreaming, disable cron automation, or manually prune session corpus files — all of which defeat the point.
Redis agent-memory-server (github.com/redis/agent-memory-server) — uses source_type / session_id / agent_id metadata at write time, consolidation pipeline filters by source_type.
Letta/MemGPT — memory architecture separates system-originated from user-originated content at the block level before archival.
LangMem — per-session importance weights applied before theme extraction.
SimpleMem (arxiv 2601.02553) — entity-novelty + semantic-divergence threshold gate, cites "phatic chit-chat and redundant confirmations" as the canonical discard case.
Local evidence files (available on request):
memory/.dreams/session-corpus/2026-04-{13,14,15}.txt — 89 lines total, 60+ from heartbeat cron
memory/.dreams/phase-signals.json — shows every heartbeat line counted equally with every real-conversation line
memory/2026-04-15.md — REM output above, Axis B themes dominating
Additional information
Willing to contribute a draft PR if maintainers confirm direction. Two candidate scopes:
Minimal (recommended first): add trigger metadata field to session creation, add dreaming.ingest.triggers config to memory-core, filter at ingestion.
Full: also add dreamingIngest: bool to openclaw cron job schema and admin UI.
Cross-link: #63921 covers the orthogonal Axis A (transcript wrapper noise). Adding a comment there with this setup's repro data to confirm regression persists in 2026.4.14.
Happy to also seed a phrase blocklist for the cron preambles (HEARTBEAT_OK, HEARTBEAT.md, NO_REPLY, [cron:...]) as a lower-cost Phase 0 fix while trigger metadata lands — these are safe to stopword because they're literal protocol tokens, not semantic content.
Summary
Add
triggermetadata to agent sessions (values:user,cron,subagent,hook) and excludetrigger: cronsessions from memory-core Dreaming ingestion by default, with opt-in override per cron job.Problem to solve
memory-core's Dreaming pipeline ingests cron-triggered sessions (heartbeat pings, scheduled automation, email-watch jobs) into
__dreaming_sessions__identically to user-initiated conversations. On any deployment that usesopenclaw cronnon-trivially, this starves the REM and deep-promotion phases of real signal.Concrete example from a fresh memory-core install, day 1, single-agent personal Donnie on Discord (OpenClaw 2026.4.14):
The corpus file
memory/.dreams/session-corpus/2026-04-13.txtcontains 60 lines of:Actual signal (family context, golf communications, project work) scores identically at confidence 0.58 per line, and gets buried. The deep phase's promotion gates (
minScore 0.8 / minRecallCount 3 / minUniqueQueries 3) can never fire on real content because it's outweighed by cron repetition.This is closely related to #63921 (transcript wrapper noise), but that issue's proposed fixes (stopword filter, wrapper stripping, role-token normalization) operate at the token level and don't address cron-content pollution. Heartbeat content is valid English prose that repeats — no stopword list can remove it without also removing legitimate user content.
Related: #63921 #59095 #29442.
Proposed solution
1. Session-level trigger metadata (new)
Every session gets a
triggerfield set at creation, written to session state and available to plugins:usercronopenclaw cronscheduled jobsubagenthookThe
[cron:<id> <name>]preamble already emitted byopenclaw cronis sufficient signal — formalize it as session metadata at session open time rather than as in-band text.2. memory-core Dreaming opt-out for non-user triggers (new default)
memory-core config gains a
dreaming.ingest.triggersarray. Default:{ "memory-core": { "dreaming": { "ingest": { "triggers": ["user"] } } } }Non-matching sessions are skipped during
__dreaming_sessions__enumeration. Operators who want a cron workload reflected on explicitly can set["user", "cron"].3. Per-cron-job override (fine-grained)
openclaw cronjob definition gainsdreamingIngest: boolean(defaultfalseif not set, same outcome as trigger filter). Lets someone whitelist a specific high-signal cron (e.g. a daily journaling prompt) without opening the floodgates.4. Backward compatibility
Existing sessions without a
triggerfield default touser— matches current behavior, zero regression for users who don't run cron jobs.Alternatives considered
Token/phrase blocklist only (what [Bug]: Dreaming/REM surfaces raw session-corpus metadata (untrusted, user, assistant) instead of meaningful reflections #63921 proposes): insufficient for cron content because heartbeat messages are valid English, not structural boilerplate. Scales poorly — every new cron job needs manual phrase additions.
Entropy/novelty gating (SimpleMem arxiv 2601.02553, entity novelty + semantic divergence threshold τ=0.35): principled but substantially more implementation work, requires embedding every exchange pre-ingestion, and gives fuzzy results when the right answer is a hard "skip." Good candidate for a Phase 2 layer on top of trigger filtering.
Min-token exchange gate: simple, catches heartbeat (4-6 tokens) but not longer cron runs like email-watch playbook invocations. Useful belt-and-suspenders but not sufficient alone.
Per-session importance weighting pre-TF-IDF (LangMem pattern — multiply phrase frequencies by a session weight before REM theme extraction): equivalent outcome to trigger filtering but more invasive change to the theme extractor. Trigger-based ingestion gating is simpler and affects fewer components.
Do nothing, rely on volume: wait for real user conversation to eventually outweigh cron noise. Doesn't work — cron runs on a fixed cadence, so the ratio stays roughly constant as real usage grows.
Impact
Affected: Anyone using
openclaw cronwith memory-core Dreaming enabled. As memory-core becomes the default memory plugin and cron gets used for automation (heartbeats, scheduled email checks, daily journaling prompts, periodic agent-driven tasks), this affects a growing share of users.Severity: High for users who rely on Dreaming-promoted long-term memory. On my setup, deep phase produced zero promotions in week 1 despite real conversational content being present, because cron sessions dominated the corpus. Effectively breaks Dreaming's value proposition on any non-trivial cron deployment.
Frequency: Every Dreaming run. Daily for most users (default cron
0 3 * * *).Consequence: Promoted "lasting truths" become noise or nothing. Operators lose trust in memory-core's consolidation layer and either disable Dreaming, disable cron automation, or manually prune session corpus files — all of which defeat the point.
Evidence/examples
Prior art:
filtering.ts(PR feat(openclaw): improve extraction quality with noise filtering, deduplication, and better instructions mem0ai/mem0#4302) is a message-level blocklist; author concluded it's insufficient alone and that source-level gating is the real fix.source_type/session_id/agent_idmetadata at write time, consolidation pipeline filters bysource_type.Local evidence files (available on request):
memory/.dreams/session-corpus/2026-04-{13,14,15}.txt— 89 lines total, 60+ from heartbeat cronmemory/.dreams/phase-signals.json— shows every heartbeat line counted equally with every real-conversation linememory/2026-04-15.md— REM output above, Axis B themes dominatingAdditional information
Willing to contribute a draft PR if maintainers confirm direction. Two candidate scopes:
triggermetadata field to session creation, adddreaming.ingest.triggersconfig to memory-core, filter at ingestion.dreamingIngest: booltoopenclaw cronjob schema and admin UI.Cross-link: #63921 covers the orthogonal Axis A (transcript wrapper noise). Adding a comment there with this setup's repro data to confirm regression persists in 2026.4.14.
Happy to also seed a phrase blocklist for the cron preambles (
HEARTBEAT_OK,HEARTBEAT.md,NO_REPLY,[cron:...]) as a lower-cost Phase 0 fix while trigger metadata lands — these are safe to stopword because they're literal protocol tokens, not semantic content.