<?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: Akash Birajdar</title>
    <description>The latest articles on DEV Community by Akash Birajdar (@akashb5).</description>
    <link>https://dev.to/akashb5</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%2F2629012%2F2d70adab-8044-4c17-ab57-fe4216b3666f.png</url>
      <title>DEV Community: Akash Birajdar</title>
      <link>https://dev.to/akashb5</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/akashb5"/>
    <language>en</language>
    <item>
      <title>Building an AI-Powered Unified Inbox with Kiro: A Deep Dive into Spec-Driven Development</title>
      <dc:creator>Akash Birajdar</dc:creator>
      <pubDate>Fri, 05 Dec 2025 20:40:15 +0000</pubDate>
      <link>https://dev.to/akashb5/building-an-ai-powered-unified-inbox-with-kiro-a-deep-dive-into-spec-driven-development-36gg</link>
      <guid>https://dev.to/akashb5/building-an-ai-powered-unified-inbox-with-kiro-a-deep-dive-into-spec-driven-development-36gg</guid>
      <description>&lt;h1&gt;
  
  
  Building Champa: An AI-Powered Unified Inbox
&lt;/h1&gt;

&lt;p&gt;Ever feel overwhelmed juggling Gmail, Slack, and Calendar? Context-switching between platforms wastes hours every week. That's why I built &lt;strong&gt;Champa&lt;/strong&gt;—an intelligent unified inbox that consolidates all your communications into one AI-enhanced interface.&lt;/p&gt;

&lt;p&gt;The interesting part? I built it using &lt;strong&gt;Kiro&lt;/strong&gt;, an AI-powered IDE that goes beyond traditional coding assistants. This article shares what Champa does and how Kiro's advanced features made the development process remarkably efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Communication Chaos
&lt;/h2&gt;

&lt;p&gt;Modern professionals deal with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📧 Important emails buried in spam&lt;/li&gt;
&lt;li&gt;💬 Urgent Slack messages lost in channels&lt;/li&gt;
&lt;li&gt;📅 Calendar events scattered across platforms&lt;/li&gt;
&lt;li&gt;⏰ Hours spent crafting professional responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Champa&lt;/strong&gt; solves this by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Aggregating messages from Gmail, Slack, and Calendar&lt;/li&gt;
&lt;li&gt;Using AI to summarize, prioritize, and extract action items&lt;/li&gt;
&lt;li&gt;Generating smart replies that match your writing style&lt;/li&gt;
&lt;li&gt;Requiring human approval before sending (you stay in control)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;strong&gt;Backend&lt;/strong&gt;: FastAPI, LangGraph, LangChain, PostgreSQL, Qdrant&lt;br&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: React 18, TypeScript, RetroUI&lt;br&gt;
&lt;strong&gt;AI&lt;/strong&gt;: OpenAI GPT-4, Sentence Transformers&lt;br&gt;
&lt;strong&gt;Testing&lt;/strong&gt;: pytest with Hypothesis (property-based testing)&lt;/p&gt;

&lt;p&gt;But the real star of the show? &lt;strong&gt;Kiro&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Makes Kiro Different?
&lt;/h2&gt;

&lt;p&gt;Kiro isn't just an autocomplete tool. It's a full AI-powered development environment with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Spec-Driven Development&lt;/strong&gt;: Define requirements, design, and tasks—Kiro implements them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steering Docs&lt;/strong&gt;: Project-wide guidelines that ensure consistency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent Hooks&lt;/strong&gt;: Automated workflows triggered by file changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Integration&lt;/strong&gt;: Real-time access to up-to-date documentation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vibe Coding&lt;/strong&gt;: Natural language prompts for rapid prototyping&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let me show you how each feature accelerated Champa's development.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Spec-Driven Development: The Game Changer
&lt;/h2&gt;

