<?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: Cess Mbugua</title>
    <description>The latest articles on DEV Community by Cess Mbugua (@mbugua_cessy).</description>
    <link>https://dev.to/mbugua_cessy</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3626809%2F8965597d-6873-451e-8e28-585d0370197b.jpeg</url>
      <title>DEV Community: Cess Mbugua</title>
      <link>https://dev.to/mbugua_cessy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mbugua_cessy"/>
    <language>en</language>
    <item>
      <title>Day 24 of 60: I Built an AI Clinic Receptionist That Handles Appointments, Emergencies, and Payments on WhatsApp</title>
      <dc:creator>Cess Mbugua</dc:creator>
      <pubDate>Fri, 05 Jun 2026 17:03:39 +0000</pubDate>
      <link>https://dev.to/mbugua_cessy/day-24-of-60-i-built-an-ai-clinic-receptionist-that-handles-appointments-emergencies-and-4907</link>
      <guid>https://dev.to/mbugua_cessy/day-24-of-60-i-built-an-ai-clinic-receptionist-that-handles-appointments-emergencies-and-4907</guid>
      <description>&lt;p&gt;Today's build is the most commercially viable thing I have shipped so far.&lt;/p&gt;

&lt;p&gt;A mid-sized private clinic in Nairobi with 40-50 appointments per day faces three costly problems every single week.&lt;/p&gt;

&lt;p&gt;No-shows. At a 20% no-show rate with KES 2,000 per consultation, that is KES 400,000-500,000 in lost revenue every month. Gone. Because a patient forgot.&lt;/p&gt;

&lt;p&gt;Confirmation calls. The receptionist spends 2+ hours every day calling patients just to confirm they are coming. That is 2 hours of skilled human time spent on a task a system can do automatically.&lt;/p&gt;

&lt;p&gt;Manual booking errors. Double bookings, lost entries, missed WhatsApp messages from patients who contact the clinic outside office hours.&lt;/p&gt;

&lt;p&gt;Meet &lt;strong&gt;MediFlow.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## How It Works&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Patient sends WhatsApp message
↓
Twilio receives and forwards to MediFlow API
↓
Claude reads the message + patient history + clinic knowledge base
↓
Claude decides: booking, reschedule, question, emergency, or payment
↓
Response sent back to patient via WhatsApp
↓
Every message, decision, and action logged to PostgreSQL
↓
Emergencies escalated to receptionist immediately
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real Conversations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Booking:&lt;/strong&gt;&lt;br&gt;
Patient: Hello, I would like to book an appointment with Dr. Sarah Kamau at 10am this Friday&lt;/p&gt;

&lt;p&gt;MediFlow: Perfect, Cess! Your appointment is confirmed.&lt;br&gt;
Date: Friday 6th June 2026&lt;br&gt;
Time: 10:00 AM&lt;br&gt;
Doctor: Dr. Sarah Kamau&lt;br&gt;
Fee: KES 2,000&lt;br&gt;
Location: 123 Kenyatta Avenue, Nairobi CBD&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Emergency detection:&lt;/strong&gt;&lt;br&gt;
Patient: My child has been having chest pains and difficulty breathing since this morning&lt;/p&gt;

&lt;p&gt;MediFlow: This is a medical emergency. Please call 999 immediately or go to the nearest hospital emergency department right away.&lt;/p&gt;

&lt;p&gt;Simultaneously the receptionist receives: MEDIFLOW ESCALATION — Patient experiencing chest pain and difficulty breathing; please respond directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NHIF question:&lt;/strong&gt;&lt;br&gt;
Patient: Do you accept NHIF?&lt;/p&gt;

&lt;p&gt;MediFlow: Yes, we accept NHIF for outpatient consultations. Bring your NHIF card to your appointment.&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%2Fithdc8cxfidqzltegpm7.jpeg" 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%2Fithdc8cxfidqzltegpm7.jpeg" alt=" " width="540" height="1204"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq66ld0oeqvxusiiocm1l.jpeg" 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%2Fq66ld0oeqvxusiiocm1l.jpeg" alt=" " width="540" height="1204"&gt;&lt;/a&gt;&lt;br&gt;
**&lt;/p&gt;

&lt;h2&gt;
  
  
  What the System Decides vs What Humans Decide**
&lt;/h2&gt;

&lt;p&gt;System decides automatically:&lt;br&gt;
Slot availability. Appointment confirmation. Reminder sending. Clinic questions from knowledge base. Outstanding balance enforcement with M-PESA instructions.&lt;/p&gt;

&lt;p&gt;Human decides always:&lt;br&gt;
Emergency symptoms. Balance disputes. Complex or ambiguous cases.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Numbers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before MediFlow&lt;/th&gt;
&lt;th&gt;After MediFlow&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;No-show rate&lt;/td&gt;
&lt;td&gt;20%+&lt;/td&gt;
&lt;td&gt;Projected 5-8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Confirmation calls&lt;/td&gt;
&lt;td&gt;2+ hours per day&lt;/td&gt;
&lt;td&gt;Near zero&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;After-hours enquiries&lt;/td&gt;
&lt;td&gt;0% handled&lt;/td&gt;
&lt;td&gt;100% handled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Monthly revenue lost&lt;/td&gt;
&lt;td&gt;KES 400,000-500,000&lt;/td&gt;
&lt;td&gt;KES 80,000-150,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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

&lt;p&gt;Twilio WhatsApp Business API. Claude API (claude-opus-4-5). FastAPI. PostgreSQL. SQLAlchemy. n8n for reminder scheduling. Railway for cloud deployment.&lt;/p&gt;




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

