Teaching an AI assistant to forget a deleted Lattice goal
Picture this. A manager writes a harsh piece of feedback about someone on their team, then thinks better of it and deletes it in Lattice. A week later your AI assistant is still happy to quote it, word for word, to anyone who asks about that person. Nothing crashed. The assistant just remembers som

A manager writes a harsh piece of feedback about someone on their team, then thinks better of it and deletes it in Lattice. A week later your AI assistant is still happy to quote it, word for word, to anyone who asks about that person.
Nothing crashed. The assistant just remembers something that no longer exists, and this time it is the most sensitive thing a company writes down.
For Mergetober I built a Lattice connector for Cognee with that in mind. The code is in PR for issue #4801.
Cognee turns documents into a knowledge graph an agent can search. The connector feeds it from Lattice:
source = lattice_source () # LATTICE_API_KEY from the environment await cognee. remember ( source, dataset_name = " lattice " ) Enter fullscreen mode Exit fullscreen mode Opting in to the sensitive parts is explicit: include_feedback=True reads only feedback shared with the whole company, and private feedback needs a second flag. Review responses need the ids of the cycles you pick. Only reviews a reviewer actually submitted are read, and no review document ever names its reviewer, only "peer review" or "downward review". Peer reviews are often anonymous to the person they are about, and memory has more readers than Lattice does.
It only ever sends GET requests, and the README tells you to make the API key from a low-privilege user, because Lattice keys carry their creator's permissions.
Lattice has no way to ask for "what changed since last time". Goals, feedback and review cycles have no updatedAt filter, feedback has no updatedAt at all, and there is no delete feed. A goal's updatedAt also only moves when the goal itself is edited, not when someone posts a check-in.
So each run lists everything in scope and lets Cognee do the incremental part by content. A document whose text is unchanged keeps its id and is never read by the LLM again. The check-ins are part of the goal's text, so a new one changes it. A goal that stops being listed is forgotten.
I assumed the simple full-snapshot model had a hole. If you switch feedback off, or the last goal is deleted, nothing is left to say "this table is now empty", so the old documents might stay.
I checked it with a throwaway source through the real Cognee pipeline. Switching feedback off forgot the feedback. Emptying the goals forgot the goals. The model works.
It only works if all four tables still exist in the run, even when empty. I then tried the tempting shortcut of leaving out the resource for anything switched off, and the test that withdraws feedback failed: the feedback stayed in memory. That test now guards it.
A wrong delete is worse than a missed one, so a few rules came from reading my own client the way a reviewer would:
Lattice has no public sandbox, so everything runs against an in-memory fake built from its published OpenAPI schemas: cursor paging in both list shapes, Retry-After, the filters, integer timestamps.
There are 105 tests on Python 3.11, 3.12 and 3.13. 17 of them run the whole Cognee pipeline with a mocked LLM: deleted, archived and privatized goals leave the graph, a new check-in is picked up, an unchanged re-sync makes no LLM call, withdrawn feedback is purged, and a failed run forgets nothing. I also broke each safeguard on purpose and checked a test fails without it.
The example is packages/connector/lattice/examples/example.py. You need a Lattice API key (Admin > Platform > API keys) and your region, US or EMEA. It prints your review cycles first, so you can pick which ones to read.
If you point it at real people's data, start with goals only, use a separate dataset, and turn feedback on only when you mean to. I'd like to hear what breaks.