<?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: Kumar Deepanshu</title>
    <description>The latest articles on DEV Community by Kumar Deepanshu (@kumard3).</description>
    <link>https://dev.to/kumard3</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%2F547736%2F36cfad3b-d1ea-4da8-bfcb-edb46455a374.jpeg</url>
      <title>DEV Community: Kumar Deepanshu</title>
      <link>https://dev.to/kumard3</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kumard3"/>
    <language>en</language>
    <item>
      <title>Durable Email Workflows with Temporal and Lumbox</title>
      <dc:creator>Kumar Deepanshu</dc:creator>
      <pubDate>Wed, 03 Jun 2026 18:00:34 +0000</pubDate>
      <link>https://dev.to/kumard3/durable-email-workflows-with-temporal-and-lumbox-60d</link>
      <guid>https://dev.to/kumard3/durable-email-workflows-with-temporal-and-lumbox-60d</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://lumbox.co/blog/temporal-durable-email-workflows-lumbox/" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Temporal solves the problem every async workflow eventually hits: what happens if the process dies mid-flow? For email, it's acute — you kick off a signup, the worker crashes, and now you have a Lumbox inbox waiting for an OTP that no one is listening for. Temporal activities make that durable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern: inbox creation as an activity
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;proxyActivities&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@temporalio/workflow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;activities&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./activities&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;createInbox&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;submitSignup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;waitForOtp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;submitOtp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;proxyActivities&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;activities&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;startToCloseTimeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;5 minutes&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;signupWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createInbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`signup-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;submitSignup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;service&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;inbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;waitForOtp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;submitOtp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&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;h2&gt;
  
  
  Long waits are fine
&lt;/h2&gt;

&lt;p&gt;Some verification flows send a link that expires in 24 hours. Temporal can hold a workflow open for days with no resource cost — when the worker comes back, the state picks up. Lumbox inboxes don't expire unless you tell them to, so a workflow that sleeps for a day and then checks the inbox works exactly as expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retries are automatic
&lt;/h2&gt;

&lt;p&gt;If &lt;code&gt;waitForOtp&lt;/code&gt; times out, Temporal retries per your activity policy. Lumbox's timeout is server-side — the HTTP call cleanly returns after the timeout window, and Temporal handles the rest. &lt;a href="https://lumbox.co" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>temporal</category>
      <category>durableexecution</category>
      <category>email</category>
      <category>workflows</category>
    </item>
    <item>
      <title>Mastra + Lumbox: TypeScript-First Agent Email in 30 Lines</title>
      <dc:creator>Kumar Deepanshu</dc:creator>
      <pubDate>Sun, 31 May 2026 18:00:38 +0000</pubDate>
      <link>https://dev.to/kumard3/mastra-lumbox-typescript-first-agent-email-in-30-lines-3n1k</link>
      <guid>https://dev.to/kumard3/mastra-lumbox-typescript-first-agent-email-in-30-lines-3n1k</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://lumbox.co/blog/mastra-email-tool-lumbox/" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Mastra filled a gap: a genuinely good TypeScript framework for agents. LangChain.js never felt like a first-class citizen; Mastra does. Here's how to bolt Lumbox on in about 30 lines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining email tools
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createTool&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@mastra/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Lumbox&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lumbox&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&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="nx"&gt;lumbox&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;Lumbox&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LUMBOX_API_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createInbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create_inbox&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Create a fresh email inbox for a specific task.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;purpose&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inbox&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;lumbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inboxes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;purpose&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;inboxId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;waitForOtp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wait_for_otp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Block until a verification OTP arrives.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;inboxId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&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;lumbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inboxes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForOtp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inboxId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;otp&lt;/span&gt; &lt;span class="p"&gt;};&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;h2&gt;
  
  
  The agent
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Agent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@mastra/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signupAgent&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;Agent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;signup_agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You sign users up for services. Use create_inbox, then wait_for_otp.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;anthropic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-opus-4-7&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createInbox&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;waitForOtp&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;h2&gt;
  
  
  Workflow orchestration
&lt;/h2&gt;

&lt;p&gt;Mastra's workflows give you checkpointed, resumable flows. A signup that stalls at the OTP step can be resumed hours later — Lumbox keeps the inbox alive and the OTP retrievable. &lt;a href="https://lumbox.co" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>mastra</category>
      <category>typescript</category>
      <category>aiagents</category>
      <category>email</category>
    </item>
    <item>
      <title>LlamaIndex + Lumbox: Treat Your Inbox as a Queryable Knowledge Source</title>
      <dc:creator>Kumar Deepanshu</dc:creator>
      <pubDate>Thu, 28 May 2026 18:00:43 +0000</pubDate>
      <link>https://dev.to/kumard3/llamaindex-lumbox-treat-your-inbox-as-a-queryable-knowledge-source-ejd</link>
      <guid>https://dev.to/kumard3/llamaindex-lumbox-treat-your-inbox-as-a-queryable-knowledge-source-ejd</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://lumbox.co/blog/llamaindex-email-tool-lumbox/" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;LlamaIndex made RAG something you can ship in an afternoon. Load docs into an index, attach an LLM, query. The gap most teams hit isn't the framework — it's finding a good data source. Your agent's own Lumbox inbox is a better source than most.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the inbox is good RAG fodder
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;It's high-signal, low-noise (it's already filtered by being sent to you).&lt;/li&gt;
&lt;li&gt;It's structured — sender, date, subject, thread ID are all fields.&lt;/li&gt;
&lt;li&gt;It grows organically as the agent does its work.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wiring it up
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;llama_index.core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Document&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;lumbox&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Lumbox&lt;/span&gt;

&lt;span class="n"&gt;lumbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Lumbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LUMBOX_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&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;load_inbox_as_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inbox_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="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lumbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inboxes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list_messages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inbox_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;inbox_id&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;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nc"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;from&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;subject&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;received_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thread_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;thread_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;load_inbox_as_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_inbox_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VectorStoreIndex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;query_engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_query_engine&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query_engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What did Acme say about the Q3 timeline?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Keep it fresh with webhooks
&lt;/h2&gt;

&lt;p&gt;Subscribe to Lumbox's &lt;code&gt;email.received&lt;/code&gt; webhook and incrementally upsert new messages into the index. No re-indexing, no polling. &lt;a href="https://lumbox.co" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>llamaindex</category>
      <category>rag</category>
      <category>python</category>
      <category>aiagents</category>
    </item>
    <item>
      <title>AX (Agent Experience): What Email APIs Should Look Like for Agents, Not Humans</title>
      <dc:creator>Kumar Deepanshu</dc:creator>
      <pubDate>Mon, 25 May 2026 18:00:38 +0000</pubDate>
      <link>https://dev.to/kumard3/ax-agent-experience-what-email-apis-should-look-like-for-agents-not-humans-1cgo</link>
      <guid>https://dev.to/kumard3/ax-agent-experience-what-email-apis-should-look-like-for-agents-not-humans-1cgo</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://lumbox.co/blog/ax-agent-experience-email-apis/" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Resend coined Agent Experience — AX — as the agent-first parallel to DX. The idea: APIs designed for humans reading docs on a Tuesday afternoon look different from APIs designed for LLMs calling tools in a tight loop. For email APIs, the gap is huge.&lt;/p&gt;

&lt;h2&gt;
  
  
  What bad AX looks like in email APIs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Polling required.&lt;/strong&gt; Agent burns tokens checking "any new mail?" every 5 seconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Raw MIME.&lt;/strong&gt; Agent has to parse multipart boundaries before it can read the body.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No first-class OTP field.&lt;/strong&gt; Agent runs regex on HTML to find the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opaque errors.&lt;/strong&gt; Agent gets &lt;code&gt;"500: internal error"&lt;/code&gt; with no recovery guidance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No idempotency.&lt;/strong&gt; Agent retries and sends duplicates.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What good AX looks like
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Long-poll endpoints.&lt;/strong&gt; One call, blocks until event or timeout.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured extraction.&lt;/strong&gt; OTP, links, attachments, category — all as first-class JSON fields.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typed errors.&lt;/strong&gt; &lt;code&gt;{"error": "timeout", "retryable": true, "wait_ms": 5000}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Idempotency keys.&lt;/strong&gt; Every mutating endpoint accepts one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP-native.&lt;/strong&gt; Tools are discoverable via a manifest, not scraped from HTML docs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Machine-readable docs.&lt;/strong&gt; OpenAPI + .well-known/agent-skills + llms.txt.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lumbox's take
&lt;/h2&gt;

&lt;p&gt;Every Lumbox endpoint was designed with a question: "how would a tool-calling LLM invoke this?" That's why &lt;code&gt;waitForOtp&lt;/code&gt; exists instead of a &lt;code&gt;listMessages&lt;/code&gt; + filter pattern. It's why responses include &lt;code&gt;otp&lt;/code&gt;, &lt;code&gt;links&lt;/code&gt;, and &lt;code&gt;category&lt;/code&gt; alongside the raw body. It's why we publish an MCP server on day one.&lt;/p&gt;

&lt;p&gt;AX isn't a checkbox. It's the shape of the whole API surface. &lt;a href="https://lumbox.co" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>agentexperience</category>
      <category>apidesign</category>
      <category>aiagents</category>
      <category>email</category>
    </item>
    <item>
      <title>Email as Memory for AI Agents</title>
      <dc:creator>Kumar Deepanshu</dc:creator>
      <pubDate>Fri, 22 May 2026 18:00:18 +0000</pubDate>
      <link>https://dev.to/kumard3/email-as-memory-for-ai-agents-850</link>
      <guid>https://dev.to/kumard3/email-as-memory-for-ai-agents-850</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://lumbox.co/blog/email-as-memory-ai-agents-lumbox/" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every agent framework now ships a memory module. Vectors, summaries, reflection loops, graph-based recall. They all miss the simplest and most reliable memory primitive on the internet: the email inbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  What email gets right as memory
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Append-only by default.&lt;/strong&gt; You don't lose history.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Addressable.&lt;/strong&gt; Every message has a stable ID and thread ID.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Searchable.&lt;/strong&gt; Full-text search is built in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured where it matters.&lt;/strong&gt; Sender, subject, date, attachments — all first-class fields.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pull model.&lt;/strong&gt; The agent reads when it needs, not streaming 24/7.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interoperable.&lt;/strong&gt; The rest of the world writes to the inbox without you asking.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The agent-memory pattern
&lt;/h2&gt;

&lt;p&gt;Give the agent an inbox. When the agent takes an action, send a record email to itself summarizing what it did. When it needs to recall, query the inbox. Lumbox's API gives you list, search, thread, and filter — the full memory surface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// agent acts&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;lumbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inboxes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inbox_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[memory] signed up for stripe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Account created with card ending 4242, verified at 14:22Z&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="c1"&gt;// later, agent recalls&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;memories&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;lumbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inboxes&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="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inbox_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[memory]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;since&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-05-01&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When it beats a vector store
&lt;/h2&gt;

&lt;p&gt;When you need &lt;em&gt;verbatim&lt;/em&gt; recall, temporal ordering, and cross-agent handoffs. Vector stores excel at fuzzy semantic similarity. Inboxes excel at "what did I do last Tuesday and who did I talk to about it."&lt;/p&gt;

&lt;h2&gt;
  
  
  Hybrid is fine
&lt;/h2&gt;

&lt;p&gt;Use the inbox for durable, addressable, audit-able memory. Use a vector store for similarity search over summaries. They complement each other. &lt;a href="https://lumbox.co" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>memory</category>
      <category>architecture</category>
      <category>aiagents</category>
      <category>email</category>
    </item>
    <item>
      <title>Pydantic AI + Lumbox: Type-Safe Email Tools for Agents</title>
      <dc:creator>Kumar Deepanshu</dc:creator>
      <pubDate>Tue, 19 May 2026 18:00:05 +0000</pubDate>
      <link>https://dev.to/kumard3/pydantic-ai-lumbox-type-safe-email-tools-for-agents-4ea5</link>
      <guid>https://dev.to/kumard3/pydantic-ai-lumbox-type-safe-email-tools-for-agents-4ea5</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://lumbox.co/blog/pydantic-ai-email-agent-lumbox/" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Pydantic AI leaned into the one thing Python agent frameworks were missing: type safety at the tool boundary. Define a tool as a function with Pydantic-validated inputs and outputs, and the framework handles the LLM-side schema and the runtime-side coercion. It's the right shape for production agents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lumbox as Pydantic AI tools
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic_ai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;lumbox&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Lumbox&lt;/span&gt;

&lt;span class="n"&gt;lumbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Lumbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LUMBOX_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Inbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;inbox_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OtpResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;received_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

&lt;span class="n"&gt;email_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic:claude-opus-4-7&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You handle email verification for signup flows.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@email_agent.tool_plain&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_inbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;purpose&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;Inbox&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Create a fresh inbox for a verification task.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;inbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lumbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inboxes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;purpose&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Inbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inbox_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;inbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;inbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@email_agent.tool_plain&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inbox_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;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;120&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;OtpResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Block until an OTP arrives in the inbox.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lumbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inboxes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inbox_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;OtpResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;received_at&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;received_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why type-safe tools matter for email
&lt;/h2&gt;

&lt;p&gt;When an agent calls &lt;code&gt;wait_for_otp&lt;/code&gt; with a timeout, you don't want a runtime error because the LLM passed &lt;code&gt;"60s"&lt;/code&gt; instead of &lt;code&gt;60&lt;/code&gt;. Pydantic coerces at the tool boundary. Same for inbox IDs — Pydantic ensures you always get a well-formed &lt;code&gt;inbox_id&lt;/code&gt;, never &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error handling
&lt;/h2&gt;

&lt;p&gt;If the OTP wait times out, the tool raises — Pydantic AI surfaces the typed error back to the agent, which can retry or escalate. Cleaner than parsing string error messages out of generic HTTP responses. &lt;a href="https://lumbox.co" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>pydanticai</category>
      <category>python</category>
      <category>typesafety</category>
      <category>aiagents</category>
    </item>
    <item>
      <title>Infraforge vs Lumbox: Deliverability-First vs Agent-Native Email</title>
      <dc:creator>Kumar Deepanshu</dc:creator>
      <pubDate>Sat, 16 May 2026 18:01:06 +0000</pubDate>
      <link>https://dev.to/kumard3/infraforge-vs-lumbox-deliverability-first-vs-agent-native-email-3keb</link>
      <guid>https://dev.to/kumard3/infraforge-vs-lumbox-deliverability-first-vs-agent-native-email-3keb</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://lumbox.co/blog/infraforge-vs-lumbox-agent-email/" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Infraforge appears on most "best AgentMail alternatives" lists because it targets the deliverability-first segment of email infrastructure. Lumbox targets the AI-agent-first segment. Both valid, different focuses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Infraforge's shape
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Managed outbound email infrastructure — warming pools, IP rotation, reputation management.&lt;/li&gt;
&lt;li&gt;Focused on cold outreach, transactional at scale, and B2B email workflows.&lt;/li&gt;
&lt;li&gt;Strong on deliverability tooling, domain authentication, and sender analytics.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lumbox's shape
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Agent-native — every agent gets its own inbox.&lt;/li&gt;
&lt;li&gt;OTP / magic-link / verification-link extraction built in.&lt;/li&gt;
&lt;li&gt;Long-poll endpoints so agents don't waste tokens polling.&lt;/li&gt;
&lt;li&gt;MCP server so Claude and Cursor can treat Lumbox as a tool out of the box.&lt;/li&gt;
&lt;li&gt;BYOS: bring your own SMTP/domain when you want full deliverability control.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When they overlap
&lt;/h2&gt;

&lt;p&gt;If you're running outbound-heavy agent workflows (cold outreach, mass notification), you need both: Lumbox for agent identity + inbox, and a deliverability layer (either Infraforge, SES with warm IPs, or Lumbox's BYOS mode with your own SMTP). The inbox side and the deliverability side are different problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  When they don't
&lt;/h2&gt;

&lt;p&gt;If you're running inbound-heavy flows — signups, verifications, agent-to-service interactions — Lumbox is the primitive. Deliverability is not the constraint; per-agent isolation and OTP extraction are. &lt;a href="https://lumbox.co" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>infraforge</category>
      <category>comparison</category>
      <category>emailapi</category>
      <category>deliverability</category>
    </item>
    <item>
      <title>Unipile vs Lumbox: Unified Messaging API vs Agent-First Email</title>
      <dc:creator>Kumar Deepanshu</dc:creator>
      <pubDate>Wed, 13 May 2026 18:01:12 +0000</pubDate>
      <link>https://dev.to/kumard3/unipile-vs-lumbox-unified-messaging-api-vs-agent-first-email-51n3</link>
      <guid>https://dev.to/kumard3/unipile-vs-lumbox-unified-messaging-api-vs-agent-first-email-51n3</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://lumbox.co/blog/unipile-vs-lumbox-unified-email/" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Unipile and Lumbox show up together in "best email API for AI agents" listicles, but they're solving different problems. Here's how to tell which you actually need.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Unipile does
&lt;/h2&gt;

&lt;p&gt;Unipile is a unified communications API. One SDK, many channels — LinkedIn, WhatsApp, Instagram, Telegram, Gmail, Outlook, IMAP. You authenticate &lt;em&gt;your users'&lt;/em&gt; accounts, then send and receive on their behalf across channels. Use case: building a multi-channel inbox product where end users connect their own accounts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Lumbox does
&lt;/h2&gt;

&lt;p&gt;Lumbox provisions &lt;em&gt;net-new&lt;/em&gt; email inboxes for AI agents. Every agent gets a fresh identity — not piggybacking on a user's Gmail, not sharing an account. Plus OTP extraction, long-poll, MCP server, and per-agent isolation. Use case: autonomous agents that need their own email to interact with the web.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pick Unipile if...
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You're building a product where end users connect their own accounts.&lt;/li&gt;
&lt;li&gt;You need multi-channel reach (LinkedIn + WhatsApp + email).&lt;/li&gt;
&lt;li&gt;You're building on behalf of humans, not agents.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pick Lumbox if...
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Your agent needs its own email identity, not a user's.&lt;/li&gt;
&lt;li&gt;You need OTP/verification-link extraction out of the box.&lt;/li&gt;
&lt;li&gt;You need long-poll endpoints so agents don't burn tokens polling.&lt;/li&gt;
&lt;li&gt;You need per-agent isolation and fast lifecycle (create/destroy in seconds).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Can you use both?
&lt;/h2&gt;

&lt;p&gt;Yes. A common pattern: use Unipile for the human-facing side of your product (LinkedIn DMs, WhatsApp replies) and Lumbox for the autonomous-agent side (signups, verifications, outbound to third-party APIs). Different problems, different tools. &lt;a href="https://lumbox.co" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>unipile</category>
      <category>comparison</category>
      <category>emailapi</category>
      <category>aiagents</category>
    </item>
    <item>
      <title>Give Your Replit Agent a Real Email Inbox with Lumbox</title>
      <dc:creator>Kumar Deepanshu</dc:creator>
      <pubDate>Sun, 10 May 2026 18:00:14 +0000</pubDate>
      <link>https://dev.to/kumard3/give-your-replit-agent-a-real-email-inbox-with-lumbox-56cb</link>
      <guid>https://dev.to/kumard3/give-your-replit-agent-a-real-email-inbox-with-lumbox-56cb</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://lumbox.co/blog/replit-agent-email-lumbox/" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Replit Agent makes a promise that sounds almost too good: describe the app you want, and it'll scaffold the code, deploy it, and wire up the third-party services. The reality is that 80% of those "third-party services" require email verification. If the agent is using your personal Gmail, you're one step away from a ban.&lt;/p&gt;

&lt;h2&gt;
  
  
  One inbox per agent session
&lt;/h2&gt;

&lt;p&gt;Before the Replit Agent run starts, provision a dedicated inbox:&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 https://api.lumbox.co/v1/inboxes &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-API-Key: &lt;/span&gt;&lt;span class="nv"&gt;$LUMBOX_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&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;'{"displayName":"replit-session"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expose the inbox address and &lt;code&gt;waitForOtp&lt;/code&gt; endpoint as tools in the agent's prompt. Every signup during the session uses the dedicated address, and every OTP arrives at the right inbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "deploy-then-verify" pattern
&lt;/h2&gt;

&lt;p&gt;Replit Agent's strength is end-to-end flows — code, deploy, test. When the deployed app asks the user to verify their email, route it through Lumbox so the agent can confirm deployability before handing off. If verification works, the app ships. If it doesn't, the agent fixes and retries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom domain for the agent identity
&lt;/h2&gt;

&lt;p&gt;For production-y Replit apps, point an MX record at Lumbox and give the agent a custom-domain inbox: &lt;code&gt;hello@myapp.com&lt;/code&gt;. The third-party services see a branded sender, and the agent keeps its own identity separate from any human's. &lt;a href="https://lumbox.co" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>replit</category>
      <category>aiagents</category>
      <category>email</category>
      <category>otp</category>
    </item>
    <item>
      <title>Give Your Sim Studio Agent an Email with Lumbox</title>
      <dc:creator>Kumar Deepanshu</dc:creator>
      <pubDate>Thu, 07 May 2026 18:00:35 +0000</pubDate>
      <link>https://dev.to/kumard3/give-your-sim-studio-agent-an-email-with-lumbox-ngl</link>
      <guid>https://dev.to/kumard3/give-your-sim-studio-agent-an-email-with-lumbox-ngl</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://lumbox.co/blog/sim-studio-agent-email-lumbox/" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Sim Studio's pitch is speed: build a working agent by dragging blocks instead of writing loops. It works — until your agent needs to sign up for anything. Visual builders are great at orchestrating steps but they can't see past the verification wall without an email primitive.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lumbox block
&lt;/h2&gt;

&lt;p&gt;Sim Studio exposes HTTP blocks for any REST API. Lumbox becomes three blocks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Create inbox&lt;/strong&gt; → POST &lt;code&gt;https://api.lumbox.co/v1/inboxes&lt;/code&gt; → output: &lt;code&gt;inbox_id&lt;/code&gt;, &lt;code&gt;address&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wait for OTP&lt;/strong&gt; → GET &lt;code&gt;https://api.lumbox.co/v1/inboxes/{id}/otp?timeout=120&lt;/code&gt; → output: &lt;code&gt;otp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send email&lt;/strong&gt; → POST &lt;code&gt;https://api.lumbox.co/v1/inboxes/{id}/send&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A complete signup flow in blocks
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Create inbox&lt;/em&gt; block at the top of the flow&lt;/li&gt;
&lt;li&gt;Feed &lt;code&gt;address&lt;/code&gt; into the &lt;em&gt;Browser automation&lt;/em&gt; block that submits the signup form&lt;/li&gt;
&lt;li&gt;After form submission, call &lt;em&gt;Wait for OTP&lt;/em&gt; with the &lt;code&gt;inbox_id&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Pipe the returned &lt;code&gt;otp&lt;/code&gt; into the next browser block to complete verification&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this beats shared Gmail in a visual tool
&lt;/h2&gt;

&lt;p&gt;Sim Studio flows are often deployed in parallel — multiple concurrent executions of the same template. Shared Gmail means multiple OTPs collide in one inbox. Lumbox gives each execution its own inbox automatically, with zero collision risk. &lt;a href="https://lumbox.co" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt; — grab a key, paste it in Sim Studio, ship.&lt;/p&gt;

</description>
      <category>simstudio</category>
      <category>nocode</category>
      <category>aiagents</category>
      <category>email</category>
    </item>
    <item>
      <title>LangGraph + Lumbox: Email as a State Transition</title>
      <dc:creator>Kumar Deepanshu</dc:creator>
      <pubDate>Mon, 04 May 2026 18:01:03 +0000</pubDate>
      <link>https://dev.to/kumard3/langgraph-lumbox-email-as-a-state-transition-2idp</link>
      <guid>https://dev.to/kumard3/langgraph-lumbox-email-as-a-state-transition-2idp</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://lumbox.co/blog/langgraph-email-state-machine-lumbox/" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;LangGraph pushed LangChain into a direction many people had been asking for: explicit state, explicit transitions, deterministic control flow. It's a better fit for production agents than a freeform ReAct loop. It's also a perfect fit for modeling email-driven workflows — because "wait for email" is literally a state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Email workflows as graphs
&lt;/h2&gt;

&lt;p&gt;Consider the most common agent task: sign up for a service, verify the email, complete the flow. Modeled as a graph:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;create_inbox&lt;/code&gt; → &lt;code&gt;submit_signup&lt;/code&gt; → &lt;code&gt;wait_for_otp&lt;/code&gt; → &lt;code&gt;submit_otp&lt;/code&gt; → &lt;code&gt;done&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each node is a concrete step with inputs and outputs. The edges are deterministic. If OTP times out, transition to &lt;code&gt;retry&lt;/code&gt; or &lt;code&gt;fail&lt;/code&gt;. This is exactly what LangGraph's &lt;code&gt;StateGraph&lt;/code&gt; was built for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wiring Lumbox as graph nodes
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langgraph.graph&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TypedDict&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;lumbox&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Lumbox&lt;/span&gt;

&lt;span class="n"&gt;lumbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Lumbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LUMBOX_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TypedDict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;inbox_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;target_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_inbox_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&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;AgentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;inbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lumbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inboxes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;display_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signup&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;inbox_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;address&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&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;submit_signup_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&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;AgentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# browser automation fills form with state["address"]
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wait_for_otp_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&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;AgentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lumbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inboxes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;inbox_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;otp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;otp&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;submit_otp_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AgentState&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;AgentState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# browser automation enters state["otp"]
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;

&lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StateGraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AgentState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;create_inbox&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;create_inbox_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;submit_signup&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;submit_signup_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wait_for_otp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wait_for_otp_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_node&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;submit_otp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;submit_otp_node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_entry_point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;create_inbox&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;create_inbox&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;submit_signup&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;submit_signup&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;wait_for_otp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wait_for_otp&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;submit_otp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_edge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;submit_otp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;END&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Durability
&lt;/h2&gt;

&lt;p&gt;LangGraph's checkpointing plays perfectly with Lumbox — the &lt;code&gt;wait_for_otp&lt;/code&gt; node can run, resume, or replay. If your process crashes mid-flow, the state is persisted and picks up where it left off. Lumbox inboxes persist server-side, so the OTP is still retrievable when you come back. &lt;a href="https://lumbox.co" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>langgraph</category>
      <category>python</category>
      <category>statemachine</category>
      <category>aiagents</category>
    </item>
    <item>
      <title>Email as Identity for AI Agents: The First-Class Primitive</title>
      <dc:creator>Kumar Deepanshu</dc:creator>
      <pubDate>Fri, 01 May 2026 18:00:35 +0000</pubDate>
      <link>https://dev.to/kumard3/email-as-identity-for-ai-agents-the-first-class-primitive-2b0e</link>
      <guid>https://dev.to/kumard3/email-as-identity-for-ai-agents-the-first-class-primitive-2b0e</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://lumbox.co/blog/email-as-identity-ai-agents-lumbox/" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every major web service treats email as the primary identity. Not your phone number, not your OAuth account, not your crypto wallet — your email. It's the recovery path, the login fallback, the ticket lookup, the receipt address. The web runs on email.&lt;/p&gt;

&lt;h2&gt;
  
  
  Humans solved this in 1996
&lt;/h2&gt;

&lt;p&gt;A human developer has Gmail. They use it to sign up for hundreds of services over the years. Each service builds a record tied to that address. When the human forgets a password, the service emails them. It works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agents are still stuck in 2004
&lt;/h2&gt;

&lt;p&gt;When an AI agent needs to interact with the internet — book a flight, subscribe to an API, claim a free credit — it has no email of its own. Builders force agents to share the developer's Gmail, which immediately breaks scaling (see: our Gmail-bans post), or hard-code an account that belongs to no one in particular.&lt;/p&gt;

&lt;h2&gt;
  
  
  Email as a first-class agent primitive
&lt;/h2&gt;

&lt;p&gt;Give every agent its own email address the moment it's instantiated. Not a shared pool. Not an alias. A real, deliverable inbox with a full identity footprint.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Signup:&lt;/strong&gt; the agent enters its own address. No collision with other agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recovery:&lt;/strong&gt; if the agent forgets a password, the reset email comes back to it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit:&lt;/strong&gt; every external system has a record of this specific agent acting on its own behalf — not hidden behind a human developer's identity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revocation:&lt;/strong&gt; kill the inbox, kill the identity. Clean shutdown.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The design principle
&lt;/h2&gt;

&lt;p&gt;An agent without an email is like a microservice without a URL. It may exist, but it can't be addressed by the rest of the web. Lumbox's thesis is simple: provisioning an email should be as fast and programmatic as provisioning a container. &lt;a href="https://lumbox.co" rel="noopener noreferrer"&gt;lumbox.co&lt;/a&gt; ships that primitive.&lt;/p&gt;

</description>
      <category>identity</category>
      <category>aiagents</category>
      <category>architecture</category>
      <category>email</category>
    </item>
  </channel>
</rss>
