<?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: Rishiraj Debnath</title>
    <description>The latest articles on DEV Community by Rishiraj Debnath (@rishiraj_debnath_37f27161).</description>
    <link>https://dev.to/rishiraj_debnath_37f27161</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%2F4203892%2Ffdb58e67-35fa-4522-ab08-bbc9aa0fb651.jpg</url>
      <title>DEV Community: Rishiraj Debnath</title>
      <link>https://dev.to/rishiraj_debnath_37f27161</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rishiraj_debnath_37f27161"/>
    <language>en</language>
    <item>
      <title>Why Tesseract Fails on Cursive Handwriting (And How We Built a Two-Tier Vision Pipeline in Node.js)</title>
      <dc:creator>Rishiraj Debnath</dc:creator>
      <pubDate>Mon, 09 Nov 2026 11:56:51 +0000</pubDate>
      <link>https://dev.to/rishiraj_debnath_37f27161/why-tesseract-fails-on-cursive-handwriting-and-how-we-built-a-two-tier-vision-pipeline-in-nodejs-3bbp</link>
      <guid>https://dev.to/rishiraj_debnath_37f27161/why-tesseract-fails-on-cursive-handwriting-and-how-we-built-a-two-tier-vision-pipeline-in-nodejs-3bbp</guid>
      <description>&lt;p&gt;When building Holder—a personal information vault and second brain for screenshots, links, and documents—we ran into a classic computer vision bottleneck: handwritten lecture notes and cursive whiteboards.&lt;/p&gt;

&lt;p&gt;If you've ever used classical OCR engines like Tesseract on handwritten notes, you know what happens:&lt;/p&gt;

&lt;p&gt;Original handwriting: "A random process X(t) is said to be stationary if all its statistical properties..."&lt;br&gt;
Tesseract output: "Sie xe esp Peo cep... fp yaudom Precen X(t) 2 Ad fe te sfefiono ~y i ike stafistieck Prepertioa..."&lt;/p&gt;

&lt;p&gt;Here is why classical OCR fails on cursive handwriting, why sending every image to a multimodal AI model is a bad idea, and how we solved it with an automated two-tier pipeline.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Why Classical OCR Fails on Cursive
&lt;/h2&gt;

&lt;p&gt;Classical OCR engines like Tesseract rely on Otsu binarization and character segmentation. They operate under the assumption that individual characters have distinct physical separation or predictable typographic spacing.&lt;/p&gt;

&lt;p&gt;In cursive or student lecture notes:&lt;/p&gt;

&lt;p&gt;Adjacent letters are connected by fluid, continuous strokes.&lt;br&gt;
Letter heights, slants, and baselines continuously drift.&lt;br&gt;
Letter boundaries do not exist in the traditional print sense.&lt;/p&gt;

&lt;p&gt;Because Tesseract has no choice but to segment connected strokes, it chops words into random character fragments. It outputs strings of non-words with low confidence scores (often between 25% and 40%).&lt;/p&gt;
&lt;h2&gt;
  
  
  2. The Naive Fix (And Why It Fails in Production)
&lt;/h2&gt;

&lt;p&gt;The obvious modern fix is: "Just send every image to a Vision LLM like GPT-4o, Claude 3.5 Sonnet, or Llama 3.2 Vision."&lt;/p&gt;

&lt;p&gt;In production, this creates two major problems:&lt;/p&gt;

&lt;p&gt;Upload Latency: Vision models take 3 to 8 seconds to process an image. If run synchronously on upload, the user sits staring at an "Uploading..." button unable to save.&lt;br&gt;
Cost &amp;amp; Quota Burn: In a personal vault app, 80% of uploads are clean screenshots, tweets, terminal errors, or website bookmarks. Burning GPU cycles and API quotas on images that classical OCR can read in 800ms for $0 is wasteful.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. The Architecture: Two-Tier Automated Fallback
&lt;/h2&gt;

&lt;p&gt;To achieve sub-second saving, zero unnecessary API costs, and 100% handwriting transcription accuracy, we built a two-tier architecture:&lt;/p&gt;

&lt;p&gt;[ User Uploads Image ] | v [ Save to Storage &amp;amp; Return UI Preview (&amp;lt; 400ms) ] --&amp;gt; User can save immediately | v (Background Queue) [ Tier 1: Fast Local OCR (Tesseract.js) ] | v [ Gibberish &amp;amp; Handwriting Heuristic Check ] | +---&amp;gt; [ Clean / High Confidence (&amp;gt; 80%) ] ----&amp;gt; Save Local OCR Output | +---&amp;gt; [ Gibberish / Handwriting Detected ] ---&amp;gt; [ Tier 2: Cloudflare Llama 3.2 11B Vision ] | v [ Extract Math &amp;amp; Cursive Text ] | v [ Live UI Update via Polling ]&lt;/p&gt;