&lt;p&gt;I started by creating a comprehensive spec in &lt;code&gt;.kiro/specs/champa-unified-inbox/&lt;/code&gt;:&lt;/p&gt;
&lt;h3&gt;
  
  
  requirements.md
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Requirement 7&lt;/span&gt;
&lt;span class="gs"&gt;**User Story:**&lt;/span&gt; As a user, I want the system to generate draft replies 
for my emails, so that I can respond quickly without starting from scratch.

&lt;span class="gu"&gt;#### Acceptance Criteria&lt;/span&gt;
&lt;span class="p"&gt;1.&lt;/span&gt; WHEN a user requests a smart reply for an email 
   THEN the system SHALL fetch the complete thread context
&lt;span class="p"&gt;2.&lt;/span&gt; WHEN generating a smart reply 
   THEN the Deep Agent SHALL retrieve relevant User Persona data
&lt;span class="p"&gt;3.&lt;/span&gt; WHEN generating a smart reply 
   THEN the Deep Agent SHALL create a step-by-step plan using LangGraph
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  design.md
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Correctness Properties&lt;/span&gt;

&lt;span class="gu"&gt;### Property 27: Smart reply fetches thread context&lt;/span&gt;
&lt;span class="ge"&gt;*For any*&lt;/span&gt; smart reply request, the system should fetch the complete 
thread context including all related messages.
&lt;span class="gs"&gt;**Validates: Requirements 7.1**&lt;/span&gt;

&lt;span class="gu"&gt;### Property 28: Smart reply uses persona data&lt;/span&gt;
&lt;span class="ge"&gt;*For any*&lt;/span&gt; smart reply being generated, the Deep Agent should retrieve 
and use relevant User Persona data.
&lt;span class="gs"&gt;**Validates: Requirements 7.2**&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  tasks.md
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; [ ] 8.3 Implement smart reply generation workflow
&lt;span class="p"&gt;  -&lt;/span&gt; Create fetch_thread_context method
&lt;span class="p"&gt;  -&lt;/span&gt; Create retrieve_persona method
&lt;span class="p"&gt;  -&lt;/span&gt; Create reply planning agent
&lt;span class="p"&gt;  -&lt;/span&gt; Create draft generation agent
&lt;span class="p"&gt;  -&lt;/span&gt; Implement platform-specific formatting
&lt;span class="p"&gt;  -&lt;/span&gt; _Requirements: 7.1, 7.2, 7.4_
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;The magic&lt;/strong&gt;: When I asked Kiro to "implement task 8.3", it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read the requirements and understood the acceptance criteria&lt;/li&gt;
&lt;li&gt;Checked the correctness properties it needed to satisfy&lt;/li&gt;
&lt;li&gt;Generated complete code with LangGraph's interrupt mechanism for human approval&lt;/li&gt;
&lt;li&gt;Created property-based tests to verify the implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No more "I hope the AI understood what I meant." The spec was the single source of truth.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Steering Docs: Consistency on Autopilot
&lt;/h2&gt;

&lt;p&gt;I created three steering documents that Kiro automatically included in every interaction:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tech.md&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Key Technical Constraints&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; All UI components must use RetroUI library
&lt;span class="p"&gt;-&lt;/span&gt; Platform integrations must go through abstract interfaces
&lt;span class="p"&gt;-&lt;/span&gt; All AI-generated email replies require human approval before sending
&lt;span class="p"&gt;-&lt;/span&gt; Property-based tests must run minimum 100 iterations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;structure.md&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## File Naming Conventions&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Python**&lt;/span&gt;: snake_case for files and functions
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**TypeScript/React**&lt;/span&gt;: PascalCase for components, camelCase for utilities
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Tests**&lt;/span&gt;: &lt;span class="sb"&gt;`test_*.py`&lt;/span&gt; for Python, &lt;span class="sb"&gt;`*.test.tsx`&lt;/span&gt; for React
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: Every component Kiro generated automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Used RetroUI (no manual fixes needed)&lt;/li&gt;
&lt;li&gt;Followed our naming conventions&lt;/li&gt;
&lt;li&gt;Placed files in the correct directories&lt;/li&gt;
&lt;li&gt;Implemented property-based tests with 100+ iterations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without steering docs, I'd spend hours fixing consistency violations. With them, code was production-ready from the start.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Agent Hooks: Automated Quality Checks
&lt;/h2&gt;

