Problem
The SessionMemoryObserverActor only triggers memory distillation on ReceiveTimeout — 90 seconds of complete silence. For busy sessions with long tool loops (10+ minutes of continuous activity), memories don't form until the session goes fully idle. This makes memory formation very slow for active sessions and painful during testing.
Current behavior
- Observer accumulates transcript lines as
SendUserMessage, SessionOutput, etc. arrive
- Sets
_hasNewContent = true when substantive content is received
- Waits for
ReceiveTimeout (default 90s of no messages) to trigger distillation
- No other trigger path exists (the
DistillMemories explicit request is wired but not sent during passivation)
A session doing a 25-iteration tool loop at 30s/call runs for ~12 minutes with no distillation. Memories only form after the user stops talking and 90 seconds pass.
Proposed change
Add a turn-based trigger that distills every N completed turns, regardless of idle state. For example, after every 3 TurnCompleted events, trigger distillation of the accumulated transcript.
Tradeoffs to consider
Waiting longer (current approach):
- More context available → potentially higher-quality distillation (more connections, better dedup)
- Fewer LLM distillation calls → lower cost
- Natural batching of related turns
Distilling more frequently (proposed):
- Memories form during active sessions, not just after
- Smaller transcripts per distillation → faster/cheaper per call, but more calls total
- Risk of fragmented memories that a single larger distillation would have merged
- Better for testing and interactive feedback loops
Suggested approach
- Make the turn interval configurable:
MemoryObserverDistillEveryNTurns (default 3-5)
- Keep the idle timeout as a fallback for partial-turn content
- The turn-based trigger and idle trigger should both check
_hasNewContent to avoid empty distillations
Relevant code
src/Netclaw.Actors/Sessions/SessionMemoryObserverActor.cs — observer logic, TriggerDistillation(), ReceiveTimeout handler
src/Netclaw.Configuration/SessionConfig.cs — MemoryObserverIdleSeconds (default 90)
Related
Problem
The
SessionMemoryObserverActoronly triggers memory distillation onReceiveTimeout— 90 seconds of complete silence. For busy sessions with long tool loops (10+ minutes of continuous activity), memories don't form until the session goes fully idle. This makes memory formation very slow for active sessions and painful during testing.Current behavior
SendUserMessage,SessionOutput, etc. arrive_hasNewContent = truewhen substantive content is receivedReceiveTimeout(default 90s of no messages) to trigger distillationDistillMemoriesexplicit request is wired but not sent during passivation)A session doing a 25-iteration tool loop at 30s/call runs for ~12 minutes with no distillation. Memories only form after the user stops talking and 90 seconds pass.
Proposed change
Add a turn-based trigger that distills every N completed turns, regardless of idle state. For example, after every 3
TurnCompletedevents, trigger distillation of the accumulated transcript.Tradeoffs to consider
Waiting longer (current approach):
Distilling more frequently (proposed):
Suggested approach
MemoryObserverDistillEveryNTurns(default 3-5)_hasNewContentto avoid empty distillationsRelevant code
src/Netclaw.Actors/Sessions/SessionMemoryObserverActor.cs— observer logic,TriggerDistillation(),ReceiveTimeouthandlersrc/Netclaw.Configuration/SessionConfig.cs—MemoryObserverIdleSeconds(default 90)Related