&lt;h2&gt;
  
  
  4. The Gibberish Detection Heuristic
&lt;/h2&gt;

&lt;p&gt;How does the server automatically know whether an image needs deep handwriting vision without human intervention?&lt;br&gt;
We implemented a multi-factor lexical and statistical check in Node.js:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;shouldTriggerVisionHtr&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 1. Tesseract confidence threshold (cursive handwriting typically scores &amp;lt; 65%)&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// 2. Large canvas but sparse text (&amp;lt; 35 chars)&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rawTokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rawTokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alphaTokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rawTokens&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[^&lt;/span&gt;&lt;span class="sr"&gt;a-z&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&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;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// 3. Valid English word ratio against a dictionary set&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alphaTokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recognized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;alphaTokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;COMMON_ENGLISH_WORDS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recognizedRatio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;recognized&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;alphaTokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="c1"&gt;// Low dictionary match ratio (&amp;lt; 42%) indicates garbled non-words&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recognizedRatio&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.42&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;82&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// 4. Fragmented stroke ratio (typical of chopped cursive: fy, fa, fp, te, fe)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shortTokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rawTokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[^&lt;/span&gt;&lt;span class="sr"&gt;a-zA-Z0-9&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shortRatio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;shortTokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;rawTokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shortRatio&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.35&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;82&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// 5. Unpronounceable consonant clusters (4+ consecutive consonants)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gibberishCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rawTokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isGibberishToken&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gibberishCount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gibberishCount&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;rawTokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.20&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&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="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Tier 2: Serverless Vision Execution
&lt;/h2&gt;

&lt;p&gt;When an image trips the gibberish check, it is dispatched to Cloudflare Workers AI running &lt;a class="mentioned-user" href="https://dev.to/cf"&gt;@cf&lt;/a&gt;/meta/llama-3.2-11b-vision-instruct on serverless edge GPUs.&lt;/p&gt;

&lt;p&gt;Because multimodal LLMs process images through vision-language transformers, they do not merely segment characters—they understand linguistic semantics and domain context.&lt;/p&gt;

&lt;p&gt;In our physics notes example:&lt;/p&gt;

&lt;p&gt;Tesseract Word Accuracy: ~10% (confidence: 36%)&lt;br&gt;
Llama 3.2 Vision Word Accuracy: 100% (transcribed formulas, strict sense stationary definitions, and bullet points perfectly)&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Key Takeaways for Builders
&lt;/h2&gt;

&lt;p&gt;Decouple Ingestion from AI Processing: Never block a user's upload flow on a heavy ML/LLM inference call. Store the file, render the preview, return HTTP 201, and process asynchronously.&lt;br&gt;
Heuristic Routing Saves Budgets: Using classical OCR as a fast, zero-cost classifier allows you to reserve expensive vision models for the 20% of inputs that actually require them.&lt;br&gt;
Lexical Analysis Over Confidence Alone: Confidence scores can be misleading (Tesseract can be 70% confident in a garbled word). Testing output tokens against a vocabulary dictionary provides a reliable signal for handwriting detection.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>javascript</category>
      <category>machinelearning</category>
      <category>node</category>
    </item>
    <item>
      <title>ZeroDown: Building an AI-Powered On-Call Assistant &amp; ChatOps Engine with Switch &amp; MCP</title>
      <dc:creator>Rishiraj Debnath</dc:creator>
      <pubDate>Sat, 07 Nov 2026 17:59:39 +0000</pubDate>
      <link>https://dev.to/rishiraj_debnath_37f27161/zerodown-building-an-ai-powered-on-call-assistant-chatops-engine-with-switch-mcp-15n1</link>
      <guid>https://dev.to/rishiraj_debnath_37f27161/zerodown-building-an-ai-powered-on-call-assistant-chatops-engine-with-switch-mcp-15n1</guid>
      <description>&lt;p&gt;The 3:00 AM Nightmare Every Developer Knows&lt;/p&gt;

&lt;p&gt;Your phone buzzes frantically. Multiple Discord channels light up with duplicate messages: "Is the site down?", "Auth is failing!", "Can anyone checkout?".&lt;/p&gt;

