## ADDED Requirements ### Requirement: Debounced memory update queue The system SHALL collect memory update requests into a queue and process them after a configurable debounce period. #### Scenario: Items enqueued per (thread, user, agent) key - **WHEN` a conversation context is added to the queue - **THEN** it SHALL be keyed by `(thread_id, user_id, agent_name)` for deduplication - **WHEN** a second context arrives for the same key before processing - **THEN** the previous context SHALL be replaced with the newer one #### Scenario: Debounce timer resets on each enqueue - **WHEN` a new item is enqueued - **THEN** the debounce timer SHALL reset to the configured `debounce_seconds` - **WHEN** no new items arrive within the debounce window - **THEN** the queue SHALL be processed #### Scenario: Immediate processing option - **WHEN** `add_nowait()` is called instead of `add()` - **THEN** the queue SHALL start processing immediately in a background thread ### Requirement: Background thread execution for memory updates The system SHALL execute memory updates (LLM extraction + persistence) in a background thread to avoid blocking the agent loop. #### Scenario: Async flush via threading.Thread - **WHEN` conversation messages are flushed to memory - **THEN** the flush SHALL run in a `threading.Thread` (daemon=True) - **THEN` the main agent SHALL NOT wait for the flush to complete #### Scenario: Thread pool for sync LLM calls - **WHEN** a memory update requires a synchronous LLM call - **THEN** the call SHALL be offloaded to a `ThreadPoolExecutor` (max_workers=4) - **THEN** this SHALL prevent blocking the main event loop ### Requirement: Content deduplication for flush The system SHALL deduplicate message content before flushing to avoid redundant summarization. #### Scenario: MD5 content hash dedup - **WHEN** messages are about to be flushed - **THEN** each message content SHALL be MD5-hashed - **WHEN** a hash matches a previously flushed message - **THEN** that message SHALL be skipped #### Scenario: Scheduler pair stripping - **WHEN** messages contain scheduler-injected pairs (marked with `[SCHEDULED]` prefix) - **THEN** the scheduler user message and its paired assistant response SHALL be stripped before flushing ### Requirement: Configuration-driven memory processing The system SHALL support configuration to enable/disable background memory processing. #### Scenario: Memory processing disabled - **WHEN** `memory_config.enabled` is `False` - **THEN** no memory updates SHALL be queued or processed - **THEN** queue `add()` calls SHALL be no-ops #### Scenario: Rate limiting between updates - **WHEN** processing multiple queued memory updates - **THEN` a 0.5 second delay SHALL be inserted between updates to avoid LLM API rate limits