<?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: Nevin-Bali100</title>
    <description>The latest articles on DEV Community by Nevin-Bali100 (@nevin100).</description>
    <link>https://dev.to/nevin100</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%2F1919147%2Fa3f5bee6-ac15-4f5d-a356-bc433b59769c.jpeg</url>
      <title>DEV Community: Nevin-Bali100</title>
      <link>https://dev.to/nevin100</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nevin100"/>
    <language>en</language>
    <item>
      <title>Building DevDocAI — A Production Multi-Agent LangGraph System | Part 3 - GitHub Webhooks, Redis Caching</title>
      <dc:creator>Nevin-Bali100</dc:creator>
      <pubDate>Sun, 14 Jun 2026 16:35:01 +0000</pubDate>
      <link>https://dev.to/nevin100/building-devdocai-a-production-multi-agent-langgraph-system-part-3-github-webhooks-redis-1mgk</link>
      <guid>https://dev.to/nevin100/building-devdocai-a-production-multi-agent-langgraph-system-part-3-github-webhooks-redis-1mgk</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Series:&lt;/strong&gt; Building DevDocAI — A Production Multi-Agent LangGraph System&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 3&lt;/strong&gt; — GitHub Webhooks, Redis Caching &amp;amp; Making DevDocAI Truly Autonomous&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Real Talk First
&lt;/h2&gt;

&lt;p&gt;Between Part 2 and this post, I had university exams.&lt;/p&gt;

&lt;p&gt;Not just one. A full exam week.&lt;/p&gt;

&lt;p&gt;And honestly? I almost paused the project.&lt;/p&gt;

&lt;p&gt;But then I thought — if I can't build while life is happening, what's the point?&lt;/p&gt;

&lt;p&gt;So I kept going. Exams in the morning, code at night.&lt;/p&gt;

&lt;p&gt;This post is the result of that.&lt;/p&gt;




&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;By the end of Part 2, DevDocAI had:&lt;/p&gt;

&lt;p&gt;✅ A fully working LangGraph multi-agent pipeline&lt;br&gt;&lt;br&gt;
✅ AST-level codebase parsing&lt;br&gt;&lt;br&gt;
✅ LLM-powered documentation generation&lt;br&gt;&lt;br&gt;
✅ Brave Search enrichment&lt;br&gt;&lt;br&gt;
✅ Human-in-the-Loop review&lt;br&gt;&lt;br&gt;
✅ Qdrant vector store + RAG chatbot  &lt;/p&gt;

&lt;p&gt;But there was one major problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It was still manual.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Someone had to trigger the pipeline every time.&lt;/p&gt;

&lt;p&gt;That's not autonomous documentation. That's just a fancy script.&lt;/p&gt;

&lt;p&gt;Phase 5 fixes that.&lt;/p&gt;


&lt;h2&gt;
  
  
  What Phase 5 Adds
&lt;/h2&gt;

&lt;p&gt;Two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Webhooks&lt;/strong&gt; — DevDocAI listens for PR merges and auto-triggers the pipeline&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redis Caching&lt;/strong&gt; — pipeline status, docs, and repo data cached for speed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After this phase, the flow becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer merges a PR
        ↓
GitHub sends webhook to DevDocAI
        ↓
DevDocAI finds the repo in DB
        ↓
Verifies the webhook signature
        ↓
Creates a PipelineRun record
        ↓
Triggers the full agent pipeline
        ↓
Docs auto-update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Zero manual intervention.&lt;/p&gt;


&lt;h2&gt;
  
  
  GitHub Webhooks — How It Works
&lt;/h2&gt;

&lt;p&gt;A GitHub webhook is simple.&lt;/p&gt;

&lt;p&gt;When something happens in a repo (PR merged, push, etc.), GitHub sends a POST request to a URL you configure.&lt;/p&gt;

&lt;p&gt;DevDocAI listens at &lt;code&gt;/webhooks/github&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But there's a security problem.&lt;/p&gt;

&lt;p&gt;Anyone can send a fake POST request to that URL.&lt;/p&gt;

&lt;p&gt;GitHub solves this with &lt;strong&gt;HMAC-SHA256 signatures&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every webhook request has an &lt;code&gt;X-Hub-Signature-256&lt;/code&gt; header.&lt;/p&gt;

&lt;p&gt;It's a hash of the payload signed with a shared secret.&lt;/p&gt;

&lt;p&gt;We verify it before doing anything:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;verify_github_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature&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;secret&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;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sha256=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha256&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compare_digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If the signature doesn't match, request is rejected.&lt;/p&gt;

&lt;p&gt;Simple. Secure.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Webhook Handler
&lt;/h2&gt;

&lt;p&gt;The full webhook flow in code:&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="nd"&gt;@router.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/github&lt;/span&gt;&lt;span class="sh"&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;def&lt;/span&gt; &lt;span class="nf"&gt;github_webhook&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;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...):&lt;/span&gt;

    &lt;span class="c1"&gt;# Only care about merged PRs
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;closed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;merged&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&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;ignored&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Find repo in our DB
&lt;/span&gt;    &lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_repo_by_github_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;github_repo_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Verify signature
&lt;/span&gt;    &lt;span class="nf"&gt;verify_github_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload_bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Create PipelineRun record
&lt;/span&gt;    &lt;span class="n"&gt;pipeline_run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;PipelineRun&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trigger&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pr_merge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pr_number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pr_number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Cache pipeline status in Redis
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;cache_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pipeline_status_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&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;status&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;running&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# Trigger the pipeline
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;run_pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;initial_state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc_graph&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Clean, sequential, easy to follow.&lt;/p&gt;

&lt;p&gt;Each step has one job.&lt;/p&gt;


&lt;h2&gt;
  
  
  Redis Caching — Why It Matters
&lt;/h2&gt;

&lt;p&gt;Every time someone opens the dashboard, should we query PostgreSQL for everything?&lt;/p&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;That's where Redis comes in.&lt;/p&gt;

&lt;p&gt;Three main cache keys:&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="nf"&gt;repo_docs_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c1"&gt;# "repo:{id}:docs"
&lt;/span&gt;&lt;span class="nf"&gt;pipeline_status_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# "pipeline:{thread_id}:status"
&lt;/span&gt;&lt;span class="nf"&gt;user_repos_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="c1"&gt;# "user:{id}:repos"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When a PR triggers the pipeline, old docs cache is invalidated immediately:&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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;cache_delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;repo_docs_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When someone checks pipeline status, it comes from Redis — not a DB query.&lt;/p&gt;

&lt;p&gt;Fast. Cheap. Simple.&lt;/p&gt;


&lt;h2&gt;
  
  
  What the Full System Looks Like Now
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;backend/
├── auth/
│   ├── jwt.py
│   ├── github_oauth.py
│   └── routes.py
├── db/
│   ├── database.py
│   └── models.py
├── repositories/
│   └── user_repository.py
├── schemas/
│   └── auth_schemas.py
├── services/
│   └── auth_service.py
├── utils/
│   ├── helper_auth.py
│   └── encryption.py
├── mcp/
│   └── github_server.py
├── agents/
│   ├── codebase_parser.py
│   ├── doc_generator.py
│   ├── brave_researcher.py
│   ├── doc_publisher.py
│   └── onboarding_chatbot.py
├── graph/
│   ├── state.py
│   ├── pipeline.py
│   └── hitl.py
├── vectorstore/
│   ├── embeddings.py
│   └── qdrant_store.py
├── webhooks/
│   └── github_pr.py       ← new
├── cache/
│   └── redis_client.py    ← new
└── main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Backend is complete.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Endpoints Now
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET   /health
POST  /auth/register
POST  /auth/login
GET   /auth/github
POST  /auth/github/callback
GET   /auth/me
POST  /webhooks/github      ← new
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Building During Exams — What I Learned
&lt;/h2&gt;

&lt;p&gt;Honestly, shipping Phase 5 while having exams taught me more than just code.&lt;/p&gt;

&lt;p&gt;A few things I noticed:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constraints force focus.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When you only have 2 hours, you don't waste time on perfect folder naming or over-engineering. You build what matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Momentum is everything.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Missing one day makes it easier to miss two. Shipping something small every day — even just one file — keeps the project alive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;University teaches you to work under pressure. Building teaches you to create under pressure.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Both matter. They're not enemies.&lt;/p&gt;

&lt;p&gt;I'm not saying skip studying. I'm saying you don't have to choose between learning and building.&lt;/p&gt;

&lt;p&gt;Do both. It's harder. It's worth it.&lt;/p&gt;


&lt;h2&gt;
  
  
  Key Technical Learnings from Phase 5
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Always verify webhook signatures.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Without HMAC verification, anyone can trigger your pipeline. Never skip this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Invalidate cache on state change.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When docs update, old cache must go. Stale cache is worse than no cache.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Background tasks need proper state.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
When the webhook triggers a pipeline, it runs async. Make sure state is fully initialized before kicking it off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. &lt;code&gt;psycopg[binary]&lt;/code&gt; is required for LangGraph PostgreSQL checkpointer on Windows.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Spent more time than I'd like to admit on this one.&lt;/p&gt;


&lt;h2&gt;
  
  
  What's Next — Part 4
&lt;/h2&gt;