&lt;p&gt;Before you’ve even rubbed the sleep from your eyes, you're faced with:&lt;/p&gt;

&lt;p&gt;Sifting through disconnected logs across cloud dashboards.&lt;br&gt;
Trying to remember who is authorized to restart the gateway.&lt;br&gt;
Running risky manual SSH commands while half-asleep.&lt;br&gt;
Answering anxious teammates across multiple chat platforms.&lt;/p&gt;

&lt;p&gt;We built ZeroDown to turn this chaos into a calm, automated, and secure workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is ZeroDown?
&lt;/h2&gt;

&lt;p&gt;ZeroDown is a full-stack, autonomous on-call incident response and ChatOps engine. It pairs a high-frequency microservice monitoring pipeline with local AI agents via Switch Console and the Model Context Protocol (MCP).&lt;/p&gt;

&lt;p&gt;Whenever downtime occurs, ZeroDown:&lt;/p&gt;

&lt;p&gt;Detects the outage before your users notice.&lt;br&gt;
Deduplicates teammate alerts across Discord and Telegram into a single active ticket.&lt;br&gt;
Runs AI-driven root cause analysis directly against live HTTP failure traces and subsystem probes.&lt;br&gt;
Enables In-Chat Safe Remediation: Engineers can review diagnostic findings and authorize recovery actions directly inside Discord with a simple command: @on-call-ai oncall approve.&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%2Fb2lp9bb3tnct3ipqb4xp.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%2Fb2lp9bb3tnct3ipqb4xp.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Architectural Deep Dive
&lt;/h2&gt;

&lt;p&gt;ZeroDown was engineered from the ground up as a microservices architecture designed for resilience:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Real-Time Monitor Engine (services/monitor)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A non-blocking probe worker that pings target application health endpoints every 30 seconds. It tracks latency, HTTP status codes, and individual subsystem health checks (e.g. database, auth, redis). When consecutive failures exceed the configured threshold, it automatically opens an incident.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The AI Triage &amp;amp; Diagnostic Engine (services/triage)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When an outage is declared, the triage service collects:&lt;/p&gt;

&lt;p&gt;Recent probe failure traces (e.g., HTTP 503, connection timeouts).&lt;br&gt;
Subsystem health checks.&lt;br&gt;
Unverified teammate chat reports from Discord and Telegram.&lt;/p&gt;

&lt;p&gt;It structures these inputs and runs root-cause analysis, returning:&lt;/p&gt;

&lt;p&gt;Confirmed Facts vs. Hypotheses&lt;br&gt;
Confidence Score&lt;br&gt;
Recommended Action&lt;br&gt;
Strictly Typed Recovery Proposal (manual_operator_action)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Bridging Local AI to Discord with Switch Console &amp;amp; MCP&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Traditional chatbots require hosting webhook servers, managing Discord bot websockets, and writing custom gateway adapters.&lt;/p&gt;

&lt;p&gt;Instead, we used Switch Console to bridge an OpenCode agent (on-call-ai) directly to Discord and Telegram. We built a custom Model Context Protocol (MCP) server (oncall-mcp.js) running over stdio that exposes safe incident investigation and ChatOps tools to the LLM:&lt;/p&gt;

&lt;p&gt;oncall_get_incident: Queries current incident status without requiring UUIDs.&lt;br&gt;
oncall_investigate_incident: Triggers root-cause triage on demand.&lt;br&gt;
oncall_approve_incident_recovery: Validates operator permissions and records signed remediation approvals.&lt;br&gt;
oncall_format_incident_reply: Converts raw JSON diagnostics into Discord-friendly Markdown summaries.&lt;br&gt;
How It Works in Practice: A Real Outage Walkthrough&lt;/p&gt;

&lt;p&gt;Here is what an incident looks like in action:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Automated Detection&lt;/strong&gt;&lt;br&gt;
The production database connection drops. The monitor detects three consecutive 503 responses and triggers an incident ticket on the Next.js Dashboard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Teammate Interaction in Discord&lt;/strong&gt;&lt;br&gt;
An engineer sees an alert in the team’s #general channel and checks in:&lt;/p&gt;

&lt;p&gt;Rishi [MLH]: @on-call-ai oncall status&lt;/p&gt;

