Why Use This Integration
- Schema-Aware Graphs: Foreign key relationships are preserved as first-class edges in the knowledge graph
- Deterministic Graph Construction: Structured data bypasses LLM entity extraction — no hallucination risk
- Mixed Ingestion: Combine structured (dlt) and unstructured (text, PDF) data in the same dataset
- Multiple Input Modes: Pass explicit dlt resources, CSV file paths, or database connection strings
- Write Dispositions: Control how data is synced — merge (upsert), append, or replace
Installation
Quick Start
1. Ingest a dlt Resource
Define a dlt resource and pass it tocognee.remember(). The dlt-specific structured-ingestion options primary_key, write_disposition, SQL query, and max_rows_per_table are accepted by cognee.remember() and forwarded to the underlying ingestion step. After ingestion, use cognee.recall(...) to query the graph.
pets inside each user) and creates separate tables with foreign key relationships.
The lower-level
cognee.add(...) + cognee.cognify(...) pair still accepts the same dlt kwargs and remains useful when you need to run ingestion and graph building as separate steps. For the runnable end-to-end version of this walkthrough, see examples/demos/dlt_ingestion_example.py.2. Build and Query the Graph
Onceremember() finishes ingesting and building the graph, use cognee.recall(...) to query it.
Other Input Modes
CSV Auto-Detection
Pass a.csv file path and cognee creates a dlt source automatically:
Database Connection String
Ingest tables directly from an existing database:postgresql:// connection strings; keep provider-required SSL parameters such as ?sslmode=require. Amazon Redshift is also compatible since it speaks the PostgreSQL wire protocol — use a standard postgresql:// connection string pointing to your Redshift endpoint.
For Snowflake and Google BigQuery, construct a dlt source directly and pass it to cognee.remember() (see the Cloud Data Warehouses accordion below).
You can optionally filter with a SQL WHERE clause:
Mixed Structured + Unstructured
Combine dlt resources with unstructured text in a single dataset:Structured data creates deterministic graph nodes from the schema, while unstructured text goes through LLM-based entity extraction. Both are combined in the same knowledge graph.
Write Dispositions
Control how data is synced on repeated runs using thewrite_disposition parameter:
replace(default): Drop and recreate tables on each run. Use for full snapshot refreshes.merge: Upsert by primary key — updates existing rows, inserts new ones. Best for data that changes over time.append: Always insert without deduplication. Use for time-series data and event logs.
How It Works
- Source Detection: cognee identifies dlt resources, CSV files, and connection strings in the input
- Pipeline Execution: A dlt pipeline loads data into a per-dataset staging database
- Schema Extraction: Table schemas, primary keys, and foreign keys are extracted
- Graph Construction: Each row becomes a document node; foreign keys become edges between nodes
- LLM Bypass: Structured rows skip chunking, entity extraction, and summarization — the graph is built entirely from schema metadata
The
primary_key parameter controls upsert behavior when you use write_disposition="merge". If not specified, cognee auto-detects from an id column or falls back to the first column. Use the max_rows_per_table kwarg on remember() / add() to override the per-table row cap for a single call, or set the DLT_MAX_ROWS_PER_TABLE environment variable (default: 50) to change the process-wide default.Foreign Key Resolution
A foreign key becomes a graph edge only when both the source row and the target row are loaded in the same ingestion run. Two edge cases are worth knowing about — cognee now logs a warning in each so they are diagnosable rather than silent:- Target row not loaded: if a foreign key points at a row that wasn’t ingested — most commonly because the target table hit the
max_rows_per_tablecap — the reference is dropped and no edge is created. The warning identifies the dropped references assource_table.column -> ref_table:value. If you see missing edges, raisemax_rows_per_tableso the referenced rows are included. - Duplicate primary keys within a table: if multiple rows in a table share the same primary key, foreign key edges that target that key resolve to the last such row loaded; earlier rows with the same key are shadowed for FK targeting. The warning names the affected
tableandpk.
Connectors
Connectors are dlt sources for a specific system. The list below keeps the current connector packages visible; the routing details are tucked away for reference.Connector Modes
Connector Modes
Cognee supports two DLT connector modes:
- Relational connectors take the default dlt path described above: each row becomes a schema-context document and foreign keys become edges, all built deterministically without LLM extraction.
- Document-mode connectors opt each row into normal cognify instead: the row is turned into a text document that goes through LLM entity extraction, just like unstructured text passed to
remember().
cognee_document_source attribute (via the document_source_tag() helper in cognee.tasks.ingestion.dlt_utils) to a short source tag. cognee then routes every row from that source through cognify rather than the relational schema-context path:- Each row is built from its
titleandcontentcolumns (rendered as# {title}\n\n{content}, or just the content when there is no title), with optionalurlandidcolumns preserved in metadata. external_metadata["source"]is set to the connector’s own tag (for example"notion") instead of"dlt", alongsidetitleand, when present,urlandexternal_id(from the row’sid).
max_rows_per_table=0) and honor the write_disposition you pass: use replace for snapshot sources with no delete feed and merge with a hard-delete tombstone column for incremental sources that emit real deletions. primary_key defaults to id. Orphan cleanup is scoped to the source tag, so reconciling a document source only removes that source’s rows, and relational ("dlt") rows and other sources’ rows are never cross-deleted in a mixed dataset. Cleanup is skipped when the fresh read-back is empty, so an empty snapshot is treated as a failed sync rather than a signal to delete everything.Orphan cleanup now runs in the foreground of
add() / remember(): blocking runs execute it synchronously after the fresh rows are committed, so upstream deletions are reflected within the same call. Background runs (run_in_background=True) perform it up front instead.Gmail connector
Gmail connector
Gmail Connector
The Gmail connector is a first-class dlt source that turns your inbox into cognee memory. It reuses the sameremember() + dlt path described above, so it gets incremental re-sync and forget-on-delete for free. gmail_source() returns a dlt resource that you hand directly to cognee.remember().The Gmail connector ships as the standalone community package
cognee-community-connector-gmail, maintained in the cognee-community repository, so core stays free of the Google client SDKs. Install it with pip install cognee-community-connector-gmail, then import gmail_source from cognee_community_connector_gmail as shown below.Installation
dlt[sqlalchemy], google-api-python-client, google-auth, and google-auth-oauthlib. The Google client libraries are imported lazily, so the core cognee install stays slim.One-Time OAuth Setup
The connector authenticates with Gmail via the OAuth2 installed-app (Desktop app) flow using the read-only scopehttps://www.googleapis.com/auth/gmail.readonly — it never modifies your mailbox.- In the Google Cloud Console, enable the Gmail API, configure an OAuth consent screen (add yourself as a test user), and create an OAuth 2.0 Client ID of type Desktop app.
- Download the client-secret JSON and save it as
credentials.json(or pointcredentials_pathat it). - The first run opens a browser to consent and caches the resulting user token at
token.json(token_path). Later runs reuse and silently refresh that token.
Usage
gmail_source() accepts these keyword-only parameters:The returned resource (
gmail_messages) is preconfigured with primary_key="id", write_disposition="merge", and an _deleted hard-delete column, so combined with primary_key="id" on remember() it performs idempotent upserts by Gmail message id.cognee’s dlt ingestion reads at most
max_rows_per_table rows from the dlt destination (default 50). For a real inbox, pass max_rows_per_table=0 (unlimited) so forget-on-delete compares against the whole synced corpus rather than a truncated window.How It Works
- Incremental sync: The first run does a full (label-scoped) backfill and records the mailbox
historyId. This cursor is persisted in dlt’s per-resource state, so re-runningremember()on the same dataset resumes where it left off — subsequent runs callusers.history.list(startHistoryId=...)and emit only the delta (added / changed / deleted messages). - Forget-on-delete: Messages reported as deleted or trashed by the History API are emitted with the
_deletedhard-delete marker. dlt removes those rows from its destination onmerge, and cognee’s existingorphan_cleanupthen purges them from the graph, vector, and relational stores. - History expiry: Gmail expires history after roughly a week. If the stored
historyIdis too old, the History API returns a 404; the connector detects this and falls back to a full backfill so memory re-syncs rather than silently stalling.
cognee-community-connector-gmail package in the cognee-community repository.Use Cases
CRM and Relational Data
CRM and Relational Data
Load customer, order, and product tables from a database. Foreign keys between tables (e.g.,
order.customer_id → customer.id) become graph edges, enabling cross-table queries like “Which customers ordered product X?”CSV Analytics Pipeline
CSV Analytics Pipeline
Point cognee at CSV exports from analytics tools. Each row becomes a searchable node in the graph, and you can combine them with unstructured reports in the same dataset.
Event Log Ingestion
Event Log Ingestion
Use
write_disposition="append" to stream event batches into cognee without deduplication. Query across the full event history with natural language.Database Mirroring
Database Mirroring
Use
write_disposition="merge" to keep cognee’s graph in sync with a live database. Rows that are removed upstream are cleaned up best-effort; any orphaned rows that fail to delete are logged and retried on the next ingest.Cloud Data Warehouses (Snowflake, Redshift, BigQuery)
Cloud Data Warehouses (Snowflake, Redshift, BigQuery)
Amazon Redshift speaks the PostgreSQL wire protocol, so the standard connection string auto-detection works:Snowflake requires constructing a dlt The
sql_database source manually (install snowflake-sqlalchemy first):account_identifier is the part before .snowflakecomputing.com in your Snowflake URL (e.g. myorg-myaccount). Omit table_names to ingest all tables in the schema.Google BigQuery works the same way using dlt’s BigQuery connector — construct the source and pass it directly to cognee.remember(). See the dlt sql_database docs for connector-specific setup.Remember Operation
Learn more about data ingestion in cognee
dlt Documentation
Official dlt documentation and guides