&lt;p&gt;Phase 6 is the &lt;strong&gt;Next.js frontend&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Three pages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dashboard&lt;/strong&gt; — connected repos, pipeline status, doc overview&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review Panel&lt;/strong&gt; — HITL approval UI (approve/reject generated docs)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chat&lt;/strong&gt; — onboarding chatbot interface&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where DevDocAI becomes something you can actually show someone without saying "trust me, it works."&lt;/p&gt;

&lt;p&gt;Exams are still going. Building is still happening.&lt;/p&gt;

&lt;p&gt;Part 4 dropping soon. 🚀&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.amazonaws.com%2Fuploads%2Farticles%2Fygu9toyrdg70ns00zuw0.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.amazonaws.com%2Fuploads%2Farticles%2Fygu9toyrdg70ns00zuw0.png" alt="Code Base SS"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  GitHub
&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/Nevin100" rel="noopener noreferrer"&gt;
        Nevin100
      &lt;/a&gt; / &lt;a href="https://github.com/Nevin100/DevdocxAI" rel="noopener noreferrer"&gt;
        DevdocxAI
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      DevDocxAI is a production-grade multi-agent AI system that automatically generates, maintains, and updates engineering documentation by deeply understanding you…DevDocAI is a production-grade multi-agent AI system that automatically generates, maintains, and updates doc. by understanding deeply.
    &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;DevDocxAI 🤖📄&lt;/h1&gt;
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;DevDocxAi is a production-grade multi-agent LangGraph system that automatically generates and updates engineering documentation from your GitHub codebase.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/807252c6cff24d131a3381ca3bfb31e16b34adfc533e605432a3ebffd29ff466/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507974686f6e2d332e31322d626c75653f7374796c653d666c61742d737175617265266c6f676f3d707974686f6e"&gt;&lt;img src="https://camo.githubusercontent.com/807252c6cff24d131a3381ca3bfb31e16b34adfc533e605432a3ebffd29ff466/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507974686f6e2d332e31322d626c75653f7374796c653d666c61742d737175617265266c6f676f3d707974686f6e" alt="Python"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/9a3024d9f71a2127707cc8c40e5b20188dc57d03f051129b56bee65ca98f7bee/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f466173744150492d302e3131352d677265656e3f7374796c653d666c61742d737175617265266c6f676f3d66617374617069"&gt;&lt;img src="https://camo.githubusercontent.com/9a3024d9f71a2127707cc8c40e5b20188dc57d03f051129b56bee65ca98f7bee/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f466173744150492d302e3131352d677265656e3f7374796c653d666c61742d737175617265266c6f676f3d66617374617069" alt="FastAPI"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/17cf441b5dce665864bd3add5657a7929e00a8209442b67861e9acf237c3c46b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c616e6747726170682d302e322d6f72616e67653f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/17cf441b5dce665864bd3add5657a7929e00a8209442b67861e9acf237c3c46b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c616e6747726170682d302e322d6f72616e67653f7374796c653d666c61742d737175617265" alt="LangGraph"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/c83193d768f5fd708e5ba1a6ec44a81ffb9d0e47094385e6022a1742511452f7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f506f737467726553514c2d31362d626c75653f7374796c653d666c61742d737175617265266c6f676f3d706f737467726573716c"&gt;&lt;img src="https://camo.githubusercontent.com/c83193d768f5fd708e5ba1a6ec44a81ffb9d0e47094385e6022a1742511452f7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f506f737467726553514c2d31362d626c75653f7374796c653d666c61742d737175617265266c6f676f3d706f737467726573716c" alt="PostgreSQL"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/f3cd9467f1a2673efb050d325944267a717320385a6e45da3a19f994f9004339/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f773f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/f3cd9467f1a2673efb050d325944267a717320385a6e45da3a19f994f9004339/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f773f7374796c653d666c61742d737175617265" alt="License"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/27ee412fbf2ea617f1088ddd749c768146852cea00776460fc2b81837787a6b0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5374617475732d416374697665253230446576656c6f706d656e742d627269676874677265656e3f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/27ee412fbf2ea617f1088ddd749c768146852cea00776460fc2b81837787a6b0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5374617475732d416374697665253230446576656c6f706d656e742d627269676874677265656e3f7374796c653d666c61742d737175617265" alt="Status"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚨 The Problem&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Every engineering team has the same dirty secret — &lt;strong&gt;the docs are lying.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Not intentionally. Code moves fast, documentation doesn't.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New dev joins → 2 weeks reading outdated wikis&lt;/li&gt;
&lt;li&gt;Senior engineers constantly interrupted with "what does this do?"&lt;/li&gt;
&lt;li&gt;PR gets merged → docs never updated&lt;/li&gt;
&lt;li&gt;Generic RAG chatbots don't understand code &lt;em&gt;structure&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;DevDocAI fixes this.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;✨ What It Does&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;🔍 &lt;strong&gt;Connects to your GitHub repo&lt;/strong&gt; via OAuth&lt;/li&gt;
&lt;li&gt;🌳 &lt;strong&gt;Parses your codebase at the AST level&lt;/strong&gt; — understands functions, classes, modules&lt;/li&gt;
&lt;li&gt;📝 &lt;strong&gt;Auto-generates structured documentation&lt;/strong&gt; per module and function&lt;/li&gt;
&lt;li&gt;🔄 &lt;strong&gt;Updates docs on every PR merge&lt;/strong&gt; via GitHub webhooks&lt;/li&gt;
&lt;li&gt;👀 &lt;strong&gt;Human-in-the-Loop review&lt;/strong&gt; — you approve before anything goes live&lt;/li&gt;
&lt;li&gt;💬 &lt;strong&gt;Onboarding chatbot&lt;/strong&gt; — new devs ask questions, get answers from live code&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🤖 Agent Pipeline&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code&gt;START
  ↓
codebase_parser&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/Nevin100/DevdocxAI" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;





&lt;p&gt;&lt;em&gt;Building in public — through exams, late nights, and all.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Tags: &lt;code&gt;python&lt;/code&gt; &lt;code&gt;ai&lt;/code&gt; &lt;code&gt;langgraph&lt;/code&gt; &lt;code&gt;fastapi&lt;/code&gt; &lt;code&gt;redis&lt;/code&gt; &lt;code&gt;webhooks&lt;/code&gt; &lt;code&gt;opensource&lt;/code&gt; &lt;code&gt;webdev&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>fastapi</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Building DevDocAI - An AI That Writes Your Docs Automatically | Part 2: LangGraph Core, Agents &amp; RAG</title>
      <dc:creator>Nevin-Bali100</dc:creator>
      <pubDate>Sun, 07 Jun 2026 13:36:28 +0000</pubDate>
      <link>https://dev.to/nevin100/-building-devdocai-an-ai-that-writes-your-docs-automatically-part-2-langgraph-core-agents--3j27</link>
      <guid>https://dev.to/nevin100/-building-devdocai-an-ai-that-writes-your-docs-automatically-part-2-langgraph-core-agents--3j27</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Series:&lt;/strong&gt; Building DevDocAI — A Production Multi-Agent LangGraph System&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 2&lt;/strong&gt; — LangGraph Core, Human-in-the-Loop Workflows, Agents &amp;amp; RAG&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;In Part 1, I built the foundation of DevDocAI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI backend&lt;/li&gt;
&lt;li&gt;PostgreSQL database&lt;/li&gt;
&lt;li&gt;JWT authentication&lt;/li&gt;
&lt;li&gt;GitHub OAuth&lt;/li&gt;
&lt;li&gt;MCP server for GitHub tools&lt;/li&gt;
&lt;li&gt;Clean layered architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At that point, the infrastructure was ready, but the actual AI system didn't exist yet.&lt;/p&gt;

&lt;p&gt;This phase changes that.&lt;/p&gt;

&lt;p&gt;In this article, I'm covering &lt;strong&gt;Phase 3 and Phase 4&lt;/strong&gt;, where DevDocAI finally becomes a real multi-agent system powered by LangGraph.&lt;/p&gt;




&lt;h2&gt;
  
  
  What We Built in This Phase
&lt;/h2&gt;

&lt;p&gt;The goal was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Take a GitHub repository and turn it into living documentation through an orchestrated AI workflow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To make that happen, I built:&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 3 — LangGraph Core
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;State Management&lt;/li&gt;
&lt;li&gt;Workflow Pipeline&lt;/li&gt;
&lt;li&gt;Human-in-the-Loop (HITL)&lt;/li&gt;
&lt;li&gt;PostgreSQL Checkpointing&lt;/li&gt;
&lt;li&gt;Conditional Routing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Phase 4 — Agents &amp;amp; RAG
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AST-based Code Parser Agent&lt;/li&gt;
&lt;li&gt;Documentation Generator Agent&lt;/li&gt;
&lt;li&gt;Brave Researcher Agent&lt;/li&gt;
&lt;li&gt;Documentation Publisher Agent&lt;/li&gt;
&lt;li&gt;Qdrant Vector Store&lt;/li&gt;
&lt;li&gt;Embeddings Pipeline&lt;/li&gt;
&lt;li&gt;Onboarding Chatbot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where DevDocAI went from "backend project" to "actual AI product."&lt;/p&gt;




&lt;h2&gt;
  
  
  The Updated Workflow
&lt;/h2&gt;

&lt;p&gt;The complete pipeline now looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;START
  ↓
