Skip to main content

cognee.cognify()

Description

Transform ingested data into a structured knowledge graph. This is the core processing step in Cognee that converts raw text and documents into an intelligent knowledge graph. It analyzes content, extracts entities and relationships, and creates semantic connections for enhanced search and reasoning. Prerequisites:
  • LLM_API_KEY: Must be configured (required for entity extraction and graph generation)
  • Data Added: Must have data previously added via cognee.add()
  • Vector Database: Must be accessible for embeddings storage
  • Graph Database: Must be accessible for relationship storage
Input Requirements:
  • Datasets: Must contain data previously added via cognee.add()
  • Content Types: Works with any text-extractable content including:
    • Natural language documents
    • Structured data (CSV, JSON)
    • Code repositories
    • Academic papers and technical documentation
    • Mixed multimedia content (with text extraction)
Processing Pipeline:
  1. Document Classification: Identifies document types and structures
  2. Text Chunking: Breaks content into semantically meaningful segments
  3. Entity Extraction: Identifies key concepts, people, places, organizations
  4. Relationship Detection: Discovers connections between entities
  5. Graph Construction: Builds semantic knowledge graph with embeddings
  6. Content Summarization: Creates hierarchical summaries for navigation
Graph Model Customization: The graph_model parameter allows custom knowledge structures:
  • Default: General-purpose KnowledgeGraph for any domain
  • Custom Models: Domain-specific schemas (e.g., scientific papers, code analysis)
  • Ontology Integration: Pass an ontology resolver via config (or set the ONTOLOGY_FILE_PATH environment variable) for predefined vocabularies