&lt;p&gt;The hardest part was not the booking logic. It was teaching Claude to read the emotional tone of a message and decide whether it is a routine enquiry or a genuine emergency that needs immediate human intervention.&lt;/p&gt;

&lt;p&gt;The difference between "my child has a fever" and "my child has chest pain and difficulty breathing" is not just vocabulary. It is the difference between a standard response and an immediate escalation. Getting that boundary right required careful prompt engineering and extensive testing.&lt;/p&gt;

&lt;p&gt;Also: building for Swahili speakers was a deliberate decision. If the system only works in English it does not work for most of the patients it is supposed to serve.&lt;/p&gt;




&lt;p&gt;🔗 Full project on GitHub → &lt;a href="https://github.com/mbuguacessy-glitch" rel="noopener noreferrer"&gt;https://github.com/mbuguacessy-glitch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;36 more to go.&lt;/p&gt;

&lt;h1&gt;
  
  
  python #fastapi #claudeapi #twilio #whatsapp #healthcare #kenya #automation #buildinpublic #learninpublic #100DaysOfCode
&lt;/h1&gt;

</description>
    </item>
    <item>
      <title>Self-Taught AI Automation Engineer Looking for an Internship. Here Is What I Have Built.</title>
      <dc:creator>Cess Mbugua</dc:creator>
      <pubDate>Tue, 02 Jun 2026 11:46:34 +0000</pubDate>
      <link>https://dev.to/mbugua_cessy/self-taught-ai-automation-engineer-looking-for-an-internship-here-is-what-i-have-built-2pjj</link>
      <guid>https://dev.to/mbugua_cessy/self-taught-ai-automation-engineer-looking-for-an-internship-here-is-what-i-have-built-2pjj</guid>
      <description>&lt;p&gt;My name is Cecilia Mbugua. I am an AI Automation Engineer based in Nairobi, Kenya and I am actively looking for an internship at an AI company or tech team.&lt;/p&gt;

&lt;p&gt;I started a 60-day public build challenge; one production-ready AI system every single day. Here is what I have shipped so far:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ClearVet: Enterprise Client Evaluation Pipeline&lt;/strong&gt;&lt;br&gt;
Potential clients fill a Typeform. Claude evaluates them across 6 dimensions in the background. Score calculated. Slack notification sent with approval buttons. Human decides. Everything logged to PostgreSQL. Zero manual screening.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live Document Q&amp;amp;A System&lt;/strong&gt;&lt;br&gt;
Ask any question against any document. Get an answer with source citations in under 3 seconds. Running 24/7 on the cloud.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Async Document Processing Pipeline&lt;/strong&gt;&lt;br&gt;
Submit a document, receive a job ID instantly, Claude processes in the background. Built for Kenyan law firms, SACCOs, and insurance companies handling high document volumes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Secured Multi-Tenant API&lt;/strong&gt;&lt;br&gt;
JWT authentication, API key management per client, rate limiting, usage tracking. Production ready and deployed.&lt;/p&gt;

&lt;p&gt;I built all of this but I know there is a level of growth that only comes from working within a real team on real products at scale.&lt;/p&gt;

&lt;p&gt;I am available for international remote internships immediately.&lt;/p&gt;

&lt;p&gt;If your team is building with AI and you have room for someone who ships every day, let's talk.&lt;/p&gt;

&lt;p&gt;📩 &lt;a href="mailto:mbugua.cessy@gmail.com"&gt;mbugua.cessy@gmail.com&lt;/a&gt;&lt;br&gt;
🌐 portfolio-amber-gamma-51.vercel.app&lt;br&gt;
🔗 github.com/mbuguacessy-glitch&lt;/p&gt;

&lt;h1&gt;
  
  
  internship #opentowork #python #fastapi #aiautomation #buildinpublic #claudeapi
&lt;/h1&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>career</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Day 23 of 60: Someone Asked Me a Question on Day 3. I Put It on My Build List. Today I Shipped the Answer.</title>
      <dc:creator>Cess Mbugua</dc:creator>
      <pubDate>Sun, 31 May 2026 19:44:50 +0000</pubDate>
      <link>https://dev.to/mbugua_cessy/day-23-of-60-someone-asked-me-a-question-on-day-3-i-put-it-on-my-build-list-today-i-shipped-the-267f</link>
      <guid>https://dev.to/mbugua_cessy/day-23-of-60-someone-asked-me-a-question-on-day-3-i-put-it-on-my-build-list-today-i-shipped-the-267f</guid>
      <description>&lt;p&gt;&lt;strong&gt;This build has been on my list since Day 3.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Three weeks ago I posted my client onboarding pipeline. A commenter read it carefully and asked a question that stopped me in my tracks:&lt;/p&gt;

&lt;p&gt;"The space has a lot of tools for the work side but almost nothing for evaluating the client side before committing. What's the specific problem you're solving for freelancers?"&lt;/p&gt;

&lt;p&gt;I didn't have a full answer that day. So I wrote it down, added it to my build list, and kept going.&lt;/p&gt;

&lt;p&gt;Today I built it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Meet ClearVet.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## The Problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you run an AI automation business. Enquiries come in every day. Most are not a good fit. Wrong budget. Vague problem. Unrealistic timeline. Industries you cannot help with.&lt;/p&gt;

