Skip to main content
A minimal guide to rendering your current knowledge graph to an interactive HTML file with one call. Before you start:
  • Complete Quickstart to understand basic operations
  • Have some remembered data or any existing knowledge graph

What Graph Visualization Shows

  • Nodes (entities, types, chunks, summaries) with color coding
  • Edges with labels and weights; tooltips show extra edge properties
  • Interactive features: drag nodes, zoom/pan, hover edges for details

Code in Action

Step 1: Create Your Knowledge Graph

await cognee.forget(everything=True)

await cognee.remember(
    ["Alice knows Bob.", "NLP is a subfield of CS."],
    self_improvement=False,
)
This starts from a clean state, then uses remember() to ingest the text and build the graph in one call.

Step 2: Generate Visualization

visualize_graph_path = os.path.join(
    os.path.dirname(__file__), ".artifacts", "graph_after_remember.html"
)
await visualize_graph(visualize_graph_path)
This creates an interactive HTML file with your knowledge graph. You can specify a custom path or use the default location.

Quick Options

Default Location

from cognee.api.v1.visualize.visualize import visualize_graph

# Writes HTML to your home directory by default
await visualize_graph()

Custom Path

from cognee.api.v1.visualize.visualize import visualize_graph

# Writes to the provided file path (created/overwritten)
await visualize_graph("./my_graph.html")

Tips

  • Large graphs: Rendering a very big graph can be slow. Consider building subsets (e.g., smaller datasets) before visualizing
  • Edge weights: If present, control line thickness; multiple weights are summarized and shown in tooltips
  • Static HTML: Files are static HTML; you can open them in any modern browser or share them as artifacts

Additional information

get_schema_inventory() summarizes your knowledge graph by semantic type instead of rendering every node. It returns deterministic per-type instance counts, a bounded set of representative sample names, and the relationship distribution between types — useful for understanding the shape of a graph at a glance or for driving custom dashboards.
import cognee

inventory = await cognee.get_schema_inventory(
    dataset=None,           # optional dataset UUID to scope the graph databases
    samples_per_type=5,     # max sample instance names per type (default 5)
    sort="count",           # "count" (default, descending) or "none" (discovery order)
)
Each list entry is a dict describing one semantic type:
{
    "type": "Person",           # semantic type name
    "count": 42,                 # total instances of this type
    "samples": ["Carlos", ...],  # up to samples_per_type representative names
    "sample_size": 5,            # number of names actually returned
    "relationships": [           # aggregated edges involving this type
        {"to_type": "Broker", "relation": "works_at", "count": 12},
        # incoming edges are shown with a "← " prefix on the relation name
    ],
}
Extracted entities are grouped under their resolved semantic type (the EntityType reached via the is_a edge) rather than the generic "Entity" label, and the internal EntityType taxonomy nodes are not surfaced as their own group. Passing a negative samples_per_type, or a sort value other than "count"/"none", raises ValueError.The same projection is available over HTTP at GET /api/v1/schema/inventory (query params dataset_id, samples_per_type, sort). The endpoint is caller-scoped: it returns 403 when the caller is not authorized to read the dataset, and 409 if the inventory cannot be built.
visualize_memory_provenance() renders the ownership and data-flow story behind your memory — Tenant → User → Agent → Dataset → file, plus agent read/write access and agent-written sessions — to a self-contained HTML file.
import os
import cognee

dest = os.path.join(os.path.expanduser("~"), "memory_provenance.html")

