feat: add windowed session history + LTM extraction/retrieval

- New memory_manager.py with:
  - check_and_compact: runs compaction on flagged sessions (extracts LTM via
    Claude Haiku, stores as AgentCore Memory event, deletes old events)
  - check_window_and_flag: sets DynamoDB flag when session > 100 events
  - load_ltm: retrieves LTM extractions and formats as system prompt block
- Wired into main.py:
  - Compaction runs before session_manager creation (trims old events)
  - LTM block injected into system prompt
  - Window check runs after session close
- SESSION_WINDOW_SIZE = 100 (named constant)
- Compaction is idempotent (uses event timestamps as cursor)
- LTM retrieval failure is non-fatal (logs and continues)
This commit is contained in:
daniel
2026-05-13 11:57:50 -05:00
parent d217842917
commit 3a34e61479
2 changed files with 331 additions and 0 deletions

View File

@@ -10,6 +10,7 @@ from bedrock_agentcore.runtime import BedrockAgentCoreApp
from channels.telegram import TelegramAdapter
from prompt_builder import build_system_prompt, invalidate_prompt
import memory_manager
from tools import web as web_tools
from tools import workspace as ws_tools
from tools import messaging
@@ -313,6 +314,9 @@ async def main(payload: dict, context):
_scheduler_module._current_actor_id = actor_id
_scheduler_module._current_chat_id = chat_id
# Run compaction if flagged from previous invocation (trims old events before load)
memory_manager.check_and_compact(actor_id, session_id)
memory_config = AgentCoreMemoryConfig(
memory_id=MEMORY_ID,
session_id=session_id,
@@ -352,6 +356,11 @@ async def main(payload: dict, context):
user_context += f'\nEnrolled services: {", ".join(enrolled)}'
system_prompt = build_system_prompt(user_context=user_context, actor_id=actor_id)
# Inject long-term memory block before conversation history
ltm_block = memory_manager.load_ltm(actor_id)
if ltm_block:
system_prompt = system_prompt + '\n\n---\n\n' + ltm_block
# Inject current datetime so the model always has accurate time context
from datetime import datetime
from zoneinfo import ZoneInfo
@@ -398,6 +407,8 @@ async def main(payload: dict, context):
finally:
_typing_active = False
session_manager.close()
# Check if session exceeds window — flag for compaction on next invocation
memory_manager.check_window_and_flag(actor_id, session_id)
app.run()