-
Notifications
You must be signed in to change notification settings - Fork 29
Fix deduplication for "message" type long-term memories #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The memory server indexes any messages from working memory into "message" type memory records in long-term memory. However, we were not attempting to deduplicate these memory records -- only the higher-level long-term memory types, like semantic and episodic memory. This change refactors the logic we use to store messages long-term such that they work similarly to long-term memories the client adds to working memory. When a client adds a message to working memory, the client gives the memory an ID, and the memory gets a blank `persisted_at` timestamp. After setting working memory, we kick off a background task to persist any promoted long-term memories and messages in long-term memory. When we copy the messages into long-term memory, we now update the `persisted_at` timestamp. If we see that working memory again and try to persist any new memories or messages, we'll skip any that have already been persisted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR refactors message handling so that long-term “message” memories support deduplication and proper persisted timestamps, aligning their lifecycle with other memory types.
- Added
idandpersisted_atfields toMemoryMessagein both server and client models - Updated
set_working_memoryandpromote_working_memory_to_long_termto initialize, dedupe, and batch‐persist messages - Adjusted client methods and tests to use
MemoryMessageobjects with attribute access
Reviewed Changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_client_enhancements.py | Switched test assertions from dict indexing (["content"]) to attribute access (.content). |
| tests/test_client_api.py | Same as above for MemoryAPIClient; updated indexing assertions. |
| tests/test_api.py | Broadened response checks: validate message count, roles, contents, and auto-generated IDs. |
| agent_memory_server/models.py | Added id and persisted_at fields to MemoryMessage. |
| agent_memory_server/mcp.py | In set_working_memory, convert all messages to MemoryMessage with persisted_at=None. |
| agent_memory_server/long_term_memory.py | In promote_working_memory_to_long_term, identify unpersisted messages, dedupe by ID, set persisted_at, and index them. |
| agent_memory_server/api.py | Removed old message‐indexing logic; now only schedules promotion for structured memories. |
| agent-memory-client/models.py | Converted client MemoryMessage from TypedDict to BaseModel, added tracking fields. |
| agent-memory-client/client.py | Updated append_messages_to_working_memory to accept and convert MemoryMessage objects. |
Comments suppressed due to low confidence (1)
agent_memory_server/mcp.py:694
- [nitpick] The docstring describes only dict inputs. It should also note that
MemoryMessageobjects are accepted directly.
messages: List of conversation messages (role/content pairs with optional id/persisted_at)
rbs333
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
The memory server indexes any messages from working memory into "message" type memory records in long-term memory. However, we were not attempting to deduplicate these memory records -- only the higher-level long-term memory types, like semantic and episodic memory.
This change refactors the logic we use to store messages long-term such that they work similarly to long-term memories the client adds to working memory. When a client adds a message to working memory, the client gives the memory an ID, and the memory gets a blank
persisted_attimestamp. After setting working memory, we kick off a background task to persist any promoted long-term memories and messages in long-term memory. When we copy the messages into long-term memory, we now update thepersisted_attimestamp. If we see that working memory again and try to persist any new memories or messages, we'll skip any that have already been persisted.