Repository navigation
Deduplicate a Bot-formed memory per Bot, and keep forgetting person-wide - #788
Open
Chebaleomkar wants to merge 2 commits into
Open
Chebaleomkar wants to merge 2 commits into
Chebaleomkar wants to merge 2 commits into
Conversation
Two of these fail on main: the second Bot is answered as a duplicate of the first Bot's row, so it never keeps the fact it formed.
formMemory deduplicated on (person, content), but retrieval gives a Bot only the rows it formed. Include formedByAgentId in the lookup, the onConflictDoNothing target and personal_memories_formed_digest_idx (migration 0057). A tombstone from any Bot still answers forgotten, so forgetting stays person-wide. Fixes CopilotKit#714
Chebaleomkar
requested review from
MikeRyanDev,
davidmckayv,
guidovizoso,
mxmzb and
tylerslaton
as code owners
October 14, 2026 12:45
This branch has not been deployed
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.
Fixes #714, as decided there: option 1, with forgetting kept person-wide.
What this changes
formMemorydeduplicated a Bot-formed memory per person and content, butretrievegives a Bot only the rows it formed. A second Bot forming a fact the first already held gotduplicate: truewith the first Bot's row, so it could never recall the fact.onConflictDoNothingtarget andpersonal_memories_formed_digest_idxnow includeformedByAgentId. Migration0057_memory_dedup_per_botrebuilds the index and keeps every row. Existing rows cannot collide under the wider key, so there is no backfill.forgotten: trueto every Bot, even one that had already formed its own copy.Where it runs
Server:
save_observed_memoryand background research, the two callers offormMemory.remember_personal_factusescreateand is unchanged.Boundary and audit
No change. A Bot still recalls only what it formed, from apps it still holds.
Changelog
An entry under Unreleased, plus a "Before upgrading" bullet for the migration.
Tradeoffs
A server still on the previous release fails to save a newly formed Bot memory once
0057has run, because its conflict target needs the old index. Keeping the old index for a release does not avoid this: while it exists it still refuses the second Bot's copy, which is the bug itself. I used the single index swap and stated the window in the changelog. The same conclusion was reached in the review on #766, which covers the index and the same-Bot cases. This PR adds person-wide forgetting and the reset case NathanTarbert asked for, on the next free migration number.Proof
The tests land in their own commit before the fix. Against PostgreSQL 17 with every migration applied:
main, two of the new tests fail. "the same fact formed by two Bots is kept for each" receivesduplicate: true, and "resetting one Bot leaves another Bot's copy" finds no row for the other Bot. The forgetting test passes onmainand guards that behaviour against this change.memory-store.integration,bot-lifecycle.integrationandmemorypass 38/38.memory-intelligence.integration,proactive-store.integrationandproactivepass 24/24.tsc, Biome format and lint, anddrizzle-kit checkare clean. The live index reads(owner_user_id, formed_by_agent_id, import_digest) WHERE formed_by = 'bot'.Thanks to @kvnloo for tracing the schema contract on #714.