<?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: Komal deep</title>
    <description>The latest articles on DEV Community by Komal deep (@komal_deep_355).</description>
    <link>https://dev.to/komal_deep_355</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%2F4047872%2F8ff91215-5a7e-4982-a0f0-d213cfb89ee7.png</url>
      <title>DEV Community: Komal deep</title>
      <link>https://dev.to/komal_deep_355</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/komal_deep_355"/>
    <language>en</language>
    <item>
      <title>FriendOS: I Built an AI That Tells My Panicking Friend What to Do Next</title>
      <dc:creator>Komal deep</dc:creator>
      <pubDate>Mon, 05 Oct 2026 06:54:12 +0000</pubDate>
      <link>https://dev.to/komal_deep_355/friendos-i-built-an-ai-that-tells-my-panicking-friend-what-to-do-next-59af</link>
      <guid>https://dev.to/komal_deep_355/friendos-i-built-an-ai-that-tells-my-panicking-friend-what-to-do-next-59af</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;FriendOS&lt;/strong&gt;, a little AI thinking partner that answers one question: &lt;strong&gt;"What should I do next?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I built it for a friend who is always one deadline away from panic.&lt;/p&gt;

&lt;p&gt;She isn't lazy, and she isn't unorganized in the way people usually mean it. Her problem is that everything arrives at once. An assignment is due today. A message needs a reply. Something needs buying. Her room needs cleaning. And all of it is in her head at the same time, loud and tangled.&lt;/p&gt;

&lt;p&gt;When that happens, she freezes. Not because she doesn't know what the tasks are, but because she doesn't know &lt;strong&gt;which one to start&lt;/strong&gt;, or &lt;strong&gt;where to start&lt;/strong&gt; with it.&lt;/p&gt;

&lt;p&gt;Then comes the second problem. To actually do anything, she bounces between five or six places at once: a search tab for one thing, her email for another, a shopping site, a notes app, an AI chat, a study page. Nothing is connected. Every task needs its own hunt for the right resource, and by the time she's found it, she's lost the thread and the panic is worse than before.&lt;/p&gt;

&lt;p&gt;A normal to-do app didn't help her. It gave her &lt;strong&gt;more information&lt;/strong&gt; when she needed &lt;strong&gt;less thinking&lt;/strong&gt;. So I built something different.&lt;/p&gt;

&lt;p&gt;FriendOS skips the forms. You brain-dump everything, by typing or by speaking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I need to submit my assignment today, finish two sections, clean my room this weekend, and buy a charger because mine is damaged."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;FriendOS turns that into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔥 &lt;strong&gt;DO NOW&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🌼 &lt;strong&gt;DO SOON&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🌿 &lt;strong&gt;CAN WAIT&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;⏱️ &lt;strong&gt;NEXT 30 MINUTES&lt;/strong&gt;: one to three small, realistic steps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then it helps her actually &lt;strong&gt;start&lt;/strong&gt;, so she doesn't have to go hunting. Each task comes with a first move: a shopping task opens a search, an email task builds a prompt and opens Gmail, a study or writing task generates a breakdown prompt and opens an AI assistant. Instead of juggling tabs, she gets one place that says &lt;em&gt;do this, start here&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The most important rule is that FriendOS &lt;strong&gt;only works with what you actually tell it&lt;/strong&gt;. My first version kept adding things like "research potential topics for future assignments" that nobody asked for. For someone who is already overwhelmed, a planner that invents more work is the last thing she needs. So FriendOS never invents tasks or deadlines.&lt;/p&gt;