codebase_parser
  ↓
doc_generator
  ↓
brave_researcher
  ↓
HITL checkpoint
  ↓
doc_publisher
  ↓
END

Parallel

onboarding_chatbot
      ↓
  Vector Store
      ↓
 Generated Docs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Every node performs a specific task and passes information to the next node through a shared graph state.&lt;/p&gt;


&lt;h1&gt;
  
  
  Phase 3 — LangGraph Core
&lt;/h1&gt;

&lt;p&gt;Before building agents, I needed a reliable workflow engine.&lt;/p&gt;

&lt;p&gt;This is where LangGraph came in.&lt;/p&gt;

&lt;p&gt;Unlike a simple chain, LangGraph allows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stateful execution&lt;/li&gt;
&lt;li&gt;Checkpointing&lt;/li&gt;
&lt;li&gt;Human approval workflows&lt;/li&gt;
&lt;li&gt;Conditional routing&lt;/li&gt;
&lt;li&gt;Resume after interruption&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exactly what a production documentation system needs.&lt;/p&gt;


&lt;h2&gt;
  
  
  State Management
&lt;/h2&gt;

&lt;p&gt;The first thing I built was a central state object.&lt;/p&gt;

&lt;p&gt;Every agent in the graph reads from and writes to the same state.&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DevDocState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;repo_full_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;repo_raw_content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

    &lt;span class="n"&gt;parsed_structure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;
    &lt;span class="n"&gt;generated_docs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

    &lt;span class="n"&gt;current_step&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;review_status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;dev_notes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

    &lt;span class="n"&gt;final_docs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Think of this as the memory of the entire workflow.&lt;/p&gt;

&lt;p&gt;Instead of passing dozens of variables between agents, everything flows through a single structured state.&lt;/p&gt;

&lt;p&gt;This makes debugging significantly easier.&lt;/p&gt;


&lt;h2&gt;
  
  
  Building the Pipeline
&lt;/h2&gt;

&lt;p&gt;Once the state was defined, I created the graph itself.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;START
  ↓
code_parser_node
  ↓
doc_generator_node
  ↓
hitl_review_node
  ↓
doc_publisher_node
  ↓
END
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Each node performs one responsibility.&lt;/p&gt;
&lt;h3&gt;
  
  
  Code Parser Node
&lt;/h3&gt;

&lt;p&gt;Reads the repository and analyzes the code structure.&lt;/p&gt;
&lt;h3&gt;
  
  
  Documentation Generator Node
&lt;/h3&gt;

&lt;p&gt;Creates documentation using the parsed output.&lt;/p&gt;
&lt;h3&gt;
  
  
  HITL Node
&lt;/h3&gt;

&lt;p&gt;Pauses execution and waits for a human decision.&lt;/p&gt;
&lt;h3&gt;
  
  
  Publisher Node
&lt;/h3&gt;

&lt;p&gt;Publishes approved documentation.&lt;/p&gt;

&lt;p&gt;This separation keeps the graph modular and easy to extend.&lt;/p&gt;


&lt;h2&gt;
  
  
  Human-in-the-Loop (HITL)
&lt;/h2&gt;

&lt;p&gt;This was one of the most interesting parts of the project.&lt;/p&gt;

&lt;p&gt;I didn't want an AI that automatically pushes documentation to production.&lt;/p&gt;

&lt;p&gt;Developers need control.&lt;/p&gt;

&lt;p&gt;So the graph pauses before publishing.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Generated Docs
      ↓
    Review
      ↓
 Approved ? 
   /     \
 Yes      No
  ↓        ↓
Publish   Stop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The workflow literally waits for a developer's decision.&lt;/p&gt;

&lt;p&gt;This is not a prompt-based approval.&lt;/p&gt;

&lt;p&gt;This is actual workflow orchestration.&lt;/p&gt;

&lt;p&gt;The graph execution stops and resumes later based on user input.&lt;/p&gt;


&lt;h2&gt;
  
  
  PostgreSQL Checkpointing
&lt;/h2&gt;

&lt;p&gt;A paused workflow is useless if the state disappears.&lt;/p&gt;

&lt;p&gt;That's why I implemented checkpoint persistence.&lt;/p&gt;

&lt;p&gt;The complete graph state is stored in PostgreSQL.&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;checkpoint&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;
&lt;span class="n"&gt;resume&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;restore&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;
&lt;span class="k"&gt;continue&lt;/span&gt; &lt;span class="n"&gt;execution&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Workflow survives server restarts&lt;/li&gt;
&lt;li&gt;Long-running executions become possible&lt;/li&gt;
&lt;li&gt;Human approval can happen hours later&lt;/li&gt;
&lt;li&gt;Full auditability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This was one of the biggest advantages of choosing LangGraph.&lt;/p&gt;


&lt;h2&gt;
  
  
  Conditional Routing
&lt;/h2&gt;

&lt;p&gt;After review, the graph makes a decision.&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;should_publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;review_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;approved&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;publish&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reject&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The graph dynamically routes execution.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Review
   ↓
Approved?
   ↓
 ┌───────┬────────┐
 │ Yes   │ No     │
 ↓       ↓
Publish  Reject
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Simple idea.&lt;/p&gt;

&lt;p&gt;Very powerful in production workflows.&lt;/p&gt;


&lt;h1&gt;
  
  
  Phase 4 — Building the Agents
&lt;/h1&gt;

&lt;p&gt;Once the graph was ready, it was time to build the intelligence layer.&lt;/p&gt;

&lt;p&gt;I created four specialized agents.&lt;/p&gt;

&lt;p&gt;Each one solves a specific problem.&lt;/p&gt;


&lt;h2&gt;
  
  
  Agent 1 — Codebase Parser
&lt;/h2&gt;

&lt;p&gt;This agent is responsible for understanding the repository.&lt;/p&gt;

&lt;p&gt;Instead of treating source code as plain text, it analyzes the code using Python's AST.&lt;/p&gt;
&lt;h3&gt;
  
  
  What it extracts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Functions&lt;/li&gt;
&lt;li&gt;Classes&lt;/li&gt;
&lt;li&gt;Imports&lt;/li&gt;
&lt;li&gt;Modules&lt;/li&gt;
&lt;li&gt;Dependencies&lt;/li&gt;
&lt;li&gt;Documentation patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The parser understands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Function name&lt;/li&gt;
&lt;li&gt;Parameters&lt;/li&gt;
&lt;li&gt;Relationships&lt;/li&gt;
&lt;li&gt;Dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not just raw text.&lt;/p&gt;

&lt;p&gt;Actual code structure.&lt;/p&gt;

&lt;p&gt;This becomes the foundation for documentation generation.&lt;/p&gt;


&lt;h2&gt;
  
  
  Agent 2 — Documentation Generator
&lt;/h2&gt;

&lt;p&gt;After parsing, the next challenge is turning code into useful documentation.&lt;/p&gt;

&lt;p&gt;This agent takes structured information and generates docs.&lt;/p&gt;

&lt;p&gt;Capabilities include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Markdown generation&lt;/li&gt;
&lt;li&gt;HTML generation&lt;/li&gt;
&lt;li&gt;Function explanations&lt;/li&gt;
&lt;li&gt;Usage examples&lt;/li&gt;
&lt;li&gt;API documentation&lt;/li&gt;
&lt;li&gt;Multiple documentation styles
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input:
Parsed AST Structure

Output:
Developer-Friendly Documentation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is the core value proposition of DevDocAI.&lt;/p&gt;


&lt;h2&gt;
  
  
  Agent 3 — Brave Researcher
&lt;/h2&gt;

&lt;p&gt;Documentation generated purely from code is often incomplete.&lt;/p&gt;

&lt;p&gt;Libraries, frameworks and external tools also need context.&lt;/p&gt;

&lt;p&gt;To solve this, I built the Brave Researcher.&lt;/p&gt;

&lt;p&gt;It uses the Brave Search API to gather additional information.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Library explanations&lt;/li&gt;
&lt;li&gt;Framework documentation&lt;/li&gt;
&lt;li&gt;Best practices&lt;/li&gt;
&lt;li&gt;External references&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates richer documentation than code analysis alone.&lt;/p&gt;


&lt;h2&gt;
  
  
  Agent 4 — Documentation Publisher
&lt;/h2&gt;

&lt;p&gt;Generating docs isn't enough.&lt;/p&gt;

&lt;p&gt;They need to be distributed.&lt;/p&gt;

&lt;p&gt;The publisher agent handles that responsibility.&lt;/p&gt;

&lt;p&gt;Supported targets include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub Wiki&lt;/li&gt;
&lt;li&gt;README generation&lt;/li&gt;
&lt;li&gt;File storage&lt;/li&gt;
&lt;li&gt;Versioned documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rest of the system doesn't care where docs go.&lt;/p&gt;

&lt;p&gt;The publisher abstracts that away.&lt;/p&gt;


&lt;h1&gt;
  
  
  Adding RAG with Qdrant
&lt;/h1&gt;

&lt;p&gt;The next challenge was onboarding.&lt;/p&gt;

&lt;p&gt;Imagine a new engineer joins a project.&lt;/p&gt;

&lt;p&gt;Instead of reading hundreds of files, they should be able to ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What does the authentication flow look like?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which service handles payment processing?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To make that possible, I added Retrieval-Augmented Generation (RAG).&lt;/p&gt;