&lt;p&gt;To figure out which ones are worth your time you have to read every single one manually, ask follow up questions, think about it, and decide. Twenty enquiries a week is hours of screening before you do any real work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ClearVet automates that entire process.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## The Full Pipeline&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Potential client fills Typeform
↓
n8n receives submission via webhook
↓
ClearVet FastAPI endpoint
↓
Claude evaluates across 6 dimensions as background task
↓
Score calculated — HIGH, MEDIUM, or LOW
↓
Slack message sent with dimension scores and approval buttons
↓
Human approves or rejects via API
↓
Decision logged to PostgreSQL with timestamp and notes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;## The 6 Evaluation Dimensions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Budget Fit: is the budget realistic for the solution needed?&lt;br&gt;
Problem Clarity: how well defined and specific is the problem?&lt;br&gt;
Timeline Realism: is the timeline actually achievable?&lt;br&gt;
AI Readiness: is the client ready to adopt AI solutions?&lt;br&gt;
Industry Fit: does the industry align with our capabilities?&lt;br&gt;
Growth Potential: what is the long-term revenue potential?&lt;/p&gt;

&lt;p&gt;Claude scores each dimension 0-10 with reasoning. Overall score determines the recommendation tier.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;## A Real Evaluation Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"company_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nairobi Logistics Ltd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"overall_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;7.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"recommendation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scores"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"problem_clarity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"reasoning"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Problem is exceptionally well-defined"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"growth_potential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"reasoning"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"200 reports daily suggests high volume"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"approved"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"approved_by"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cess"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;## What Makes This Different&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Human in the loop. Every evaluation requires a human decision before any action is taken. Claude does the analysis. You make the call.&lt;/p&gt;

&lt;p&gt;Full audit trail. Every evaluation, score, dimension reasoning, decision, and timestamp stored in PostgreSQL. Nothing disappears.&lt;/p&gt;

&lt;p&gt;Background processing. The API responds immediately. Claude evaluates in the background. Slack notification arrives when ready.&lt;/p&gt;

&lt;p&gt;Real intake form. Connected to Typeform via n8n webhook. The same form a real potential client would fill out.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## What This Is Worth&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A system like this for one agency is a KES 80,000-150,000 setup fee. It replaces hours of manual screening every week. The ROI is immediate and measurable.&lt;/p&gt;

&lt;p&gt;37 more to go.&lt;/p&gt;

&lt;p&gt;🔗 Full project on GitHub → &lt;a href="https://github.com/mbuguacessy-glitch" rel="noopener noreferrer"&gt;https://github.com/mbuguacessy-glitch&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  python #fastapi #claudeapi #n8n #automation #buildinpublic #learninpublic #clearvet #100DaysOfCode &lt;a class="mentioned-user" href="https://dev.to/keynition"&gt;@keynition&lt;/a&gt;
&lt;/h1&gt;

</description>
      <category>buildinpublic</category>
      <category>productivity</category>
      <category>showdev</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>Day 22 of 60: I Built a Production Background Task Pipeline That Processes AI Jobs Asynchronously</title>
      <dc:creator>Cess Mbugua</dc:creator>
      <pubDate>Fri, 29 May 2026 11:06:58 +0000</pubDate>
      <link>https://dev.to/mbugua_cessy/day-22-of-60-i-built-a-production-background-task-pipeline-that-processes-ai-jobs-asynchronously-3na3</link>
      <guid>https://dev.to/mbugua_cessy/day-22-of-60-i-built-a-production-background-task-pipeline-that-processes-ai-jobs-asynchronously-3na3</guid>
      <description>&lt;p&gt;** The Problem**&lt;/p&gt;

&lt;p&gt;Processing large documents through an AI model takes 30-60 seconds. A synchronous API makes the client wait the entire time. Browsers timeout. Users think it crashed. The experience feels broken.&lt;/p&gt;

&lt;p&gt;Yesterday I learned why this happens. Today I built the fix.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## What I Built&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A document processing pipeline with FastAPI and PostgreSQL that handles long-running AI tasks in the background. Three task types. Immediate response. Full audit trail.&lt;/p&gt;

&lt;p&gt;Client submits a document and gets a job ID in milliseconds. Claude processes it in the background. Client polls for the result when ready. Everything logged to PostgreSQL.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## Three Task Types&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Summarise: submit a document and receive a structured summary with executive overview and key points. Focus area is configurable.&lt;/p&gt;

&lt;p&gt;Extract: specify which fields you want pulled out. Company name, net profit, revenue, key risks. Claude reads the document and returns exactly what you asked for as structured JSON.&lt;/p&gt;

&lt;p&gt;Evaluate: provide a list of criteria and Claude checks whether the document meets each one. Returns a pass or fail with reasoning for every criterion.&lt;/p&gt;




&lt;p&gt;*&lt;em&gt;## How the Pipeline Works&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /jobs/summarise
↓
Job ID returned in milliseconds
status: pending
↓
Claude processes in background
status: running
↓
GET /jobs/{job_id}
status: completed
full result ready
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optional webhook support means the server can call your endpoint when the job completes and no polling needed.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## The Database Behind It&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every job is stored in PostgreSQL with full audit trail:&lt;/p&gt;

&lt;p&gt;Job ID, status at every stage, task type, input data as JSONB, result as JSONB, error message if failed, webhook URL, created timestamp, completed timestamp.&lt;/p&gt;

&lt;p&gt;If a job fails the error is recorded for debugging. Nothing disappears silently.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## Real Use Cases&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Contract review for law firms. Loan application screening for SACCOs. Insurance claims processing. Report summarisation for enterprises.&lt;/p&gt;

&lt;p&gt;The same pipeline. Different documents. Different criteria. One system.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;FastAPI's BackgroundTasks is the simplest way to separate submission from processing. The endpoint returns immediately. The heavy work happens after the response is sent.&lt;/p&gt;

&lt;p&gt;JSONB in PostgreSQL stores the full input and result as structured data — not a string you have to parse later. Query it, index it, use it.&lt;/p&gt;