&lt;p&gt;on-call-ai [APP]:&lt;br&gt;
🔴 Active Incident: 3e2b1a66-e329-46b9-8f2d-5fb0b316e2f0&lt;br&gt;
• Application: Demo Application / Campus Card&lt;br&gt;
• Severity: High · Status: Open&lt;br&gt;
• Detected: 3 consecutive probe failures (HTTP 503)&lt;br&gt;
• Investigation: Ready to investigate. Reply with @on-call-ai oncall investigate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: In-Chat AI Root Cause Analysis&lt;/strong&gt;&lt;br&gt;
The engineer requests an investigation:&lt;/p&gt;

&lt;p&gt;Rishi [MLH]: @on-call-ai oncall investigate&lt;/p&gt;

&lt;p&gt;on-call-ai [APP]:&lt;br&gt;
🔍 Investigation Results:&lt;br&gt;
• Summary: Demo Application is degraded due to database check failures.&lt;br&gt;
• Probable Cause: Internal failure in subsystem: database (unconfirmed).&lt;br&gt;
• Confidence: 75%&lt;br&gt;
• Proposed Action: Restart service process to clear transient connection pool exhaustion.&lt;br&gt;
• To Authorize: Reply with @on-call-ai oncall approve.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Direct ChatOps Approval&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Rather than logging into cloud consoles or running shell scripts, authorized operators approve the remediation right in the thread:&lt;/p&gt;

&lt;p&gt;Rishi [MLH]: @on-call-ai oncall approve&lt;/p&gt;

&lt;p&gt;on-call-ai [APP]:&lt;br&gt;
✅ Recovery Proposal Approved&lt;br&gt;
• Incident: 3e2b1a66&lt;br&gt;
• Authorized Action: manual_operator_action (Restart service process)&lt;br&gt;
• Authorized By: Switch On-Call Bot (rishi09509)&lt;br&gt;
• Status: Pending execution by remediation runner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Challenges &amp;amp; Lessons Learned
&lt;/h2&gt;

&lt;p&gt;Clean Failure Fallbacks: During local development and hackathons, remote databases or AI services can occasionally be unreachable. We implemented smart in-memory fallback repositories and deterministic heuristic root-cause inference engines. If OpenCode or Docker is momentarily offline, ZeroDown continues running smoothly without dropping incidents.&lt;br&gt;
UUID-Free Frictionless ChatOps: Nobody wants to type a 36-character UUID on a mobile phone during a 3:00 AM incident. We built smart active-incident resolution so plain commands like oncall status, oncall investigate, and oncall approve automatically infer the ongoing ticket.&lt;br&gt;
Safety First: AI agents should never execute destructive production commands autonomously. ZeroDown enforces human-in-the-loop approvals with cryptographically signed tokens and role-based permissions before any recovery action is authorized.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next for ZeroDown?
&lt;/h2&gt;

&lt;p&gt;Dynamic Multi-Website Management: Adding a one-click dashboard modal to register and manage multiple URLs dynamically.&lt;br&gt;
Proactive Outbound Alerting: Expanding Switch’s event bus to push unsolicited proactive alerts into bridged channels the second an anomaly is detected.&lt;br&gt;
Automated Canary Rollbacks: Connecting recovery approvals directly to Kubernetes and GitHub Actions deployment runners.&lt;br&gt;
Conclusion&lt;/p&gt;

&lt;p&gt;Incident response shouldn't require juggling ten tabs, copying logs, and panicking over terminal windows. By pairing real-time observability with local AI agents via Switch and MCP, ZeroDown brings SRE-level automation directly to where teams already communicate.&lt;/p&gt;

&lt;p&gt;Built with Next.js, Node.js, OpenCode, Switch Console, and Model Context Protocol (MCP).&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>devops</category>
      <category>mcp</category>
    </item>
    <item>
      <title>HOLDER: A Personal Vault That Helps You Stop Losing Useful Things</title>
      <dc:creator>Rishiraj Debnath</dc:creator>
      <pubDate>Sat, 24 Oct 2026 18:16:12 +0000</pubDate>
      <link>https://dev.to/rishiraj_debnath_37f27161/holder-a-personal-vault-that-helps-you-stop-losing-useful-things-23ce</link>
      <guid>https://dev.to/rishiraj_debnath_37f27161/holder-a-personal-vault-that-helps-you-stop-losing-useful-things-23ce</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;I built HOLDER, a personal vault for all the digital stuff we save and then struggle to find later.&lt;/p&gt;

&lt;p&gt;Think about how often we save a useful link, a YouTube video, a screenshot, a PDF, or a random note. A few days later, when we actually need it, we have no idea where we saved it.&lt;/p&gt;

&lt;p&gt;HOLDER is my attempt to solve that problem.&lt;/p&gt;