&lt;h2&gt;
  
  
  Vector Store Architecture
&lt;/h2&gt;

&lt;p&gt;Generated documentation is embedded and stored in Qdrant.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Generated Docs
       ↓
Embeddings
       ↓
Qdrant
       ↓
Semantic Search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Instead of keyword matching, the system performs semantic retrieval.&lt;/p&gt;

&lt;p&gt;This allows developers to ask natural language questions.&lt;/p&gt;


&lt;h2&gt;
  
  
  Embeddings Pipeline
&lt;/h2&gt;

&lt;p&gt;Every document is converted into vectors.&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;Document&lt;/span&gt;
   &lt;span class="err"&gt;↓&lt;/span&gt;
&lt;span class="n"&gt;Embedding&lt;/span&gt; &lt;span class="n"&gt;Model&lt;/span&gt;
   &lt;span class="err"&gt;↓&lt;/span&gt;
&lt;span class="n"&gt;Vector&lt;/span&gt;
   &lt;span class="err"&gt;↓&lt;/span&gt;
&lt;span class="n"&gt;Qdrant&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;These vectors capture meaning rather than exact words.&lt;/p&gt;

&lt;p&gt;That makes retrieval dramatically better.&lt;/p&gt;


&lt;h1&gt;
  
  
  The Onboarding Chatbot
&lt;/h1&gt;

&lt;p&gt;The final piece of Phase 4 was the onboarding assistant.&lt;/p&gt;

&lt;p&gt;This chatbot sits on top of the vector store.&lt;/p&gt;

&lt;p&gt;Workflow:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Developer Question
        ↓
Vector Search
        ↓
Relevant Docs
        ↓
LLM
        ↓
Answer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now a developer can ask questions about the codebase without manually searching through files.&lt;/p&gt;

&lt;p&gt;The answers come from generated documentation and repository knowledge.&lt;/p&gt;

&lt;p&gt;Not generic internet responses.&lt;/p&gt;


&lt;h1&gt;
  
  
  Why I Chose Specialized Agents
&lt;/h1&gt;

&lt;p&gt;One giant prompt could technically do everything.&lt;/p&gt;

&lt;p&gt;But that's not how production systems scale.&lt;/p&gt;

&lt;p&gt;Instead:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parser Agent
      ↓
Research Agent
      ↓
Generator Agent
      ↓
Publisher Agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Each agent has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One responsibility&lt;/li&gt;
&lt;li&gt;Clear inputs&lt;/li&gt;
&lt;li&gt;Clear outputs&lt;/li&gt;
&lt;li&gt;Independent testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes the system easier to maintain and improve.&lt;/p&gt;


&lt;h1&gt;
  
  
  What the Project Structure Looks Like Now
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;backend/
├── agents/
│   ├── brave_researcher.py
│   ├── codebase_parser.py
│   ├── doc_generator.py
│   ├── doc_publisher.py
│   └── onboarding_chatbot.py
│
├── graph/
│   ├── state.py
│   ├── pipeline.py
│   └── hitl.py
│
└── vectorstore/
    ├── embeddings.py
    └── qdrant_client.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The architecture is starting to resemble a real production AI platform.&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.amazonaws.com%2Fuploads%2Farticles%2Fig53cyhkaaxw5u31q1p9.jpg" 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.amazonaws.com%2Fuploads%2Farticles%2Fig53cyhkaaxw5u31q1p9.jpg" alt="CodeBase File Structure" width="799" height="424"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h1&gt;
  
  
  Key Learnings from Phase 3 &amp;amp; 4
&lt;/h1&gt;
&lt;h2&gt;
  
  
  1. Agents Need Structure
&lt;/h2&gt;

&lt;p&gt;Most AI projects fail because every responsibility gets stuffed into one prompt.&lt;/p&gt;

&lt;p&gt;Breaking responsibilities into specialized agents makes the system dramatically more reliable.&lt;/p&gt;


&lt;h2&gt;
  
  
  2. Human Approval Matters
&lt;/h2&gt;

&lt;p&gt;Fully autonomous documentation publishing sounds cool until it publishes something wrong.&lt;/p&gt;

&lt;p&gt;HITL workflows provide the safety net production systems need.&lt;/p&gt;


&lt;h2&gt;
  
  
  3. RAG Is Only As Good As Your Documents
&lt;/h2&gt;

&lt;p&gt;A chatbot is useless if the underlying knowledge base is poor.&lt;/p&gt;

&lt;p&gt;Investing in quality documentation generation improves everything downstream.&lt;/p&gt;


&lt;h2&gt;
  
  
  4. State Management Becomes Critical
&lt;/h2&gt;

&lt;p&gt;Once workflows span multiple agents, checkpoints and persistence become mandatory.&lt;/p&gt;

&lt;p&gt;Without state management, debugging becomes a nightmare.&lt;/p&gt;


&lt;h1&gt;
  
  
  What's Next — Part 3
&lt;/h1&gt;

&lt;p&gt;The core AI system is now complete.&lt;/p&gt;

&lt;p&gt;Next, I'll focus on Phase 5:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub Webhooks&lt;/li&gt;
&lt;li&gt;Automatic PR Detection&lt;/li&gt;
&lt;li&gt;Incremental Documentation Updates&lt;/li&gt;
&lt;li&gt;Redis Caching&lt;/li&gt;
&lt;li&gt;Event-Driven Pipeline Execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where DevDocAI becomes truly autonomous.&lt;/p&gt;

&lt;p&gt;Every merged PR will automatically trigger documentation updates.&lt;/p&gt;

&lt;p&gt;No manual intervention required.&lt;/p&gt;


&lt;h2&gt;
  
  
  GitHub
&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/Nevin100" rel="noopener noreferrer"&gt;
        Nevin100
      &lt;/a&gt; / &lt;a href="https://github.com/Nevin100/DevdocxAI" rel="noopener noreferrer"&gt;
        DevdocxAI
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      DevDocxAI is a production-grade multi-agent AI system that automatically generates, maintains, and updates engineering documentation by deeply understanding you…DevDocAI is a production-grade multi-agent AI system that automatically generates, maintains, and updates doc. by understanding deeply.
    &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;DevDocxAI 🤖📄&lt;/h1&gt;
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;DevDocxAi is a production-grade multi-agent LangGraph system that automatically generates and updates engineering documentation from your GitHub codebase.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/807252c6cff24d131a3381ca3bfb31e16b34adfc533e605432a3ebffd29ff466/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507974686f6e2d332e31322d626c75653f7374796c653d666c61742d737175617265266c6f676f3d707974686f6e"&gt;&lt;img src="https://camo.githubusercontent.com/807252c6cff24d131a3381ca3bfb31e16b34adfc533e605432a3ebffd29ff466/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507974686f6e2d332e31322d626c75653f7374796c653d666c61742d737175617265266c6f676f3d707974686f6e" alt="Python"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/9a3024d9f71a2127707cc8c40e5b20188dc57d03f051129b56bee65ca98f7bee/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f466173744150492d302e3131352d677265656e3f7374796c653d666c61742d737175617265266c6f676f3d66617374617069"&gt;&lt;img src="https://camo.githubusercontent.com/9a3024d9f71a2127707cc8c40e5b20188dc57d03f051129b56bee65ca98f7bee/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f466173744150492d302e3131352d677265656e3f7374796c653d666c61742d737175617265266c6f676f3d66617374617069" alt="FastAPI"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/17cf441b5dce665864bd3add5657a7929e00a8209442b67861e9acf237c3c46b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c616e6747726170682d302e322d6f72616e67653f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/17cf441b5dce665864bd3add5657a7929e00a8209442b67861e9acf237c3c46b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c616e6747726170682d302e322d6f72616e67653f7374796c653d666c61742d737175617265" alt="LangGraph"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/c83193d768f5fd708e5ba1a6ec44a81ffb9d0e47094385e6022a1742511452f7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f506f737467726553514c2d31362d626c75653f7374796c653d666c61742d737175617265266c6f676f3d706f737467726573716c"&gt;&lt;img src="https://camo.githubusercontent.com/c83193d768f5fd708e5ba1a6ec44a81ffb9d0e47094385e6022a1742511452f7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f506f737467726553514c2d31362d626c75653f7374796c653d666c61742d737175617265266c6f676f3d706f737467726573716c" alt="PostgreSQL"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/f3cd9467f1a2673efb050d325944267a717320385a6e45da3a19f994f9004339/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f773f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/f3cd9467f1a2673efb050d325944267a717320385a6e45da3a19f994f9004339/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f773f7374796c653d666c61742d737175617265" alt="License"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/27ee412fbf2ea617f1088ddd749c768146852cea00776460fc2b81837787a6b0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5374617475732d416374697665253230446576656c6f706d656e742d627269676874677265656e3f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/27ee412fbf2ea617f1088ddd749c768146852cea00776460fc2b81837787a6b0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5374617475732d416374697665253230446576656c6f706d656e742d627269676874677265656e3f7374796c653d666c61742d737175617265" alt="Status"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚨 The Problem&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Every engineering team has the same dirty secret — &lt;strong&gt;the docs are lying.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Not intentionally. Code moves fast, documentation doesn't.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New dev joins → 2 weeks reading outdated wikis&lt;/li&gt;
&lt;li&gt;Senior engineers constantly interrupted with "what does this do?"&lt;/li&gt;
&lt;li&gt;PR gets merged → docs never updated&lt;/li&gt;
&lt;li&gt;Generic RAG chatbots don't understand code &lt;em&gt;structure&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;DevDocAI fixes this.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;✨ What It Does&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;🔍 &lt;strong&gt;Connects to your GitHub repo&lt;/strong&gt; via OAuth&lt;/li&gt;
&lt;li&gt;🌳 &lt;strong&gt;Parses your codebase at the AST level&lt;/strong&gt; — understands functions, classes, modules&lt;/li&gt;
&lt;li&gt;📝 &lt;strong&gt;Auto-generates structured documentation&lt;/strong&gt; per module and function&lt;/li&gt;
&lt;li&gt;🔄 &lt;strong&gt;Updates docs on every PR merge&lt;/strong&gt; via GitHub webhooks&lt;/li&gt;
&lt;li&gt;👀 &lt;strong&gt;Human-in-the-Loop review&lt;/strong&gt; — you approve before anything goes live&lt;/li&gt;
&lt;li&gt;💬 &lt;strong&gt;Onboarding chatbot&lt;/strong&gt; — new devs ask questions, get answers from live code&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🤖 Agent Pipeline&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code&gt;START
  ↓