&lt;p&gt;Webhooks flip the polling model entirely. Instead of the client asking if the job is done, the server tells the client when it is ready.&lt;/p&gt;




&lt;p&gt;🔗 Full project on GitHub → &lt;a href="https://github.com/mbuguacessy-glitch" rel="noopener noreferrer"&gt;https://github.com/mbuguacessy-glitch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;38 more to go.&lt;/p&gt;

&lt;h1&gt;
  
  
  python #fastapi #async #claudeapi #postgresql #automation #learninpublic #buildinpublic #100DaysOfCode
&lt;/h1&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>backend</category>
      <category>python</category>
    </item>
    <item>
      <title>Day 20 of 60: I Built a Production-Grade Authentication System with JWT Tokens and API Key Managemen</title>
      <dc:creator>Cess Mbugua</dc:creator>
      <pubDate>Thu, 28 May 2026 12:31:47 +0000</pubDate>
      <link>https://dev.to/mbugua_cessy/day-20-of-60-i-built-a-production-grade-authentication-system-with-jwt-tokens-and-api-key-managemen-5ebm</link>
      <guid>https://dev.to/mbugua_cessy/day-20-of-60-i-built-a-production-grade-authentication-system-with-jwt-tokens-and-api-key-managemen-5ebm</guid>
      <description>&lt;p&gt;Every API I've built up to this point has been open. Anyone with the URL could call it. Today I fixed that.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## The Problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most beginner APIs have no authentication layer. Anyone who finds your endpoint can call it, abuse it, or overload it. In production that is not acceptable. Real APIs need to know who is calling them, track how often they are being called, and cut off anyone who is abusing them.&lt;/p&gt;

&lt;p&gt;Today I built that entire layer from scratch.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## What I Built&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A production-grade authenticated multi-tenant API with two separate authentication systems working together:&lt;br&gt;
**&lt;br&gt;
&lt;strong&gt;JWT Authentication for admin users&lt;/strong&gt;**&lt;br&gt;
Admin logs in with email and password. Server verifies credentials, generates a signed token valid for 30 minutes. Every admin request must include that token. No token, no access.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API Key Management for clients&lt;/strong&gt;&lt;br&gt;
Admin creates a client via a JWT-protected endpoint. Server generates a random 32-byte key using secrets.token_urlsafe(32). The raw key is shown once and never stored. Only its SHA-256 hash lives in the database. Client includes the key in every request as X-API-Key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Usage Tracking&lt;/strong&gt;&lt;br&gt;
Every request increments the client's request counter and records the last used timestamp. Full visibility into who is calling what and when.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rate Limiting&lt;/strong&gt;&lt;br&gt;
Sliding window algorithm. Each API key gets 10 requests per 60-second window. Exceed that and you get a 429 Too Many Requests error. Abuse is blocked automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Revocation&lt;/strong&gt;&lt;br&gt;
Admin can deactivate any client's key instantly. One endpoint call and that client is locked out immediately.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Tech Behind It
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI: web framework&lt;/li&gt;
&lt;li&gt;PostgreSQL: database for users and API keys&lt;/li&gt;
&lt;li&gt;SQLAlchemy: ORM for database interaction&lt;/li&gt;
&lt;li&gt;python-jose: JWT token generation and verification&lt;/li&gt;
&lt;li&gt;passlib and bcrypt: password hashing&lt;/li&gt;
&lt;li&gt;python-dotenv: environment variable management&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;## What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most important lesson today: never store secrets in plain text. Not passwords. Not API keys. Ever.&lt;/p&gt;

&lt;p&gt;Passwords are hashed with bcrypt before storage. API keys are hashed with SHA-256 before storage. The raw key is shown once at creation and never seen again. If your database is compromised the attacker still cannot use any of the credentials.&lt;/p&gt;

&lt;p&gt;That is what production security actually looks like.&lt;/p&gt;




&lt;p&gt;🔗 Full project on GitHub → &lt;a href="https://github.com/mbuguacessy-glitch" rel="noopener noreferrer"&gt;https://github.com/mbuguacessy-glitch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;40 more to go.&lt;/p&gt;

&lt;h1&gt;
  
  
  python #fastapi #jwt #security #authentication #learninpublic #buildinpublic #100DaysOfCode
&lt;/h1&gt;

</description>
      <category>api</category>
      <category>backend</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Day 19 of 60: From Raw SQL to a Full Stack FastAPI App.</title>
      <dc:creator>Cess Mbugua</dc:creator>
      <pubDate>Tue, 26 May 2026 19:51:11 +0000</pubDate>
      <link>https://dev.to/mbugua_cessy/day-19-of-60-from-raw-sql-to-a-full-stack-fastapi-app-4jp4</link>
      <guid>https://dev.to/mbugua_cessy/day-19-of-60-from-raw-sql-to-a-full-stack-fastapi-app-4jp4</guid>
      <description>&lt;p&gt;&lt;strong&gt;Today was the heaviest single day of the challenge so far.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Three challenges. Pure databases. From writing raw SQL queries like a data analyst to building a full stack FastAPI application backed by PostgreSQL. All in one sitting.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## Challenge 1: Query an Existing Database Like a Data Analyst&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No new tables. Pure querying against existing leads and notes tables. Eight real business questions answered using SQL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I wrote:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Which lead has the most notes? Show their name, email and note count&lt;/li&gt;
