Build a Personal Assistant with Memory

Store and recall personal facts across sessions using a knowledge graph.

Introduction

30 Second Summary

Have you ever wished your AI assistant could remember things about you between conversations? Most chatbots start with a blank slate every time you talk to them, forgetting everything from previous sessions.

In this project, you will build a terminal-based personal assistant that stores facts about you in a knowledge graph and recalls them across completely separate script runs, proving that memory persists even after your program exits.

What You'll Build

A Python-powered personal assistant that uses Cognee Cloud's REST API to store, process, and retrieve your personal facts through a combination of vector embeddings and graph relationships.

By the end of this project, you'll have:

  • A store_memory.py script that feeds personal facts to Cognee Cloud and triggers knowledge graph construction (entity extraction, vector embeddings, and graph relationships).
  • A recall_memory.py script that queries those memories from a completely separate process, proving persistent cross-session memory.
  • An interactive assistant.py that lets you store and recall memories in a loop with simple commands.
  • Secret Mission: Compare vector search vs graph search vs hybrid retrieval to understand why Cognee uses both layers.

Are there any prerequisites?

You need basic Python familiarity (variables, functions, loops) and a Google account to sign in to Cognee Cloud. No prior experience with AI, APIs, or knowledge graphs is required.

Set Up Your Project

Before your assistant can remember anything, it needs a connection to Cognee Cloud. Cognee Cloud is the hosted service that stores your knowledge graph, runs the AI processing, and keeps your memories available 24/7.

In this step, you will create a Cognee Cloud account, set up a Python project with the right dependencies, and confirm that your code can talk to Cognee's servers.

In this step, get ready to:
  • Create a Cognee Cloud account and generate an API key.
  • Set up a Python project with a virtual environment and the requests library.
  • Verify that your API key works by hitting Cognee's health endpoint.
Create a Cognee Cloud account

Cognee Cloud gives you a hosted knowledge graph, vector database, and LLM processing pipeline. You access it all through a single API key.

  • Open your browser and navigate to platform.cognee.ai.
  • Click Google to sign in with your Google account.
  • In the sidebar, click API Keys.
  • Click Create API key.
  • Copy the generated key immediately. It is shown only once.

What is an API key?

An API key is a unique string that identifies your code to Cognee's servers. Every request you send must include this key so Cognee knows who is asking. Think of it like a password that proves your script has permission to read and write your memories.

Is this free?

The free tier includes 1M tokens (about 750,000 words of processing) and requires no credit card according to cognee.ai pricing. If you are prompted for a payment method during sign-up, this is standard for activating the free tier. You will not be charged within the free tier limits.

Set up the Python project

Now you will create a dedicated folder and a Python virtual environment to keep this project's dependencies isolated from your system.

  • Press Ctrl+Alt+T to open a terminal.
  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create your project folder and move into it by running these commands:
mkdir cognee-memory
cd cognee-memory
  • Confirm the folder exists by running:
pwd

You should see a path ending in cognee-memory.

  • Create and activate a Python virtual environment by running these commands:
python3 -m venv .venv
source .venv/bin/activate

Your terminal prompt should now show (.venv) at the beginning. This confirms the virtual environment is active.

  • Install the requests library by running:
pip install requests

You should see output ending with Successfully installed followed by the package name.

Seeing a permission error or network timeout?

  • Make sure you activated the virtual environment first. Your prompt should show (.venv).
  • Check your internet connection. pip needs to download packages from the internet.
  • If you see a pip version warning, you can ignore it safely. The install still succeeded.

Still stuck? Help me troubleshoot my pip install.

Now create the configuration file that stores your API key and base URL. Open your text editor and create a new file called config.py inside the cognee-memory folder.

  • Paste the following code into config.py:
API_KEY = "your-api-key-here"
BASE_URL = "https://api.cognee.ai"

HEADERS = {
    "Content-Type": "application/json",
    "X-Api-Key": API_KEY
}
  • Replace your-api-key-here with the API key you copied from Cognee Cloud. Keep the quotes around it.

What does this file do?

  • API_KEY stores your personal key that authenticates requests to Cognee.
  • BASE_URL is the root address of Cognee's cloud API.
  • HEADERS bundles the content type and your API key together so every request uses the same authentication automatically.
  • Save config.py.

Not sure where to save the file?

The file must be saved directly inside the cognee-memory folder on your Desktop. If you run ls in your terminal, you should see config.py listed.

Having trouble? Help me find where to save my config file.

Verify the connection

Before building anything further, you need to confirm that your API key works and your code can reach Cognee's servers.

  • Create a new file called test_connection.py in the same cognee-memory folder.
  • Paste the following code into test_connection.py:
import requests
from config import BASE_URL, HEADERS

print("Testing connection to Cognee Cloud...")
response = requests.get(f"{BASE_URL}/health", headers=HEADERS)
print(f"Status: {response.status_code}")
print(f"Response: {response.text}")

if response.status_code == 200:
    print("\nConnection successful! Your API key works.")
