<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: AMAN KUMAR MAURYA</title>
    <description>The latest articles on DEV Community by AMAN KUMAR MAURYA (@aman_kumarmaurya_a501550).</description>
    <link>https://dev.to/aman_kumarmaurya_a501550</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4012577%2Fb86e3066-3c43-4907-aa43-6b2b1652ff37.jpg</url>
      <title>DEV Community: AMAN KUMAR MAURYA</title>
      <link>https://dev.to/aman_kumarmaurya_a501550</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aman_kumarmaurya_a501550"/>
    <language>en</language>
    <item>
      <title>I Made an AI Agent Debug Itself Using SigNoz's MCP Server</title>
      <dc:creator>AMAN KUMAR MAURYA</dc:creator>
      <pubDate>Sun, 26 Jul 2026 18:24:24 +0000</pubDate>
      <link>https://dev.to/aman_kumarmaurya_a501550/i-made-an-ai-agent-debug-itself-using-signozs-mcp-server-1l70</link>
      <guid>https://dev.to/aman_kumarmaurya_a501550/i-made-an-ai-agent-debug-itself-using-signozs-mcp-server-1l70</guid>
      <description>&lt;p&gt;I asked a terminal command a question — "Why are check_inventory calls failing? Give concrete numbers." — and got back:&lt;/p&gt;

&lt;p&gt;In the last 6 hours on the sre-agent service:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total spans named execute_tool check_inventory: 11&lt;/li&gt;
&lt;li&gt;Error spans: 0 (0%)&lt;/li&gt;
&lt;li&gt;Fraction with an error: 0 / 11 (0%)
Queried directly using signoz_aggregate_traces via the sre-agent service filter.
That wasn't me reading a dashboard. That was a second AI agent, with zero prior knowledge of my system, connecting to SigNoz's MCP server, picking the right query tool on its own, and answering with a real number instead of a guess. This post is about building that, and about the four separate ways it broke before it worked.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem I was actually trying to solve&lt;br&gt;
AI agents fail quietly. A tool call times out, an LLM call gets slow, a retry loop triples your token spend — and none of that looks like a crash. It looks like nothing, until a user complains. For the Agents of SigNoz hackathon (Track 01: AI &amp;amp; Agent Observability), I didn't want to just wire an agent up to SigNoz and screenshot a trace. I wanted to answer a sharper question: can the observability data itself become the thing a second agent uses to explain what went wrong?&lt;/p&gt;

&lt;p&gt;What I built&lt;br&gt;
Two pieces. First, sre-agent: a tool-calling support bot on FastAPI + Gemini, with three tools — a weather lookup, a docs search, and an inventory check I made deliberately unreliable on purpose:&lt;/p&gt;

&lt;p&gt;def check_inventory(sku: str) -&amp;gt; str:&lt;br&gt;
    with tracer.start_as_current_span("execute_tool check_inventory") as span:&lt;br&gt;
        span.set_attribute("gen_ai.tool.name", "check_inventory")&lt;br&gt;
        try:&lt;br&gt;
            latency = random.choice([0.05, 0.08, 0.1, 0.1, 2.4])  # occasional slow path&lt;br&gt;
            time.sleep(latency)&lt;br&gt;
            if random.random() &amp;lt; 0.25:&lt;br&gt;
                raise RuntimeError(f"inventory-service timeout for sku={sku}")&lt;br&gt;
            ...&lt;br&gt;
        except Exception as exc:&lt;br&gt;
            span.record_exception(exc)&lt;br&gt;
            span.set_status(Status(StatusCode.ERROR, str(exc)))&lt;br&gt;
            tool_call_errors.add(1, {"tool.name": "check_inventory"})&lt;br&gt;
25% failure rate, occasional 2.4-second stalls. Without a real, ugly failure mode, a "look, it's observable!" demo is just theater.&lt;/p&gt;

&lt;p&gt;Second, the SRE Sidekick: a completely separate script that connects to SigNoz's MCP server, lists its available tools at runtime, and lets an LLM decide which ones to call to answer a diagnostic question. No hardcoded queries. It has to actually reason about what to ask SigNoz.&lt;/p&gt;