codebase_parser&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/Nevin100/DevdocxAI" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;





&lt;p&gt;&lt;em&gt;Building in public. Part 3 dropping soon.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Tags: &lt;code&gt;python&lt;/code&gt; &lt;code&gt;ai&lt;/code&gt; &lt;code&gt;langgraph&lt;/code&gt; &lt;code&gt;langchain&lt;/code&gt; &lt;code&gt;rag&lt;/code&gt; &lt;code&gt;fastapi&lt;/code&gt; &lt;code&gt;opensource&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>python</category>
      <category>agents</category>
      <category>ai</category>
    </item>
    <item>
      <title>Building DevDocAI - An AI That Writes Your Docs | Part 1: Foundation</title>
      <dc:creator>Nevin-Bali100</dc:creator>
      <pubDate>Fri, 05 Jun 2026 08:57:25 +0000</pubDate>
      <link>https://dev.to/nevin100/building-devdocai-an-ai-that-writes-your-docs-part-1-foundation-5cjh</link>
      <guid>https://dev.to/nevin100/building-devdocai-an-ai-that-writes-your-docs-part-1-foundation-5cjh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Series:&lt;/strong&gt; Building DevDocAI — A Production Multi-Agent LangGraph System&lt;br&gt;
&lt;strong&gt;Part 1 of 6&lt;/strong&gt; — Foundation: Backend, Auth, DB, GitHub OAuth, MCP Server&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Every engineering team has the same dirty secret: &lt;strong&gt;the docs are lying.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not intentionally. Code moves fast, documentation doesn't. A new dev joins → spends 2 weeks reading outdated wikis → still has to disturb 3 senior engineers just to understand one service.&lt;/p&gt;

&lt;p&gt;I got tired of it. So I'm building &lt;strong&gt;DevDocAI&lt;/strong&gt;.&lt;/p&gt;




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

