> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cognee.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Python Quickstart

> Run your first Cognee workflow with remember and recall.

export const quickstartGraph = {
  "nodes": [{
    "id": "dfbf1aee-1683-5906-945f-90459994d6ac",
    "name": "This chunk states that Cognee turns documents into AI memory. This chunk is about: - Companies: Cognee - Concepts: AI me",
    "type": "TextSummary"
  }, {
    "id": "d71a5252-9709-5136-a411-de523e28ce01",
    "name": "Cognee turns documents into AI memory.",
    "type": "DocumentChunk"
  }, {
    "id": "716f5e85-0419-5919-9019-75e19078d293",
    "name": "text_ae7ae5366a86ae451c74069fc885d07c",
    "type": "TextDocument"
  }, {
    "id": "9f4a531f-57f8-5ea5-a4fa-aad1f6b11884",
    "name": "cognee",
    "type": "Entity"
  }, {
    "id": "b3859a30-625c-5a9c-99c0-5df14c3ab5a4",
    "name": "ai memory",
    "type": "Entity"
  }, {
    "id": "d2a381fa-3658-5ca6-ada9-2109cfc9331d",
    "name": "concept",
    "type": "EntityType"
  }, {
    "id": "388f60fb-220d-55e8-ae9c-3ac93cead308",
    "name": "organization",
    "type": "EntityType"
  }, {
    "id": "4df5a7f1-369f-54f2-87a9-a5a746c7a9dd",
    "name": "documents",
    "type": "Entity"
  }, {
    "id": "3d897781-1f4f-59f0-9622-97d2f17ed585",
    "name": "document",
    "type": "EntityType"
  }],
  "links": [{
    "source": "dfbf1aee-1683-5906-945f-90459994d6ac",
    "target": "d71a5252-9709-5136-a411-de523e28ce01",
    "relation": "made_from"
  }, {
    "source": "d71a5252-9709-5136-a411-de523e28ce01",
    "target": "716f5e85-0419-5919-9019-75e19078d293",
    "relation": "is_part_of"
  }, {
    "source": "d71a5252-9709-5136-a411-de523e28ce01",
    "target": "9f4a531f-57f8-5ea5-a4fa-aad1f6b11884",
    "relation": "contains"
  }, {
    "source": "d71a5252-9709-5136-a411-de523e28ce01",
    "target": "b3859a30-625c-5a9c-99c0-5df14c3ab5a4",
    "relation": "contains"
  }, {
    "source": "d71a5252-9709-5136-a411-de523e28ce01",
    "target": "4df5a7f1-369f-54f2-87a9-a5a746c7a9dd",
    "relation": "contains"
  }, {
    "source": "9f4a531f-57f8-5ea5-a4fa-aad1f6b11884",
    "target": "b3859a30-625c-5a9c-99c0-5df14c3ab5a4",
    "relation": "turns_documents_into"
  }, {
    "source": "9f4a531f-57f8-5ea5-a4fa-aad1f6b11884",
    "target": "388f60fb-220d-55e8-ae9c-3ac93cead308",
    "relation": "is_a"
  }, {
    "source": "b3859a30-625c-5a9c-99c0-5df14c3ab5a4",
    "target": "d2a381fa-3658-5ca6-ada9-2109cfc9331d",
    "relation": "is_a"
  }, {
    "source": "4df5a7f1-369f-54f2-87a9-a5a746c7a9dd",
    "target": "b3859a30-625c-5a9c-99c0-5df14c3ab5a4",
    "relation": "are_turned_into_by_cognee"
  }, {
    "source": "4df5a7f1-369f-54f2-87a9-a5a746c7a9dd",
    "target": "3d897781-1f4f-59f0-9622-97d2f17ed585",
    "relation": "is_a"
  }]
};

