<?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: Ricardo Cabral</title>
    <description>The latest articles on DEV Community by Ricardo Cabral (@ricardocabral).</description>
    <link>https://dev.to/ricardocabral</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%2F3753744%2Fb3d07f74-81c0-4603-abf3-2236b04a68a6.jpeg</url>
      <title>DEV Community: Ricardo Cabral</title>
      <link>https://dev.to/ricardocabral</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ricardocabral"/>
    <language>en</language>
    <item>
      <title>Introducing NornWeave: Giving AI Agents Their Own Email Inbox</title>
      <dc:creator>Ricardo Cabral</dc:creator>
      <pubDate>Wed, 04 Feb 2026 21:20:31 +0000</pubDate>
      <link>https://dev.to/ricardocabral/introducing-nornweave-giving-ai-agents-their-own-email-inbox-h9i</link>
      <guid>https://dev.to/ricardocabral/introducing-nornweave-giving-ai-agents-their-own-email-inbox-h9i</guid>
      <description>&lt;p&gt;I've been quietly building something for the past few months, and this week I decided to take the leap: &lt;strong&gt;NornWeave is now open source and being built in public.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're building AI agents that need to communicate via email, I'd love for you to check it out.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem I Kept Running Into
&lt;/h2&gt;

&lt;p&gt;Every time I tried to give an AI agent the ability to read and send email, I hit the same wall. Standard email APIs are built for transactional sending—fire off a welcome email, send a receipt, done. They're stateless by design.&lt;/p&gt;

&lt;p&gt;But agents need context. They need to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"What did the customer say three messages ago?"&lt;/li&gt;
&lt;li&gt;"Is this a new conversation or part of an ongoing thread?"&lt;/li&gt;
&lt;li&gt;"What's the actual content without all the HTML cruft and signature blocks?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I found myself writing the same threading logic, the same HTML-to-text conversion, the same webhook handlers over and over. So I built NornWeave to solve this once and share it with everyone facing the same challenge.&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;NornWeave&lt;/strong&gt; is an open-source, self-hosted &lt;strong&gt;Inbox-as-a-Service API&lt;/strong&gt; built specifically for AI agents. It adds two layers on top of raw email:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A Stateful Layer&lt;/strong&gt; — Virtual inboxes, conversation threads, full message history&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An Intelligent Layer&lt;/strong&gt; — HTML→Markdown parsing, automatic threading, semantic search&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your agents consume email through a clean REST API or directly via MCP (Model Context Protocol) instead of wrestling with raw webhooks and HTML soup.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Highlights
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📬 Virtual Inboxes for Your Agents
&lt;/h3&gt;

&lt;p&gt;Each agent gets its own email address. Create as many as you need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8000/v1/inboxes &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "Support Agent", "email_username": "support"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more sharing a single inbox and filtering by subject line. Each agent owns its conversations.&lt;/p&gt;

&lt;h3&gt;
  
  
  🧵 Automatic Threading
&lt;/h3&gt;

&lt;p&gt;NornWeave groups related messages into threads automatically using email headers (&lt;code&gt;In-Reply-To&lt;/code&gt;, &lt;code&gt;References&lt;/code&gt;, &lt;code&gt;Message-ID&lt;/code&gt;). When you fetch a thread, you get an LLM-friendly format:&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"th_123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"subject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Re: Pricing Question"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"messages"&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="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bob@gmail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"How much is it?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"assistant"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agent@myco.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$20/mo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;No more "parse the email chain and figure out who said what." It's already done.&lt;/p&gt;

&lt;h3&gt;
  
  
  🧹 Clean Content, No Cruft
&lt;/h3&gt;

&lt;p&gt;Incoming HTML emails get converted to clean Markdown. Signatures, disclaimers, and quoted reply blocks are stripped out. Your agent sees the actual message, not the noise.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔌 MCP Integration
&lt;/h3&gt;

&lt;p&gt;This is where it gets fun. NornWeave exposes an MCP server that plugs directly into Claude, Cursor, and other MCP-compatible clients:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;create_inbox&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Provision a new email address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;send_email&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Send an email (auto-converts Markdown→HTML)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;search_email&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Find relevant messages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wait_for_reply&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Block until a reply arrives (experimental)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Configure it in your MCP client:&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;"nornweave"&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;"nornweave-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;"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;"--api-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;"http://localhost:8000"&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;Now your agent can say "check my inbox" and actually do it.&lt;/p&gt;

