DEV Community

Shikhar Goel
Shikhar Goel

Posted on

I Gave My AI a Memory of Every Book I've Read (Goodreads x Cognee)

This is my Mergetober hackathon entry for the Goodreads connector (PR, proposed in cognee#6486).

I've tracked my reading on Goodreads since 2016. Nine years of data: every book, every rating, every half-finished review I typed into a phone at 1am. It's the most complete record of what I've learned and felt that I own — and it's completely inert. Goodreads won't answer a question for me. It certainly won't tell my AI assistant what I thought of Thinking, Fast and Slow or which books on systems design I've already absorbed.

So I built the missing pipe: a cognee connector that turns a Goodreads library export into agent memory.

Why an export parser and not an API

Goodreads retired its public API in 2020. The library export (Settings → Import/Export → "Export Library") is the only supported access path left — and it's actually a better one for this use case: one file, everything in it, no rate limits, no OAuth. The connector takes the CSV path, no credentials:

import cognee
from cognee_community_connector_goodreads import goodreads_source

await cognee.remember(
    goodreads_source("goodreads_library_export.csv"),
    dataset_name="goodreads",
    primary_key="id",
    write_disposition="merge",   # required: see below
    max_rows_per_table=0,
)

answers = await cognee.recall(
    "Which books did I read about distributed systems, and what did I think of them?",
    datasets=["goodreads"],
)
Enter fullscreen mode Exit fullscreen mode

What actually ends up in memory

Every book becomes one document: title, author, year, ISBN, shelves, status (read / currently reading / to-read), average rating — and the interesting part, my per-read timeline. Goodreads exports re-reads as repeated Date Read / My Rating / My Review columns; the connector zips them into a sorted timeline, so a book I read twice keeps both dates, both ratings and both reviews, HTML stripped. Books also link in the graph by shelf and author via node sets — no LLM extraction needed to know that two books share a shelf.

The two design decisions that matter

Incremental sync via merge. Re-export and re-run: only books whose content changed get re-processed, because rows are rendered deterministically (no ingestion timestamps) and keyed by Goodreads' global book id. An unchanged library costs nothing.

Forget-on-delete. Remove a book from your Goodreads library, re-export, re-sync — the connector diffs the new export against the previous one and emits a hard-delete marker, and cognee's orphan cleanup removes it from the graph and the vector stores. Your agent's memory of your library tracks your actual library, in both directions.

Verified so far

The connector runs end-to-end today: the full suite passes against fixtures that mirror the real export format, and the delivery tests drive a real dlt pipeline where an edited review updates its row in place and a removed book physically disappears from the destination after the _deleted tombstone.

$ uv run pytest tests/ -q
34 passed in 2.86s
Enter fullscreen mode Exit fullscreen mode

I'll add numbers from my own library export here as the syncs run.

Honest limitations

  • The export is a snapshot: removals and edits are only detected when you re-export.
  • Switching to a different account's export merges by book id (Goodreads ids are global).
  • No reading-position data for "currently reading" books — Goodreads doesn't export it.

The connector is at packages/connector/goodreads/ in cognee-community PR #597, with 34 tests against the real export format (re-read columns, ="ISBN" escaping, footer junk, UTF-8 BOM) and delivery tests that prove edits upsert and deletions physically disappear. Try it: uv add cognee-community-connector-goodreads once it merges.

Top comments (0)