Skip to main content

cognee.datasets

Static class for managing datasets and their data. Methods that target a specific dataset identify it by UUID, never by name — see dataset name vs dataset id for how the two relate and which identifier each operation accepts. For lower-level helpers such as get_dataset(), get_datasets_by_name(), and create_authorized_dataset(), see Dataset helper methods below.

Methods

datasets.list_datasets()

Returns all datasets accessible to the resolved user.

datasets.discover_datasets()

Discover dataset names from a local directory layout.

datasets.list_data()

Returns all Data records in a dataset, newest first (created_at descending, ties broken by id). This is the API to use when you want to read back DataItem fields stored during cognee.add(), such as label and external_metadata. The method itself takes no paging arguments and always returns the complete set, whatever its size. How it gets there differs by mode: locally it reads every row in one query, with no pagination or offset limit in play, while in remote mode it walks the server’s bounded pages for you — see below.

Remote mode (serve())

While a serve() connection is active, list_data() reads the remote dataset over GET /api/v1/datasets/{dataset_id}/data instead of the local store, so it works for datasets that exist only on the remote instance. The user argument is ignored on that path: the API key used by serve() identifies the caller, and the server runs its own permission check. That endpoint is paginated, so the remote path requests pages of 1000 rows and advances until a short page comes back, deduplicating rows on id in case a concurrent insert or delete shifts them between pages. The return value is still the whole dataset, but it is assembled from several round trips rather than one — reading a large dataset over a connection costs one request per 1000 rows. A server that does not honor the request raises RuntimeError rather than looping: a response that is not a list, and one that comes back longer than the requested page or contains only rows already seen. Any 4xx/5xx raises too — including the 422 the server returns once traversal passes offset 1,000,000, which puts a dataset of 1,001,000 rows or more out of reach of this method (at exactly that size the last page comes back full, so the traversal asks for one more and takes the 422 instead of returning). If you only need a total, call GET /api/v1/datasets/{dataset_id}/data/count instead of listing the rows. Remote rows are parsed back through DataDTO, the same wire model the server serializes them with, so the fields it returns carry the same attribute names and types as their local counterparts — row.id is a UUID (not a string), and the field is row.mime_type (not camelCase mimeType). label and external_metadata survive the round trip, so the DataItem fields stored during cognee.add() are readable remotely too. A remote row exposes exactly these fields: id, name, created_at, updated_at, extension, mime_type, raw_data_location, dataset_id, label, external_metadata, and data_size (the stored file size in bytes, None for a row written without one). created_at is also optional and can be None for rows written by a writer that skipped the ORM default. A local Data record carries more — content_hash, owner_id, tenant_id, loader_engine, system_metadata, and others — so code that reads those attributes works locally and raises AttributeError over a connection.
list_datasets() is not routed to the remote instance — it still reads the local store. The common pattern of listing datasets and then reading one’s data breaks over a serve() connection, because the dataset ids come from the local store and the data lookup goes to the remote one. Get remote dataset ids from the instance itself (GET /api/v1/datasets) or from the Cognee Cloud UI, and pass them to list_data() directly.

datasets.has_data()

Check whether a dataset contains any data.

datasets.get_status()

Get pipeline status for one or more datasets. When pipeline_names is omitted, this method keeps the legacy flat shape and returns the status of cognify_pipeline only. With no pipeline_names or a single pipeline name, the method returns {str(dataset_id): PipelineRunStatus}. With multiple pipeline names, it returns {str(dataset_id): {pipeline_name: PipelineRunStatus}}. Possible values: Datasets with no recorded run for the requested pipeline are absent from the result.
get_status() reports the state of a dataset’s pipeline run. For the state of its individual items — which data items carry the per-item completion stamp for a pipeline — use the HTTP endpoint GET /api/v1/datasets/{dataset_id}/processing-status. There is no SDK method for it.
get_status() expects dataset_ids to be a list of dataset UUIDs, not dataset names or string ids. Internally the values are bound against the pipeline_runs.dataset_id UUID column, so passing a plain string raises a SQLAlchemy StatementError wrapping one of:
  • AttributeError: 'str' object has no attribute 'hex'
  • ValueError: badly formed hexadecimal UUID string