&lt;p&gt;DevDocAI is a &lt;strong&gt;production-grade multi-agent LangGraph system&lt;/strong&gt; that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connects to your GitHub repo&lt;/li&gt;
&lt;li&gt;Reads your codebase at the &lt;strong&gt;AST level&lt;/strong&gt; (not just text — actual code structure)&lt;/li&gt;
&lt;li&gt;Auto-generates structured documentation per module/function&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Updates docs automatically&lt;/strong&gt; every time a PR gets merged&lt;/li&gt;
&lt;li&gt;Has an &lt;strong&gt;onboarding chatbot&lt;/strong&gt; — new devs can ask "what does this function do?" and get real answers from live code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key word is &lt;strong&gt;agent&lt;/strong&gt; — not just a RAG chatbot. This system understands your code.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Full Agent Pipeline (What I'm Building)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;START
  ↓
codebase_parser      ← AST-level parsing of GitHub repo
  ↓
doc_generator        ← LLM generates structured docs per module/function
  ↓
brave_researcher     ← enriches with external context (libraries, best practices)
  ↓
HITL checkpoint      ← YOU review generated docs before publish
  ↓
doc_publisher        ← saves to DB + updates vector store
  ↓
pr_watcher           ← GitHub webhook re-triggers on every PR merge
  ↓
END

Parallel → onboarding_chatbot ← RAG over vector store for new devs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;strong&gt;HITL (Human-in-the-Loop)&lt;/strong&gt; part is what makes this real. The LangGraph pipeline literally &lt;em&gt;pauses&lt;/em&gt;, waits for a dev to approve via the frontend, then resumes. Not just vibes — actual workflow.&lt;/p&gt;


&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Tech&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Agent Framework&lt;/td&gt;
&lt;td&gt;LangGraph&lt;/td&gt;
&lt;td&gt;Multi-agent, HITL, checkpointing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;FastAPI + Python&lt;/td&gt;
&lt;td&gt;Async, fast, clean&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;Next.js + Tailwind&lt;/td&gt;
&lt;td&gt;(coming Phase 6)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LLM&lt;/td&gt;
&lt;td&gt;Groq llama-3.3-70b&lt;/td&gt;
&lt;td&gt;Blazing fast inference&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Embeddings&lt;/td&gt;
&lt;td&gt;Cohere&lt;/td&gt;
&lt;td&gt;Best-in-class embeddings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vector DB&lt;/td&gt;
&lt;td&gt;Qdrant&lt;/td&gt;
&lt;td&gt;Production-grade, pure Python client&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web Search&lt;/td&gt;
&lt;td&gt;Brave Search API&lt;/td&gt;
&lt;td&gt;Dev-focused, privacy-first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observability&lt;/td&gt;
&lt;td&gt;LangSmith&lt;/td&gt;
&lt;td&gt;Agent traces, debugging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tool Protocol&lt;/td&gt;
&lt;td&gt;MCP&lt;/td&gt;
&lt;td&gt;Modern tool standard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auth&lt;/td&gt;
&lt;td&gt;JWT + GitHub OAuth&lt;/td&gt;
&lt;td&gt;Secure, industry standard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache&lt;/td&gt;
&lt;td&gt;Redis (Upstash)&lt;/td&gt;
&lt;td&gt;(coming Phase 5)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;AWS S3&lt;/td&gt;
&lt;td&gt;Doc storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DB&lt;/td&gt;
&lt;td&gt;PostgreSQL&lt;/td&gt;
&lt;td&gt;Neon (prod), Docker (dev)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;ECR + ECS Fargate&lt;/td&gt;
&lt;td&gt;(coming Phase 7)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CI/CD&lt;/td&gt;
&lt;td&gt;GitHub Actions&lt;/td&gt;
&lt;td&gt;(coming Phase 7)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  Architecture — The Pattern I Follow
&lt;/h2&gt;

&lt;p&gt;Every layer has &lt;strong&gt;one job&lt;/strong&gt;. No exceptions.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Route      → HTTP only (request/response)
    ↓
Service    → Business logic
    ↓
Repository → DB queries only
    ↓
Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is what separates a demo from something real. When 5 engineers touch the same codebase, this pattern saves you.&lt;/p&gt;
&lt;h3&gt;
  
  
  Folder Structure
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;backend/
├── auth/
│   ├── jwt.py              ← token create/verify
│   ├── github_oauth.py     ← GitHub OAuth flow
│   └── routes.py           ← HTTP layer only
├── db/
│   ├── database.py         ← async PostgreSQL
│   └── models.py           ← SQLAlchemy models
├── repositories/
│   └── user_repository.py  ← all DB queries here
├── schemas/
│   └── auth_schemas.py     ← Pydantic request/response
├── services/
│   └── auth_service.py     ← business logic
├── utils/
│   ├── helper_auth.py      ← bcrypt helpers
│   └── encryption.py       ← Fernet token encryption
├── mcp/
│   └── github_server.py    ← GitHub tools for agents
├── agents/                 ← Phase 4
├── graph/                  ← Phase 3
├── webhooks/               ← Phase 5
└── main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Database Design
&lt;/h2&gt;

&lt;p&gt;4 tables, all connected:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
  └── Repository
          ├── Document       ← generated docs (PENDING → APPROVED → PUBLISHED)
          └── PipelineRun    ← LangGraph execution tracking
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A few production decisions I made:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UUIDs over integer IDs&lt;/strong&gt; — no sequential ID enumeration attacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fernet encryption for GitHub tokens&lt;/strong&gt; — never store access tokens in plaintext. Ever.&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="c1"&gt;# utils/encryption.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cryptography.fernet&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Fernet&lt;/span&gt;

&lt;span class="n"&gt;_fernet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Fernet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ENCRYPTION_KEY&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&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;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_fernet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&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;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_fernet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Indexes on Document table&lt;/strong&gt; — &lt;code&gt;repo_id&lt;/code&gt;, &lt;code&gt;file_path&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt; are all indexed because these will be queried constantly at scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DocStatus enum&lt;/strong&gt; for proper state machine:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PENDING → APPROVED → PUBLISHED
PENDING → REJECTED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  GitHub OAuth Flow
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frontend → GET /auth/github  →  GitHub redirect URL
              ↓
    User authorizes on GitHub
              ↓
GitHub → POST /auth/github/callback?code=xxx
              ↓
    Code → access_token exchange
              ↓
    Token encrypted → stored in DB
              ↓
    JWT returned → Frontend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Clean separation — &lt;code&gt;routes.py&lt;/code&gt; only handles HTTP, &lt;code&gt;auth_service.py&lt;/code&gt; has all the logic, &lt;code&gt;user_repository.py&lt;/code&gt; handles all DB queries.&lt;/p&gt;


&lt;h2&gt;
  
  
  MCP Server — GitHub Tools for Agents
&lt;/h2&gt;

&lt;p&gt;Built 6 tools that LangGraph agents will use:&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;GITHUB_TOOLS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;get_repo_contents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;# list files/folders
&lt;/span&gt;    &lt;span class="n"&gt;get_file_content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;# read a file's source code
&lt;/span&gt;    &lt;span class="n"&gt;list_branches&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;# all branches
&lt;/span&gt;    &lt;span class="n"&gt;get_pr_details&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="c1"&gt;# PR changed files (for pr_watcher)
&lt;/span&gt;    &lt;span class="n"&gt;get_repo_info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;# repo metadata
&lt;/span&gt;    &lt;span class="n"&gt;list_python_files&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;# recursively find all .py files
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;These are &lt;code&gt;@tool&lt;/code&gt; decorated LangChain tools — agents can call them directly in the pipeline.&lt;/p&gt;


&lt;h2&gt;
  
  
  Dev vs Prod Database Setup
&lt;/h2&gt;

&lt;p&gt;One thing I'm proud of: &lt;strong&gt;proper environment parity from day one.&lt;/strong&gt;&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="c1"&gt;# database.py
&lt;/span&gt;&lt;span class="n"&gt;connect_args&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;ssl&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;require&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DATABASE_SSL&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="n"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_async_engine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;connect_args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;connect_args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="p"&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 plaintext"&gt;&lt;code&gt;Dev  → Docker postgres:16 locally  → DATABASE_SSL=False
Prod → Neon PostgreSQL             → DATABASE_SSL=True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Same code, different config. No hacks.&lt;/p&gt;


&lt;h2&gt;
  
  
  What It Looks Like Running
&lt;/h2&gt;

&lt;p&gt;After &lt;code&gt;uvicorn main:app --reload&lt;/code&gt;, the DB initializes automatically:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="n"&gt;repostatus&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;ENUM&lt;/span&gt; &lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TYPE&lt;/span&gt; &lt;span class="n"&gt;docstatus&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;ENUM&lt;/span&gt; &lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;repositories&lt;/span&gt; &lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="p"&gt;(...)&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;indexes&lt;/span&gt;
&lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;pipeline_runs&lt;/span&gt; &lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="k"&gt;Database&lt;/span&gt; &lt;span class="n"&gt;initialized&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Tables&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="n"&gt;Application&lt;/span&gt; &lt;span class="n"&gt;startup&lt;/span&gt; &lt;span class="n"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And Swagger UI at &lt;code&gt;/docs&lt;/code&gt; shows all endpoints live:&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.amazonaws.com%2Fuploads%2Farticles%2Fsxbqhaqg9wo2uatx72bg.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.amazonaws.com%2Fuploads%2Farticles%2Fsxbqhaqg9wo2uatx72bg.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Key Learnings from Phase 1 + 2
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Foundation takes time — and that's fine.&lt;/strong&gt;&lt;br&gt;
Two phases before writing a single agent. Every senior engineer says the same thing: boring infrastructure is what separates a demo from a product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Pydantic v2 — use &lt;code&gt;model_config&lt;/code&gt;, not &lt;code&gt;class Config&lt;/code&gt;.&lt;/strong&gt;&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="c1"&gt;# Wrong (Pydantic v1 style)
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;from_attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

&lt;span class="c1"&gt;# Correct (Pydantic v2)
&lt;/span&gt;&lt;span class="n"&gt;model_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConfigDict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from_attributes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;3. Never store tokens in plaintext.&lt;/strong&gt;&lt;br&gt;
Fernet encryption, always. Takes 10 minutes to set up, protects your users forever.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Repository layer is not optional.&lt;/strong&gt;&lt;br&gt;
The moment you have DB queries in your service layer, you've lost. Create a &lt;code&gt;repositories/&lt;/code&gt; folder early, thank yourself later.&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.amazonaws.com%2Fuploads%2Farticles%2F1w9y4wpjx5okh00x7np3.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.amazonaws.com%2Fuploads%2Farticles%2F1w9y4wpjx5okh00x7np3.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What's Next — Part 2
&lt;/h2&gt;

&lt;p&gt;Phase 3 is &lt;strong&gt;LangGraph Core&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;graph/state.py&lt;/code&gt; — the State schema that flows through all agents&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;graph/pipeline.py&lt;/code&gt; — connecting all agents into one graph&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;graph/hitl.py&lt;/code&gt; — the pause/resume HITL checkpoint logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where it gets exciting. The graph will actually start running.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Follow the series&lt;/strong&gt; to catch Part 2 when it drops! 🚀&lt;/p&gt;


&lt;h2&gt;
  
  
  GitHub
&lt;/h2&gt;
&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/Nevin100" rel="noopener noreferrer"&gt;
        Nevin100
      &lt;/a&gt; / &lt;a href="https://github.com/Nevin100/DevdocxAI" rel="noopener noreferrer"&gt;
        DevdocxAI
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      DevDocxAI is a production-grade multi-agent AI system that automatically generates, maintains, and updates engineering documentation by deeply understanding you…DevDocAI is a production-grade multi-agent AI system that automatically generates, maintains, and updates doc. by understanding deeply.
    &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;DevDocxAI 🤖📄&lt;/h1&gt;
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;A production-grade multi-agent LangGraph system that automatically generates and updates engineering documentation from your GitHub codebase.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/807252c6cff24d131a3381ca3bfb31e16b34adfc533e605432a3ebffd29ff466/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507974686f6e2d332e31322d626c75653f7374796c653d666c61742d737175617265266c6f676f3d707974686f6e"&gt;&lt;img src="https://camo.githubusercontent.com/807252c6cff24d131a3381ca3bfb31e16b34adfc533e605432a3ebffd29ff466/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507974686f6e2d332e31322d626c75653f7374796c653d666c61742d737175617265266c6f676f3d707974686f6e" alt="Python"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/9a3024d9f71a2127707cc8c40e5b20188dc57d03f051129b56bee65ca98f7bee/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f466173744150492d302e3131352d677265656e3f7374796c653d666c61742d737175617265266c6f676f3d66617374617069"&gt;&lt;img src="https://camo.githubusercontent.com/9a3024d9f71a2127707cc8c40e5b20188dc57d03f051129b56bee65ca98f7bee/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f466173744150492d302e3131352d677265656e3f7374796c653d666c61742d737175617265266c6f676f3d66617374617069" alt="FastAPI"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/17cf441b5dce665864bd3add5657a7929e00a8209442b67861e9acf237c3c46b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c616e6747726170682d302e322d6f72616e67653f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/17cf441b5dce665864bd3add5657a7929e00a8209442b67861e9acf237c3c46b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c616e6747726170682d302e322d6f72616e67653f7374796c653d666c61742d737175617265" alt="LangGraph"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/c83193d768f5fd708e5ba1a6ec44a81ffb9d0e47094385e6022a1742511452f7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f506f737467726553514c2d31362d626c75653f7374796c653d666c61742d737175617265266c6f676f3d706f737467726573716c"&gt;&lt;img src="https://camo.githubusercontent.com/c83193d768f5fd708e5ba1a6ec44a81ffb9d0e47094385e6022a1742511452f7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f506f737467726553514c2d31362d626c75653f7374796c653d666c61742d737175617265266c6f676f3d706f737467726573716c" alt="PostgreSQL"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/f3cd9467f1a2673efb050d325944267a717320385a6e45da3a19f994f9004339/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f773f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/f3cd9467f1a2673efb050d325944267a717320385a6e45da3a19f994f9004339/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f773f7374796c653d666c61742d737175617265" alt="License"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/27ee412fbf2ea617f1088ddd749c768146852cea00776460fc2b81837787a6b0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5374617475732d416374697665253230446576656c6f706d656e742d627269676874677265656e3f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/27ee412fbf2ea617f1088ddd749c768146852cea00776460fc2b81837787a6b0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5374617475732d416374697665253230446576656c6f706d656e742d627269676874677265656e3f7374796c653d666c61742d737175617265" alt="Status"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚨 The Problem&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;Every engineering team has the same dirty secret — &lt;strong&gt;the docs are lying.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not intentionally. Code moves fast, documentation doesn't.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New dev joins → 2 weeks reading outdated wikis&lt;/li&gt;
&lt;li&gt;Senior engineers constantly interrupted with "what does this do?"&lt;/li&gt;
&lt;li&gt;PR gets merged → docs never updated&lt;/li&gt;
&lt;li&gt;Generic RAG chatbots don't understand code &lt;em&gt;structure&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;DevDocAI fixes this.&lt;/strong&gt;&lt;/p&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;✨ What It Does&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;🔍 &lt;strong&gt;Connects to your GitHub repo&lt;/strong&gt; via OAuth&lt;/li&gt;
&lt;li&gt;🌳 &lt;strong&gt;Parses your codebase at the AST level&lt;/strong&gt; — understands functions, classes, modules&lt;/li&gt;
&lt;li&gt;📝 &lt;strong&gt;Auto-generates structured documentation&lt;/strong&gt; per module and function&lt;/li&gt;
&lt;li&gt;🔄 &lt;strong&gt;Updates docs on every PR merge&lt;/strong&gt; via GitHub webhooks&lt;/li&gt;
&lt;li&gt;👀 &lt;strong&gt;Human-in-the-Loop review&lt;/strong&gt; — you approve before anything goes live&lt;/li&gt;
&lt;li&gt;💬 &lt;strong&gt;Onboarding chatbot&lt;/strong&gt; — new devs ask questions, get answers from live code&lt;/li&gt;
&lt;/ul&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🤖 Agent Pipeline&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code&gt;START
  ↓
codebase_parser      ← AST-level&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/Nevin100/DevdocxAI" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;/h2&gt;


&lt;p&gt;&lt;em&gt;Building in public. Part 2 dropping soon.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Tags: &lt;code&gt;python&lt;/code&gt; &lt;code&gt;ai&lt;/code&gt; &lt;code&gt;langchain&lt;/code&gt; &lt;code&gt;productivity&lt;/code&gt; &lt;code&gt;beginners&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>mcp</category>
      <category>langchain</category>
    </item>
    <item>
      <title>I Turned My npm Package Into a Full DevOps Security Toolkit (v2.0.0)</title>
      <dc:creator>Nevin-Bali100</dc:creator>
      <pubDate>Fri, 22 May 2026 19:06:33 +0000</pubDate>
      <link>https://dev.to/nevin100/i-turned-my-npm-package-into-a-full-devops-security-toolkit-v200-18lo</link>
      <guid>https://dev.to/nevin100/i-turned-my-npm-package-into-a-full-devops-security-toolkit-v200-18lo</guid>
      <description>&lt;p&gt;A few weeks ago I published dep-inspector-cli — a dependency analyzer for Node.js projects. It went from 107 → 240 weekly downloads in a day, which honestly surprised me.&lt;br&gt;
But the more I used it in real projects, the more I kept thinking: dependency scanning is just one piece. What about secrets, Docker misconfigs, broken CI pipelines?&lt;br&gt;
So I rebuilt it. v2.0.0 is out now — and it's a completely different tool.&lt;/p&gt;

&lt;p&gt;What changed&lt;br&gt;
v1 did one thing: dependency + vulnerability analysis.&lt;br&gt;
v2 does six:&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.amazonaws.com%2Fuploads%2Farticles%2Fp2mbrw8447timgp615sx.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.amazonaws.com%2Fuploads%2Farticles%2Fp2mbrw8447timgp615sx.png" alt=" " width="499" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The features in detail&lt;br&gt;
🔐 scan:secrets — what it catches&lt;br&gt;
This one I'm most proud of. It scans your entire codebase for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Access Keys &amp;amp; Secret Keys&lt;/li&gt;
&lt;li&gt;OpenAI, Groq, GitHub tokens&lt;/li&gt;
&lt;li&gt;Hardcoded JWT secrets&lt;/li&gt;
&lt;li&gt;MongoDB / PostgreSQL connection strings with credentials&lt;/li&gt;
&lt;li&gt;Stripe &amp;amp; Razorpay live keys (not test keys)&lt;/li&gt;
&lt;li&gt;Generic password= / secret= assignments in source files&lt;/li&gt;
&lt;li&gt;.env files not listed in .gitignore&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last one is important — it doesn't scan .env content (that's expected to have secrets), but it checks whether .env is gitignored. A surprising number of projects miss this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dep-inspector scan:secrets