await cognee.visualize_memory_provenance(
    destination_file_path=dest,
    include_memory=False,   # when True, fold in extracted entities/relationships
)
This projection is read purely from the relational database — it does not require the graph backend or an LLM, so it works even when the graph database is unavailable. Set include_memory=True to also fold in the extracted entities/relationships (from the relational nodes/edges tables) and link them back to the files they were extracted from.If you only need the projected graph data (in the same (nodes, edges) shape the renderer consumes) rather than HTML, call get_memory_provenance_graph():
nodes, edges = await cognee.get_memory_provenance_graph(include_memory=True)
Both functions accept scope_tenant_ids and scope_user_ids to restrict the projection to a tenant or user. In multi-tenant deployments you must pass a scope — an unscoped read returns every tenant’s actors, datasets, and files. When neither scope is given the read is global, which is the intended behavior only for single-user / OSS installs where one user owns everything. The HTTP endpoint GET /api/v1/schema/provenance (query param include_memory) always scopes to the authenticated caller’s tenant (or user).
If visualize_graph() logs No nodes found in the database (or the HTML opens empty) even though add() and cognify() ran without errors, the most common causes are:
  • Graph path mismatch. With the default Ladybug backend, the graph is stored on disk under <SYSTEM_ROOT_DIRECTORY>/databases/. By default, SYSTEM_ROOT_DIRECTORY is an absolute .cognee_system path under Cognee’s package root. In notebooks like Colab, it is safer to set explicit absolute paths before running add(), cognify(), and visualize_graph() so every step uses the same persisted location across cells and runtime changes:
    import cognee
    
    cognee.config.system_root_directory("/content/cognee_system")
    cognee.config.data_root_directory("/content/cognee_data")
    
  • cognify() produced no nodes. A run can finish “successfully” yet extract nothing — for example if no data was actually ingested, or graph extraction silently returned empty results (often a misconfigured or failing LLM/embedding provider). Don’t rely on the absence of an error; verify the graph was populated.
  • Data was pruned in between. Calling cognee.forget(everything=True) (or cognee.prune) after cognify() clears the graph, so a later visualize_graph() sees nothing.

Verify the graph was populated

Before visualizing, query the graph engine directly. get_graph_data() returns a (nodes, edges) tuple, and get_graph_metrics() reports the node/edge counts:
from cognee.infrastructure.databases.graph import get_graph_engine

graph_engine = await get_graph_engine()

nodes, edges = await graph_engine.get_graph_data()
print(f"nodes={len(nodes)}, edges={len(edges)}")

metrics = await graph_engine.get_graph_metrics()
print(metrics)  # {'num_nodes': ..., 'num_edges': ..., ...}
If len(nodes) is 0 here, the problem is upstream in add()/cognify() (or a path mismatch), not in visualization. A non-zero count from the same process that then reports No nodes found points to a path/config mismatch between steps.

Full Examples

Two runnable demos exercise the schema inventory and provenance projection end-to-end without an LLM and write standalone HTML to your home directory:
  • examples/python/schema_inventory_demo.py~/cognee_schema_demo.html
  • examples/python/memory_provenance_demo.py~/cognee_provenance_demo.html
Additional examples about Graph visualization are available on our github.
import asyncio
import cognee
import os
from cognee.api.v1.visualize.visualize import visualize_graph


async def main():
    # Prune data and system metadata before running, only if we want "fresh" state.
    await cognee.forget(everything=True)

    await cognee.remember(
        ["Alice knows Bob.", "NLP is a subfield of CS."],
        self_improvement=False,
    )

    visualize_graph_path = os.path.join(
        os.path.dirname(__file__), ".artifacts", "graph_after_remember.html"
    )
    await visualize_graph(visualize_graph_path)


if __name__ == "__main__":
    asyncio.run(main())
import asyncio
import cognee
import os
from cognee.api.v1.visualize.visualize import visualize_graph


async def main():
    await cognee.add(["Alice knows Bob.", "NLP is a subfield of CS."])
    await cognee.cognify()

    visualize_graph_path = os.path.join(
        os.path.dirname(__file__), ".artifacts", "graph_visualization.html"
    )
    await visualize_graph(visualize_graph_path)


if __name__ == "__main__":
    asyncio.run(main())
This simple example uses basic text data for demonstration. In practice, you can visualize complex knowledge graphs with thousands of nodes and relationships.

Core Concepts

Understand knowledge graph fundamentals

Custom Data Models

Learn about custom data models