&lt;li&gt;Show all leads and their most recent note. Leads with no notes appear with NULL&lt;/li&gt;
&lt;li&gt;How many leads are in each status? Sorted by count descending&lt;/li&gt;
&lt;li&gt;Which sources produced more than one lead?&lt;/li&gt;
&lt;li&gt;Show all notes written by a specific author with the lead name next to each&lt;/li&gt;
&lt;li&gt;Find all leads who have never had a note written by that author&lt;/li&gt;
&lt;li&gt;Show the first note ever written for each lead&lt;/li&gt;
&lt;li&gt;Show leads whose status is not new and who have at least one note&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The hardest query was number 6, finding leads with no notes from a specific author required thinking about what is absent rather than what is present. Subqueries started making real sense here.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## Challenge 2: Build a SQLAlchemy Model from Scratch&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A completely new SQLAlchemy model file for a products and orders system — built without copying anything.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Product model with id, name, price, stock and created_at&lt;/li&gt;
&lt;li&gt;Order model with id, product_id as foreign key, quantity, total_price and created_at&lt;/li&gt;
&lt;li&gt;Bidirectional relationship so order.product and product.orders both work&lt;/li&gt;
&lt;li&gt;Tables created in PostgreSQL using Base.metadata.create_all()&lt;/li&gt;
&lt;li&gt;4 products and 6 orders inserted using SQLAlchemy sessions — no raw SQL&lt;/li&gt;
&lt;li&gt;Python logic to find the most expensive order and print product name, quantity and total price&lt;/li&gt;
&lt;li&gt;Stock update logic that deducts after an order is placed&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;## Challenge 3: Full Database Layer in FastAPI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A completely new FastAPI application managing products and orders, backed by the SQLAlchemy models from Challenge 3. Six endpoints built and tested in the docs UI.&lt;/p&gt;

&lt;p&gt;Endpoints built and tested:&lt;/p&gt;

&lt;p&gt;GET /products: all products with stock levels&lt;br&gt;
POST /products: create a new product&lt;br&gt;
GET /products/{id}L: one product with all its orders&lt;br&gt;
POST /orders: place an order, stock deducts automatically. Returns 400 if stock is insufficient&lt;br&gt;
GET /orders: all orders with product name next to each&lt;br&gt;
DELETE /products/{id}: deletes product and all its orders&lt;/p&gt;

&lt;p&gt;Then tested the full workflow manually:&lt;br&gt;
Added a product, confirmed it appeared, retrieved it with orders, placed an order and confirmed stock deducted, retrieved all orders with product names, deleted a product and confirmed its orders disappeared too.&lt;/p&gt;

&lt;p&gt;Also practiced truncating the database to reset state cleanly between test runs.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Three things that clicked today that I will carry into every project:&lt;/p&gt;

&lt;p&gt;Subqueries think about absence not presence. Finding what does not exist requires a completely different mental model from finding what does.&lt;/p&gt;

&lt;p&gt;SQLAlchemy sessions are the right way to talk to a database from Python. Raw SQL works but ORM models make the code readable, maintainable and safe.&lt;/p&gt;

&lt;p&gt;Full stack means every layer has a job. PostgreSQL stores it. SQLAlchemy talks to it. FastAPI exposes it. Each layer does one thing and does it well.&lt;/p&gt;




&lt;p&gt;No GitHub link today, pure challenge day documented publicly.&lt;/p&gt;

&lt;p&gt;41 more to go. &lt;/p&gt;

&lt;h1&gt;
  
  
  sql #postgresql #sqlalchemy #fastapi #python #databases #learninpublic #buildinpublic #100DaysOfCode
&lt;/h1&gt;

</description>
      <category>devchallenge</category>
      <category>postgres</category>
      <category>python</category>
      <category>sql</category>
    </item>
    <item>
      <title>Day 17 of 60: I Deployed My First Production AI API and It's Live 24/7 (This Changes Everything)</title>
      <dc:creator>Cess Mbugua</dc:creator>
      <pubDate>Tue, 19 May 2026 18:56:52 +0000</pubDate>
      <link>https://dev.to/mbugua_cessy/day-17-of-60-i-deployed-my-first-production-ai-api-and-its-live-247-this-changes-everything-569o</link>
      <guid>https://dev.to/mbugua_cessy/day-17-of-60-i-deployed-my-first-production-ai-api-and-its-live-247-this-changes-everything-569o</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Today everything became real.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Every system I've built over the past 16 days lived only on my local machine. The moment I closed my laptop it went offline. n8n Cloud couldn't reach it without ngrok running. No client could access it. I couldn't share it with anyone without being physically present.&lt;/p&gt;

&lt;p&gt;Today I fixed that. My AI Agent API is live. 24/7. No laptop required.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## The Gap This Closes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is a clear line between a developer project and a professional product.&lt;/p&gt;

&lt;p&gt;A portfolio of systems that only run locally is a collection of demos. A deployed API that runs 24/7 from a cloud server is a product; something you can hand to a client, link to from your LinkedIn, or build a business on.&lt;/p&gt;

&lt;p&gt;Today I crossed that line.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## What Got Deployed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A production-ready FastAPI server combining the capabilities from the last three projects into one unified AI agent API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Document Q&amp;amp;A endpoint:&lt;/strong&gt; ask questions against any document&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Research endpoint:&lt;/strong&gt; multi-agent research and report generation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data analysis endpoint:&lt;/strong&gt; CSV analysis with AI-generated insights&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deployed to Render's free cloud hosting. Permanently accessible at a real URL. n8n Cloud workflows can now call it directly. Clients can access it. It's in my portfolio.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;requirements.txt:&lt;/strong&gt; the dependency file that tells cloud platforms what to install. Standard for every Python deployment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Environment variables in production:&lt;/strong&gt; storing API keys securely on Render so they are never in code or GitHub. This is non-negotiable in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Production start command:&lt;/strong&gt; the uvicorn command Render uses to start the server. Different from how you run it locally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Health check endpoint:&lt;/strong&gt; the GET / endpoint that tells Render your service is alive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auto-deploy from GitHub:&lt;/strong&gt; every time I push new code Render redeploys automatically. Continuous deployment from day one.&lt;/p&gt;