&lt;p&gt;It works in English, Hindi, Punjabi, and Hinglish, because my friend doesn't think in only one language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;strong&gt;Live app:&lt;/strong&gt; &lt;a href="https://friendos-rizl.onrender.com/" rel="noopener noreferrer"&gt;https://friendos-rizl.onrender.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try this brain dump:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I need to submit my assignment to my professor today. I still need to finish two sections. I also need to clean my room this weekend. I want to buy a new charger because mine is damaged.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/KomalDeep355" rel="noopener noreferrer"&gt;
        KomalDeep355
      &lt;/a&gt; / &lt;a href="https://github.com/KomalDeep355/FriendOS" rel="noopener noreferrer"&gt;
        FriendOS
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;FriendOS 🌼&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Your little thinking partner. It answers one question: "What should I do next?"&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;FriendOS turns a messy brain dump into a calm, realistic priority plan, then tells you exactly what small step to take in the next 30 minutes. It only works with what you actually tell it. It does not invent tasks or deadlines.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Demo:&lt;/strong&gt; &lt;a href="https://friendos-rizl.onrender.com/" rel="nofollow noopener noreferrer"&gt;https://friendos-rizl.onrender.com/&lt;/a&gt;
&lt;strong&gt;Code:&lt;/strong&gt; &lt;a href="https://github.com/KomalDeep355/FriendOS" rel="noopener noreferrer"&gt;https://github.com/KomalDeep355/FriendOS&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why I built it&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;I built FriendOS for a friend who always has too many things to keep track of: assignments, errands, things to buy, things to clean. They didn't need another productivity dashboard. They already knew what was on their plate. The hard part was deciding &lt;strong&gt;which thing to do right now&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The problem isn't a lack of organization. It's decision overload.&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code&gt;Too many things in my head
        ↓
Brain dump instead of forms
        ↓
AI prioritization instead of manual sorting
        ↓
NEXT 30 MINUTES instead of&lt;/code&gt;&lt;/pre&gt;…&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/KomalDeep355/FriendOS" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Text or microphone
      ↓
FastAPI  →  ElevenLabs Scribe v2 (voice only)
      ↓
FastAPI  /api/organize
      ↓
Open-weight Llama
      ↓
Strict JSON → validation → plan
      ↓
DO NOW / DO SOON / CAN WAIT / NEXT 30 → contextual action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; plain HTML, CSS, and JavaScript, with a calm, cozy, Pinterest-style board look. Task completion is saved in &lt;code&gt;localStorage&lt;/code&gt;, so there's no database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Python and FastAPI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI:&lt;/strong&gt; an open-weight &lt;strong&gt;Llama&lt;/strong&gt; model, called through an OpenAI-compatible chat endpoint. Locally I ran it with &lt;strong&gt;Ollama&lt;/strong&gt; (&lt;code&gt;llama3.2:3b&lt;/code&gt;). For the public demo I point the same code at a hosted Llama endpoint, so anyone can try it without installing anything. Switching is two environment variables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Voice:&lt;/strong&gt; the browser records audio with &lt;code&gt;MediaRecorder&lt;/code&gt;, FastAPI sends it to &lt;strong&gt;ElevenLabs Scribe v2&lt;/strong&gt;, and the transcript goes straight into the planning pipeline. This is voice &lt;strong&gt;input&lt;/strong&gt; only. FriendOS doesn't speak back.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosting:&lt;/strong&gt; Render.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Making a small model behave.&lt;/strong&gt; The system prompt tells the model never to invent tasks, deadlines, or events, never to duplicate tasks, not to force tasks into categories, and to keep NEXT 30 realistic. I don't trust the prompt alone, though. A normalization layer in the backend strips markdown fences, fills missing fields, removes empty and duplicate tasks, and drops any NEXT 30 item that points to a task that doesn't exist. That combination is what stopped the made-up tasks.&lt;/p&gt;