else:
    print("\nConnection failed. Check your API key in config.py")

What does this script do?

  • It imports BASE_URL and HEADERS from your config.py so it knows where to connect and how to authenticate.
  • It sends a GET request to the /health endpoint, which is a simple availability check on Cognee's servers.
  • If the response status code is 200, your key is valid and the connection works.
  • Save test_connection.py.
  • Run the test script by executing this command in your terminal:
python3 test_connection.py

You should see output that includes Status: 200 and the message Connection successful! Your API key works..

Seeing Connection failed or a non-200 status?

  • Open config.py and double-check that your API key is pasted correctly with no extra spaces.
  • Make sure BASE_URL is exactly https://api.cognee.ai with no trailing slash.
  • Confirm your virtual environment is still active (you should see (.venv) in your prompt). If not, run source .venv/bin/activate again.

Still stuck? Help me debug my Cognee Cloud connection test.

✔️ Awesome, I've got everything!

Great. Double check you have saved both files.

ⓧ I'd like to double check the full code

Here is the complete code for both files at this point:

API_KEY = "your-api-key-here"
BASE_URL = "https://api.cognee.ai"

HEADERS = {
    "Content-Type": "application/json",
    "X-Api-Key": API_KEY
}
import requests
from config import BASE_URL, HEADERS

print("Testing connection to Cognee Cloud...")
response = requests.get(f"{BASE_URL}/health", headers=HEADERS)
print(f"Status: {response.status_code}")
print(f"Response: {response.text}")

if response.status_code == 200:
    print("\nConnection successful! Your API key works.")
else:
    print("\nConnection failed. Check your API key in config.py")

Your environment is ready and your code can talk to Cognee Cloud. Next up, you will feed personal facts into Cognee and watch it build a knowledge graph.

Feed Memories to Cognee

Your connection to Cognee Cloud is working. Now it's time to give it something to remember.

In this step, you'll write a script that sends personal facts about you to Cognee and then triggers the AI to build a knowledge graph from those facts. Think of it as feeding ingredients to a chef, then asking the chef to cook.

In this step, get ready to:
  • Write an ingestion script that sends facts to Cognee's servers.
  • Trigger the knowledge graph build and watch the LLM do its work.
  • Verify the graph was built successfully.
Write the ingestion script

Ingestion is the first stage of Cognee's pipeline. You send raw text to Cognee Cloud, and it stores that text on its servers. No AI processing happens yet.

  • Create a new file called store_memory.py in your cognee-memory folder and add the following ingestion code:
import requests
import time
from config import BASE_URL, HEADERS

print("=" * 50)
print("STEP 1: Feeding memories to Cognee")
print("=" * 50)

memories = [
    "My name is Alex and I am a developer.",
    "I know Python and Go programming languages. I have more experience with Go than Python.",
    "I am participating in the WeMakeDevs x Cognee hackathon.",
    "I prefer building backend systems over frontend.",
    "I am learning about AI agents, knowledge graphs, and vector search.",
]

print("\nSending facts to Cognee Cloud (ingestion)...")
print("This is like putting ingredients on the counter - no cooking yet.\n")

for memory in memories:
    response = requests.post(
        f"{BASE_URL}/api/v1/add",
        json={"data": memory},
        headers=HEADERS
    )
    status = "OK" if response.status_code == 200 else f"ERROR {response.status_code}"
    print(f"  [{status}] {memory}")

What does this code do?

The memories list holds five facts about you. These are the raw ingredients for your knowledge graph.

The for loop sends each fact to Cognee's /api/v1/add endpoint one at a time. This is pure ingestion. Cognee receives the text and holds it, but no AI has processed it yet.

You won't run this file yet. The next chunk adds the step that triggers the AI.

Trigger the knowledge graph build

Ingestion only stores raw text. To turn that text into structured knowledge, you need to call the cognify endpoint. This is where Cognee sends your text to an LLM for real processing.

  • Add the following code to the bottom of store_memory.py:
print("\n" + "=" * 50)
print("STEP 2: Building the knowledge graph (cognify)")
print("=" * 50)

print("\nThis triggers the LLM to:")
print("  1. Chunk the text into pieces")
print("  2. Extract entities (Alex, Python, Go, hackathon...)")
print("  3. Find relationships (Alex KNOWS Python, Alex PARTICIPATES_IN hackathon)")
print("  4. Create vector embeddings (number-representations of meaning)")
print("  5. Store entities + relationships in graph database")
print("  6. Store embeddings in vector database")
print("\nThis is where tokens get used - the LLM is doing real work!\n")

response = requests.post(
    f"{BASE_URL}/api/v1/cognify",
    json={"datasets": ["main_dataset"]},
    headers=HEADERS
)
print(f"Cognify triggered: {response.status_code}")
print(f"Response: {response.text[:200]}")

print("\nWaiting 15 seconds for the knowledge graph to be built...")
time.sleep(15)