&lt;p&gt;I set up three hooks in &lt;code&gt;.kiro/hooks/&lt;/code&gt; that ran automatically on file changes:&lt;/p&gt;

&lt;h3&gt;
  
  
  security-review-hook.kiro.hook
&lt;/h3&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;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"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;"Security Review on File Changes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"when"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fileEdited"&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;"then"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"askAgent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Review the changed files for potential security issues..."&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="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;This hook caught multiple instances where I almost committed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API keys in environment files&lt;/li&gt;
&lt;li&gt;Hardcoded OAuth credentials&lt;/li&gt;
&lt;li&gt;Database connection strings&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  code-quality-analyzer.kiro.hook
&lt;/h3&gt;

&lt;p&gt;Suggested refactoring our platform adapters to use the Strategy pattern, making it trivial to add new platforms (Discord, Teams, etc.).&lt;/p&gt;

&lt;h3&gt;
  
  
  docs-sync-on-change.kiro.hook
&lt;/h3&gt;

&lt;p&gt;Automatically updated README and API docs when I modified endpoints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Impact&lt;/strong&gt;: Continuous feedback without interrupting flow. Issues caught immediately, not during code review.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. MCP: Real-Time Documentation Access
&lt;/h2&gt;

&lt;p&gt;I configured two MCP servers in my Kiro settings:&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;"mcpServers"&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;"context7"&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;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&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="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@upstash/context7-mcp"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"disabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&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;"docs-langchain"&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;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://docs.langchain.com/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"disabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"autoApprove"&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="s2"&gt;"SearchDocsByLangChain"&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this matters&lt;/strong&gt;: LangGraph and LangChain are rapidly evolving. Kiro's training data might not include the latest features.&lt;/p&gt;

&lt;p&gt;With MCP, when I asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How do I implement human-in-the-loop with LangGraph?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kiro queried the official docs and gave me the exact, current implementation pattern using LangGraph's interrupt mechanism.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without MCP&lt;/strong&gt;: Outdated patterns, manual doc searching, trial and error.&lt;br&gt;
&lt;strong&gt;With MCP&lt;/strong&gt;: Expert-level knowledge of the latest APIs, first-time-right implementations.&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Vibe Coding: Rapid Prototyping
&lt;/h2&gt;

&lt;p&gt;For exploratory work, I used natural language prompts:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Build a LangGraph deep agent that generates smart replies using user persona memory"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kiro generated the entire &lt;code&gt;deep_agent.py&lt;/code&gt; module with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Planning middleware for breaking down reply generation&lt;/li&gt;
&lt;li&gt;LangGraph Store integration for persona memory&lt;/li&gt;
&lt;li&gt;Interrupt mechanism for human approval&lt;/li&gt;
&lt;li&gt;Proper error handling and fallback logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Most impressive generation&lt;/strong&gt;: The AI pipeline. I described:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Analyze messages in parallel for summary, intent, priority, tasks, and spam detection"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kiro created a complete LangChain-based pipeline with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Async handling for parallel processing&lt;/li&gt;
&lt;li&gt;Retry logic with exponential backoff&lt;/li&gt;
&lt;li&gt;Qdrant vector storage integration&lt;/li&gt;
&lt;li&gt;Fallback mechanisms for AI failures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All in one go. Production-ready.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Kiro Workflow
&lt;/h2&gt;

&lt;p&gt;My typical development cycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Define in Spec
   ↓
2. Ask Kiro: "Implement task X"
   ↓