&lt;p&gt;*&lt;em&gt;🌐 Live API → &lt;a href="https://ai-agent-api-w7uh.onrender.com" rel="noopener noreferrer"&gt;https://ai-agent-api-w7uh.onrender.com&lt;/a&gt;&lt;br&gt;
🔗 GitHub → &lt;a href="https://github.com/mbuguacessy-glitch" rel="noopener noreferrer"&gt;https://github.com/mbuguacessy-glitch&lt;/a&gt;&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
43 more to go!. &lt;/p&gt;

&lt;h1&gt;
  
  
  python #fastapi #deployment #render #claudeapi #automation #learninpublic #buildinpublic #100DaysOfCode
&lt;/h1&gt;

</description>
    </item>
    <item>
      <title>Day 15 of 60: I Built a Multi-Agent Research System That Researches, Writes and Reviews Reports in Under 60 Seconds</title>
      <dc:creator>Cess Mbugua</dc:creator>
      <pubDate>Mon, 18 May 2026 14:01:00 +0000</pubDate>
      <link>https://dev.to/mbugua_cessy/day-15-of-60-i-built-a-multi-agent-research-system-that-researches-writes-and-reviews-reports-in-4f20</link>
      <guid>https://dev.to/mbugua_cessy/day-15-of-60-i-built-a-multi-agent-research-system-that-researches-writes-and-reviews-reports-in-4f20</guid>
      <description>&lt;p&gt;&lt;strong&gt;Today's build is the most sophisticated thing I've shipped so far.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A single AI call handles one task well. But complex research requires four fundamentally different cognitive tasks; finding information, synthesising it, writing a structured report, and reviewing its quality. Each needs different instructions. Different tools. Different evaluation criteria.&lt;/p&gt;

&lt;p&gt;So I stopped using one agent and built three.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## The Real World Problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you send a complex research question to a single Claude prompt you get a single pass. The response might be well-written but poorly researched. Or well-researched but poorly structured. Or both good but containing errors nobody checked.&lt;/p&gt;

&lt;p&gt;In the real world every high-quality deliverable goes through multiple specialist hands. Research agencies, law firms, consulting firms, and newsrooms all use teams, not because one person cannot do the work, but because specialisation and review produce dramatically better results.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## The Analogy That Made It Click&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think of a newspaper editorial team. When a breaking story comes in three people handle it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The journalist:&lt;/strong&gt; gathers facts, interviews sources, finds the data. Does not write the final article.&lt;br&gt;
&lt;strong&gt;The writer:&lt;/strong&gt; takes the journalist's notes and turns them into a polished, structured article. Was not at the scene.&lt;br&gt;
&lt;strong&gt;The editor:&lt;/strong&gt; reads the finished article before it publishes. Checks facts, identifies gaps, suggests improvements. Did not gather or write anything.&lt;/p&gt;

&lt;p&gt;Three specialists. Three distinct roles. One final product better than any one of them could produce alone.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;## How the System Works&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Topic comes in
↓
Researcher Agent: searches the web via Tavily
                   summarises findings
↓
Writer Agent: takes research output
               produces structured written report
↓
Reviewer Agent: reads the report
                 returns quality score + specific improvements
↓
Final reviewed report delivered in under 60 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The cast:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Researcher&lt;/code&gt; = The journalist: finds information via Tavily web search&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Writer&lt;/code&gt; = The writer: turns research into a structured report&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Reviewer&lt;/code&gt; = The editor: checks quality and flags improvements&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Orchestrator&lt;/code&gt; = The news desk: coordinates handoffs between agents&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Claude&lt;/code&gt; = The intelligence powering all three with different instructions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Tavily&lt;/code&gt; = The press pass: gives the Researcher access to live web search&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;## What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The biggest shift today was thinking in &lt;strong&gt;roles not prompts&lt;/strong&gt;. Every agent has its own identity, its own instructions, and its own output format. The output of each becomes the input of the next.&lt;/p&gt;

&lt;p&gt;This is the architecture behind every serious AI product being built in 2026. Content agencies, research firms, legal teams, and marketing departments all need research-to-report pipelines that don't require a human at every step.&lt;/p&gt;




&lt;p&gt;**🔗 Full project on GitHub → &lt;a href="https://github.com/mbuguacessy-glitch" rel="noopener noreferrer"&gt;https://github.com/mbuguacessy-glitch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;45 more to go.** &lt;/p&gt;

&lt;h1&gt;
  
  
  ai #multiagent #claudeapi #python #automation #learninpublic #buildinpublic #100DaysOfCode
&lt;/h1&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>automation</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Day 14 of 60: I Completed RAG and Now I Understand Why It Changes Everything</title>
      <dc:creator>Cess Mbugua</dc:creator>
      <pubDate>Sat, 16 May 2026 15:15:25 +0000</pubDate>
      <link>https://dev.to/mbugua_cessy/day-14-of-60-i-completed-rag-and-now-i-understand-why-it-changes-everything-5bj1</link>
      <guid>https://dev.to/mbugua_cessy/day-14-of-60-i-completed-rag-and-now-i-understand-why-it-changes-everything-5bj1</guid>
      <description>&lt;p&gt;Today I finished what I started yesterday. RAG is done. And I finally understand why every serious AI engineer needs to know this.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## Quick Recap: What is RAG?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Retrieval Augmented Generation. Instead of relying purely on what an LLM was trained on, RAG retrieves relevant information from an external knowledge base and passes it to the model as context before generating a response.&lt;/p&gt;

