Cognee 的 Google Calendar 連接器:修正重複記憶問題
One calendar, two names: fixing duplicate memories in Cognee's Google Calendar connector
Cognee 的 Google Calendar 連接器修正了主要日曆別名 `primary` 與電郵地址被當作兩個日曆、令事件重複儲存的問題。修正後,兩種名稱會視為同一個鍵,並保留設定中的第一種寫法;舊同步留下的重複資料會在下次執行時清除。舊問題曾導致 cognify 時的 LLM 呼叫倍增,並在知識圖譜中產生重複事實。
AI agents are only as good as what they remember. Cognee is an open-source memory layer for agents: you hand it documents, chats or data, and it builds a knowledge graph the agent can query later. For Mergetober (WeMakeDevs × Cognee) I spent my contribution on the Google Calendar connector, which turns your calendar into agent memory, so you can ask things like "what did I agree to in last week's design review?" or "when is my next 1:1 with Priya?".
How the connector works
The connector is a dlt source. You hand it to Cognee in one call:
import cognee
from cognee_community_connector_google_calendar import google_calendar_source
await cognee.remember(
google_calendar_source(calendar_ids=["primary"]),
dataset_name="calendar",
primary_key="id",
write_disposition="merge",
)
answer = await cognee.recall("When is my next design review?")
Each event becomes a short text document ("Calendar event: Design review / When: ... / Attendees: ..."), which Cognee chunks and turns into entities and relations. Later syncs use Google's sync tokens, so only changed events are re-read, and deleted events are forgotten.
The bug: one calendar, two names
In Google Calendar your main calendar has two names: the alias "primary", and its real id, which is your email address. The connector's helper script examples/login.py lists your calendars by their real ids, so a natural setup looks like this:
GOOGLE_CALENDAR_IDS=primary,me@gmail.com
The connector treated those as two different calendars. It kept separate sync state for each and built row ids from the configured string (gcal:primary:<event> and gcal:me@gmail.com:<event>), so every event was stored twice. That means double the LLM calls during cognify and duplicate facts in the graph. It's the kind of quiet bug that never crashes anything; your agent just gets noisier and more expensive.
The fix
The sync already lists your calendars to get their display names, and that listing marks which one is primary. So the fix reuses it:
- List calendars once and find the primary calendar's real id.
- Treat
"primary"and that id as the same key, and keep only the first spelling you configured. - Leave everything else alone.
Keeping the first spelling matters: someone with the default ["primary"] setup sees no change at all (same row ids, same sync state, nothing re-ingested). And if an earlier sync already stored both copies, the second spelling now counts as a calendar removed from the config, so the connector's existing forget path cleans the duplicates up on the next run.
Testing it
The connector's tests run against an in-memory fake of the Calendar API, so no Google account is needed. I added three tests: both spellings sync as one calendar, the first spelling is kept, and a leftover duplicate from an older sync gets forgotten. Then I ran the whole suite plus ruff on Python 3.11 and 3.13 with GitHub Actions on my fork.
What I learned
- Aliases are identity bugs waiting to happen. Whenever an API gives one thing two names, anything keyed on the raw string can split it in two.
- Read how the data is keyed, not just how it's fetched. The bug wasn't in any API call; it was in which string became the key.
- Fast feedback beats big ideas. I first planned a brand-new connector, then found hundreds of connector proposals already queued. A small, well-tested fix to code people already use is easier to review and more useful.
Links:
- Pull request: https://github.com/topoteretes/cognee-community/pull/587
- Issue: https://github.com/topoteretes/cognee/issues/6481
- Also reported along the way: https://github.com/topoteretes/cognee/issues/6470 (all-day events stored one day too long)
來源:DEV Community · dev.to