print("\n" + "=" * 50)
print("DONE!")
print("=" * 50)
print("\nYour memories are now stored in a knowledge graph on Cognee Cloud.")
print("The graph has ENTITIES (you, Python, Go, hackathon)")
print("and RELATIONSHIPS between them (you KNOW Python, you PARTICIPATE_IN hackathon).")
print("\nNow CLOSE this script and run: python3 recall_memory.py")
print("That will prove memory persists across sessions!")

What happens inside cognify?

When you call /api/v1/cognify, Cognee sends your stored text to an LLM on its servers. The LLM extracts entities (like "Alex", "Python", "Go") and relationships between them (like "Alex KNOWS Python").

Cognee then creates vector embeddings (number-representations of meaning) and stores everything in two databases: a graph database for relationships, and a vector database for semantic search. This is why it uses your free-tier tokens.

The time.sleep(15) pause gives the LLM time to finish processing. Cognify is asynchronous, meaning it runs in the background after you call it.

Run the script and verify the build
  • Save store_memory.py.
  • Run the script by entering this command in your terminal:
python3 store_memory.py

You should see each memory printed with an [OK] status, followed by the cognify explanation, a 15-second wait, and a "DONE!" message at the end.

What should I see?

Your terminal will show five lines with [OK] next to each memory. Then you'll see the cognify step fire, a 15-second pause, and a final message telling you to close the script and run recall_memory.py.

If you see [ERROR 401] next to any memory, your API key in config.py is incorrect. Double check it matches what you copied from the Cognee Cloud dashboard.

Seeing errors when you run the script?

  • If you see ModuleNotFoundError: No module named 'requests', your virtual environment is not activated. Run source .venv/bin/activate and try again.
  • If you see [ERROR 401] for every memory, your API key is wrong. Open config.py and paste the correct key from platform.cognee.ai.
  • If the script hangs or times out on the cognify step, Cognee Cloud may be under heavy load. Wait a minute and run the script again.

Help me debug my store_memory.py script

✔️ Awesome, I've got everything!

Great. Double check you've saved store_memory.py and that your terminal shows the "DONE!" message.

ⓧ I'd like to double check the full code

Here is the complete store_memory.py file:

import requests
import time
from config import BASE_URL, HEADERS

print("=" * 50)
print("STEP 1: Feeding memories to Cognee")
print("=" * 50)

memories = [
    "My name is Alex and I am a developer.",
    "I know Python and Go programming languages. I have more experience with Go than Python.",
    "I am participating in the WeMakeDevs x Cognee hackathon.",
    "I prefer building backend systems over frontend.",
    "I am learning about AI agents, knowledge graphs, and vector search.",
]

print("\nSending facts to Cognee Cloud (ingestion)...")
print("This is like putting ingredients on the counter - no cooking yet.\n")

for memory in memories:
    response = requests.post(
        f"{BASE_URL}/api/v1/add",
        json={"data": memory},
        headers=HEADERS
    )
    status = "OK" if response.status_code == 200 else f"ERROR {response.status_code}"
    print(f"  [{status}] {memory}")

print("\n" + "=" * 50)
print("STEP 2: Building the knowledge graph (cognify)")
print("=" * 50)

print("\nThis triggers the LLM to:")
print("  1. Chunk the text into pieces")
print("  2. Extract entities (Alex, Python, Go, hackathon...)")
print("  3. Find relationships (Alex KNOWS Python, Alex PARTICIPATES_IN hackathon)")
print("  4. Create vector embeddings (number-representations of meaning)")
print("  5. Store entities + relationships in graph database")
print("  6. Store embeddings in vector database")
print("\nThis is where tokens get used - the LLM is doing real work!\n")

response = requests.post(
    f"{BASE_URL}/api/v1/cognify",
    json={"datasets": ["main_dataset"]},
    headers=HEADERS
)
print(f"Cognify triggered: {response.status_code}")
print(f"Response: {response.text[:200]}")

print("\nWaiting 15 seconds for the knowledge graph to be built...")
time.sleep(15)

print("\n" + "=" * 50)
print("DONE!")
print("=" * 50)
print("\nYour memories are now stored in a knowledge graph on Cognee Cloud.")
print("The graph has ENTITIES (you, Python, Go, hackathon)")
print("and RELATIONSHIPS between them (you KNOW Python, you PARTICIPATE_IN hackathon).")
print("\nNow CLOSE this script and run: python3 recall_memory.py")
print("That will prove memory persists across sessions!")

Your knowledge graph is now live on Cognee Cloud. The real test comes next. You'll write a completely separate script and prove that your memories persist even after this script is long gone.

Prove Persistent Memory

In the last step, you fed personal facts to Cognee and built a knowledge graph with entities and relationships. Your store_memory.py script is now closed.

Now comes the real test. You will write a brand new Python script that has zero connection to store_memory.py. If Cognee can answer questions about you from this completely separate process, that proves your memories live on Cognee's servers, not in your program's RAM.