&lt;p&gt;The model doesn't need to have been trained on your data. It just needs to be able to read it at the moment you ask.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;##: The Complete RAG Pipeline&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Documents ingested → chunked into pieces
↓
Each chunk converted into a vector embedding
↓
Embeddings stored in a vector database
↓
User query comes in
↓
Query converted to embedding
↓
Vector database searched for similar chunks
↓
Relevant chunks retrieved
↓
Chunks + query passed to Claude
↓
Claude generates grounded response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;## What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Three concepts that finally clicked today:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chunking:&lt;/strong&gt; you can't pass an entire document to an LLM at once. You split it into smaller overlapping pieces so nothing important falls through the gaps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vector embeddings:&lt;/strong&gt; text converted into numbers that capture meaning. Similar concepts end up close together in vector space. That's how the search knows what's relevant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Grounding:&lt;/strong&gt; the difference between an AI that guesses and an AI that knows. RAG grounds every response in real retrieved data.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## Why This Changes My Builds&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every automation I've built so far sends data directly in the prompt. RAG means I can now build systems that reference entire company knowledge bases, months of historical data, or hundreds of documents, and still return accurate, grounded responses.&lt;/p&gt;

&lt;p&gt;The builds coming next are on a completely different level.&lt;/p&gt;




&lt;p&gt;No GitHub link today, pure learning day documented publicly.&lt;/p&gt;

&lt;p&gt;46 more to go. &lt;/p&gt;

&lt;h1&gt;
  
  
  rag #ai #learninpublic #buildinpublic #python #claudeapi #100DaysOfCode
&lt;/h1&gt;

</description>
    </item>
    <item>
      <title>Day 13 of 60: Today I Started Learning RAG</title>
      <dc:creator>Cess Mbugua</dc:creator>
      <pubDate>Fri, 15 May 2026 18:32:35 +0000</pubDate>
      <link>https://dev.to/mbugua_cessy/day-13-of-60-today-i-started-learning-rag-21eh</link>
      <guid>https://dev.to/mbugua_cessy/day-13-of-60-today-i-started-learning-rag-21eh</guid>
      <description>&lt;p&gt;&lt;strong&gt;RAG. Retrieval Augmented Generation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No build today. Just learning. And honestly it was one of the most mind-expanding study sessions since I started this challenge.&lt;/p&gt;




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

&lt;p&gt;Every AI model I've worked with so far: Claude, GPT, any LLM, has a knowledge cutoff. It knows what it was trained on and nothing else. Ask it about your company's internal documents, your client's data, or anything that happened after training; it has no idea.&lt;/p&gt;

&lt;p&gt;RAG fixes that.&lt;/p&gt;

&lt;p&gt;Instead of relying purely on what the model was trained on, RAG retrieves relevant information from an external source; a database, a document store, a knowledge base — and passes it to the model as context before generating a response.&lt;/p&gt;

&lt;p&gt;The model doesn't need to have been trained on your data. It just needs to be able to read it at the moment you ask.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Changes Everything for Automation
&lt;/h2&gt;

&lt;p&gt;Every automation I've built so far sends data directly to Claude in the prompt. That works for small, structured inputs.&lt;/p&gt;

&lt;p&gt;But what about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A chatbot that answers questions about a company's entire document library?&lt;/li&gt;
&lt;li&gt;A support system that references hundreds of past tickets to resolve new ones?&lt;/li&gt;
&lt;li&gt;A report generator that pulls from months of historical data?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can't paste all of that into a prompt. RAG is how you solve that.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Learned Today
&lt;/h2&gt;

&lt;p&gt;The core RAG pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User query
↓
Search knowledge base for relevant chunks
↓
Pass retrieved chunks + query to LLM
↓
LLM generates response grounded in real data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The builds that are coming next are going to be on a completely different level.&lt;/p&gt;




&lt;p&gt;No GitHub link today, just a study day documented publicly.&lt;/p&gt;

&lt;p&gt;47 more to go. &lt;/p&gt;

&lt;h1&gt;
  
  
  rag #ai #learninpublic #buildinpublic #python #claudeapi #100DaysOfCode
&lt;/h1&gt;

</description>
      <category>ai</category>
      <category>learning</category>
      <category>llm</category>
      <category>rag</category>
    </item>
    <item>
      <title>Day 12 of 60: I Built the Final Piece That Completes a Full AI Automation Stack (Zero Human Reporting)</title>
      <dc:creator>Cess Mbugua</dc:creator>
      <pubDate>Thu, 14 May 2026 19:27:58 +0000</pubDate>
      <link>https://dev.to/mbugua_cessy/day-12-of-60-i-built-the-final-piece-that-completes-a-full-ai-automation-stack-zero-human-5990</link>
      <guid>https://dev.to/mbugua_cessy/day-12-of-60-i-built-the-final-piece-that-completes-a-full-ai-automation-stack-zero-human-5990</guid>
      <description>&lt;p&gt;&lt;strong&gt;Today I closed the loop.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every business running automations eventually faces the same question: what actually happened this week? Someone has to pull data from multiple sources, count the records, write a summary, and send it. For one client that's 30 minutes. For ten clients it's half a day. Every single week.&lt;/p&gt;

&lt;p&gt;Today I automated that entirely.&lt;/p&gt;