&lt;p&gt;It brings links, YouTube videos, images, PDFs, and notes into one searchable space. You can organize items with folders and favorites, and OCR makes text inside screenshots searchable too.&lt;/p&gt;

&lt;p&gt;The goal is simple: save something once and find it when you need it, without going through the same files and tabs all over again.&lt;/p&gt;

&lt;p&gt;I also included an AI Assistant entry point to make the vault more useful and help me to search and find anything I need.&lt;/p&gt;

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


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://doc-pied-five.vercel.app/" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;doc-pied-five.vercel.app&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


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

&lt;p&gt;GitHub repository: &lt;/p&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/13507-IN" rel="noopener noreferrer"&gt;
        13507-IN
      &lt;/a&gt; / &lt;a href="https://github.com/13507-IN/Doc" rel="noopener noreferrer"&gt;
        Doc
      &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;Holder — Personal Assistant &amp;amp; Info Vault&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Holder&lt;/strong&gt; is an intelligent personal information assistant and knowledge vault built with &lt;strong&gt;Next.js 14&lt;/strong&gt;, &lt;strong&gt;Express.js&lt;/strong&gt;, &lt;strong&gt;MongoDB&lt;/strong&gt;, and a &lt;strong&gt;Chrome Browser Extension&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Store, categorize, search, and converse with all your important information—including YouTube videos, images, web links, code snippets, and private credentials.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/0886008a7a625644533e6f35e08ebdf3340e9886d81c9a81574ede6792c31ca6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f537461636b2d4e6578742e6a73253230253743253230457870726573732532302537432532304d6f6e676f4442253230253743253230457874656e73696f6e2d363336366631"&gt;&lt;img src="https://camo.githubusercontent.com/0886008a7a625644533e6f35e08ebdf3340e9886d81c9a81574ede6792c31ca6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f537461636b2d4e6578742e6a73253230253743253230457870726573732532302537432532304d6f6e676f4442253230253743253230457874656e73696f6e2d363336366631" alt="Holder Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;✨ Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;📁 &lt;strong&gt;Multi-Folder Collections&lt;/strong&gt;: Organize items into custom folders (e.g. 💼 &lt;em&gt;Brand Assets&lt;/em&gt;, 🔒 &lt;em&gt;Private Vault&lt;/em&gt;, 🎥 &lt;em&gt;YouTube Tutorials&lt;/em&gt;, 🌐 &lt;em&gt;Bookmarks&lt;/em&gt;) with emoji icons, color badges, and description notes.&lt;/li&gt;
&lt;li&gt;🎥 &lt;strong&gt;YouTube Auto Metadata &amp;amp; Lightbox Player&lt;/strong&gt;: Paste any YouTube link to automatically extract channel metadata, title, and high-res thumbnails, with responsive video playback inside the app.&lt;/li&gt;
&lt;li&gt;🖼️ &lt;strong&gt;Image Vault &amp;amp; Uploads&lt;/strong&gt;: Upload local images or paste image URLs, complete with lightboxes.&lt;/li&gt;
&lt;li&gt;📄 &lt;strong&gt;PDF Document Vault &amp;amp; Viewer&lt;/strong&gt;: Upload PDF documents or paste direct PDF links, with inline interactive PDF…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/13507-IN/Doc" 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;p&gt;I built HOLDER with a separate frontend, backend, and browser extension.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The client is built with Next.js 16 and React 19.&lt;/p&gt;

&lt;p&gt;Next.js 16: Application framework&lt;/p&gt;

&lt;p&gt;React 19: UI components and interactions&lt;/p&gt;

&lt;p&gt;Axios: API communication&lt;/p&gt;

&lt;p&gt;lucide-react: Icons&lt;/p&gt;

&lt;p&gt;ESLint 9: Code quality and linting&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The server uses Node.js and Express 4.&lt;/p&gt;

&lt;p&gt;MongoDB and Mongoose 8: Data persistence&lt;/p&gt;

&lt;p&gt;Passport and Google OAuth: Google authentication&lt;/p&gt;

&lt;p&gt;JWT and bcryptjs: Authentication and password-related security&lt;/p&gt;

&lt;p&gt;Cloudinary: Media storage&lt;/p&gt;

&lt;p&gt;Multer: File uploads&lt;/p&gt;

&lt;p&gt;Tesseract.js: OCR and text extraction from images&lt;/p&gt;

&lt;p&gt;Cheerio: HTML parsing and content extraction&lt;/p&gt;

&lt;p&gt;Helmet and express-rate-limit: Security headers and request-rate limiting&lt;/p&gt;