In this step, get ready to:
  • Write a completely separate recall_memory.py script.
  • Query the knowledge graph with natural language questions.
  • Observe and understand persistent cross-session memory.
Write recall_memory.py as a completely separate script

This new script shares only config.py (the API key) with your previous script. It has no imports from store_memory.py, no shared variables, and no reference to the memories you stored.

  • Create a new file called recall_memory.py in your cognee-memory folder.
  • Add the imports and opening identity section by pasting this code:
import requests
from config import BASE_URL, HEADERS

print("=" * 50)
print("THIS IS A BRAND NEW PYTHON PROCESS")
print("=" * 50)
print("\nThis script has NO connection to store_memory.py.")
print("It only knows the API key. Nothing else.")
print("If Cognee answers correctly, that PROVES persistent memory!\n")
print("-" * 50)

# Define the questions to ask the knowledge graph
questions = [
    "What is the user's name?",
    "What programming languages does the user know?",
    "What is the user participating in?",
    "Does the user prefer frontend or backend?",
]

What does this code do?

The print statements at the top announce that this is a brand new Python process. This makes it crystal clear when you run the script that no data is being carried over from store_memory.py.

The questions list holds four natural language questions that correspond to the facts you stored earlier. If Cognee can answer these from a separate script, memory is persistent.

  • Save recall_memory.py.
Query the knowledge graph with natural language questions

Now you will add the code that actually talks to Cognee's search endpoint. This sends each question to the /api/v1/search endpoint using the GRAPH_COMPLETION search type, which uses both graph relationships and vector embeddings to build an LLM-powered answer.

  • Add the query loop and conclusion below your questions list by pasting this code:
for question in questions:
    print(f"\nQ: {question}")
    response = requests.post(
        f"{BASE_URL}/api/v1/search",
        json={
            "query": question,
            "search_type": "GRAPH_COMPLETION"
        },
        headers=HEADERS
    )
    if response.status_code == 200:
        result = response.json()
        print(f"A: {result}")
    else:
        print(f"Error: {response.status_code} - {response.text[:100]}")

print("\n" + "=" * 50)
print("MEMORY PERSISTS ACROSS SESSIONS!")
print("=" * 50)
print("\nThe data lives in Cognee Cloud's databases (graph + vector),")
print("NOT in your program's RAM. Any script with the API key can access it.")
print("This is exactly how agents, copilots, and assistants get persistent memory.")

What does this code do?

  • The loop iterates over each question and sends a POST request to the /api/v1/search endpoint with the question as the query parameter.
  • The search_type of GRAPH_COMPLETION tells Cognee to traverse entity relationships in the graph AND use vector similarity, then have an LLM compose a full answer.
  • The conclusion prints reinforce that the data lives on Cognee's servers, not in your program's memory.
  • Save recall_memory.py.

What is GRAPH_COMPLETION?

GRAPH_COMPLETION is Cognee's hybrid search strategy. It combines vector search (finding text chunks that are similar in meaning) with graph traversal (following relationships between entities like "Alex KNOWS Python"). An LLM then reads both sources to compose a coherent answer.

This is more powerful than simple vector search alone because it can connect facts that were stored in completely separate sentences.

✔️ Awesome, I've got everything!

Great. Make sure you have saved your file before running it.

ⓧ I'd like to double check the full code

import requests
from config import BASE_URL, HEADERS

print("=" * 50)
print("THIS IS A BRAND NEW PYTHON PROCESS")
print("=" * 50)
print("\nThis script has NO connection to store_memory.py.")
print("It only knows the API key. Nothing else.")
print("If Cognee answers correctly, that PROVES persistent memory!\n")
print("-" * 50)

questions = [
    "What is the user's name?",
    "What programming languages does the user know?",
    "What is the user participating in?",
    "Does the user prefer frontend or backend?",
]

for question in questions:
    print(f"\nQ: {question}")
    response = requests.post(
        f"{BASE_URL}/api/v1/search",
        json={
            "query": question,
            "search_type": "GRAPH_COMPLETION"
        },
        headers=HEADERS
    )
    if response.status_code == 200:
        result = response.json()
        print(f"A: {result}")
    else:
        print(f"Error: {response.status_code} - {response.text[:100]}")

print("\n" + "=" * 50)
print("MEMORY PERSISTS ACROSS SESSIONS!")
print("=" * 50)
print("\nThe data lives in Cognee Cloud's databases (graph + vector),")
print("NOT in your program's RAM. Any script with the API key can access it.")
print("This is exactly how agents, copilots, and assistants get persistent memory.")
Run recall_memory.py and observe persistent memory

This is the moment of truth. You already ran store_memory.py in the previous step and closed it. That script is gone from memory. Now you will run a completely different Python process and see if Cognee still remembers you.

  • Run the recall script by running this command:
python3 recall_memory.py

You should see Cognee answering your four questions correctly. It knows your name, your programming languages, what you are participating in, and your backend preference.

Why does this prove persistent memory?

