fix(memory): set updated_at on creation and preserve pre-existing created_at#4499
Merged
whysosaket merged 3 commits intomainfrom Mar 27, 2026
Merged
fix(memory): set updated_at on creation and preserve pre-existing created_at#4499whysosaket merged 3 commits intomainfrom
whysosaket merged 3 commits intomainfrom
Conversation
…ated_at _create_memory (sync and async) had two gaps: 1. updated_at was never set — new memories had updated_at=None until first update, breaking sort-by-updated queries and forcing every consumer to null-check the field. 2. created_at was unconditionally overwritten — any pre-existing value in metadata was silently discarded. 3. add_history was not passed updated_at for ADD events, leaving the history table column NULL for newly created memories. Fix: initialise updated_at=created_at on creation, guard created_at with an existence check, and forward updated_at to add_history. Related to #3720 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 tasks
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
whysosaket
reviewed
Mar 23, 2026
Applies our timestamp fixes (updated_at on creation, created_at preservation) on top of the deepcopy(metadata) refactor from main, using new_metadata consistently. Preserves all TestMetadataNotMutated tests from main. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
whysosaket
approved these changes
Mar 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
_create_memory(both syncMemoryand asyncAsyncMemory) had three gaps in how it handled timestamps:Problem 1:
updated_atwas never set on creationWhen a memory was first created, only
created_atwas set.updated_atremainedNonein the vector store payload until the memory was explicitly updated via_update_memory. This caused:updated_atsince it was sometimes a string, sometimesNoneupdated_at(e.g. "most recently changed") dropped all never-updated memoriesProblem 2:
created_atwas unconditionally overwrittenIf any caller pre-set
created_atin the metadata dict (e.g. an integration backdating a memory, or the platform API honoring a user-providedtimestamp), it was silently overwritten with the current time.Problem 3: History table missing
updated_atfor ADD events_update_memorypassedupdated_attodb.add_history(), but_create_memorydid not — leaving theupdated_atcolumnNULLfor all ADD history entries, even though the value was available.Solution
In both sync and async
_create_memory:created_atwithif "created_at" not in metadata— only auto-generate if not already presentupdated_at = created_at— a newly created record was "last modified" at creation timeupdated_attodb.add_history()— consistent with_update_memorybehaviorRelated to #3720
Type of change
How Has This Been Tested?
19 tests in
tests/memory/test_main.py(7 new + 12 existing), all passing.New tests:
test_create_memory_sets_updated_atupdated_atis set on creation, equalscreated_at, is UTC, and is passed to historytest_create_memory_preserves_existing_created_atcreated_atin metadata is not overwritten;updated_atmatches ittest_async_create_memory_sets_updated_attest_async_create_memory_preserves_existing_created_attest_create_then_search_and_get_all_return_same_timestampssearch()andget_all()return identical non-nullcreated_atandupdated_attest_update_preserves_created_at_and_updates_updated_atcreated_atis unchanged,updated_atis refreshedtest_search_and_get_all_consistent_after_updatesearch()andget_all()still return identical timestampsExisting tests (all still pass):
test_create_memory_uses_utc_timestamps—created_atis UTCtest_update_memory_uses_utc_timestamps—updated_atis UTC,created_atpreserved and normalized_normalize_iso_timestamp_to_utctests_add_to_vector_storeerror handling testsAlso verified against the broader test suite:
Checklist:
Maintainer Checklist