3. Kiro Generates (references spec + steering + existing code)
   ↓
4. Hooks Validate (security, quality, docs)
   ↓
5. Property Tests Run (100+ iterations)
   ↓
6. Iterate based on feedback
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow let me build 10,000+ lines of production-ready code in a fraction of the time traditional development would take.&lt;/p&gt;

&lt;h2&gt;
  
  
  Property-Based Testing: The Secret Weapon
&lt;/h2&gt;

&lt;p&gt;Kiro helped me implement property-based testing with Hypothesis—something I'd never used before.&lt;/p&gt;

&lt;p&gt;Instead of writing:&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;test_normalize_gmail_message&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_test_gmail_message&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;normalized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalize_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;platform&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gmail&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I wrote:&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;# Feature: champa-unified-inbox, Property 12: All messages are normalized
&lt;/span&gt;&lt;span class="nd"&gt;@given&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;message_strategy&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;test_message_normalization&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;normalized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalize_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;platform&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gmail&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;slack&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;calendar&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs 100+ iterations with randomly generated data, catching edge cases I never would have thought of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Empty sender fields&lt;/li&gt;
&lt;li&gt;Malformed timestamps&lt;/li&gt;
&lt;li&gt;Missing metadata&lt;/li&gt;
&lt;li&gt;Unicode edge cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kiro understood the property definitions in my spec and translated them into executable tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features of Champa
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Unified Message Feed
&lt;/h3&gt;

&lt;p&gt;All your communications in one place with AI-generated summaries, priority scores, and platform indicators.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Smart Reply Generation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# The AI learns your writing style
&lt;/span&gt;&lt;span class="n"&gt;persona&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;retrieve_user_persona&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="n"&gt;thread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch_thread_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;draft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_reply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;persona&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Human approval required before sending
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;interrupt_for_approval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;draft&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Actionable Item Extraction
&lt;/h3&gt;

&lt;p&gt;AI automatically identifies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tasks ("Can you review the PR?")&lt;/li&gt;
&lt;li&gt;Deadlines ("Need this by Friday")&lt;/li&gt;
&lt;li&gt;Meeting requests ("Let's sync tomorrow at 2pm")&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Semantic Search
&lt;/h3&gt;

&lt;p&gt;Powered by Qdrant vector database:&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;# Find similar messages
&lt;/span&gt;&lt;span class="n"&gt;query_embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_embedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;similar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qdrant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query_embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Chat Assistant
&lt;/h3&gt;

&lt;p&gt;Natural language queries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Show me urgent emails from this week"&lt;/li&gt;
&lt;li&gt;"What meetings do I have tomorrow?"&lt;/li&gt;
&lt;li&gt;"Find messages about the project deadline"&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture Highlights
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Dual Database Strategy
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL&lt;/strong&gt;: Structured data (messages, users, analysis)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Qdrant&lt;/strong&gt;: Vector embeddings for semantic search&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This combination enables both traditional queries and semantic search capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interface-Based Platform Integration
&lt;/h3&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;PlatformInterface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ABC&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nd"&gt;@abstractmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_messages&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="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="nd"&gt;@abstractmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_message&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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Result&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;Adding a new platform? Just implement the interface. No changes to core logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  LangGraph Deep Agents
&lt;/h3&gt;