The memory is not in your program. It is not in RAM. It is not in a Python variable. The store_memory.py process ended completely, and this new script has no reference to it.

The data persists in Cognee Cloud's databases (a graph database for entities and relationships, a vector database for embeddings). Any script with the right API key can access it. This is exactly how AI agents, copilots, and assistants get persistent memory across sessions.

Getting empty results or errors?

  • If you see empty answers, the knowledge graph may not have finished building. Wait 30 more seconds and run the script again. The cognify process is asynchronous, meaning it runs in the background.
  • If you see a 401 or 403 error, double check that your API key in config.py is correct and has no extra spaces.
  • Make sure you ran store_memory.py successfully in the previous step before trying recall.

Help me debug my recall_memory.py results

You just proved that Cognee Cloud retains knowledge across completely separate Python processes. Next up, you will inspect the knowledge graph itself to understand how vector search and graph traversal work together behind the scenes.

Inspect the Knowledge Graph

You've proven that Cognee remembers you across completely separate Python processes. That's the core concept of persistent memory.

Now let's look INSIDE the knowledge graph to understand how Cognee actually retrieves your information. Cognee doesn't just have one way to search. It offers different retrieval strategies, and understanding them reveals why a hybrid approach is more powerful than simple vector search alone.

In this step, get ready to:
  • Compare CHUNKS and GRAPH_COMPLETION search types on the same question.
  • Understand hybrid vector + graph retrieval.
  • Add new connected facts and observe richer answers.
Query for structured insights

When you ran recall_memory.py in the previous step, every query used GRAPH_COMPLETION as the search type. That gives you a polished, LLM-written answer. But Cognee also lets you see the raw building blocks behind that answer.

  • Open the Python interactive interpreter by running:
python3
  • Import your config and the requests library by pasting this into the interpreter:
import requests
from config import BASE_URL, HEADERS
  • Run a CHUNKS search to see the raw text segments that match your query by pasting this:
# CHUNKS - pure vector search, returns raw text pieces
response = requests.post(
    f"{BASE_URL}/api/v1/search",
    json={
        "query": "What programming languages does the user know?",
        "search_type": "CHUNKS"
    },
    headers=HEADERS
)
print("\nCHUNKS result (raw text segments):")
print(response.json())

You should see a list of raw text passages that Cognee found by matching your query's meaning against stored text. These are the actual pieces of text you originally sent in store_memory.py.

  • Now run the same question using GRAPH_COMPLETION to see the difference:
# GRAPH_COMPLETION - hybrid search with LLM-composed answer
response = requests.post(
    f"{BASE_URL}/api/v1/search",
    json={
        "query": "What programming languages does the user know?",
        "search_type": "GRAPH_COMPLETION"
    },
    headers=HEADERS
)
print("\nGRAPH_COMPLETION result (LLM answer using graph context):")
print(response.json())

You should see a composed answer that reads like a sentence, not just raw text chunks. The GRAPH_COMPLETION result might mention that you have more experience with Go than Python, even though that detail was stored in a separate memory from the one about knowing both languages.

What is the difference between these search types?

CHUNKS performs pure vector search. It finds text segments that are similar in MEANING to your query by comparing vector embeddings. You get back the raw passages with no processing.

GRAPH_COMPLETION is hybrid retrieval. It finds relevant chunks via embeddings AND follows entity connections in the knowledge graph, then sends everything to an LLM to compose a complete answer.

Getting empty results?

If either search returns an empty list, the knowledge graph build from store_memory.py may not have finished processing. Wait 30 seconds and try the query again.

If you see a 401 error, your API key may have expired. Check config.py to make sure your key is correct.

Why aren't my CHUNKS or GRAPH_COMPLETION searches returning results in the Python REPL?

Understand the hybrid approach

The real power of Cognee becomes clear when you ask a question that requires connecting facts from DIFFERENT memories. A pure vector search can only find text that sounds similar to your query. A graph search can traverse relationships between entities, even if those facts were stored in separate sentences.

  • Ask a question that requires connecting two separate facts by pasting this:
# A question that requires connecting facts stored in SEPARATE memories
question = "What is the user building and what hackathon are they in?"

# Try CHUNKS first
response = requests.post(
    f"{BASE_URL}/api/v1/search",
    json={"query": question, "search_type": "CHUNKS"},
    headers=HEADERS
)
print(f"\nQuestion: {question}")
print(f"\nCHUNKS (vector only): {response.json()}")
  • Now try the same question with GRAPH_COMPLETION:
# Same question, hybrid retrieval
response = requests.post(
    f"{BASE_URL}/api/v1/search",
    json={"query": question, "search_type": "GRAPH_COMPLETION"},
    headers=HEADERS
)
print(f"\nGRAPH_COMPLETION (hybrid): {response.json()}")

Notice how GRAPH_COMPLETION can connect the fact that you're learning about AI agents with the fact that you're in the WeMakeDevs hackathon. These were stored as separate memories, but the graph links them through your entity.

Why is hybrid search more powerful than simple RAG?

