<?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: Kartik Hirijaganer</title>
    <description>The latest articles on DEV Community by Kartik Hirijaganer (@kartik_hirijaganer_d600ea).</description>
    <link>https://dev.to/kartik_hirijaganer_d600ea</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%2F3587512%2Fdbf25207-f4b5-43cc-9948-ac2d82fc276d.jpg</url>
      <title>DEV Community: Kartik Hirijaganer</title>
      <link>https://dev.to/kartik_hirijaganer_d600ea</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kartik_hirijaganer_d600ea"/>
    <language>en</language>
    <item>
      <title>I Built an AI Email Agent: Here’s What Nobody Told Me</title>
      <dc:creator>Kartik Hirijaganer</dc:creator>
      <pubDate>Wed, 10 Jun 2026 16:05:16 +0000</pubDate>
      <link>https://dev.to/kartik_hirijaganer_d600ea/i-built-an-ai-email-agent-heres-what-nobody-told-me-4i7n</link>
      <guid>https://dev.to/kartik_hirijaganer_d600ea/i-built-an-ai-email-agent-heres-what-nobody-told-me-4i7n</guid>
      <description>&lt;p&gt;&lt;em&gt;“People hand you these single little messages that are no heavier than a river pebble. But it doesn’t take long until you have acquired a pile of pebbles that’s taller than you and heavier than you could ever hope to move.” — Merlin Mann&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Multiple inboxes. Multiple accounts. A pile of notifications I kept meaning to unsubscribe from but never did.&lt;/p&gt;

&lt;p&gt;By the time I actually checked my email each morning, I was already staring at 300+ unread messages, a mix of stuff that mattered, stuff that used to matter, and a graveyard of newsletters I’d forgotten I signed up for. It compounds fast.&lt;/p&gt;

&lt;p&gt;Paid tools felt like overkill. Free ones didn’t fit how I actually worked. So I built it myself, and honestly, with AI tools in the mix, the barrier to actually shipping is lower than ever.&lt;/p&gt;

&lt;p&gt;I spent a few days mapping out the problem: which features actually mattered and what the architecture should look like.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Briefed actually does&lt;/strong&gt;&lt;br&gt;
Briefed is a personal AI email agent. Every morning, it reads your Gmail and hands you back a brief, not a notification, not a summary dump, a brief. Like an executive assistant wrote it for you.&lt;/p&gt;

&lt;p&gt;It does four things:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Classifies.&lt;/strong&gt; Every email gets sorted into one of four buckets: must-read, good-to-read, ignore, or waste. Against a classification rubric you own and can edit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summarizes.&lt;/strong&gt; The must-read pile gets condensed. You read the gist, not the thread.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clusters.&lt;/strong&gt; Thirty newsletter rows become one digest entry. Your inbox stops looking like a fire hose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recommends.&lt;/strong&gt; It scores your noisiest senders by volume, engagement rate, and wasted-email signals, then recommends which ones to unsubscribe from, with reasoning.&lt;/p&gt;

&lt;p&gt;The constraint I never compromised on: &lt;strong&gt;it never acts without you.&lt;/strong&gt; No auto-archiving. No auto-unsubscribing. Every destructive action requires explicit confirmation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The thing nobody talks about with AI products&lt;/strong&gt;&lt;br&gt;
Here’s the truth about building production AI systems.&lt;/p&gt;

&lt;p&gt;The LLM call is the easy part. This is the hard part:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3 retries with exponential backoff and jitter, applied only to retryable errors&lt;/li&gt;
&lt;li&gt;A circuit breaker that trips after 5 consecutive failures and fails fast instead of cascading&lt;/li&gt;
&lt;li&gt;Per-model hard caps (100 Haiku calls/day, cost control is not optional)&lt;/li&gt;
&lt;li&gt;A catalog-driven fallback chain: Gemini 2.5 Flash primary, Claude Haiku fallback, model swap without touching application code&lt;/li&gt;
&lt;li&gt;Per-call cost and token logging so every LLM call is auditable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The stuff nobody sees until it breaks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The security decision I’m most glad I made&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every user’s Gmail token and email content is encrypted at rest. But not just encrypted, envelope-encrypted, per row, with two customer-managed KMS keys.&lt;/p&gt;

&lt;p&gt;The encryption context binds &lt;em&gt;&lt;code&gt;{user_id, table, row_id}&lt;/code&gt;&lt;/em&gt; to every operation. A leaked ciphertext can’t be replayed across rows or users.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This took extra days to implement correctly. It’s the kind of decision that feels over-engineered until the day you’re glad you made it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shipping for real&lt;/strong&gt;&lt;br&gt;
Briefed was designed and built solo. Backend, frontend, infrastructure, CI, and documentation. What surprised me wasn’t the complexity of any single piece; it was that every piece had to work together before any of it felt real.&lt;/p&gt;

&lt;p&gt;It runs in production on AWS Lambda with SnapStart, behind CloudFront and AWS WAF, at roughly $8–11 a month, including two customer-managed KMS keys.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; FastAPI · Python 3.11 · Pydantic v2 · SQLAlchemy 2.0 async · Alembic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI layer:&lt;/strong&gt; OpenRouter → Gemini 2.5 Flash + Claude Haiku fallback&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; React 18 · TypeScript · Vite&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data:&lt;/strong&gt; Supabase Postgres with per-row envelope encryption&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infra:&lt;/strong&gt; AWS Lambda · SQS · EventBridge Scheduler · CloudFront + WAF · Terraform&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I’d tell someone starting this today&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Document your decisions before you regret them.&lt;/strong&gt; Every time I revisited a choice, I asked: Why Lambda over Fargate? Why OpenRouter? Why two KMS keys instead of one? Without documenting them, I’d be reverse-engineering my own thinking three months later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chaos drills before launch, not after.&lt;/strong&gt; I drilled DLQ replay, KMS key revocation, secret rotation, and circuit breaker trips before calling the project done. Each drill uncovered at least one gap.&lt;/p&gt;

&lt;p&gt;Try it yourself&lt;br&gt;
🔗 Live demo: &lt;a href="https://d2vki955e8ckrc.cloudfront.net/" rel="noopener noreferrer"&gt;https://d2vki955e8ckrc.cloudfront.net/&lt;/a&gt;&lt;br&gt;
📦 Full source: &lt;a href="https://github.com/Kartik-Hirijaganer/Briefed" rel="noopener noreferrer"&gt;https://github.com/Kartik-Hirijaganer/Briefed&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What’s the gap between your LLM prototype and a production system?&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