&lt;p&gt;*&lt;em&gt;## What I Built&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
A Python script that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connects to Airtable and reads all lead records&lt;/li&gt;
&lt;li&gt;Sends the data to Claude with a reporting prompt&lt;/li&gt;
&lt;li&gt;Receives a clean written summary report back&lt;/li&gt;
&lt;li&gt;Saves it as a timestamped .txt file&lt;/li&gt;
&lt;li&gt;Prints it to the terminal&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The report includes lead counts by urgency, status breakdowns, key highlights, and recommended next actions. No human involved.&lt;/p&gt;



&lt;p&gt;**&lt;/p&gt;
&lt;h2&gt;
  
  
  Why This Matters: The Full Stack
&lt;/h2&gt;

&lt;p&gt;**&lt;br&gt;
This was Challenge 5 of 5 in Phase 1. Here's what the complete pipeline looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Challenge 4 → Intake comes in
              Raw client text → Claude extracts → Pydantic validates → Airtable stores

Challenge 5 → Report goes out
              Airtable data → Claude analyses → Written report → saved as .txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Intake in. Report out. No human touches either end.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;## The Analogy That Made It Click&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think of a bank branch manager's end-of-day report. The teller system holds every transaction. Every evening a junior manager spends an hour pulling numbers and writing a summary for the regional director.&lt;/p&gt;

&lt;p&gt;What I built is the automated equivalent; a script that reads every record, hands them to Claude who writes the summary in plain English, and delivers the report automatically. Same quality. Every day. Zero manual effort.&lt;/p&gt;

&lt;p&gt;The junior manager now spends that hour on something that actually requires human judgement.&lt;/p&gt;




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

&lt;p&gt;Phase 1 is complete. Five challenges. Five scripts. One complete automation stack.&lt;/p&gt;

&lt;p&gt;The biggest lesson across all five: &lt;strong&gt;the most valuable automations aren't the flashy ones; they're the ones that eliminate the invisible repetitive work nobody talks about but everyone does.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;🔗 Full project on GitHub → &lt;a href="https://github.com/mbuguacessy-glitch" rel="noopener noreferrer"&gt;https://github.com/mbuguacessy-glitch&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;48 more to go. &lt;/p&gt;

&lt;h1&gt;
  
  
  python #claudeapi #automation #airtable #learninpublic #buildinpublic #100DaysOfCode
&lt;/h1&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>python</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Day 11 of 60: I Built a Script That Reads Raw Client Intake Text and Creates Clean CRM Records Automatically</title>
      <dc:creator>Cess Mbugua</dc:creator>
      <pubDate>Wed, 13 May 2026 21:02:19 +0000</pubDate>
      <link>https://dev.to/mbugua_cessy/day-11-of-60-i-built-a-script-that-reads-raw-client-intake-text-and-creates-clean-crm-records-1f3d</link>
      <guid>https://dev.to/mbugua_cessy/day-11-of-60-i-built-a-script-that-reads-raw-client-intake-text-and-creates-clean-crm-records-1f3d</guid>
      <description>&lt;p&gt;Every agency hits the same wall. A potential client fills out an intake form. What comes back is a block of unstructured text. Someone has to read it, extract the budget buried in the prose, assess urgency, and manually create a CRM record.&lt;/p&gt;

&lt;p&gt;For five clients a week that's an annoyance. For fifty it becomes a part-time job. For a hundred it breaks the business.&lt;/p&gt;

&lt;p&gt;So I automated it.&lt;/p&gt;




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

&lt;p&gt;A Python script that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reads raw intake text exactly as a client types it&lt;/li&gt;
&lt;li&gt;Sends it to Claude with a structured extraction prompt&lt;/li&gt;
&lt;li&gt;Receives a clean JSON object back&lt;/li&gt;
&lt;li&gt;Validates every field with Pydantic&lt;/li&gt;
&lt;li&gt;Saves the complete record to Airtable automatically&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No human reads the intake. No human creates the CRM entry. A clean lead appears in Airtable ready for follow-up — in seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  New Skills This Introduced
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Structured extraction prompting&lt;/strong&gt;&lt;br&gt;
Telling Claude to return only JSON with specific fields, making AI output predictable and parseable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pydantic field validation&lt;/strong&gt;&lt;br&gt;
Catching bad AI output before it corrupts your data, defining exactly what shape the data must be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;@field_validator&lt;/strong&gt;&lt;br&gt;
Custom rules that fix or reject individual fields e.g. if urgency is not Low/Medium/High, default to Medium.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;pyairtable&lt;/strong&gt;&lt;br&gt;
Writing records to Airtable via API from Python — your CRM integration layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;glob()&lt;/strong&gt;&lt;br&gt;
Looping over all files matching a pattern, process 2 intakes or 200 with the same code.&lt;/p&gt;




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

&lt;p&gt;The most valuable thing today wasn't the code, it was the pattern. Unstructured text in. Validated structured data out. Saved to a system of record.&lt;/p&gt;

&lt;p&gt;This same pattern applies to support ticket classification, lead qualification, invoice extraction, contract review, and survey analysis. Once you understand it, you can deliver one of the highest-value automations in the market.&lt;/p&gt;




&lt;p&gt;🔗 Full project on GitHub → &lt;a href="https://github.com/mbuguacessy-glitch" rel="noopener noreferrer"&gt;https://github.com/mbuguacessy-glitch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;49 more to go. &lt;/p&gt;

&lt;h1&gt;
  
  
  python #claudeapi #automation #airtable #learninpublic #buildinpublic #100DaysOfCode
&lt;/h1&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>productivity</category>
      <category>python</category>
    </item>
  </channel>
</rss>