&lt;p&gt;The backend connects the different parts of the application, manages stored information, and processes uploaded content.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chrome Extension&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also built a browser extension using Chrome Manifest V3 and vanilla JavaScript. This provides a browser-side way to interact with the application without building another full frontend.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI-Assisted Development&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I used OpenCode with the Big Pickle model as a coding assistant while developing HOLDER. It helped me work through implementation tasks and iterate on the code.&lt;/p&gt;

&lt;p&gt;This was part of my development workflow. The deployed application's OCR functionality is powered by Tesseract.js; Big Pickle is not presented as the model powering the live application.&lt;/p&gt;

&lt;p&gt;The core idea behind HOLDER is making saved information easier to find, and Tesseract.js plays an important role in that workflow.&lt;/p&gt;

&lt;p&gt;Tesseract.js is an open-source OCR library that uses WebAssembly to bring the Tesseract OCR engine to JavaScript environments. It extracts readable text from images. &lt;a href="https://github.com/naptha/tesseract.js" rel="noopener noreferrer"&gt;https://github.com/naptha/tesseract.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In HOLDER, I use it to extract text from screenshots so that the information inside an image can be searched later.&lt;/p&gt;

&lt;p&gt;The workflow is straightforward:&lt;/p&gt;

&lt;p&gt;A user saves a screenshot or image.&lt;/p&gt;

&lt;p&gt;Tesseract.js extracts the text contained in it.&lt;/p&gt;

&lt;p&gt;The extracted text is stored alongside the saved item.&lt;/p&gt;

&lt;p&gt;When the user searches for a word or phrase, the application can find matching content without requiring the user to open every image manually.&lt;/p&gt;

&lt;p&gt;I built the surrounding application with Next.js 16, React 19, Node.js, Express, and MongoDB. The backend handles data management, while the OCR component helps turn otherwise difficult-to-search images into searchable information.&lt;/p&gt;

&lt;p&gt;During development, I also used OpenCode with Big Pickle as a coding assistant to help implement features and work through coding tasks. Big Pickle assisted with development; it is not the model powering HOLDER's live application.&lt;/p&gt;

&lt;p&gt;My goal was to combine open-source tools with a practical problem: reducing the effort required to find information that you have already saved.&lt;/p&gt;

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

&lt;p&gt;A personal information vault can contain a lot of context about someone's work, interests, and daily life. That makes control over the AI layer an important design consideration.&lt;/p&gt;

&lt;p&gt;Using open-source AI gives developers more freedom to inspect, adapt, and replace components instead of building every AI feature around a single closed provider.&lt;/p&gt;

&lt;p&gt;For HOLDER, the important part is making the AI layer useful without making the entire application dependent on one fixed implementation.&lt;/p&gt;

&lt;p&gt;I think open innovation matters because useful tools should be adaptable. Developers should have the freedom to understand their systems, experiment with different approaches, and improve them as their needs change.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;h2&gt;
  
  
  The Lazy Payoff
&lt;/h2&gt;

&lt;p&gt;The small tasks are often the most annoying ones.&lt;/p&gt;

&lt;p&gt;Searching through old browser tabs, opening multiple folders, checking screenshots one by one, and trying to remember the name of a file all take time.&lt;/p&gt;

&lt;p&gt;HOLDER is designed to reduce that repeated effort.&lt;/p&gt;

&lt;p&gt;Save the resource, keep it organized, and search for it later. When text from screenshots is indexed through OCR, you don't have to rely only on filenames or memory to find the information again.&lt;/p&gt;

&lt;p&gt;I haven't measured a reliable time-saving figure yet, so I won't claim a made-up number. The value is in reducing the effort involved every time you need to retrieve something you saved earlier.&lt;/p&gt;

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

&lt;p&gt;Render, MongoDB&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>"AgentGuard", Way to secure your personal data from AI agents</title>
      <dc:creator>Rishiraj Debnath</dc:creator>
      <pubDate>Sat, 24 Oct 2026 05:09:18 +0000</pubDate>
      <link>https://dev.to/rishiraj_debnath_37f27161/agentguard-way-to-secure-your-personal-data-from-ai-agents-491h</link>
      <guid>https://dev.to/rishiraj_debnath_37f27161/agentguard-way-to-secure-your-personal-data-from-ai-agents-491h</guid>
      <description>&lt;p&gt;A few weeks ago, I had one of those heart-stopping developer moments.&lt;br&gt;