Args: datasets: Dataset name(s) or dataset uuid to process. Processes all available data if None.
  • Single dataset: “my_dataset”
  • Multiple datasets: [“docs”, “research”, “reports”]
  • None: Process all datasets for the user user: User context for authentication and data access. Uses default if None. graph_model: Pydantic model defining the knowledge graph structure. Defaults to KnowledgeGraph for general-purpose processing. chunker: Text chunking strategy (TextChunker, LangchainChunker).
    • TextChunker: Paragraph-based chunking (default, most reliable)
    • LangchainChunker: Recursive character splitting with overlap Determines how documents are segmented for processing. chunk_size: Maximum tokens per chunk. Auto-calculated based on LLM if None. Formula: min(embedding_max_completion_tokens, llm_max_completion_tokens // 2) Default limits: ~512-8192 tokens depending on models. Smaller chunks = more granular but potentially fragmented knowledge. chunks_per_batch: Number of chunks to be processed in a single batch in Cognify tasks. vector_db_config: Custom vector database configuration for embeddings storage. graph_db_config: Custom graph database configuration for relationship storage. run_in_background: If True, starts processing asynchronously and returns immediately. If False, waits for completion before returning. Background mode recommended for large datasets (>100MB). Use pipeline_run_id from return value to monitor progress. custom_prompt: Optional custom prompt string to use for entity extraction and graph generation. If provided, this prompt will be used instead of the default prompts for knowledge graph extraction. The prompt should guide the LLM on how to extract entities and relationships from the text content. dry_run: If True, return a stage-level estimate of LLM token usage and rough cost without making LLM calls or writing graph results. The estimate covers all data in the selected dataset(s); an incremental run may process fewer items.
Returns: Union[dict, list[PipelineRunInfo], DryRunEstimate]:
  • Blocking mode: Dictionary mapping dataset_id -> PipelineRunInfo with:
    • Processing status (completed/failed/in_progress)
    • Extracted entity and relationship counts
    • Processing duration and resource usage
    • Error details if any failures occurred
  • Background mode: List of PipelineRunInfo objects for tracking progress
    • Use pipeline_run_id to monitor status
    • Check completion via pipeline monitoring APIs
Next Steps: After successful cognify processing, use search functions to query the knowledge:
Advanced Usage:
Environment Variables: Required:
  • LLM_API_KEY: API key for your LLM provider
Optional (same as add function):
  • LLM_PROVIDER, LLM_MODEL, VECTOR_DB_PROVIDER, GRAPH_DATABASE_PROVIDER
  • AUTO_RATE_LIMIT: Turn the rate limiter on automatically when the provider shows overload evidence (default: True)
  • LLM_RATE_LIMIT_ENABLED: Enable rate limiting from the first request (default: False)
  • LLM_RATE_LIMIT_REQUESTS: Max requests per interval (default: 60; 10 for local inference servers)
Optional (contradiction detection — see Contradiction detection):
  • CONTRADICTION_DETECTION: Append the opt-in contradiction check to the pipeline (default: False)
  • CONTRADICTION_CONFIDENCE_THRESHOLD: Minimum LLM confidence for a pair to be flagged (default: 0.5)
  • CONTRADICTION_MAX_FACTS: Cap on the facts sent to the LLM in a single check (default: 500)
Optional (provenance ledger — see Provenance ledger):
  • PROVENANCE_TRACKING: Append the opt-in provenance-ledger task to the pipeline (default: False)

Parameters

Union[str, list[str], list[UUID]]
default:"None"
Dataset name(s) or UUID(s) to process. Processes all datasets if not specified.
User
default:"None"
User performing the operation.
BaseModel
default:"KnowledgeGraph"
Pydantic model defining the knowledge graph schema. Defaults to KnowledgeGraph.
Any
default:"TextChunker"
Text chunking strategy class.
int
default:"None"
Maximum size of text chunks in tokens.
int
default:"None"
Number of chunks to process per LLM batch.
Config
default:"None"
Override the full Cognee config for this run.
dict
default:"None"
Override vector database configuration.
dict
default:"None"
Override graph database configuration.
bool
default:"False"
If true, return immediately and process in background.
bool
default:"True"
If true, skip already-processed data.
Optional[str]
default:"None"
Custom system prompt for entity/relationship extraction.
bool
default:"False"
Enable temporal-aware processing.
int
default:"20"
Number of data items per processing batch.
Optional[LLMConfig]
default:"None"
LLM settings to install into the current async context for this graph-building operation. When omitted, Cognee uses the active context config or global LLM config. Import LLMConfig from cognee.infrastructure.llm.config.
Optional[EmbeddingConfig]
default:"None"
Embedding settings to install into the current async context for this graph-building operation. When omitted, Cognee uses the active context config or global embedding config. Import EmbeddingConfig from cognee.infrastructure.databases.vector.embeddings.config.
bool
default:"False"
If true, return a DryRunEstimate of LLM token usage and rough cost instead of running the pipeline. No LLM calls are made and no graph results are written. See Dry-run cost estimation.

Dry-run cost estimation

Pass dry_run=True to preview the LLM token usage and rough USD cost of a cognify() run without making any LLM calls or writing graph results. This is useful for budgeting a large dataset before committing to the run.
The estimate covers the two LLM-heavy stages of the default pipeline — structured_graph_extraction and chunk_summarization — reusing the real document classifier, chunker, and prompt templates so chunk and call counts track an actual run. The returned DryRunEstimate exposes: Behavior notes:
  • Datasets are resolved read-only. Unlike a normal run, a dry run never creates a missing dataset, so estimating a typo’d dataset name fails loudly instead of silently creating one.
  • Estimates are upper bounds for re-runs. With incremental_loading=True, a real run skips already-processed documents, so a dry run may over-estimate a re-run.
  • Not supported with temporal_cognify=True (only the default pipeline is estimated) or while connected to a remote Cognee instance via serve() — both raise a ValueError.
  • Unknown models emit a warning rather than reporting a $0 cost when no pricing entry exists for the configured model.
  • Code files are counted as skipped, at zero cost. Items that cognify() would route down the code graph pipeline are separated out before any document is read, so they are never chunked and contribute no tokens or cost. They are folded into skipped_items and reported in warnings as Skipped N code file(s) because they run the deterministic code graph pipeline — no LLM calls. See Loaders for which extensions take that route.

Processing Pipeline

When you call cognify(), data goes through these stages:
  1. Document classification — identify content type
  2. Text chunking — split into manageable segments
  3. Entity extraction — identify entities using the LLM
  4. Relationship detection — find connections between entities
  5. Graph construction — build the knowledge graph
  6. Summarization — generate summaries of content
  7. Provenance recording (opt-in, off by default) — append an audit-ledger entry for every document, chunk, entity, and relationship this run produced. Enabled with PROVENANCE_TRACKING=true; when off, the task list is identical to the pipeline above. See Provenance ledger.
  8. Contradiction detection (opt-in, off by default) — compare the facts this run touched against the facts already stored around them and record each conflict as a contradicts edge. Enabled with CONTRADICTION_DETECTION=true; when off, the task list is identical to the pipeline above. See Contradiction detection.

Provenance ledger

When PROVENANCE_TRACKING is enabled, cognify() splices one extra task (record_provenance) into the default pipeline. It runs immediately after the graph and embeddings have been written — so node ids are persisted and stable — and before the contradiction check, so the ledger never depends on contradiction edges. For each item the run produced it appends document → chunk → entity → relationship lineage entries to the append-only provenance_entries table in the relational database, committing all entries for one task invocation as a single chained transaction. There is no cognify() argument for this feature; like contradiction detection it is configured entirely through CognifyConfig:
The cognify config is cached for the lifetime of the process, so set this in your .env or environment before the first cognify() call. Changing it mid-process has no effect.
Behavior notes:
  • Failure is never fatal. The task returns its input unchanged and swallows all of its own errors, logging a warning (Provenance recording failed; ingestion unaffected: ...) instead of failing the run. Missing pipeline context or ids degrade to entries with a source_ref_key of None rather than raising. A swallowed failure rolls the whole batch back, so those entries are simply absent — they never claimed sequence numbers, the hash chain stays intact, and verify_chain() still reports valid. Verification proves the stored entries were not tampered with, not that everything an ingestion produced was recorded, so watch that warning if you depend on the ledger being complete.
  • Ledger keys are dataset-scoped. Cognee entity ids are deterministic and the ledger lives in the shared relational database, so every node-derived ledger id is prefixed with the dataset id ("{dataset_id}:{raw_id}"), and relationship ids are built from the prefixed endpoints. Two datasets mentioning the same entity name keep separate version chains.
  • There is one chain, and one writer at a time. Dataset scoping applies to ledger keys and version chains, not to the hash chain itself: every entry in the table shares a single sequence_id sequence, and each commit takes a ledger-wide write lock (a Postgres advisory lock, so it serializes across processes too). Concurrent cognify() runs — several datasets, several workers — therefore queue behind each other for their ledger commits, which is why entries are batched one transaction per task invocation.
  • Custom graph_model schemas are covered. DataPoints that do not follow the default made_from / is_part_of / contains shape are walked with the same traversal add_data_points uses, so every node and edge is still recorded.
  • The table must exist. It ships as Alembic revision b8c1d3e5f7a9; run migrations (cognee.run_migrations(), or alembic upgrade head) before enabling the flag on an existing deployment. The migration is idempotent — it is a no-op if the table is already present.
Entries are read back programmatically through ProvenanceManager, which exposes track_entity, track_chunk, track_relationship, get_provenance, get_lineage, trace_lineage, revision_history, invalidate, verify_chain, check, and get_statistics:
Each entry carries a SHA-256 checksum over its canonical JSON plus the previous entry’s checksum, linked by a unique sequence_id, so verify_chain() detects deletion, reordering, and single-field edits. It streams the ledger in sequence order by keyset pagination rather than materializing it client-side, so it is safe to run against a large table.

Contradiction detection

When CONTRADICTION_DETECTION is enabled, cognify() appends one extra task to the end of the default pipeline. It runs after the graph has been written, so both the new facts and the pre-existing ones are persisted and comparable. For each pair of facts the LLM judges to be in conflict, Cognee logs a warning and writes a contradicts edge into the graph — nothing is rewritten or deleted. There is no cognify() argument for this feature; it is configured entirely through CognifyConfig, which reads these environment variables:
The cognify config is cached for the lifetime of the process, so set these in your .env or environment before the first cognify() call. Changing them mid-process has no effect.
Because entity node ids are deterministic (Entity:<name>), a re-mentioned entity keeps the id it was first stored under — so a new fact and the stored fact it contradicts share a subject and land in the same neighbourhood:
The second run emits a WARNING of the form:
followed by an INFO line reporting how many contradictions were flagged in the graph.

The contradicts edge

Each flagged pair is written as a single edge with relationship_name "contradicts" and these properties: first_fact and second_fact are rendered by Cognee from the graph itself (<source name> <relationship name> <target name>, with underscores in the relationship name replaced by spaces), not taken from the model output, so the stored text always matches the graph. Node names are stored normalized (lowercase), so the rendered facts are lowercase too. The edge connects the two nodes that actually differ: the two subjects when the facts have different subjects, otherwise the two objects. If both facts reference exactly the same pair of nodes, no edge is written. Since it is an ordinary edge, you can read it back with the graph engine:

Scope, cost, and limits

  • Scoped to what you just ingested. Only the 1-hop neighbourhood of the entities the current run touched is inspected — not the whole graph.
  • Structural edges are ignored. contains, is_part_of, made_from, exists_in, and contradicts itself are skipped when building the candidate fact list, as are edges whose endpoints are unnamed (chunks, documents).
  • Fact cap. At most CONTRADICTION_MAX_FACTS facts are compared per check; when the cap is hit, the remainder are skipped and an INFO line is logged. Very large neighbourhoods may therefore be only partially compared.
  • Cost. One additional LLM call per chunk batch, and only when at least two candidate facts were found.
  • Fail-safe and non-destructive. The task only adds edges, returns its input unchanged, and swallows its own errors (logging a warning), so it can never break ingestion.
Contradiction detection needs a graph backend that supports neighbourhood reads. The default provider (and Neo4j, Neptune, the Postgres graph adapter (demo), and Turso) support it; with GRAPH_DATABASE_PROVIDER=kuzu the check currently logs a warning and skips silently, so no contradicts edges are written.

Examples

When custom_prompt is set, it fully replaces the default graph extraction prompt (see GRAPH_PROMPT_PATH) for the entity/relationship extraction step, so you can constrain exactly which entity types and relationship labels the LLM produces. For a step-by-step walkthrough, see the Custom Prompts guide.
custom_prompt is ignored when temporal_cognify=True.

Further details

When run_in_background=True, cognify() starts the processing pipeline as an async background task and returns immediately. The return shape is the same as blocking mode — a dict mapping dataset_idPipelineRunInfo — but each entry has status PipelineRunStarted instead of PipelineRunCompleted, and the knowledge graph construction continues in the background.
The returned PipelineRunInfo fields relevant for monitoring:Possible status values: PipelineRunStarted, PipelineRunYield, PipelineRunCompleted, PipelineRunAlreadyCompleted, PipelineRunErrored.
When using the REST API, subscribe to real-time pipeline updates with the WebSocket endpoint:
Authentication: Use the same authentication context as your REST API session. In cookie-based setups, this is typically the auth_token cookie.Usage example (JavaScript):
Each WebSocket message has this shape:
The server closes the WebSocket with code 1000 (normal closure) once the run reaches PipelineRunCompleted. If authentication fails, the connection is closed with code 1008 (policy violation).
  • Large datasets (>100 MB) where blocking would time out HTTP connections
  • API integrations where you want to return a job ID to the caller immediately
  • Parallel processing of multiple datasets without waiting for each
For small datasets or scripts, the default blocking mode (run_in_background=False) is simpler and returns the final result directly.