&lt;p&gt;Every request to the first agent produces a real OpenTelemetry trace following the GenAI semantic conventions:&lt;/p&gt;

&lt;p&gt;invoke_agent support-agent&lt;br&gt;
  chat gemini-flash-lite-latest      (LLM call decides to use a tool)&lt;br&gt;
    execute_tool check_inventory     (the flaky one)&lt;br&gt;
  chat gemini-flash-lite-latest      (LLM produces the final answer)&lt;br&gt;
with gen_ai.usage.input_tokens, gen_ai.usage.output_tokens, and an estimated gen_ai.usage.cost_usd on every LLM span. Custom metrics track tool latency and error counts. Logs are correlated to trace_id automatically via the OTel SDK's logging handler. A dashboard and two alert rules (tool error rate, P95 latency) watch all of it — and I built both of those through the MCP server, not by clicking the SigNoz UI.&lt;/p&gt;

&lt;p&gt;Four things that broke, in order&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Vercel silently breaks sibling imports
Locally, from otel_setup import ... in agent/app.py just worked. Deployed to Vercel, every request 500'd with:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;File "/var/task/agent/app.py", line 29, in &lt;br&gt;
    from otel_setup import (&lt;br&gt;
ModuleNotFoundError: No module named 'otel_setup'&lt;br&gt;
Vercel's Python runtime imports your entry file directly by path — it never adds that file's own directory to sys.path, which every local script implicitly gets for free. Fix:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;HERE = Path(&lt;/em&gt;&lt;em&gt;file&lt;/em&gt;_).resolve().parent&lt;br&gt;
if str(_HERE) not in sys.path:&lt;br&gt;
    sys.path.insert(0, str(_HERE))&lt;br&gt;
Three lines, and it only exists because "works locally" and "works as a serverless function" are different claims.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Telemetry can vanish in production while looking fine in dev
OpenTelemetry's BatchSpanProcessor buffers spans and flushes on a background timer — usually every few seconds. On a serverless platform, the process can freeze the instant the HTTP response is sent, before that timer ever fires. Traces would work in uvicorn --reload and just disappear on Vercel, with no error anywhere. I added an explicit flush at the end of every request:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;@app.post("/chat")&lt;br&gt;
def chat(req: ChatRequest):&lt;br&gt;
    try:&lt;br&gt;
        return ChatResponse(reply=run_agent(req.message), session_id=req.session_id)&lt;br&gt;
    finally:&lt;br&gt;
        flush_telemetry()  # force_flush() on the tracer/meter/logger providers&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;"Admin" in the account name doesn't mean Admin the role
I created a SigNoz service account, named it admin, and every MCP call still came back:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;SigNoz API error: unexpected status 403: only editors/admins can access this resource&lt;br&gt;
SigNoz's newer RBAC model separates creating a service account from granting it a role — the two are unrelated unless you explicitly attach one. The account name meant nothing to the permission system. Once I attached the signoz-admin role under Settings → Service Accounts, every read and write call started working immediately, with no code changes at all. Worth remembering: read the actual error text before assuming your setup is wrong.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An agent's own tool list can blow its token budget
The SRE Sidekick's first real run made five sensible MCP tool calls and then died mid-answer:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;openai.RateLimitError: Error code: 429 - Quota exceeded for metric:&lt;br&gt;
generativelanguage.googleapis.com/generate_content_free_tier_input_token_count,&lt;br&gt;
limit: 250000, model: gemini-3.5-flash-lite&lt;br&gt;
The cause wasn't the conversation history — it was that I'd handed the model all 41 of SigNoz's MCP tools, full JSON schema included, on every single turn. Some of those schemas (dashboard and alert authoring, especially) run to hundreds of lines. Re-sending that on every hop of a multi-step reasoning loop adds up fast on a free-tier quota. The fix was also just better agent design: scope the tool list to what the task actually needs.&lt;/p&gt;

&lt;p&gt;READ_TOOLS = {&lt;br&gt;
    "signoz_search_traces", "signoz_aggregate_traces", "signoz_search_logs",&lt;br&gt;
    "signoz_aggregate_logs", "signoz_list_services", "signoz_get_service_top_operations",&lt;br&gt;
    "signoz_query_metrics", "signoz_list_metrics", "signoz_list_alerts",&lt;br&gt;
}&lt;br&gt;
tool_specs = [spec(t) for t in tools if t.name in READ_TOOLS]&lt;br&gt;
Eleven tools instead of forty-one. The Sidekick's next run finished cleanly and produced the answer at the top of this post.&lt;/p&gt;

&lt;p&gt;What I'd tell past-me&lt;br&gt;
Deploy early, even a rough version. Three of these four bugs only exist in production, and I'd rather hit them with two hours of runway left than zero.&lt;br&gt;
An MCP server's tool list is not free. If you're building an agent against a big tool surface, scope it down before you assume the model is "confused" — it might just be starved of context budget by its own tool definitions.&lt;br&gt;
Permission errors are almost always exactly what they say. 403: not authorized meant not authorized — not a bug in my request.&lt;br&gt;
A deliberately broken code path (my flaky check_inventory) is worth more than a hundred clean ones for actually testing whether your observability setup does anything.&lt;br&gt;
Try it&lt;br&gt;
Repo: &lt;a href="https://github.com/23f2001033/agents-of-signoz" rel="noopener noreferrer"&gt;https://github.com/23f2001033/agents-of-signoz&lt;/a&gt;&lt;br&gt;
Live: &lt;a href="https://agents-of-signoz.vercel.app" rel="noopener noreferrer"&gt;https://agents-of-signoz.vercel.app&lt;/a&gt; — POST /chat with {"message": "..."}&lt;br&gt;
Ask the Sidekick yourself: python sre_sidekick/sidekick.py "your question here"&lt;br&gt;
If you can't observe your AI agents, you don't own them. Mine, at least, can explain itself.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>debugging</category>
      <category>mcp</category>
    </item>
    <item>
      <title>I Built an AI Tutor That Actually Remembers Me — Using Cognee</title>
      <dc:creator>AMAN KUMAR MAURYA</dc:creator>
      <pubDate>Thu, 02 Jul 2026 17:01:52 +0000</pubDate>
      <link>https://dev.to/aman_kumarmaurya_a501550/i-built-an-ai-tutor-that-actually-remembers-me-using-cognee-49mn</link>
      <guid>https://dev.to/aman_kumarmaurya_a501550/i-built-an-ai-tutor-that-actually-remembers-me-using-cognee-49mn</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5938erknjg0spcc3khzd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5938erknjg0spcc3khzd.png" alt=" " width="800" height="358"&gt;&lt;/a&gt;The problem that broke me&lt;/p&gt;

&lt;p&gt;I'm a Data Science student at IIT Madras. Every week I'm juggling multiple courses — Software Engineering, AI, Software Testing — plus hackathons, assignments, and research. My study sessions are fragmented. I pick up a topic, drop it, come back to it three days later, completely confused again.&lt;/p&gt;

&lt;p&gt;I tried every AI chat tool to help. They were all useless in the same way.&lt;/p&gt;

&lt;p&gt;Ask ChatGPT about gradient descent today, and it's great. Come back next week and say "remember when I was confused about this?" — it doesn't. It can't. Every session is a blank slate. You end up re-explaining your own confusion to the AI every time. You become the memory system for a tool that's supposed to help you learn.&lt;/p&gt;

&lt;p&gt;That's AI amnesia. And it makes AI tutors fundamentally broken.&lt;/p&gt;

&lt;p&gt;What Cognee actually is (and why it changes everything)&lt;/p&gt;

&lt;p&gt;I'd come across Cognee before — an open-source AI memory platform that builds a knowledge graph from your data instead of just chunking it into a vector store. But I hadn't deeply understood why that matters until I started building.&lt;/p&gt;

&lt;p&gt;The difference is this:&lt;/p&gt;

&lt;p&gt;With normal RAG (what every AI chatbot uses), your notes get turned into floating vector embeddings. Ask a question, retrieve the most similar chunks, send them to an LLM. It works. But it treats your knowledge as a bag of disconnected facts.&lt;/p&gt;

&lt;p&gt;With Cognee, the same notes become a graph — concepts as nodes, relationships as edges. "Backpropagation" connects to "gradient descent" connects to "chain rule" connects to "neural network training". When you ask a question, the search doesn't just find the closest text — it reasons over the graph, following relationships to give you answers that understand how concepts connect.&lt;/p&gt;

&lt;p&gt;That structural difference is what makes persistent, evolving memory actually possible.&lt;/p&gt;

&lt;p&gt;What I built: MemoryTutor&lt;/p&gt;

&lt;p&gt;GitHub: github.com/23f2001033/MemoryTutor&lt;br&gt;
Live demo: memorytutor-8xubbwgxarbmzutwjeger2.streamlit.app&lt;/p&gt;

&lt;p&gt;MemoryTutor is an AI study tutor with two layers of memory:&lt;/p&gt;

&lt;p&gt;Layer 1 — Course knowledge graph&lt;br&gt;
You upload your notes (PDF or text). Cognee ingests them with cognee.add(), then cognee.cognify() extracts entities and relationships, building a knowledge graph stored on disk. Ask a question and cognee.search(SearchType.GRAPH_COMPLETION) reasons over that graph — not just nearest-neighbour lookup.&lt;/p&gt;

&lt;p&gt;Layer 2 — Your personal learning profile&lt;br&gt;
Every question you ask, MemoryTutor extracts the topic (via a quick Gemini call). If you ask a follow-up, click "Still confused", or phrase it with confusion signals ("I don't get it", "can you explain again"), the topic gets flagged as a WeakArea. Nail it and click "Got it" — it becomes a MasteredTopic. Both states are saved to user_memory.json and mirrored into the Cognee graph as short memory statements.&lt;/p&gt;

&lt;p&gt;What this enables:&lt;/p&gt;

&lt;p&gt;Close the app. Come back tomorrow. MemoryTutor greets you:&lt;/p&gt;

&lt;p&gt;"Last session you struggled with gradient descent and chain rule — want to revisit them before we move on?"&lt;/p&gt;

&lt;p&gt;It actually knows you. It remembers. The tutor genuinely gets smarter about you the more you use it.&lt;/p&gt;

&lt;p&gt;The architecture&lt;/p&gt;

&lt;p&gt;Streamlit UI (app.py)&lt;br&gt;
    │&lt;br&gt;
    ├── engine.py     → cognee.add / cognify / search (async, persistent event loop)&lt;br&gt;
    ├── tracker.py    → WeakArea / MasteredTopic → user_memory.json + graph mirror&lt;br&gt;
    └── viz.py        → networkx + matplotlib concept graph (colored by struggle level)&lt;br&gt;
            │&lt;br&gt;
    Cognee (LiteLLM + Gemini)&lt;br&gt;
    knowledge graph stored in .cognee_system/ and .data_storage/&lt;/p&gt;

&lt;p&gt;The knowledge graph visualization was a deliberate design choice: you can literally see which concepts you know (green), which you're struggling with (red), and how they connect. It makes the invisible visible.&lt;/p&gt;

&lt;p&gt;The hard parts&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Async in Streamlit is painful&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cognee's API is fully async. Streamlit's script model is synchronous and re-runs top-to-bottom on every interaction. Bridging them required a persistent background event loop that stays alive across script reruns — not a simple asyncio.run() call.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cognee's default storage location&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By default Cognee stores its databases inside its own package directory. That means every pip install -r requirements.txt would wipe your entire knowledge graph. I overrode the storage paths in config.py to point to the project root — a small fix with a big impact for persistence.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Graph noise&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cognee's raw graph includes internal bookkeeping nodes (chunk nodes, summary nodes, document nodes) that aren't meaningful concepts. The viz layer filters these out by node type so only real course concepts appear in the visualization.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Free Gemini tier limits&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;gemini-1.5-flash and text-embedding-004 were retired after I started building. The app now defaults to gemini/gemini-flash-lite-latest and gemini/gemini-embedding-001 — both current, both free-tier friendly.&lt;/p&gt;

&lt;p&gt;What I learned about AI memory&lt;/p&gt;

&lt;p&gt;Building this changed how I think about what's missing in most AI tools.&lt;/p&gt;

&lt;p&gt;We obsess over context windows — how much the model can hold in mind at once. But the real gap is persistence — what it retains between conversations. A tutor that can hold 200,000 tokens in context but forgets you the moment you close the tab is a very smart, very forgetful professor.&lt;/p&gt;

&lt;p&gt;Cognee's graph model is the right approach here because it doesn't just store — it structures. And structured storage lets you do things raw retrieval can't: traverse relationships, reason over connections, surface context the user didn't know to ask for.&lt;/p&gt;

&lt;p&gt;The future of AI tools isn't bigger context windows. It's better memory architecture.&lt;/p&gt;

&lt;p&gt;Try it&lt;/p&gt;

&lt;p&gt;Live demo: memorytutor-8xubbwgxarbmzutwjeger2.streamlit.app&lt;br&gt;
GitHub: github.com/23f2001033/MemoryTutor&lt;br&gt;
Upload any course notes PDF and start asking questions. Come back the next day and see what it remembers.&lt;/p&gt;

&lt;p&gt;Built in one day for The Hangover Hackathon by WeMakeDevs × Cognee.&lt;/p&gt;

&lt;p&gt;Aman Kumar Maurya — IIT Madras BS Data Science student&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8r31652wlwivyf68ov2i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8r31652wlwivyf68ov2i.png" alt=" " width="800" height="358"&gt;&lt;/a&gt;The problem that broke me&lt;/p&gt;

&lt;p&gt;I'm a Data Science student at IIT Madras. Every week I'm juggling multiple courses — Software Engineering, AI, Software Testing — plus hackathons, assignments, and research. My study sessions are fragmented. I pick up a topic, drop it, come back to it three days later, completely confused again.&lt;/p&gt;

&lt;p&gt;I tried every AI chat tool to help. They were all useless in the same way.&lt;/p&gt;

&lt;p&gt;Ask ChatGPT about gradient descent today, and it's great. Come back next week and say "remember when I was confused about this?" — it doesn't. It can't. Every session is a blank slate. You end up re-explaining your own confusion to the AI every time. You become the memory system for a tool that's supposed to help you learn.&lt;/p&gt;

&lt;p&gt;That's AI amnesia. And it makes AI tutors fundamentally broken.&lt;/p&gt;

&lt;p&gt;What Cognee actually is (and why it changes everything)&lt;/p&gt;

&lt;p&gt;I'd come across Cognee before — an open-source AI memory platform that builds a knowledge graph from your data instead of just chunking it into a vector store. But I hadn't deeply understood why that matters until I started building.&lt;/p&gt;

&lt;p&gt;The difference is this:&lt;/p&gt;

&lt;p&gt;With normal RAG (what every AI chatbot uses), your notes get turned into floating vector embeddings. Ask a question, retrieve the most similar chunks, send them to an LLM. It works. But it treats your knowledge as a bag of disconnected facts.&lt;/p&gt;

&lt;p&gt;With Cognee, the same notes become a graph — concepts as nodes, relationships as edges. "Backpropagation" connects to "gradient descent" connects to "chain rule" connects to "neural network training". When you ask a question, the search doesn't just find the closest text — it reasons over the graph, following relationships to give you answers that understand how concepts connect.&lt;/p&gt;

&lt;p&gt;That structural difference is what makes persistent, evolving memory actually possible.&lt;/p&gt;

&lt;p&gt;What I built: MemoryTutor&lt;/p&gt;

&lt;p&gt;GitHub: github.com/23f2001033/MemoryTutor&lt;br&gt;
Live demo: memorytutor-8xubbwgxarbmzutwjeger2.streamlit.app&lt;/p&gt;

&lt;p&gt;MemoryTutor is an AI study tutor with two layers of memory:&lt;/p&gt;

&lt;p&gt;Layer 1 — Course knowledge graph&lt;br&gt;
You upload your notes (PDF or text). Cognee ingests them with cognee.add(), then cognee.cognify() extracts entities and relationships, building a knowledge graph stored on disk. Ask a question and cognee.search(SearchType.GRAPH_COMPLETION) reasons over that graph — not just nearest-neighbour lookup.&lt;/p&gt;

&lt;p&gt;Layer 2 — Your personal learning profile&lt;br&gt;
Every question you ask, MemoryTutor extracts the topic (via a quick Gemini call). If you ask a follow-up, click "Still confused", or phrase it with confusion signals ("I don't get it", "can you explain again"), the topic gets flagged as a WeakArea. Nail it and click "Got it" — it becomes a MasteredTopic. Both states are saved to user_memory.json and mirrored into the Cognee graph as short memory statements.&lt;/p&gt;

&lt;p&gt;What this enables:&lt;/p&gt;

&lt;p&gt;Close the app. Come back tomorrow. MemoryTutor greets you:&lt;/p&gt;

&lt;p&gt;"Last session you struggled with gradient descent and chain rule — want to revisit them before we move on?"&lt;/p&gt;

&lt;p&gt;It actually knows you. It remembers. The tutor genuinely gets smarter about you the more you use it.&lt;/p&gt;

&lt;p&gt;The architecture&lt;/p&gt;

&lt;p&gt;Streamlit UI (app.py)&lt;br&gt;
    │&lt;br&gt;
    ├── engine.py     → cognee.add / cognify / search (async, persistent event loop)&lt;br&gt;
    ├── tracker.py    → WeakArea / MasteredTopic → user_memory.json + graph mirror&lt;br&gt;
    └── viz.py        → networkx + matplotlib concept graph (colored by struggle level)&lt;br&gt;
            │&lt;br&gt;
    Cognee (LiteLLM + Gemini)&lt;br&gt;
    knowledge graph stored in .cognee_system/ and .data_storage/&lt;/p&gt;

&lt;p&gt;The knowledge graph visualization was a deliberate design choice: you can literally see which concepts you know (green), which you're struggling with (red), and how they connect. It makes the invisible visible.&lt;/p&gt;

&lt;p&gt;The hard parts&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Async in Streamlit is painful&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cognee's API is fully async. Streamlit's script model is synchronous and re-runs top-to-bottom on every interaction. Bridging them required a persistent background event loop that stays alive across script reruns — not a simple asyncio.run() call.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cognee's default storage location&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By default Cognee stores its databases inside its own package directory. That means every pip install -r requirements.txt would wipe your entire knowledge graph. I overrode the storage paths in config.py to point to the project root — a small fix with a big impact for persistence.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Graph noise&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cognee's raw graph includes internal bookkeeping nodes (chunk nodes, summary nodes, document nodes) that aren't meaningful concepts. The viz layer filters these out by node type so only real course concepts appear in the visualization.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Free Gemini tier limits&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;gemini-1.5-flash and text-embedding-004 were retired after I started building. The app now defaults to gemini/gemini-flash-lite-latest and gemini/gemini-embedding-001 — both current, both free-tier friendly.&lt;/p&gt;

&lt;p&gt;What I learned about AI memory&lt;/p&gt;

&lt;p&gt;Building this changed how I think about what's missing in most AI tools.&lt;/p&gt;

&lt;p&gt;We obsess over context windows — how much the model can hold in mind at once. But the real gap is persistence — what it retains between conversations. A tutor that can hold 200,000 tokens in context but forgets you the moment you close the tab is a very smart, very forgetful professor.&lt;/p&gt;

&lt;p&gt;Cognee's graph model is the right approach here because it doesn't just store — it structures. And structured storage lets you do things raw retrieval can't: traverse relationships, reason over connections, surface context the user didn't know to ask for.&lt;/p&gt;

&lt;p&gt;The future of AI tools isn't bigger context windows. It's better memory architecture.&lt;/p&gt;

&lt;p&gt;Try it&lt;/p&gt;

&lt;p&gt;Live demo: memorytutor-8xubbwgxarbmzutwjeger2.streamlit.app&lt;br&gt;
GitHub: github.com/23f2001033/MemoryTutor&lt;br&gt;
Upload any course notes PDF and start asking questions. Come back the next day and see what it remembers.&lt;/p&gt;

&lt;p&gt;Built in one day for The Hangover Hackathon by WeMakeDevs × Cognee.&lt;/p&gt;

&lt;p&gt;Aman Kumar Maurya — IIT Madras BS Data Science student&lt;/p&gt;

</description>
      <category>wemakedevs</category>
      <category>cognee</category>
    </item>
  </channel>
</rss>