I was tinkering with a local autonomous coding agent running on a small open-source model (Qwen 2.5 via Ollama). I gave it access to a bash tool so it could install dependencies, run test suites, and clean up build artifacts.&lt;br&gt;
Everything was going smoothly until I asked it to clean up some old logs.&lt;br&gt;
In the terminal output, I watched it calmly propose:&lt;br&gt;
bash rm -rf /var/log/mongodb&lt;/p&gt;

&lt;p&gt;And right after that, it started poking around files outside its project folder.I hit Ctrl+C so fast I almost snapped my keyboard.&lt;br&gt;
The "Polite Prompt" Trap&lt;br&gt;
Like most developers, my first instinct was to fix it with prompt engineering:&lt;br&gt;
"You are a careful assistant. Please ONLY touch files in ./workspace. NEVER use sudo. NEVER delete system folders. Pretty please."&lt;br&gt;
And you know what happened on the very next run?&lt;/p&gt;

&lt;p&gt;It did it again.&lt;/p&gt;

&lt;p&gt;Here’s the thing we don't talk about enough: Small, open-source models (3B, 7B, 14B) don't have the massive alignment layers that GPT-4 or Claude 3.5 have. When an open-source agent gets confused, hallucinates, or hits an edge case, your polite system prompt is the first thing out the window.&lt;/p&gt;

&lt;p&gt;If an AI decides to read your private banking statement or a .env full of production tokens, you shouldn't have to convince the model to behave.&lt;/p&gt;

&lt;p&gt;You wouldn't ask an untrusted web request to "please not do SQL injection"—you use parameterized queries.&lt;/p&gt;

&lt;p&gt;So why are we begging AI agents not to nuke our hard drives?&lt;/p&gt;

&lt;p&gt;What I Actually Wanted&lt;/p&gt;

&lt;p&gt;I wanted a simple rule: The agent can think whatever crazy thought it wants, but before any tool touches my operating system, someone checks its badge at the door.&lt;/p&gt;

&lt;p&gt;If the agent decides to read bank_statement.pdf, the system shouldn't plead with the AI. It should intercept the file call, say "Nope, not happening", and ensure 0 bytes of that file are ever read.&lt;/p&gt;

&lt;p&gt;That was the spark behind AgentGuard.&lt;/p&gt;

&lt;p&gt;How It Works:&lt;/p&gt;

&lt;p&gt;AgentGuard is essentially a bouncer sitting between your AI agent and your OS. It does three straightforward things:&lt;/p&gt;

&lt;p&gt;[ AI Agent / Ollama / OpenDevin ]&lt;br&gt;
               │&lt;br&gt;
               │ 1. "Hey, I want to run: cat bank_statement.pdf"&lt;br&gt;
               ▼&lt;br&gt;
   ┌───────────────────────────┐&lt;br&gt;
   │    AgentGuard Gateway     │ ◄── [ Backboard.io ]&lt;br&gt;
   └───────────────────────────┘     (Remembers previous blocks)&lt;br&gt;
          │             │&lt;br&gt;
      [ BLOCK ]    [ APPROVE ]&lt;br&gt;
          │             │&lt;br&gt;
          │             └──► Rings your dashboard bell:&lt;br&gt;
          │                  "Agent wants to pip install something. Allow?"&lt;br&gt;
          ▼&lt;br&gt;
   Refusal sent back to Agent:&lt;br&gt;
   "Access to banking file blocked. Stay in ./workspace."&lt;br&gt;
          │&lt;br&gt;
          ▼&lt;br&gt;
   Agent self-corrects:&lt;br&gt;
   "My bad! Reading ./workspace/logs/debug.log instead."&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pre-Execution Interception (0ms latency)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When an agent calls a tool (shell command, file read, file delete), AgentGuard inspects the request synchronously before execution.&lt;/p&gt;

&lt;p&gt;Trying to run sudo? → Blocked.&lt;/p&gt;

&lt;p&gt;Trying to touch .env, id_rsa, or a file matching &lt;em&gt;bank&lt;/em&gt; or &lt;em&gt;tax&lt;/em&gt;? → Blocked.&lt;/p&gt;

&lt;p&gt;Escaping ./workspace with ../../? → Blocked.&lt;br&gt;
The file handle is never opened. The shell command is never spawned.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The 5-Minute Human Review Queue&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What about grey-area actions? Say the agent wants to run pip install pymongo.&lt;/p&gt;

&lt;p&gt;You don't want to completely block package installs, but you don't want an AI silently pulling unknown wheels from PyPI either.&lt;/p&gt;