&lt;p&gt;The smart reply system uses LangGraph's deep agents with planning middleware to break down reply generation into steps, retrieve user persona data, and generate context-aware responses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;10,000+ lines of code&lt;/strong&gt; generated with Kiro&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;59 correctness properties&lt;/strong&gt; verified through property-based testing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3 automated hooks&lt;/strong&gt; providing continuous quality checks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero hardcoded credentials&lt;/strong&gt; committed (thanks to security hook)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;100% RetroUI compliance&lt;/strong&gt; (thanks to steering docs)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Spec-driven development &amp;gt; vibe coding alone&lt;/strong&gt;: Specs provide formal correctness guarantees. Vibe coding is great for prototyping, but specs ensure production quality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Steering docs are essential&lt;/strong&gt;: Without them, you'll spend hours fixing consistency violations. With them, code is right the first time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent hooks catch issues early&lt;/strong&gt;: Security vulnerabilities, code smells, and documentation drift—all caught automatically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MCP is a game-changer&lt;/strong&gt;: Real-time access to current documentation means no more outdated patterns or manual doc searching.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Property-based testing finds edge cases&lt;/strong&gt;: Traditional unit tests would have missed dozens of bugs that Hypothesis caught.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What's Next for Champa
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;More platforms&lt;/strong&gt;: Microsoft Teams, Discord, WhatsApp Business&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mobile apps&lt;/strong&gt;: Native iOS and Android&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Voice interface&lt;/strong&gt;: "Hey Champa, summarize my unread emails"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team features&lt;/strong&gt;: Shared inboxes for customer support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom AI models&lt;/strong&gt;: Fine-tuned for specific industries&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Building Champa with Kiro was eye-opening. The combination of spec-driven development, steering docs, agent hooks, and MCP integration created a development workflow that felt less like coding and more like architecting.&lt;/p&gt;

&lt;p&gt;It's not just about code generation—it's about maintaining architectural consistency, ensuring correctness through formal properties, and automating quality checks. Kiro helped me build a production-ready system with 10,000+ lines of code while maintaining quality and consistency throughout.&lt;/p&gt;

&lt;p&gt;If you're building complex applications, especially with AI components, the spec-driven approach with Kiro is worth exploring.&lt;/p&gt;

</description>
      <category>kiro</category>
      <category>ai</category>
      <category>productivity</category>
      <category>langchain</category>
    </item>
    <item>
      <title>Music Moodboard Assistant ( Auth0 AI + Spotify )</title>
      <dc:creator>Akash Birajdar</dc:creator>
      <pubDate>Thu, 23 Oct 2025 18:58:46 +0000</pubDate>
      <link>https://dev.to/akashb5/music-moodboard-assistant-auth0-ai-spotify--2apm</link>
      <guid>https://dev.to/akashb5/music-moodboard-assistant-auth0-ai-spotify--2apm</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/auth0-2025-10-08"&gt;Auth0 for AI Agents Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Music Moodboard Assistant 🎧
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;An Auth0-secured Agentic AI that turns your mood into music&lt;/strong&gt;&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;Music Moodboard Assistant&lt;/strong&gt; is an &lt;strong&gt;agentic AI application&lt;/strong&gt; that blends emotion recognition, music recommendation, and secure authentication to personalize Spotify experiences.&lt;/p&gt;

&lt;p&gt;The idea came from a simple, everyday frustration — when you feel &lt;strong&gt;sleepy&lt;/strong&gt;, &lt;strong&gt;energetic&lt;/strong&gt;, or &lt;strong&gt;unfocused&lt;/strong&gt;, Spotify doesn’t understand that feeling directly. You must search, scroll, and tweak to find what fits your mood.&lt;/p&gt;