export const CogneeGraph = ({data, height = 440, label, fallbackSrc, fallbackAlt}) => {
  const D3_SRC = "https://d3js.org/d3.v7.min.js";
  const COLORS = {
    Entity: "#6510F4",
    EntityType: "#A78BFA",
    DocumentChunk: "#78716C",
    TextSummary: "#2563EB",
    TextDocument: "#A8A29E",
    Company: "#6510F4",
    Department: "#A550FF",
    Person: "#0EA5E9",
    CompanyType: "#94A3B8",
    _default: "#94A3B8"
  };
  const loadD3 = () => {
    if (typeof window === "undefined") return Promise.reject(new Error("no window"));
    if (window.d3 && window.d3.forceSimulation) return Promise.resolve(window.d3);
    if (window.__cogneeD3Promise) return window.__cogneeD3Promise;
    window.__cogneeD3Promise = new Promise((resolve, reject) => {
      const script = document.createElement("script");
      script.src = D3_SRC;
      script.onload = () => window.d3 && window.d3.forceSimulation ? resolve(window.d3) : reject(new Error("d3 loaded without the force module"));
      script.onerror = () => reject(new Error("could not load d3 from " + D3_SRC));
      document.head.appendChild(script);
    });
    return window.__cogneeD3Promise;
  };
  const isDark = () => document.documentElement.classList.contains("dark");
  const colorForNode = d => d.color || COLORS[d.type] || COLORS._default;
  const labelFor = d => {
    const name = d.name || "";
    return name.length > 30 ? name.slice(0, 29) + "…" : name;
  };
  const drawGraph = (host, data, d3, height, label) => {
    const width = host.clientWidth || 680;
    const nodes = data.nodes.map(n => Object.assign({}, n));
    const links = data.links.map(l => Object.assign({}, l));
    const degree = {};
    links.forEach(l => {
      degree[l.source] = (degree[l.source] || 0) + 1;
      degree[l.target] = (degree[l.target] || 0) + 1;
    });
    host.textContent = "";
    const svg = d3.select(host).append("svg").attr("width", "100%").attr("height", height).attr("viewBox", [0, 0, width, height]).attr("role", "img").attr("aria-label", label || "Knowledge graph").style("display", "block").style("max-width", "100%").style("cursor", "grab");
    const root = svg.append("g");
    const zoom = d3.zoom().scaleExtent([0.3, 6]).on("zoom", event => root.attr("transform", event.transform));
    svg.call(zoom);
    const link = root.append("g").attr("stroke-linecap", "round").selectAll("line").data(links).join("line").attr("stroke", () => isDark() ? "#4b5563" : "#cbd5e1").attr("stroke-width", 1.2);
    const node = root.append("g").selectAll("g").data(nodes).join("g").style("cursor", "pointer");
    node.append("circle").attr("r", d => 6 + Math.min(degree[d.id] || 0, 6)).attr("fill", d => colorForNode(d)).attr("stroke", () => isDark() ? "#111827" : "#ffffff").attr("stroke-width", 1.5);
    node.append("title").text(d => d.name + " — " + d.type);
    node.append("text").text(d => labelFor(d)).attr("x", d => 9 + Math.min(degree[d.id] || 0, 6)).attr("y", 4).attr("font-size", 11).attr("font-family", "system-ui, -apple-system, sans-serif").attr("fill", () => isDark() ? "#e5e7eb" : "#374151").attr("paint-order", "stroke").attr("stroke", () => isDark() ? "#0b0b0d" : "#ffffff").attr("stroke-width", 3);
    const neighbors = {};
    links.forEach(l => {
      (neighbors[l.source] = neighbors[l.source] || ({}))[l.target] = true;
      (neighbors[l.target] = neighbors[l.target] || ({}))[l.source] = true;
    });
    node.on("mouseenter", (event, d) => {
      node.style("opacity", o => o.id === d.id || neighbors[d.id] && neighbors[d.id][o.id] ? 1 : 0.15);
      link.style("opacity", l => l.source.id === d.id || l.target.id === d.id ? 1 : 0.08);
    }).on("mouseleave", () => {
      node.style("opacity", 1);
      link.style("opacity", 1);
    });
    const draw = () => {
      link.attr("x1", d => d.source.x).attr("y1", d => d.source.y).attr("x2", d => d.target.x).attr("y2", d => d.target.y);
      node.attr("transform", d => "translate(" + d.x + "," + d.y + ")");
    };
    const setLabelScale = counter => {
      node.selectAll("text").attr("font-size", 11 * counter).attr("stroke-width", 3 * counter).attr("y", 4 * counter).attr("x", d => (9 + Math.min(degree[d.id] || 0, 6)) * counter);
    };
    const scaleFor = box => {
      const pad = 14;
      return Math.min((width - pad * 2) / box.width, (height - pad * 2) / box.height, 1.4);
    };
    const fit = () => {
      let box = root.node().getBBox();
      if (!(box.width > 0) || !(box.height > 0)) return;
      let scale = scaleFor(box);
      for (let pass = 0; pass < 3; pass++) {
        setLabelScale(Math.min(Math.max(1 / scale, 1), 1.9));
        box = root.node().getBBox();
        scale = scaleFor(box);
      }
      const tx = (width - scale * (box.x * 2 + box.width)) / 2;
      const ty = (height - scale * (box.y * 2 + box.height)) / 2;
      svg.call(zoom.transform, d3.zoomIdentity.translate(tx, ty).scale(scale));
    };
    const simulation = d3.forceSimulation(nodes).force("link", d3.forceLink(links).id(d => d.id).distance(70).strength(0.6)).force("charge", d3.forceManyBody().strength(-320)).force("center", d3.forceCenter(width / 2, height / 2)).force("collide", d3.forceCollide(34));
    simulation.stop();
    for (let i = 0; i < 320; i++) simulation.tick();
    draw();
    fit();
    simulation.on("tick", draw);
    node.call(d3.drag().on("start", (event, d) => {
      if (!event.active) simulation.alphaTarget(0.3).restart();
      d.fx = d.x;
      d.fy = d.y;
    }).on("drag", (event, d) => {
      d.fx = event.x;
      d.fy = event.y;
    }).on("end", (event, d) => {
      if (!event.active) simulation.alphaTarget(0);
      d.fx = null;
      d.fy = null;
    }));
    const counts = {};
    const swatch = {};
    nodes.forEach(n => {
      counts[n.type] = (counts[n.type] || 0) + 1;
      if (!swatch[n.type]) swatch[n.type] = colorForNode(n);
    });
    const legend = document.createElement("div");
    legend.style.cssText = "display:flex;flex-wrap:wrap;gap:12px;padding:8px 2px 0;font-size:12px;" + "font-family:system-ui,-apple-system,sans-serif;color:" + (isDark() ? "#9ca3af" : "#6b7280");
    Object.keys(counts).sort().forEach(type => {
      const item = document.createElement("span");
      item.style.cssText = "display:inline-flex;align-items:center;gap:5px";
      const dot = document.createElement("span");
      dot.style.cssText = "width:9px;height:9px;border-radius:50%;background:" + swatch[type];
      item.appendChild(dot);
      item.appendChild(document.createTextNode(type + " (" + counts[type] + ")"));
      legend.appendChild(item);
    });
    host.appendChild(legend);
    return () => simulation.stop();
  };
  const hostRef = useRef(null);
  const fallbackRef = useRef(null);
  useEffect(() => {
    let cancelled = false;
    let teardown = null;
    let themeObserver = null;
    let sizeObserver = null;
    const hideFallback = () => {
      if (fallbackRef.current) fallbackRef.current.style.display = "none";
    };
    const whenVisible = host => host.offsetParent !== null ? Promise.resolve() : new Promise(resolve => {
      const done = () => {
        if (sizeObserver) sizeObserver.disconnect();
        resolve();
      };
      sizeObserver = new ResizeObserver(() => {
        if (host.offsetParent !== null) done();
      });
      sizeObserver.observe(host);
      setTimeout(done, 10000);
    });
    loadD3().then(d3 => hostRef.current ? whenVisible(hostRef.current).then(() => d3) : d3).then(d3 => {
      if (cancelled || !hostRef.current) return;
      teardown = drawGraph(hostRef.current, data, d3, height, label);
      hideFallback();
      let wasDark = isDark();
      themeObserver = new MutationObserver(() => {
        if (isDark() === wasDark || cancelled || !hostRef.current) return;
        wasDark = isDark();
        if (teardown) teardown();
        teardown = drawGraph(hostRef.current, data, d3, height, label);
      });
      themeObserver.observe(document.documentElement, {
        attributes: true,
        attributeFilter: ["class"]
      });
    }).catch(err => {
      console.warn("[CogneeGraph] falling back to the static image:", err.message);
    });
    return () => {
      cancelled = true;
      if (teardown) teardown();
      if (themeObserver) themeObserver.disconnect();
      if (sizeObserver) sizeObserver.disconnect();
    };
  }, [data, height, label]);
  return <div style={{
    position: "relative",
    minHeight: height
  }} data-cognee-graph="">
      <div ref={hostRef} style={{
    minHeight: height
  }} />
      {fallbackSrc ? <img ref={fallbackRef} src={fallbackSrc} alt={fallbackAlt || label || "Knowledge graph"} style={{
    position: "absolute",
    top: 0,
    left: 0,
    width: "100%",
    height: height,
    objectFit: "contain"
  }} /> : null}
    </div>;
};