&lt;p&gt;AgentGuard pauses the agent and puts the request into a Human Review Queue:&lt;br&gt;&lt;br&gt;
You get a notification on a clean web dashboard.&lt;br&gt;&lt;br&gt;
Each request has a 5-minute cryptographic timer so old, stale commands can't accidentally execute hours later.&lt;/p&gt;

&lt;p&gt;You click [ AUTHORIZE &amp;amp; RUN ], and it runs inside a controlled sandbox right in front of your eyes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Giving the Agent an "Immune System" (Backboard.io)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One thing that drove me crazy about local models was amnesia. If you tell an agent "don't delete that folder", it apologizes... and then tries again two turns later.&lt;/p&gt;

&lt;p&gt;To fix this, I plugged in Backboard.io for persistent cloud vector memory.&lt;/p&gt;

&lt;p&gt;Whenever AgentGuard blocks a command, it writes a short lesson into Backboard:&lt;/p&gt;

&lt;p&gt;"Incident: Agent tried to run 'sudo rm -rf'. Blocked by policy shell.destructive_commands."&lt;/p&gt;

&lt;p&gt;Next time you start a task, AgentGuard pulls the relevant memories from Backboard and feeds them into the agent's context. The agent literally remembers what got it in trouble yesterday and stops proposing bad commands in the first place.&lt;/p&gt;

&lt;p&gt;What the Dashboard Looks Like&lt;/p&gt;

&lt;p&gt;I didn't want a clunky terminal-only tool, so I built an industrial, dark-mode cockpit with React and Tailwind:&lt;/p&gt;

&lt;p&gt;Top KPI Cards: Live count of blocked attacks, total actions governed, and learned Backboard memories.&lt;/p&gt;

&lt;p&gt;Review Queue: Tabs for Pending, Approved, and Expired actions with inline terminal output.&lt;/p&gt;

&lt;p&gt;Threat Lab: A built-in sandbox where you can test 1-click red-team scenarios (ransomware simulations, credential exfiltration, path traversal) to see if your local model can break out. Spoiler: 0 escapes.&lt;/p&gt;

&lt;p&gt;Making It an NPM Package: Bring Your Own Keys (BYOK)&lt;/p&gt;

&lt;p&gt;Right now, you can clone the repo and run it locally with FastAPI and MongoDB.&lt;/p&gt;

&lt;p&gt;But I realized that's still too much friction for developers who just want to npm install something and start coding.&lt;/p&gt;

&lt;p&gt;So I'm packaging this as a standalone Bring-Your-Own-Keys (BYOK) NPM SDK:&lt;/p&gt;

&lt;p&gt;bash&lt;br&gt;
npm install agentguard&lt;/p&gt;

&lt;p&gt;You drop in your own Backboard API key (for cloud memory) and your own LLM key (or Ollama endpoint):&lt;/p&gt;

&lt;p&gt;typescript&lt;br&gt;
import { AgentGuard } from 'agentguard';&lt;br&gt;
const guard = new AgentGuard({&lt;br&gt;
  backboardApiKey: process.env.BACKBOARD_API_KEY,&lt;br&gt;
  workspace: './workspace',&lt;br&gt;
});&lt;br&gt;
// Wrap any agent tool call:&lt;br&gt;
const check = await guard.inspect(proposedCommand);&lt;br&gt;
if (check.isBlocked) {&lt;br&gt;
  // Feed safety feedback back to the LLM so it self-corrects!&lt;br&gt;
  console.log(&lt;code&gt;Blocked: ${check.explanation}&lt;/code&gt;);&lt;br&gt;
} else {&lt;br&gt;
  await guard.execute(proposedCommand);&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Zero servers to host. Zero background databases to manage. Just pure protection.&lt;/p&gt;

&lt;p&gt;Wrapping Up&lt;/p&gt;

&lt;p&gt;We are entering an era where AI agents aren't just autocomplete engines anymore—they are active operators on our computers. They write code, manage files, and execute bash scripts.&lt;/p&gt;

&lt;p&gt;We have to stop treating AI safety as a philosophical prompt problem and start treating it as a systems architecture problem.&lt;/p&gt;

&lt;p&gt;Don't convince the model to behave. Just put a guard on the wire.&lt;/p&gt;

&lt;p&gt;If you're building autonomous agents or playing with local models, I'd love to hear how you're keeping them safe. Have you had an AI agent do something terrifying on your machine yet?&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>privacy</category>
      <category>security</category>
    </item>
  </channel>
</rss>