Simple RAG (Retrieval Augmented Generation) finds text chunks that are similar in meaning and passes them to an LLM. If two related facts don't share similar words, RAG might miss the connection entirely.

Cognee's hybrid approach adds graph traversal. The knowledge graph stores entities (you, Python, Go, hackathon) and relationships between them (you KNOWS Python, you PARTICIPATES_IN hackathon). When you ask a multi-hop question, Cognee follows these relationship edges to find connected information that vector search alone would miss.

Add more memories and see the graph grow

Knowledge graphs get more powerful as you add data. Unlike pure vector systems that just accumulate disconnected chunks, a graph creates NEW connections between existing entities whenever you add a related fact.

  • Add a new fact that connects to your existing entities by pasting this:
# Add a new fact that connects existing entities (Cognee + hackathon)
new_fact = "I am building a project with Cognee for the WeMakeDevs hackathon."
response = requests.post(
    f"{BASE_URL}/api/v1/add",
    json={"data": new_fact},
    headers=HEADERS
)
print(f"Added new fact: {response.status_code}")
  • Trigger the knowledge graph to process this new fact:
# Rebuild the graph to incorporate the new fact
import time
response = requests.post(
    f"{BASE_URL}/api/v1/cognify",
    json={"datasets": ["main_dataset"]},
    headers=HEADERS
)
print(f"Cognify triggered: {response.status_code}")
print("Waiting 15 seconds for processing...")
time.sleep(15)
print("Done! The graph now has a new connection.")

What just happened in the graph?

Before this new fact, your graph had separate entities for "Cognee" (from learning about AI agents) and "WeMakeDevs hackathon" (from your participation). Now the graph has a direct relationship connecting them: you ARE_BUILDING a project WITH Cognee FOR the hackathon.

This new edge means questions about your hackathon project will now pull in Cognee-related knowledge, and questions about Cognee will connect to the hackathon context. More data means richer answers.

  • Re-query to see how the answer has improved:
# Ask a question that benefits from the new connection
response = requests.post(
    f"{BASE_URL}/api/v1/search",
    json={
        "query": "What is the user building for the hackathon?",
        "search_type": "GRAPH_COMPLETION"
    },
    headers=HEADERS
)
print(f"\nQ: What is the user building for the hackathon?")
print(f"A: {response.json()}")

The answer should now specifically mention Cognee. Before adding the new fact, the graph knew you were IN the hackathon and that you were learning about AI agents, but it didn't know you were building with Cognee specifically.

  • Exit the Python interpreter:
exit()

New fact not showing up in answers?

The /api/v1/cognify endpoint is asynchronous. If your re-query returns the old answer, wait another 15-30 seconds and try again. The LLM needs time to extract entities and build the new graph connections.

Why is my newly added memory not appearing in Cognee search results?

You've now seen inside the knowledge graph and understand how Cognee's hybrid retrieval works. Next up, you'll build an interactive assistant that lets you store and recall memories in real time through a command loop.

Build the Interactive Assistant

In the previous step, you explored how Cognee combines vector search and graph traversal to answer your questions. You saw the difference between raw text chunks and LLM-powered answers that follow relationships.

Now you'll bring everything together into a single interactive program. Instead of running separate scripts for storing and recalling, you'll build an assistant that does both in a real-time loop.

In this step, get ready to:
  • Write assistant.py with a command loop for storing and recalling memories.
  • Test the assistant by remembering new facts and querying existing ones.
  • Prove persistence by quitting and reopening the assistant.
Write assistant.py with a command loop

The assistant uses a while True loop that continuously reads your input. It supports three commands: remember to store facts, ask to query your knowledge graph, and quit to exit.

  • Create a new file called assistant.py in your cognee-memory folder and add the loop skeleton by pasting this code:
import requests
import time
from config import BASE_URL, HEADERS

# Display the welcome banner with available commands
print("=" * 50)
print("  MEMORY-POWERED PERSONAL ASSISTANT")
print("=" * 50)
print("\nCommands:")
print("  remember <text>  - Store a new memory")
print("  ask <question>   - Query your memories")
print("  quit             - Exit (memories persist!)")
print("\n" + "=" * 50)

# Main loop: read input and handle quit or empty input
while True:
    user_input = input("\nYou: ").strip()

    if not user_input:
        continue

    if user_input.lower() == "quit":
        print("\nAssistant: Goodbye! Your memories are safe in the knowledge graph.")
        print("Run me again anytime - I will still remember everything.")
        break