&lt;h3&gt;
  
  
  📧 Works With Your Email Provider
&lt;/h3&gt;

&lt;p&gt;NornWeave supports the providers you're already using:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Sending&lt;/th&gt;
&lt;th&gt;Receiving&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mailgun&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS SES&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SendGrid&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resend&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Just configure your webhook URL, and NornWeave handles the rest.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture (A Little Norse Mythology)
&lt;/h2&gt;

&lt;p&gt;I named the components after Norse mythology because... honestly, I think it's fun, and the metaphor works surprisingly well.&lt;/p&gt;

&lt;p&gt;In Norse mythology, the &lt;strong&gt;Norns&lt;/strong&gt; (Urdr, Verdandi, and Skuld) dwell at the base of &lt;strong&gt;Yggdrasil&lt;/strong&gt;, the World Tree, weaving the tapestry of fate. NornWeave does something similar:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Module&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Storage Layer&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Urdr&lt;/strong&gt; (The Well)&lt;/td&gt;
&lt;td&gt;PostgreSQL/SQLite adapters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ingestion Engine&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Verdandi&lt;/strong&gt; (The Loom)&lt;/td&gt;
&lt;td&gt;Webhook processing, HTML→Markdown, threading&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outbound Layer&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Skuld&lt;/strong&gt; (The Prophecy)&lt;/td&gt;
&lt;td&gt;Email sending, rate limiting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API Gateway&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yggdrasil&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;FastAPI routes connecting everything&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MCP Resources&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Huginn&lt;/strong&gt; (Thought Raven)&lt;/td&gt;
&lt;td&gt;Read operations for AI agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MCP Tools&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Muninn&lt;/strong&gt; (Memory Raven)&lt;/td&gt;
&lt;td&gt;Write operations for AI agents&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Raw email streams in like water from the well. The Loom weaves them into coherent threads. Your agents drink from a clean, structured source.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;If you want to try it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone the repo&lt;/span&gt;
git clone https://github.com/DataCovey/nornweave.git
&lt;span class="nb"&gt;cd &lt;/span&gt;nornweave

&lt;span class="c"&gt;# Copy environment config&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env

&lt;span class="c"&gt;# Start with Docker&lt;/span&gt;
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;

&lt;span class="c"&gt;# Run migrations&lt;/span&gt;
docker compose &lt;span class="nb"&gt;exec &lt;/span&gt;api alembic upgrade &lt;span class="nb"&gt;head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or if you prefer local development with &lt;code&gt;uv&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make install-dev
make migrate
make dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full documentation is at &lt;a href="https://nornweave.datacovey.com/docs/" rel="noopener noreferrer"&gt;nornweave.datacovey.com&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;I'm building this in public now, so the roadmap is open. Here's what I'm thinking about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Better attachment handling&lt;/strong&gt; — PDFs and documents extracted to text for agent consumption&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scheduled sending&lt;/strong&gt; — "Reply tomorrow at 9am"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent handoff patterns&lt;/strong&gt; — Escalate from bot to human seamlessly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More vector search options&lt;/strong&gt; — Beyond pgvector&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But honestly? I want to hear what &lt;em&gt;you&lt;/em&gt; need. If you're building agents that deal with email, what's the hardest part? What would make your life easier? Care to help build it?&lt;/p&gt;

&lt;p&gt;NornWeave is licensed under Apache 2.0 and the repo is at &lt;a href="https://github.com/DataCovey/nornweave" rel="noopener noreferrer"&gt;github.com/DataCovey/nornweave&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Building in public is a bit scary, but also exciting. I've been heads-down on this for a while, and now I get to see if it resonates with other people solving similar problems.&lt;/p&gt;

&lt;p&gt;If you're giving AI agents the ability to communicate via email, I hope NornWeave saves you some of the headaches I ran into. And if it doesn't quite fit your needs yet—tell me why. I'm listening.&lt;/p&gt;

&lt;p&gt;Thanks for reading. Happy weaving. 🧶&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>ai</category>
      <category>python</category>
      <category>agents</category>
    </item>
  </channel>
</rss>