&lt;p&gt;I deliberately left out auth, a database, React, RAG, and multi-agent setups. I wanted something small enough to actually finish and put in front of my friend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;FriendOS is a very personal tool. People paste their half-formed worries and deadlines into it. An open-weight model made it possible to build around that.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Control over the experience.&lt;/strong&gt; Because I could shape the model's behavior through prompting and then validate its output, I could fix the exact problem my friend would have noticed: the planner inventing work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy is a real option.&lt;/strong&gt; With Ollama, the whole intelligence layer can run on your own machine, so your brain dump doesn't have to go to anyone's server. (The public demo uses a hosted Llama endpoint for convenience, and voice uses ElevenLabs, so I'm not claiming the live demo is fully local.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No lock-in, and cost stays low.&lt;/strong&gt; Because the model sits behind a standard API shape, I could develop for free locally and then switch to a hosted open-weight endpoint for deployment without rewriting the app. A solo developer building for one friend shouldn't need a paid proprietary API to get started.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best Use of ElevenLabs.&lt;/strong&gt; FriendOS takes voice input: you tap the mic and speak your brain dump, and &lt;strong&gt;ElevenLabs Scribe v2&lt;/strong&gt; transcribes it. The transcript goes straight into the Llama planning pipeline, so the plan appears without typing. This fits the category's "transcribe audio for a language model" use. FriendOS uses voice input only, not voice output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Use of Render.&lt;/strong&gt; The FastAPI backend and the frontend are deployed on Render, which serves the live demo.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>Connecting My Agent to SigNoz's MCP Server: A First-Timer's Debugging Diary</title>
      <dc:creator>Komal deep</dc:creator>
      <pubDate>Sun, 26 Jul 2026 15:35:24 +0000</pubDate>
      <link>https://dev.to/komal_deep_355/connecting-my-agent-to-signozs-mcp-server-a-first-timers-debugging-diary-4bmh</link>
      <guid>https://dev.to/komal_deep_355/connecting-my-agent-to-signozs-mcp-server-a-first-timers-debugging-diary-4bmh</guid>
      <description>&lt;p&gt;I want to start with the number that actually matters: &lt;strong&gt;three hours&lt;/strong&gt;. That's roughly how long I spent just getting a connection to succeed, out of a five-day hackathon window. If you're building something similar and hit the same walls, this post should save you most of that time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I was building, and why this angle
&lt;/h2&gt;

&lt;p&gt;This was my first hackathon. My background is data science and NLP — classification, prediction models, the kind of ML work where inputs and outputs are known quantities. Agents, MCP servers, observability — none of that was in my vocabulary two weeks ago. So this post is written from that specific angle: &lt;strong&gt;what actually trips someone up coming from ML into agent-plus-observability tooling for the first time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;Agents of SigNoz (WeMakeDevs x SigNoz)&lt;/strong&gt;, I built an agent that connects to a self-hosted SigNoz instance through its MCP server, answers natural-language questions grounded in live telemetry, and then classifies what it finds — latency, error-rate, resource-exhaustion, dependency-failure, or healthy — with a confidence score traced back into SigNoz itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up SigNoz via Foundry
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash
&lt;span class="sb"&gt;`&lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://signoz.io/foundry.sh | bash&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;yaml&lt;/span&gt;
&lt;span class="na"&gt;`apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Installation&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;signoz&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deployment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;flavor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;compose&lt;/span&gt;
    &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker&lt;/span&gt;
  &lt;span class="na"&gt;mcp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="s"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash
&lt;span class="sb"&gt;`&lt;/span&gt;foundryctl cast &lt;span class="nt"&gt;-f&lt;/span&gt; casting.yaml&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This brought up SigNoz and its bundled MCP server as separate Docker containers — a detail that turned out to matter a lot more than I expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug #1: 401 Unauthorized
&lt;/h2&gt;

&lt;p&gt;My first connection attempt to &lt;strong&gt;&lt;a href="http://localhost:8000/mcp" rel="noopener noreferrer"&gt;http://localhost:8000/mcp&lt;/a&gt;&lt;/strong&gt; returned a flat &lt;strong&gt;401&lt;/strong&gt;. Self-hosted SigNoz's MCP server needs two specific headers, not the generic Bearer-token pattern I tried first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;python&lt;/span&gt;
&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;streamablehttp_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;MCP_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SIGNOZ-API-KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SIGNOZ_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;X-SigNoz-URL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://signoz-signoz-0:8080&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;as &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read_stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;write_stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bug #2: 400 Bad Request — the Docker networking trap
&lt;/h2&gt;

&lt;p&gt;Adding the headers got me past the** 401*&lt;em&gt;, straight into a **400&lt;/em&gt;*. I initially set X-SigNoz-URL to &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;, since that's where SigNoz's UI loaded from my own machine. But the MCP server runs inside its own container — and inside that container, localhost refers to the container itself, not my SigNoz instance. The server's own logs said it plainly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`"msg":"Invalid X-SigNoz-URL header" ... "error":"host \"localhost\" is not allowed"`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;docker ps showed the actual container name — signoz-signoz-0 —, and that's what needed to go in the header instead. This is the single biggest lesson I'd hand to my past self: when a container-to-container request fails, check what hostname the containers actually use to reach each other on the Docker network. It's rarely localhost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug #3: a plain variable-naming mistake
&lt;/h2&gt;

&lt;p&gt;Once I fixed the headers, I hit a &lt;strong&gt;NameError:&lt;/strong&gt; name &lt;strong&gt;'read_stream'&lt;/strong&gt; &lt;strong&gt;is not defined&lt;/strong&gt;. I'd renamed the tuple unpacking on the async with line but hadn't updated where those names were used two lines later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;python&lt;/span&gt;
&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;as &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read_stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;write_stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;ClientSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;read_stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;write_stream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Small, but the traceback pointed into the MCP library's internals, not my own line — a good reminder that an error surfacing deep in someone else's stack trace can still be your own typo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug #4: 403 — a permissions gap, not a connection problem
&lt;/h2&gt;

&lt;p&gt;With the connection finally working, calling signoz_list_services returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`403: only viewers/editors/admins can access this resource`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API key itself was valid — the service account behind it just had no role assigned. The fix was in Settings → Service Accounts, assigning Editor or Admin. &lt;em&gt;Worth remembering: a valid key and a valid role are two separate things.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually built on top: reasoning, not just retrieval
&lt;/h2&gt;

&lt;p&gt;SigNoz's MCP server gives you raw retrieval — service lists, traces, metrics, logs. It has no opinion about what any of that data means. Coming from a classification background, my instinct was to add exactly that missing layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;python&lt;/span&gt;
&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;classify_incident&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;telemetry_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;classification_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;You are classifying an observability finding.

User question: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_question&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
Telemetry data retrieved: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;telemetry_data&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;`
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Classify this into exactly ONE category: latency, error-rate, resource-exhaustion, dependency-failure, healthy, or unknown.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Respond with ONLY valid JSON, nothing else:&lt;/strong&gt;&lt;br&gt;
`{{"category": "", "confidence": , "reasoning": ""}}"""&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;response = hf_client.chat_completion(
    model=MODEL_ID,
    messages=[{"role": "user", "content": classification_prompt}],
    max_tokens=150,
    temperature=0,
)
raw = response.choices[0].message.content.strip()
return json.loads(raw)`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The part I actually care about is where the result goes — not just into the chat response, but into SigNoz's own trace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;python&lt;/span&gt;
&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_as_current_span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;incident_classification&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;classify_span&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;classification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;classify_incident&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;telemetry_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;classify_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;incident.category&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;classification&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;classify_span&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;incident.confidence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;classification&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;confidence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means my agent's own judgment becomes something you can trace inside SigNoz, the same way you'd trace any other part of the system. SigNoz observes the target service; this makes it also observe the agent's reasoning about that service.&lt;/p&gt;

&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%2Fwbefsa0fhejkohk6fz64.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%2Fwbefsa0fhejkohk6fz64.png" alt="Screenshot: SigNoz trace view showing the incident_classification span with incident.category and incident.confidence attributes" width="799" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What I'd tell someone starting this from an ML background
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Docker networking will very likely be your biggest time sink — not the AI part. Budget for it honestly.&lt;/li&gt;
&lt;li&gt;Read the server's logs the moment a request fails for an unclear reason — docker logs_ _ told me more in thirty seconds than an hour of guessing at headers did.&lt;/li&gt;
&lt;li&gt;A service account's API key and its assigned role are two separate failure points — check both before assuming the key is broken.&lt;/li&gt;
&lt;li&gt;Look for where your actual background transfers, instead of trying to become a full infra person overnight. For me that was "don't just retrieve data, judge it" — that's ML thinking applied to an observability tool, and it's the one piece of this that's genuinely mine.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;With more time, I'd add a small retrieval layer surfacing similar past incidents, and wire a SigNoz alert to trigger the agent automatically instead of waiting on a question.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you're self-hosting SigNoz's MCP server and hit a &lt;strong&gt;401, 400, or 403&lt;/strong&gt; in that order — check your headers, your Docker hostnames, and your service account's role. That covered nearly everything that stood between a working agent and me, and I hope it saves you the three hours it cost me.&lt;/p&gt;

</description>
      <category>signoz</category>
      <category>wemakedev</category>
      <category>observability</category>
      <category>hackathon</category>
    </item>
  </channel>
</rss>