🔐 Secrets Scanner

✅ .env is gitignored
[HIGH] JWT Secret hardcoded
  File : src/middleware/auth.ts:12
  Code : const JWT_SECRET = "my-super-secret-key-123"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🐳 scan:docker — Dockerfile analysis&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dep-inspector scan:docker

🐳 Docker Analysis

[HIGH]   No non-root USER defined — container runs as root
[MEDIUM] No HEALTHCHECK instruction
[MEDIUM] Using ':latest' tag — not reproducible, pin a specific version
[LOW]    npm install without --omit=dev — devDependencies included in image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checks for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Container running as root&lt;/li&gt;
&lt;li&gt;Missing HEALTHCHECK&lt;/li&gt;
&lt;li&gt;:latest tag (non-reproducible builds)&lt;/li&gt;
&lt;li&gt;Secrets in ENV/ARG&lt;/li&gt;
&lt;li&gt;Missing .dockerignore&lt;/li&gt;
&lt;li&gt;Single-stage builds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚙️ scan:ci — GitHub Actions linting&lt;br&gt;
This one catches things that are easy to miss in CI configs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dep-inspector scan:ci

⚙️  CI/CD Pipeline Analysis

[HIGH]   deploy.yml: Deprecated '::set-output' — replace with $GITHUB_OUTPUT
[HIGH]   pr.yml: pull_request_target + actions/checkout is a privilege escalation risk
[MEDIUM] build.yml: Actions using @main — pin to a specific version
[LOW]    build.yml: No caching configured — builds will be slow
The pull_request_target + actions/checkout combination is a real security issue that's bitten several open source projects. Good to catch it early.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔌 scan:ports — port monitor&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dep-inspector scan:ports

🔌 Port &amp;amp; Process Monitor

[WARN] :27017 — Port 27017 is publicly exposed — restrict to localhost
[WARN] :6379  — Port 6379 is publicly exposed — restrict to localhost
[OK]   :3000
[OK]   :443
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flags database ports (MongoDB, Redis, PostgreSQL, MySQL) that are exposed on 0.0.0.0 instead of localhost. Works on both Linux and Windows.&lt;/p&gt;

&lt;p&gt;📋 scan:logs — logger health&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dep-inspector scan:logs

📋 Logger Health Check

✅ winston detected
⚠️  winston-daily-rotate-file not found — logs may grow unbounded
⚠️  LOG_LEVEL not set in .env — logger may default to verbose in production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Zero AI dependency by default&lt;/strong&gt;&lt;br&gt;
v1 had a problem: if you didn't have GROQ_API_KEY, the tool felt incomplete. Several people mentioned this in feedback.&lt;br&gt;
v2 fixes it properly. Every scan is pure static analysis — regex, file parsing, CLI wrappers. No API calls, no keys, works offline, works in CI.&lt;br&gt;
The --ai flag is additive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Works for everyone&lt;/span&gt;
dep-inspector scan:secrets

&lt;span class="c"&gt;# Optional enhanced output if you have a Groq key&lt;/span&gt;
dep-inspector scan:secrets &lt;span class="nt"&gt;--ai&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also dropped LangChain entirely and moved to the official groq-sdk. Fewer dependencies, no transitive vulnerabilities, faster installs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI/CD integration&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;yaml# .github/workflows/security.yml&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;Security Scan&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;dep-inspector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install -g dep-inspector-cli&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dep-inspector scan:secrets --json &amp;gt; secrets.json&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dep-inspector scan:ci&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&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;security-reports&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*.json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fail build on HIGH severity findings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bashdep-inspector scan:secrets &lt;span class="nt"&gt;--json&lt;/span&gt; | node &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"
  let d = '';
  process.stdin.on('data', c =&amp;gt; d += c);
  process.stdin.on('end', () =&amp;gt; {
    const { findings } = JSON.parse(d);
    const high = findings.filter(f =&amp;gt; f.severity === 'HIGH').length;
    if (high &amp;gt; 0) { process.exit(1); }
  });
"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;1. .git history scanning (catch secrets that were deleted but still in history)&lt;/li&gt;
&lt;li&gt;2. scan:docker — docker-compose multi-service analysis&lt;/li&gt;
&lt;li&gt;3. --report flag — HTML report with charts&lt;/li&gt;
&lt;li&gt;4. Custom rules via .depinspectorrc&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; dep-inspector-cli
&lt;span class="nb"&gt;cd &lt;/span&gt;your-project
dep-inspector scan:all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;📦 npm: npmjs.com/package/dep-inspector-cli&lt;br&gt;
🐙 GitHub: github.com/Nevin100/Dep-inspector-cli&lt;br&gt;
If it's useful, a ⭐ on GitHub helps a lot. Issues and PRs are open&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>devops</category>
      <category>security</category>
      <category>typescript</category>
    </item>
    <item>
      <title>I Built &amp; Published My First npm Package: dep-inspector-cli</title>
      <dc:creator>Nevin-Bali100</dc:creator>
      <pubDate>Mon, 20 Apr 2026 16:28:12 +0000</pubDate>
      <link>https://dev.to/nevin100/i-built-published-my-first-npm-package-dep-inspector-cli-13mk</link>
      <guid>https://dev.to/nevin100/i-built-published-my-first-npm-package-dep-inspector-cli-13mk</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;And it went from 107 → 240 weekly downloads in a day.!!!!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I've been building full-stack apps for a while now — Next.js, TypeScript, PostgreSQL, MongoDB, and much more. But I'd never shipped something to the npm registry before. *&lt;em&gt;dep-inspector-cli *&lt;/em&gt; changed that.&lt;br&gt;