What does this code do?

  • The banner prints the available commands so the user knows how to interact.
  • while True creates an infinite loop that keeps asking for input until the user types quit.
  • .strip() removes extra spaces from the input, and the empty check skips blank entries.
  • Below the break line, add the "remember" command handler by pasting this code:
    if user_input.lower().startswith("remember "):
        # Extract the text after "remember "
        text = user_input[9:]
        print(f"\nAssistant: Storing '{text}' in memory...")

        # Send the text to Cognee for ingestion
        response = requests.post(
            f"{BASE_URL}/api/v1/add",
            json={"data": text},
            headers=HEADERS
        )

        if response.status_code == 200:
            print("Assistant: Ingested! Now building into the knowledge graph...")
            # Trigger cognify to process the new memory
            requests.post(
                f"{BASE_URL}/api/v1/cognify",
                json={"datasets": ["main_dataset"]},
                headers=HEADERS
            )
            print("Assistant: Got it! Processing in the background.")
            print("           (New memories take a few seconds to become searchable)")
        else:
            print(f"Assistant: Error storing memory: {response.status_code}")

What does this code do?

  • user_input[9:] slices off the first 9 characters ("remember ") to get just the fact text.
  • The handler calls /api/v1/add to ingest the raw text, then immediately calls /api/v1/cognify to trigger the LLM extraction and graph building.
  • Cognify is asynchronous. The assistant tells the user that processing happens in the background because the LLM needs time to extract entities and build connections.
  • Below the remember handler, add the "ask" command and the fallback for unrecognized commands by pasting this code:
    elif user_input.lower().startswith("ask "):
        # Extract the question after "ask "
        question = user_input[4:]
        print(f"\nAssistant: Searching the knowledge graph...")

        # Query Cognee with GRAPH_COMPLETION for LLM-powered answers
        response = requests.post(
            f"{BASE_URL}/api/v1/search",
            json={
                "query": question,
                "search_type": "GRAPH_COMPLETION"
            },
            headers=HEADERS
        )

        if response.status_code == 200:
            result = response.json()
            print(f"Assistant: {result}")
        else:
            print(f"Assistant: Search error: {response.status_code} - {response.text[:100]}")

    else:
        print("\nAssistant: I don't understand that command.")
        print("           Use 'remember <text>' or 'ask <question>' or 'quit'")

What does this code do?

  • The "ask" handler sends the question to /api/v1/search with GRAPH_COMPLETION search type. This gives LLM-powered answers that traverse the knowledge graph relationships.
  • user_input[4:] slices off "ask " to get just the question text.
  • The else block catches anything that is not a recognized command and reminds the user of the available options.
  • Save assistant.py.

Seeing indentation errors?

The remember, elif, and else blocks must all be indented one level inside the while True: loop. Make sure they line up with the if not user_input: line above them.

help me fix an IndentationError in my assistant.py file

✔️ Awesome, I've got everything!

Great. Double check you've saved your file before moving on.

ⓧ I'd like to double check the full code

import requests
import time
from config import BASE_URL, HEADERS

print("=" * 50)
print("  MEMORY-POWERED PERSONAL ASSISTANT")
print("=" * 50)
print("\nCommands:")
print("  remember <text>  - Store a new memory")
print("  ask <question>   - Query your memories")
print("  quit             - Exit (memories persist!)")
print("\n" + "=" * 50)

while True:
    user_input = input("\nYou: ").strip()

    if not user_input:
        continue

    if user_input.lower() == "quit":
        print("\nAssistant: Goodbye! Your memories are safe in the knowledge graph.")
        print("Run me again anytime - I will still remember everything.")
        break

    if user_input.lower().startswith("remember "):
        text = user_input[9:]
        print(f"\nAssistant: Storing '{text}' in memory...")

        response = requests.post(
            f"{BASE_URL}/api/v1/add",
            json={"data": text},
            headers=HEADERS
        )

        if response.status_code == 200:
            print("Assistant: Ingested! Now building into the knowledge graph...")
            requests.post(
                f"{BASE_URL}/api/v1/cognify",
                json={"datasets": ["main_dataset"]},
                headers=HEADERS
            )
            print("Assistant: Got it! Processing in the background.")
            print("           (New memories take a few seconds to become searchable)")
        else:
            print(f"Assistant: Error storing memory: {response.status_code}")

    elif user_input.lower().startswith("ask "):
        question = user_input[4:]
        print(f"\nAssistant: Searching the knowledge graph...")

        response = requests.post(
            f"{BASE_URL}/api/v1/search",
            json={
                "query": question,
                "search_type": "GRAPH_COMPLETION"
            },
            headers=HEADERS
        )

        if response.status_code == 200:
            result = response.json()
            print(f"Assistant: {result}")
        else:
            print(f"Assistant: Search error: {response.status_code} - {response.text[:100]}")

    else:
        print("\nAssistant: I don't understand that command.")
        print("           Use 'remember <text>' or 'ask <question>' or 'quit'")
Test the interactive flow

Your assistant is ready to run. You'll store some new facts and then query both old and new memories to see the full system in action.

  • Start the assistant by running this command:
python3 assistant.py

You should see the welcome banner with the three available commands listed.

  • Store a new memory by typing this at the You: prompt:
remember I enjoy hiking on weekends

The assistant should confirm ingestion and mention that processing happens in the background.

  • Now ask a question about memories stored in earlier steps by typing:
ask What programming languages does the user know?