&lt;p&gt;Music Moodboard Assistant changes that.&lt;br&gt;
You can simply say things like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I’m sleepy and need something relaxing.”&lt;br&gt;
“Play me something upbeat to wake me up.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Behind the scenes, the agent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Authenticates you via Auth0&lt;/strong&gt;, ensuring all actions happen under your Spotify account securely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analyzes your intent&lt;/strong&gt; using an AI model hosted via &lt;strong&gt;OpenRouter&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uses Spotify APIs&lt;/strong&gt; through &lt;strong&gt;Auth0’s Token Vault&lt;/strong&gt;, without ever exposing tokens to the AI agent itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generates playlists or recommends songs&lt;/strong&gt; that match your described mood, using &lt;strong&gt;audio features&lt;/strong&gt; such as tempo, energy, and valence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fetches context from a secure RAG (Retrieval-Augmented Generation) system&lt;/strong&gt;, with fine-grained Auth0-based authorization that ensures the agent only accesses allowed information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, it’s a &lt;strong&gt;mood-to-music finder&lt;/strong&gt; that demonstrates how &lt;strong&gt;Auth0 for AI Agents&lt;/strong&gt; can secure autonomous systems interacting with third-party APIs.&lt;/p&gt;


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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live demo:&lt;/strong&gt; &lt;em&gt;&lt;a href="https://music-moodboard.vercel.app" rel="noopener noreferrer"&gt;https://music-moodboard.vercel.app&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository:&lt;/strong&gt; &lt;em&gt;&lt;a href="https://github.com/Akashdb5/music-moodboard" rel="noopener noreferrer"&gt;https://github.com/Akashdb5/music-moodboard&lt;/a&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Screenshots or video:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div&gt;
  &lt;iframe src="https://loom.com/embed/9c8ec331a2144ca1adc5332a468f3ea4"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&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%2Fp0p1kxbnag3q7yj55hd6.png" alt="Landing page"&gt;&lt;/td&gt;
&lt;td&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%2Fgyjo68xincxlgr8z3t3f.png" alt="Permission"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&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%2Fnujx8f831yri2i4qe6uo.png" alt="Home"&gt;&lt;/td&gt;
&lt;td&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%2Fqorx4n9e03q937mncfxh.jpg" alt="Mobile screenshot"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  How I Used Auth0 for AI Agents
&lt;/h2&gt;

&lt;p&gt;This project is built around &lt;strong&gt;Auth0 for AI Agents&lt;/strong&gt;, implementing its three foundational pillars:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Authenticate the User
&lt;/h3&gt;

&lt;p&gt;Every interaction starts with &lt;strong&gt;secure authentication&lt;/strong&gt; via Auth0.&lt;br&gt;
The API endpoint (&lt;code&gt;app/api/chat/route.ts&lt;/code&gt;) requires a valid Auth0 session before the agent can act.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;auth0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSession&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unauthorized&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that every chat request, playlist creation, or Spotify query is tied to a &lt;strong&gt;verified user identity&lt;/strong&gt;.&lt;br&gt;
Each session is isolated using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;setAIContext&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;threadID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;sub&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That way, the AI keeps conversation and personalization scoped to the right user.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Control the Tools (Token Vault Integration)
&lt;/h3&gt;