After completing the [installation steps](https://docs.cognee.ai/getting-started/installation) successfully, run your first Cognee example to see AI memory in action.

## Run it without an API key

If you haven't configured `LLM_API_KEY` yet, one CLI command proves the install works:

```bash theme={null}
cognee-cli demo
```

It imports a small knowledge graph that ships inside the `cognee` package and answers two example questions from it. The import is graph-only (no embeddings are computed) and the queries use `CHUNKS_LEXICAL`, a keyword search — so the whole run makes **no LLM calls and no embedding calls**, and works on a machine with no network access. The only outbound request is Cognee's anonymous telemetry event, which is best-effort (it fails silently offline) and switched off entirely by [`TELEMETRY_DISABLED=true`](/setup-configuration/overview#observability--telemetry). Clean up afterwards with `cognee-cli forget --dataset demo`.

See the [CLI reference](/cognee-cli/overview#try-the-demo-graph) for its flags and output.

<Note>
  The demo is a keyword search over a pre-built graph. The Python example below builds a graph from your own text and gets an LLM-written answer, so it does need `LLM_API_KEY` configured.
</Note>

## Basic Usage

This minimal example shows how to store content and retrieve it:

```python theme={null}
import cognee
import asyncio

async def main():
    # Create a clean slate for cognee -- reset data and system state
    await cognee.forget(everything=True)

    # Store content in memory (ingests, builds knowledge graph, enriches)
    text = "Cognee turns documents into AI memory."
    await cognee.remember(text)

    # Retrieve from memory
    results = await cognee.recall(
        query_text="What does Cognee do?"
    )

    # Print
    for result in results:
        print(result.text)

if __name__ == '__main__':
    asyncio.run(main())
```

<Accordion title="Example output">
  ```text theme={null}
  Cognee converts (transforms) documents into AI memory — a structured, queryable representation of document content for AI systems.
  ```

  Output wording may vary by provider and model, but it should answer the question using the text stored with <code>remember</code>.
</Accordion>

<Accordion title="Visualisation">
  <p>Interactive knowledge graph visualization -- drag nodes, zoom, and hover for details. Create your own visualization with 2 additional lines of code [here](/guides/graph-visualization).</p>

  <CogneeGraph data={quickstartGraph} height={420} label="Knowledge graph built by the Quickstart: one remembered sentence, chunked, summarised, and mined for entities" fallbackSrc="/images/examples/quickstart-graph.png" fallbackAlt="Force-directed graph linking a text document to its chunk, the chunk to a summary, and the chunk to the entities cognee extracted from it." />
</Accordion>

## What just happened

The code demonstrates Cognee's two primary v1.0 operations:

* **`.remember`** — Stores data in memory. Under the hood it runs ingestion, chunking, entity extraction, graph building, and a follow-up enrichment pass. The result is a fully queryable knowledge graph.
* **`.recall`** — Retrieves from memory. It auto-routes the query to the best retrieval strategy and returns contextual results from the knowledge graph.

## About `async` / `await` in Cognee

<Note>
  **Cognee uses asynchronous code extensively.** That means many of its functions are defined with `async` and must be called with `await`. This lets Python handle waiting (e.g. for I/O or network calls) without blocking the rest of your program.
</Note>

<Accordion title="Async basics">
  This example uses <code>async</code> / <code>await</code>, Python’s way of doing asynchronous programming.
  Asynchronous programming is used when functions may block because they are waiting for something (for example, a reply from an API call). By writing <code>async def</code>, you define a function that can pause at certain points.
  The <code>await</code> keyword marks those calls that may need to pause.
  To run such functions, Python provides the <code>asyncio</code> library. It uses a loop, called the event loop, which executes your code in order but, whenever a function is waiting, can temporarily run another one. From inside your function, though, everything still runs top-to-bottom: each line after an <code>await</code> only executes once the awaited call has finished.
</Accordion>

<Accordion title="Async resources">
  * A good starting point is this [guide](https://realpython.com/async-io-python/).
  * Official documentation is available [here](https://docs.python.org/3/library/asyncio.html).
</Accordion>

## Next Steps

<CardGroup cols={2}>
  <Card title="Cognee core concepts" href="/core-concepts/overview" icon="compass">
    Learn about Cognee's core concepts, architecture, building blocks, and main operations.
  </Card>

  <Card title="Improve and enrich memory" href="/core-concepts/main-operations/improve" icon="sparkles">
    Enrich an existing graph and bridge session memory into permanent memory.
  </Card>
</CardGroup>