The assistant searches the knowledge graph and returns an answer based on the facts you stored in Step 2. This works because those memories persist on Cognee Cloud's servers.

  • Try asking about the fact you just stored. Wait about 10 seconds first (to give cognify time to process), then type:
ask What does the user enjoy doing on weekends?

Why might new memories take a moment?

Cognify is asynchronous. When you store a new memory, the /api/v1/cognify call triggers background processing. The LLM needs time to extract entities, create embeddings, and build graph connections.

If the assistant does not find a new memory immediately, wait a few more seconds and ask again. This is normal.

Close and reopen to prove persistence one more time

The ultimate proof of persistent memory is quitting the assistant entirely and reopening it. If it still remembers everything, the knowledge graph is doing its job.

  • Quit the assistant by typing:
quit

The assistant prints a goodbye message confirming that your memories persist.

  • Reopen the assistant by running:
python3 assistant.py
  • Ask about facts from your very first run (Step 2) by typing:
ask What is the user's name?
  • Now ask about the fact you stored in the interactive session by typing:
ask What does the user enjoy doing on weekends?

Both answers should come back correctly. Memories from Step 2, Step 4, and this session all persist together in the knowledge graph.

Why does this prove persistent memory?

When you quit and reopen the assistant, Python creates a brand new process. All variables from the first run are gone. The only way the assistant can answer is by reaching out to Cognee Cloud's graph and vector databases.

This is the same pattern that production AI agents, copilots, and assistants use to maintain context across conversations.

Assistant not returning answers?

  • Check that your virtual environment is still active. You should see (.venv) at the start of your terminal prompt.
  • Make sure the API key in config.py is still correct. Copy it from your Cognee Cloud dashboard if needed.
  • If newly stored memories are not found, wait 15-20 seconds and try asking again. Cognify runs asynchronously.

help me debug why my assistant is not returning answers from the Cognee knowledge graph

Secret mission

Compare Search Types - Vector vs Graph vs Hybrid

You've been using GRAPH_COMPLETION for all your queries. But Cognee actually supports multiple search strategies, each with different strengths. Build a comparison script that reveals exactly why Cognee uses both a vector database AND a graph database together.

Clean Up Your Resources

Clean Up Your Resources

Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project uses the Cognee Cloud free tier, which includes 1M tokens at no cost. A learning project like this one uses only a tiny fraction of that allowance, so there are no ongoing charges.

Resources you used:

  • Cognee Cloud account with stored datasets (free tier, no ongoing charges within 1M token limit).
  • Local cognee-memory project folder on your Desktop (includes virtual environment and all scripts).

Keep everything running

No action needed. Choose this if you are still actively building on this project or plan to use it for a hackathon.

  • Your memories stay in Cognee Cloud. You can add more, query them, or build new scripts against the same data.
  • Your local cognee-memory folder stays on your Desktop with all scripts and the virtual environment ready to go.
  • The free tier does not expire as long as you stay within the 1M token limit.

Pause - I'll come back to this later

Shut down running processes to free up memory. Your data stays in Cognee Cloud and your files stay on disk.

  • If the assistant is still running in your terminal, type quit to exit it.
  • Deactivate your virtual environment by running:
deactivate
  • Your memories remain in Cognee Cloud and your local files remain on your Desktop. Reactivate the virtual environment when you return by running source .venv/bin/activate from inside the cognee-memory folder.

Delete - I don't want to use this again

Remove all project resources and start fresh. This permanently deletes your stored memories from Cognee Cloud and removes your local project files.

  • Delete all stored datasets from Cognee Cloud by running this Python command from inside your cognee-memory folder (with the virtual environment active):
python3 -c "import requests; from config import BASE_URL, HEADERS; r = requests.delete(f'{BASE_URL}/api/v1/datasets', headers=HEADERS); print(f'Status: {r.status_code}')"
  • You should see Status: 200 confirming all datasets and associated knowledge graph data have been permanently deleted.
  • Revoke your API key by opening platform.cognee.ai, navigating to API Keys in the sidebar, and clicking the delete icon next to your key.
  • Delete the local project folder by running:
cd ~/Desktop
rm -rf cognee-memory
  • This removes all Python scripts, the virtual environment, and the requests library that was installed inside it.

That's a Wrap!

That's a Wrap!

Nice work! You just built a personal assistant that remembers facts about you across completely separate Python processes, powered by Cognee Cloud's knowledge graph.

You've learned how to:

  • Connected Python to Cognee Cloud via REST API and triggered knowledge graph construction (entity extraction, vector embeddings, and graph relationships) from raw text.
  • Proved persistent memory by querying stored facts from a completely separate script with no shared state, proving that memory lives in Cognee's databases and not in your program's RAM.
  • Built an interactive terminal assistant that stores and recalls memories in a loop, with persistence that survives quitting and reopening.
  • Secret Mission: Compared vector search vs graph search vs hybrid retrieval to understand why Cognee uses both layers for richer, multi-hop answers.

Ready to quiz yourself?