&lt;p&gt;Once authenticated, the agent gains &lt;strong&gt;controlled access&lt;/strong&gt; to the Spotify API using Auth0’s &lt;strong&gt;Token Vault&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The Token Vault ensures that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The agent never handles sensitive credentials directly.&lt;/li&gt;
&lt;li&gt;Tokens are issued &lt;strong&gt;per scope&lt;/strong&gt; and &lt;strong&gt;per user&lt;/strong&gt;, based on Auth0’s configured connection.&lt;/li&gt;
&lt;li&gt;Tokens can be &lt;strong&gt;revoked or re-scoped&lt;/strong&gt; at any time, enhancing control and compliance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example (from &lt;code&gt;lib/auth0-ai.ts&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spotifyAI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;auth0AI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withTokenVault&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;spotify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;scopes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;spotifyScopes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Token Vault connection uses a &lt;strong&gt;least privilege&lt;/strong&gt; approach — defined in &lt;code&gt;lib/spotify-config.ts&lt;/code&gt; — allowing only the actions the app truly needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Playlist creation and modification&lt;/li&gt;
&lt;li&gt;Track search and recommendation&lt;/li&gt;
&lt;li&gt;Playback control&lt;/li&gt;
&lt;li&gt;Top tracks, recently played, and library access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before performing any action that changes user data (like creating a playlist or uploading an image), the AI must get &lt;strong&gt;explicit approval&lt;/strong&gt; through Auth0 Interrupts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withSpotifyPlaylistConfirmation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;auth0AI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withUserConfirmation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Do you want the assistant to create this playlist in your Spotify account?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This human-in-the-loop design ensures &lt;strong&gt;trust and transparency&lt;/strong&gt; between the user and the AI agent.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Limit Knowledge (Authorized RAG)
&lt;/h3&gt;

&lt;p&gt;In addition to Spotify actions, the project integrates a &lt;strong&gt;Retrieval-Augmented Generation (RAG)&lt;/strong&gt; system that stores and retrieves documents (for example, internal configuration or mood-to-music mapping guides).&lt;/p&gt;

&lt;p&gt;Auth0’s &lt;strong&gt;fine-grained authorization (FGA)&lt;/strong&gt; ensures that even within the RAG system, users only access data they’re permitted to view.&lt;/p&gt;

&lt;p&gt;The pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Documents are chunked and embedded with &lt;strong&gt;OpenAI’s embedding models&lt;/strong&gt; (&lt;code&gt;text-embedding-3-small&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;When a query arrives, the vector store performs a similarity search.&lt;/li&gt;
&lt;li&gt;Auth0’s &lt;strong&gt;&lt;code&gt;FGAFilter&lt;/code&gt;&lt;/strong&gt; filters out any restricted results before the AI can use them.&lt;/li&gt;
&lt;li&gt;The final answer is generated only from &lt;strong&gt;allowed&lt;/strong&gt; context snippets.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;From &lt;code&gt;lib/rag/authorized-rag.ts&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FGAFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;auth0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;modelId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;knowledge-docs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filtered&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filterResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents unauthorized data leakage during generation — a critical feature when AI systems have dynamic access to stored knowledge.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned and Takeaways
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Technical Insights
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Auth0’s Token Vault is transformative&lt;/strong&gt; for AI agents.&lt;br&gt;
It eliminates the need to store or manage refresh tokens manually, letting you control API access through Auth0 configuration alone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fine-grained authorization for RAG pipelines is essential.&lt;/strong&gt;&lt;br&gt;
It ensures sensitive or internal knowledge bases can be shared securely between different users or organizations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tool schemas matter.&lt;/strong&gt;&lt;br&gt;
By defining strong Zod schemas for tool inputs/outputs (&lt;code&gt;lib/tools/spotify.ts&lt;/code&gt;), the agent produces more reliable, interpretable calls.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interrupts make agent actions safer.&lt;/strong&gt;&lt;br&gt;
The &lt;code&gt;withSpotifyPlaylistConfirmation&lt;/code&gt; wrapper provides a natural way to ask for permission before performing actions that affect user data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Thread isolation improves user experience.&lt;/strong&gt;&lt;br&gt;
Using &lt;code&gt;threadID = session.user.sub&lt;/code&gt; ensures persistent, secure, user-scoped interactions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Personal Reflections
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Music Moodboard Assistant&lt;/strong&gt; was born from the idea that music should meet you where you are emotionally.&lt;br&gt;
When I’m &lt;strong&gt;sleepy&lt;/strong&gt;, I don’t want to hunt for “lofi sleep” playlists — I just want to say &lt;em&gt;“I’m sleepy”&lt;/em&gt; and let the assistant take over.&lt;/p&gt;

&lt;p&gt;When I first saw it create a custom playlist with low-energy, high-acousticness songs and ask,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Would you like me to add vocals or keep it instrumental?”&lt;br&gt;
I realized how natural the interaction felt — and how much more &lt;em&gt;human&lt;/em&gt; music discovery could be.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This project showed me that &lt;strong&gt;secure autonomy&lt;/strong&gt; isn’t just about tokens and permissions — it’s about building AI systems that users trust enough to act on their behalf.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>auth0challenge</category>
      <category>ai</category>
      <category>authentication</category>
    </item>
  </channel>
</rss>
