Page:
Data Flow 07 Sleep Mode Transitions
Pages
Architecture Commands and API
Architecture Context System
Architecture Core Engine
Architecture Event Sourcing
Architecture Generative Reflection
Architecture Helpers
Architecture Journal System
Architecture LLM Interaction
Architecture LLM Providers
Architecture Logging
Architecture Memory and Sleep
Architecture Overview
Architecture Persona Protection
Architecture Prompt System
Architecture RAG Implementation
Architecture Resilience System
Architecture Safety System
Architecture Self Management
Architecture Sub Agent Delegation
Architecture Task Assessment
Architecture Token Management
Architecture Tool System
Configuration Reference
Context and Memory Flow Analysis
Data Flow 01 Context Compaction
Data Flow 02 ReAct Loop
Data Flow 03 Memory Consolidation
Data Flow 04 Message Classification
Data Flow 05 Entity Profile System
Data Flow 06 Tool Execution
Data Flow 07 Sleep Mode Transitions
Data Flow 08 LLM Provider Interaction
Data Flow 09 Self Management Operations
Home
LLM Decision Patterns
Research Foundations
User Guide 00 Index
User Guide 01 Getting Started
User Guide 02 Configuration and Customization
User Guide 03 Advanced Capabilities
User Guide 04 Troubleshooting
No results
2
Data Flow 07 Sleep Mode Transitions
Blightbow edited this page 2025-12-09 04:34:35 -05:00
Data Flow 07: Sleep Mode Transitions
Engineering documentation series - Data flows in the AI Assistant system
Overview
This document describes the data flows for sleep mode transitions, including:
- Agent-initiated sleep (go_to_sleep tool)
- Scheduled sleep (time-based automation)
- Wake conditions and transitions
- Phase transitions within sleep mode
Related Documents
| Document | Description |
|---|---|
| Architecture-Memory-and-Sleep | Sleep architecture overview |
| Data-Flow-03-Memory-Consolidation | Memory operations during sleep |
| Data-Flow-01-Context-Compaction | Context compaction during dreaming |
1. Agent-Initiated Sleep (go_to_sleep)
The assistant can choose when to sleep using the go_to_sleep tool.
Trigger Point
LLM response → tool_call(go_to_sleep, {...})
└─> tools/sleep.py:GoToSleepTool.execute()
Safeguards
Before sleep can be entered, three safeguards are checked:
┌─────────────────────────────────────────────────────────────────────────────┐
│ SAFEGUARD 1: Not Already Sleeping │
│ ─────────────────────────────────────────────────────────────────────────── │
│ Check: operating_mode != "sleep" │
│ └─> If sleeping: return error "Already in sleep mode" │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ SAFEGUARD 2: Cooldown Period │
│ ─────────────────────────────────────────────────────────────────────────── │
│ Check: now >= sleep_cooldown_until │
│ └─> If in cooldown: return error with minutes remaining │
│ │
│ Default cooldown: 60 minutes after waking │
│ Purpose: Prevent rapid sleep/wake cycling │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ SAFEGUARD 3: Minimum Activity │
│ ─────────────────────────────────────────────────────────────────────────── │
│ Check: activity_since_wake >= min_activity_before_sleep │
│ └─> If insufficient: return error with activity/required counts │
│ │
│ Default: 10 interactions required before sleep is allowed │
│ Purpose: Ensure assistant is productive before resting │
└─────────────────────────────────────────────────────────────────────────────┘
Data Flow
┌─────────────────────────────────────────────────────────────────────────────┐
│ GO_TO_SLEEP TOOL EXECUTION │
│ tools/sleep.py:GoToSleepTool.execute() │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ PARAMETER EXTRACTION │
│ ─────────────────────────────────────────────────────────────────────────── │
│ Parameters: │
│ duration_hours: 1-24 (default: 4) │
│ depth: "light" | "deep" (default: "light") │
│ reason: required string (audit trail) │
│ │
│ Light sleep: wakes on urgent events (direct messages) │
│ Deep sleep: only wakes when timer expires │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ CALCULATE CONSOLIDATION WORKLOAD │
│ ─────────────────────────────────────────────────────────────────────────── │
│ journal = character.db.journal │
│ consolidated_ids = journal["consolidated_entry_ids"] │
│ │
│ unconsolidated_count = count entries where: │
│ - id NOT in consolidated_ids │
│ - content does NOT start with "[SYNTHESIS]" │
│ │
│ This determines how long "compacting" phase will take │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ SET SLEEP STATE │
│ ─────────────────────────────────────────────────────────────────────────── │
│ script.db.scheduled_wake_time = now + duration_hours │
│ script.db.sleep_depth = depth │
│ script.db.sleep_phase = "compacting" │
│ script.db.sleep_initiated_by = "tool" │
│ script.db.sleep_reason = reason │
│ script.db.consolidation_progress = { │
│ started_at: now, │
│ total_entries: unconsolidated_count, │
│ processed_entries: 0, │
│ completed: unconsolidated_count == 0 │
│ } │
│ │
│ If scheduled sleep enabled: │
│ script.db._schedule_was_enabled = True │
│ schedule["enabled"] = False # Temporarily disable │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ TRANSITION TO SLEEP MODE │
│ operating_mode.py:transition_mode(script, "sleep", reason) │
│ ─────────────────────────────────────────────────────────────────────────── │
│ 1. Calculate tick rates: │
│ - old_rate = tick_rate (e.g., 5 seconds) │
│ - new_rate = sleep_schedule["tick_rate_sleep"] (e.g., 60 seconds) │
│ │
│ 2. Update TICKER_HANDLER: │
│ - TICKER_HANDLER.remove(interval=old_rate, ...) │
│ - TICKER_HANDLER.add(interval=new_rate, ...) │
│ │
│ 3. Update state: │
│ - script.db.operating_mode = "sleep" │
│ - script.db.mode_transition_reason = reason │
│ - script.db.last_mode_transition = now │
│ │
│ 4. Notify character: "😴 Entering sleep mode: {reason}" │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ PHASE SHORTCUT │
│ ─────────────────────────────────────────────────────────────────────────── │
│ If unconsolidated_count == 0: │
│ script.db.sleep_phase = "dreaming" # Skip compacting │
│ │
│ No journal entries to consolidate = straight to dreaming │
└─────────────────────────────────────────────────────────────────────────────┘
2. Sleep Phases
Sleep mode has two phases with different capabilities:
┌────────────────────────────────────────────────────────────────────────────────────────┐
│ SLEEP MODE │
├────────────────────────────────────┬───────────────────────────────────────────────────┤
│ COMPACTING │ DREAMING │
├────────────────────────────────────┼───────────────────────────────────────────────────┤
│ • Memory consolidation active │ • Consolidation complete │
│ • Importance scoring │ • Memory link generation (A-MEM) │
│ • Journal → Mem0 transfer │ • Entity consolidation (O-Mem) │
│ • Wake deferred if triggered │ • Generative reflection │
│ │ • Episodic pruning │
│ │ • Context compaction │
├────────────────────────────────────┴───────────────────────────────────────────────────┤
│ Transition: compacting → dreaming when consolidation_progress.completed = True │
└────────────────────────────────────────────────────────────────────────────────────────┘
Phase Transition Flow
┌─────────────────────────────────────────────────────────────────────────────┐
│ SLEEP TICK (compacting phase) │
│ rag_memory.py:run_sleep_tick() │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ COMPACTING OPERATIONS │
│ ─────────────────────────────────────────────────────────────────────────── │
│ 1. score_pending_entries() │
│ - Batch LLM scoring of journal entries │
│ - Upgrades heuristic scores to LLM scores │
│ │
│ 2. run_sleep_consolidation() │
│ - Journal entries → Mem0 semantic memory │
│ - Updates consolidated_entry_ids │
│ - Returns {completed: bool, consolidated: int} │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ CHECK COMPLETION │
│ ─────────────────────────────────────────────────────────────────────────── │
│ if consolidation_result["completed"]: │
│ script.db.sleep_phase = "dreaming" │
│ log: "Sleep phase transition: compacting -> dreaming" │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼ (subsequent sleep ticks)
┌─────────────────────────────────────────────────────────────────────────────┐
│ DREAMING OPERATIONS (10+ tasks per tick) │
│ ─────────────────────────────────────────────────────────────────────────── │
│ 1. run_dreaming_tick() - A-MEM style memory link generation │
│ 2. prune_orphaned_memory_links() - Clean up dead references │
│ 3. run_entity_consolidation_batch() - O-Mem Pf→Pa synthesis │
│ 4. run_reflection() (if triggered) - Generative Agents insights │
│ 5. prune_low_importance_entries() - Episodic memory cleanup │
│ 6. clear_stale_conversations() - Working memory cleanup │
│ 7. run_pre_compaction_extraction() - Journal critical facts │
│ 8. compact_conversation_history() - Context summarization │
└─────────────────────────────────────────────────────────────────────────────┘
3. Wake Conditions
Check Points
Wake conditions are checked after each sleep tick:
assistant_script.py:at_tick() lines 695-713
└─> operating_mode.py:check_wake_conditions(script)
Wake Decision Flow
┌─────────────────────────────────────────────────────────────────────────────┐
│ check_wake_conditions(script) │
│ operating_mode.py lines 301-357 │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ CHECK 1: Scheduled Wake Time │
│ ─────────────────────────────────────────────────────────────────────────── │
│ if scheduled_wake_time is set: │
│ wake_time = parse_isoformat(scheduled_wake_time) │
│ if now >= wake_time: │
│ reason = "Scheduled wake time reached" │
│ if phase == "compacting": │
│ return (True, reason, deferred=True) # Defer wake │
│ else: │
│ return (True, reason, deferred=False) # Wake now │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ CHECK 2: Urgent Events (light sleep only) │
│ ─────────────────────────────────────────────────────────────────────────── │
│ if sleep_depth == "light": │
│ for event in pending_events: │
│ if is_urgent_event(event): │
│ reason = f"Urgent event: {event_type}" │
│ if phase == "compacting": │
│ return (True, reason, deferred=True) │
│ else: │
│ return (True, reason, deferred=False) │
│ │
│ Urgent events: │
│ - event_type == "direct_message" │
│ - metadata.urgent == True │
│ - metadata.priority >= 8 │
│ - classification_reason in ("direct_addressing", "direct_message") │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ NO WAKE CONDITION MET │
│ ─────────────────────────────────────────────────────────────────────────── │
│ return (False, None, False) │
│ Continue sleeping... │
└─────────────────────────────────────────────────────────────────────────────┘
Deferred Wake
When wake is deferred (during compacting phase):
┌─────────────────────────────────────────────────────────────────────────────┐
│ DEFERRED WAKE HANDLING │
│ assistant_script.py lines 701-712 │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ should_wake, wake_reason, deferred = check_wake_conditions(script) │
│ │
│ if should_wake: │
│ if deferred: │
│ # Wake after consolidation completes (next tick in dreaming) │
│ log: "Wake deferred (compacting): {wake_reason}" │
│ # Continue sleep tick - wake happens after phase transition │
│ else: │
│ # Wake immediately (dreaming phase) │
│ success, msg = perform_wake_transition(script, wake_reason) │
└─────────────────────────────────────────────────────────────────────────────┘
4. Wake Transition
perform_wake_transition()
┌─────────────────────────────────────────────────────────────────────────────┐
│ perform_wake_transition(script, reason) │
│ operating_mode.py lines 360-424 │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ SET COOLDOWN │
│ ─────────────────────────────────────────────────────────────────────────── │
│ cooldown_minutes = script.db.sleep_cooldown_minutes or 60 │
│ cooldown_until = now + timedelta(minutes=cooldown_minutes) │
│ script.db.sleep_cooldown_until = cooldown_until.isoformat() │
│ │
│ Purpose: Prevent immediate re-entry to sleep mode │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ RESET ACTIVITY COUNTER │
│ ─────────────────────────────────────────────────────────────────────────── │
│ script.db.activity_since_wake = 0 │
│ │
│ Resets the counter that gates go_to_sleep availability │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ CLEAR SLEEP STATE │
│ ─────────────────────────────────────────────────────────────────────────── │
│ script.db.scheduled_wake_time = None │
│ script.db.sleep_depth = None │
│ script.db.sleep_phase = None │
│ script.db.sleep_initiated_by = None │
│ script.db.sleep_reason = None │
│ script.db.consolidation_progress = { │
│ started_at: None, total_entries: 0, │
│ processed_entries: 0, completed: False │
│ } │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ RESTORE SCHEDULED SLEEP │
│ ─────────────────────────────────────────────────────────────────────────── │
│ if script.db._schedule_was_enabled: │
│ schedule = script.db.sleep_schedule │
│ schedule["enabled"] = True │
│ script.db._schedule_was_enabled = False │
│ log: "Restored scheduled sleep after tool-initiated wake" │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ TRANSITION TO AWAKE MODE │
│ operating_mode.py:transition_mode(script, "awake", reason) │
│ ─────────────────────────────────────────────────────────────────────────── │
│ 1. Update TICKER_HANDLER: │
│ - old_rate = sleep_schedule["tick_rate_sleep"] (e.g., 60s) │
│ - new_rate = tick_rate (e.g., 5s) │
│ │
│ 2. Update state: │
│ - script.db.operating_mode = "awake" │
│ - script.db.mode_transition_reason = reason │
│ - script.db.last_mode_transition = now │
│ │
│ 3. Notify character: "👁 Entering awake mode: {reason}" │
└─────────────────────────────────────────────────────────────────────────────┘
5. Scheduled Sleep
Time-based automatic transitions (optional feature).
Configuration
script.db.sleep_schedule = {
"enabled": True,
"sleep_start_hour": 2, # 2:00 AM
"sleep_duration_hours": 4, # Until 6:00 AM
"tick_rate_sleep": 60, # 60 seconds between sleep ticks
"min_awake_ticks": 10, # Minimum ticks before auto-sleep
}
Check Flow
check_sleep_schedule(script)
└─> Called from at_tick() periodically
└─> Checks current_hour vs sleep window
└─> Returns (should_transition, target_mode, reason)
7. Configuration Reference
| Attribute | Default | Description |
|---|---|---|
operating_mode |
"awake" |
Current mode: "awake" or "sleep" |
sleep_phase |
None |
"compacting" or "dreaming" |
sleep_depth |
None |
"light" or "deep" |
scheduled_wake_time |
None |
ISO timestamp for scheduled wake |
sleep_cooldown_until |
None |
ISO timestamp, blocks go_to_sleep |
sleep_cooldown_minutes |
60 |
Cooldown duration after waking |
activity_since_wake |
0 |
Interactions since last wake |
min_activity_before_sleep |
10 |
Required before go_to_sleep allowed |
sleep_schedule.enabled |
False |
Enable time-based auto-sleep |
sleep_schedule.tick_rate_sleep |
60 |
Tick interval during sleep (seconds) |
8. Key Files
| File | Relevant Lines | Purpose |
|---|---|---|
tools/sleep.py |
25-219 | GoToSleepTool |
tools/sleep.py |
222-325 | WakeUpTool |
tools/sleep.py |
328-471 | WaitTool |
operating_mode.py |
121-193 | transition_mode() |
operating_mode.py |
301-357 | check_wake_conditions() |
operating_mode.py |
360-424 | perform_wake_transition() |
assistant_script.py |
689-713 | Sleep tick handling, wake check |
rag_memory.py |
1052-1234 | run_sleep_tick() |
Document created: 2025-12-06