Here's the honest story of what it does, why I built it, and what's coming next.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Problem:
&lt;/h2&gt;

&lt;p&gt;Every Node.js project eventually runs into this moment:&lt;br&gt;
&lt;code&gt;npm audit&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You get a wall of text. Severity levels, CVE IDs, a list of packages - but zero context about which of your actual dependencies pulled the vulnerable one in, or what you should realistically do about it.&lt;br&gt;
I wanted something that actually connected the dots.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution:
&lt;/h2&gt;

&lt;p&gt;What dep-inspector-cli Does&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; dep-inspector-cli
dep-inspector
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it from your project root and you get:&lt;br&gt;
🌳 Visual Dependency Tree — shows your full dep graph with outdated versions flagged inline, not as a separate report.&lt;br&gt;
🛡️ Vulnerability Scan — wraps npm audit but surfaces results with severity, version delta, and a breaking-change warning if the fix is a major bump.&lt;br&gt;
🔗 Dependency Chains — this is the part I care most about. It traces exactly which package in your tree pulled in the vulnerable dep. No more guessing.&lt;br&gt;
📦 Package Context — homepage, author, repo link for flagged packages. Because knowing what a package is matters when you're deciding whether to update or swap it out.&lt;br&gt;
🤖 AI Insights (optional) — add --ai and it uses Groq (llama-3.3-70b) to give you a plain-English breakdown: what the vuln is, what it affects in your specific project, and a recommended fix.&lt;br&gt;
📄 JSON Output — --json flag for CI/CD pipelines. Fail the build if vulnerabilities are found, upload reports as artifacts, the works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Output:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;⚠️  Vulnerability Analysis

📦 axios
  Severity   : HIGH
  Version    : 0.21.1 → 1.7.2
  ⚠️  Breaking change possible!
  Repo       : https://github.com/axios/axios
  🔗 Chain: root → axios

💡 Fix Suggestions
  → axios: npm install axios@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  CI/CD Integration
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&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;Check dependencies&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dep-inspector --json &amp;gt; dep-report.json&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;Upload report&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v3&lt;/span&gt;
  &lt;span class="na"&gt;with&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;dependency-report&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dep-report.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;p&gt;I used following tech stack to develop the initial version of this npm package:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript (fully typed)&lt;/li&gt;
&lt;li&gt;Commander.js for CLI parsing&lt;/li&gt;
&lt;li&gt;Chalk + Ora for terminal UX&lt;/li&gt;
&lt;li&gt;LangChain + Groq for the --ai flag&lt;/li&gt;
&lt;li&gt;Semver for version comparison&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Coming Next (v1.2+):
&lt;/h2&gt;

&lt;p&gt;The current version handles vulnerability scanning well, but I want dep-inspector to be genuinely useful for production-grade projects too. Here's what I'm actively working on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;🏥 Dependency Health Scoring - an overall health score for your project's dependency tree. Factors: vulnerability count, how outdated your deps are, and whether maintainers are active. One number that tells you roughly how much debt you're carrying.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;📊 Production Package Support - first-class analysis for packages like winston, pino, morgan (logging), helmet, cors, express-rate-limit (security middleware), dotenv, zod (config/validation). Currently, these show up in the tree, but there's no opinionated analysis. Coming soon: known best-practice checks and upgrade guidance specific to each ecosystem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🔍 License Audit - flag packages with restrictive licenses (GPL, AGPL) that might be a problem in commercial projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;📈 Trend Tracking — run dep-inspector over time and see if your health score is improving or regressing. Useful for teams that do regular dependency maintenance sprints.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It and can raise an issue and some suggestions in the comments:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; dep-inspector-cli
&lt;span class="nb"&gt;cd &lt;/span&gt;your-project
dep-inspector
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;📦 npm: npmjs.com/package/dep-inspector-cli&lt;/li&gt;
&lt;li&gt;🐙 GitHub: &lt;a href="https://github.com/Nevin100/Dep-inspector-cli" rel="noopener noreferrer"&gt;https://github.com/Nevin100/Dep-inspector-cli&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If it's useful, a ⭐ on GitHub goes a long way. And if you run into issues or have feature requests — PRs are open.&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.amazonaws.com%2Fuploads%2Farticles%2Fzyk4h7f5wwmreosodln5.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.amazonaws.com%2Fuploads%2Farticles%2Fzyk4h7f5wwmreosodln5.png" alt="Main Package Page"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Ffa3hys75b4y2si8y1loe.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.amazonaws.com%2Fuploads%2Farticles%2Ffa3hys75b4y2si8y1loe.png" alt="A Description of Usage of the tool on npm official platform"&gt;&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fv7sxg03tmijwb5cs99kb.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.amazonaws.com%2Fuploads%2Farticles%2Fv7sxg03tmijwb5cs99kb.png" alt="Usage and Commands"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>node</category>
      <category>devtools</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Revision and completing Nextronix.ai</title>
      <dc:creator>Nevin-Bali100</dc:creator>
      <pubDate>Tue, 06 May 2025 17:54:21 +0000</pubDate>
      <link>https://dev.to/nevin100/revision-and-completing-nextronixai-261o</link>
      <guid>https://dev.to/nevin100/revision-and-completing-nextronixai-261o</guid>
      <description>&lt;p&gt;Just did revision of nextjs while completing the nextronix.ai Project.&lt;/p&gt;

&lt;h1&gt;
  
  
  Day 4 of coding and learning!!!
&lt;/h1&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>ai</category>
    </item>
    <item>
      <title>Nextronix.ai on the verge of complete!!</title>
      <dc:creator>Nevin-Bali100</dc:creator>
      <pubDate>Mon, 05 May 2025 16:23:06 +0000</pubDate>
      <link>https://dev.to/nevin100/nextronixai-on-the-verge-of-complete-559g</link>
      <guid>https://dev.to/nevin100/nextronixai-on-the-verge-of-complete-559g</guid>
      <description></description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>ai</category>
    </item>
    <item>
      <title>Nextronix Diet: Forks Over Fail</title>
      <dc:creator>Nevin-Bali100</dc:creator>
      <pubDate>Sat, 03 May 2025 18:10:32 +0000</pubDate>
      <link>https://dev.to/nevin100/nextronix-diet-forks-over-fail-2pp5</link>
      <guid>https://dev.to/nevin100/nextronix-diet-forks-over-fail-2pp5</guid>
      <description>&lt;p&gt;Welcome to &lt;strong&gt;Nextronix.ai&lt;/strong&gt; — my AI-powered fitness diet planner, built as part of my journey to master full-stack development and AI integration! Powered by &lt;strong&gt;Gemini API, Vapi Voice Assistant, and crafted using Next.js, TypeScript, Convex DB, and Clerk&lt;/strong&gt;, this project listens to your voice, gathers key details, and creates a free, personalized diet plan just for you.&lt;/p&gt;

&lt;p&gt;🔹 AI Voice Assistant Calls (via Vapi)&lt;br&gt;
🔹 Info gathering through natural conversation&lt;br&gt;
🔹 Personalized fitness diet plan&lt;br&gt;
🔹 Real-time database with Convex&lt;br&gt;
🔹 Auth handled by Clerk&lt;br&gt;
🔹 Built for learning, sharing, and consistency&lt;/p&gt;

&lt;p&gt;Learning from the tutorial on Youtube: Codesistency&lt;/p&gt;

&lt;p&gt;This is Day 2 (missed Day 1 😅), but I’m showing up consistently from here on!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Insightful Article Post</title>
      <dc:creator>Nevin-Bali100</dc:creator>
      <pubDate>Tue, 13 Aug 2024 18:17:39 +0000</pubDate>
      <link>https://dev.to/nevin100/insightful-article-post-op9</link>
      <guid>https://dev.to/nevin100/insightful-article-post-op9</guid>
      <description>&lt;p&gt;I read this post on the dev.daily about the good and bad commit changes on the git which I found quite insightful.&lt;br&gt;
It was able to draw some important conclusions regarding the approach of doing proper commits but also I would like to add my perspective that for some scenarios,one can stash their current changes and can move to higher branch.&lt;/p&gt;

&lt;p&gt;post link : &lt;a href="https://dev.to/sheraz4194/good-commit-vs-bad-commit-best-practices-for-git-1plc"&gt;https://dev.to/sheraz4194/good-commit-vs-bad-commit-best-practices-for-git-1plc&lt;/a&gt;&lt;br&gt;
credits: Sheraz Manzoor &lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>webdev</category>
    </item>
    <item>
      <title>My-Portfolio</title>
      <dc:creator>Nevin-Bali100</dc:creator>
      <pubDate>Mon, 12 Aug 2024 16:44:02 +0000</pubDate>
      <link>https://dev.to/nevin100/my-portfolio-ii0</link>
      <guid>https://dev.to/nevin100/my-portfolio-ii0</guid>
      <description>&lt;p&gt;As a Full Stack Developer, I have created a dynamic portfolio using React JS and Framer-motion. It showcases my skills and projects, highlighting my expertise in building efficient and user-friendly web applications. Let's connect and explore new opportunities!&lt;/p&gt;

</description>
      <category>react</category>
      <category>framermotion</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
