DEV Community

Vinayak Sonthalia
Vinayak Sonthalia

Posted on

Building a Postman Connector for Cognee: What I Learned About Safer Syncs

A Postman sync that knows when to stop

What repeated review taught me about snapshots, deletion safety, privacy, and proving a Cognee connector works end to end.

A Postman request changed from “Aster lives in Oslo” to “Aster lives in Lima.” After syncing the edit into a local Cognee setup, a search found Lima; checks of the stored content found no remaining Oslo text. When I deleted the synthetic request, the corresponding Data, graph, and vector records were empty too.

That small lifecycle captures the difficult part of building a connector: getting fresh content in is easy to demonstrate. Getting changes and removals right, without deleting unrelated data or leaking secrets, takes more work.

The sync is a snapshot, not an append

A connector that only adds documents can leave old facts behind. The Postman source therefore emits a complete snapshot for its own stable resource identity. Unchanged documents are retained from cache, while changed and removed documents flow through Cognee’s replacement path.

flowchart TD
    A[Validate account and workspace] --> B[Read collection inventory]
    B --> C{Inventory complete and stable?}
    C -- No --> X[Stop; keep prior snapshot]
    C -- Yes --> D[Fetch changed trees; reuse unchanged cached rows]
    D --> E[Build complete retained snapshot]
    E --> F{Removal is ambiguous or exceeds guard?}
    F -- Yes --> Y[Stop and report UIDs for explicit confirmation]
    F -- No --> G[Publish scoped replacement to Cognee]
    G --> H[Verify Data, graph, vectors, and search]

This design keeps unchanged content in the snapshot instead of confusing “not fetched this time” with “deleted.” Resource names provide isolation between sibling sources. A deliberate selection change can retire content from one resource without wiping another.

Deletion is where an ordinary inventory comparison becomes dangerous. A partial listing caused by access changes can resemble mass deletion. The connector waits for matching inventory passes before trusting changed listings, refuses to clear a populated cache from an empty inventory without confirmation, and keeps pending removals across runs. Pending entries do not vanish just because a scheduled sync was delayed.

These checks reduce accidental loss; they do not reveal why Postman stopped showing a collection. It may have been deleted, moved, unshared, or hidden by permissions. The documented removal policy makes that tradeoff explicit and allows callers to require confirmation.

Privacy is a boundary, not a regex promise

A collection can place credentials in auth settings, variables, query parameters, custom headers, URL paths, or request bodies. Early review rounds exposed both sides of the problem: redaction that ate ordinary words, and secrets that still appeared in generated prose.

Each reported example became a regression case. The current filtering covers known sensitive fields and credential patterns, including secret variables, sensitive body fields, custom auth headers, query values, long token-like strings, hex tokens, JWT shapes, and known path patterns. Raw request trees are not persisted, and auth, scripts, examples, and raw values are omitted from rendered documents.

That is best-effort filtering, not universal secret detection. A short value can be indistinguishable from a normal word; an unusual credential can evade known patterns. The documentation says so. Users should review source collections and provide explicit values to redact where needed.

Review comments became executable cases

The PR went through several rounds of detailed review. Feedback covered false deletion, inventory gaps, documentation-only collections, redaction, request URLs, retry limits, unnecessary API calls, and error reporting. The useful shift was to stop treating each comment as a local patch and instead ask: what small test would fail if this happens again?

The latest recorded offline suite reports 185 passed and 1 skipped. The skipped test is an optional model integration test, so it is not counted as a pass in that run. The validation record also includes several installed-wheel Python/Cognee/dlt combinations, a locked development environment, and lint, format, lock, and wheel checks. Those are recorded results for the listed environments, not proof of every allowed version or backend.

Testing with local Cognee stores

Mocked Postman responses are useful for repeatable edge cases, but they cannot show that Cognee’s stores update as expected. A separate local run used a synthetic Postman collection and actual Cognee Data, graph, and vector stores. It covered an initial ingest, unchanged sync, edit, and deletion, with store inspection as well as search.

The local model-backed setup used cached models; it did not use Cognee Cloud credits or paid model calls. Provider writes were limited to synthetic test collections, and a postflight check confirmed that the original collection remained and the synthetic fixtures were removed.

The evidence has boundaries: the provider and Cognee runs use a small synthetic workspace and the recorded versions. They do not prove behavior on every backend, every provider permission setup, or every possible partial failure. The package’s README.md has the quickstart; VALIDATION.md and VALIDATION_RESULTS.json describe reproducible commands, environments, and limitations. The authenticated lifecycle requires a Postman API key and a dedicated test workspace.

What changed in how I build connectors

This started as an API client and document mapper. It became a synchronization system with state, identity, deletion policy, privacy boundaries, and recovery behavior. Those are part of the product contract, so they need tests and documentation of their own.

I also learned that review is most useful when it produces a sharper test. A comment about a disappearing collection can become a multi-run regression. A redaction example can become a fixture that checks both what must disappear and what ordinary prose must preserve. That turns review from a list of opinions into a growing set of concrete behaviors.

The work is proposed in Cognee Community PR #366.

Top comments (2)

Collapse
 
marcusykim profile image
Marcus Kim •

The stable inventory check still leaves an interesting failure case: two complete passes can agree after a permission change. I'd add a multi-run fixture where a collection disappears from the listing, its direct fetch becomes forbidden, and it later reappears unchanged. The assertion would be that its previous snapshot stays quarantined rather than being treated as confirmed deletion. Does your pending-removal record retain the reason and last successful fetch, so an operator can distinguish that case from an explicit delete?

Collapse
 
vinayaksonthalia profile image
Vinayak Sonthalia •

Thanks, Marcus — this is a useful failure case. I checked the code: a forbidden fetch raises before the connector returns a replacement snapshot, and pending-removal state stores the UID only, not the reason or last successful fetch. We have separate tests for missing collections, fetch failures, and reappearance, but I haven’t yet verified your exact permission-loss → forbidden fetch → unchanged reappearance sequence against Cognee’s persisted stores. I’m working on that isolated local test and will update the post and PR based on its result.