If you already hold a string id (for example one read back from the HTTP API), wrap it in UUID before calling:

datasets.empty_dataset()

Delete all data in a dataset and remove the dataset itself.
Despite the name, empty_dataset() does not leave an empty dataset record behind. It deletes graph content, data records, and the dataset entity itself.

datasets.delete_data()

Delete a specific data item from a dataset.
mode="hard" is preserved for backward compatibility, but the implementation explicitly warns not to use it.
delete_data() is not a relational-only operation. It cleans up every backend that holds memory derived from the targeted data item:Session cleanup is best-effort: a cache failure is logged as a warning and never fails delete_data(), so a {"status": "success"} result does not guarantee every entry was removed. It is also the fine-grained variant — empty_dataset() deletes every session attributed to the dataset outright (and only then applies this same targeted pass to unattributed sessions), and forget(everything=True) prunes the cache wholesale.What is intentionally left behind:
  • Shared nodes. An entity such as "New York" that another data item also references stays in the graph and vector store; only nodes unique to the deleted item are dropped. Relationships between surviving shared nodes are not deleted either.
  • The dataset. The dataset record survives unless you pass delete_dataset_if_empty=True and the removed item was the last one.
See Delete for the same flow in narrative form, and forget() for a scope matrix across all deletion modes.
delete_data() only removes; it never re-extracts. To propagate an edit to a source document through the graph and vector stores, use update(), which by default diffs the new content against the stored text and replaces only the chunks the edit touched — falling back to a full rebuild that drops the document’s memory with forget(memory_only=True), refreshes the same record with the new content, and re-runs cognify on the dataset when the chunk-level preconditions are not met:
Relationships that existed only in the old version disappear with the deleted nodes; relationships found in the new content are created by the cognify step. incremental_loading=True (the default) keeps the other, unchanged documents in the dataset from being reprocessed — pass incremental_loading=False only when the whole dataset should be rebuilt, for example after changing your graph model or prompts.To clear a document’s derived memory while keeping its record and raw file, use forget(..., memory_only=True) and re-run cognify.

datasets.delete_all()

Delete all datasets the user has permission to delete.

Dataset helper methods

cognee.datasets covers the common cases. Underneath it, Cognee exports a set of dataset helpers importable from cognee.modules.data.methods. Use them when you need to resolve a dataset by name or id, create one explicitly, or apply a permission type other than read. All of them are async except check_dataset_name().

Fetching datasets

Ownership-scoped lookups (they match on Dataset.owner_id only, ignoring ACLs): Permission-aware lookups (they take a User object and go through the permissions system, so they also return datasets shared with the user): permission_type is one of read, write, delete, or share.

Creating and deleting datasets

Because a Data row belongs to exactly one dataset, delete_dataset() also deletes that dataset’s Data rows. Each removal goes through the same raw-file rule as delete_data(): the file on disk is only removed when no other Data row still points at that raw_data_location and it lives under DATA_ROOT_DIRECTORY. Use datasets.empty_dataset() when you want to clear a dataset’s data but keep the dataset itself.

Examples

Use get_status() in a wait loop to confirm all datasets in a parallel batch have finished indexing before querying.
The same pattern works when indexing is triggered via the HTTP API — poll get_status() from a separate process until all datasets reach DATASET_PROCESSING_COMPLETED or DATASET_PROCESSING_ERRORED.
external_metadata is stored on the relational Data record only. It is not placed into the vector store or knowledge graph and is not returned by cognee.search(). If you need metadata to be vector-searchable, define a custom DataPoint subclass and list the fields to embed in metadata.index_fields. See DataPoints.