DEV Community

Akshat Gupta
Akshat Gupta

Posted on

Teaching an AI assistant to forget a deleted Figma comment

Picture this.

A team spends a week arguing in the comments of a Figma file about whether the sign-up button should be a pill. They settle it, the designer deletes the thread to tidy up, and a month later your AI assistant is still telling new hires that "the team agreed on a pill, see the comments". The comment is gone from Figma. The memory of it is not.

Nothing crashed. The assistant just remembers something that no longer exists, and design decisions are exactly the kind of thing people ask it about.

For Mergetober I built a Figma connector for Cognee with that in mind. The code is in PR #372 for issue #4552.

What it does

Cognee turns documents into a knowledge graph an agent can search. The connector feeds it from Figma:

  • Each file becomes one document: its type, folder, page names, frame and section names, and the text of every text layer. FigJam stickies count too.
  • Each comment thread becomes one document: the comment and its replies in time order with their authors, which frame it is pinned to, and whether it is resolved.
  • Geometry, images, hidden layers and default layer names like "Frame 12" are never read. A Figma file is a canvas, not prose, so only the text is kept.
  • A deleted file, a deleted comment, or a folder you deselect is forgotten on the next sync.
source = figma_source(token, folder_ids=["<folder id>"])
await cognee.remember(source, dataset_name="figma")
Enter fullscreen mode Exit fullscreen mode

Files and their comments share one node set per folder, so a search can be limited to one folder. There is also an optional OAuth integration that plugs into Cognee's connect and folder-picker flow.

What the API does not give you

Figma has no change feed and no delete feed. The folder listing gives each file's last_modified, not its version number, and the part that costs is GET /v1/files/:key, the whole node tree, which sits in Figma's strictest rate-limit tier. Figma's docs list 10 to 20 requests a minute for Dev and Full seats and about 20 a month for View and Collab seats. Comments do not move a file's timestamp. You cannot list a user's teams. Listing folders needs a private OAuth app, because public apps are not allowed the folders:read scope.

So each run lists the selection, fetches only the files whose last_modified moved, and serves the rest from a cache. Comments are read every run, one cheap request per file, because they never change the stamp. Cognee does the incremental part by content: a document whose text is unchanged keeps its id and never reaches the LLM again.

Two things my first design got wrong

I found both by reading my own code the way a reviewer would.

It cached too much. The cache kept whole rendered rows, title and folder name included. A rename or a folder move may not change a file's timestamp, so the cache would have kept serving the old title. Now the cache holds only what the node tree contributes, and the title and folder come from the fresh listing every run.

It could never finish a big team. When Figma returned a 429 that outlasted the retries, the whole run failed and the next run started from zero, hitting the same wall. Now at most 100 node trees are fetched per run, and a rate limit stops the fetching cleanly. Files not reached keep the text they were last synced with, so nothing is forgotten, and the next run carries on. The sync counts say so with failed_budget or failed_rate_limit.

I also made it stricter than it needed to be. An empty selection raises, because an empty list must never mean "forget everything". A selection that suddenly lists no files, when files were synced before, raises too. Earlier reviewers on my Stripe connector pointed out that a node set per record makes a big graph, so I used one per folder.

How I tested it

There are 68 tests on Python 3.10 and 3.12. Figma is an in-memory fake behind dlt's real HTTP stack. 8 of them run the whole Cognee pipeline with a mocked LLM: deleted files and comments leave the graph, an unchanged re-sync makes no LLM call, a sync cut short by the budget keeps what it has, and a file and its comments share a node set.

Then I ran it against a real Figma account on the free plan: a folder with two design files and one comment thread with a reply.

  • First sync: both files and the thread came in, and a search answered correctly from the design text.
  • Re-sync with nothing changed: 0 file downloads and 0 LLM calls.
  • A new comment: only that thread went to the LLM.
  • A deleted comment: forgotten.
  • A text edit in one file: only that file was fetched again, the new text was in the graph and the old text was gone.
  • A file moved to the trash: forgotten on the next sync, the rest untouched.

The only surprise was timing. My first sync after the edit saw nothing, because Figma saved the change a few seconds after I read the folder. The next run caught it.

What I did not test

The OAuth connect flow, because it needs a private Figma app. Large files and long syncs: I used two small files. Paid plans, and the actual rate limits of the free plan. All of that is covered by the fake, not by Figma.

Try it

The example is packages/connector/figma/examples/example.py. You need a personal access token (Settings, Security) with the scopes file_content:read, file_comments:read, folders:read and file_metadata:read, plus a folder id or a team id. Use a separate dataset, and tell me what breaks.

Top comments (0)