<?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: MarouaB</title>
    <description>The latest articles on DEV Community by MarouaB (@marouaboud).</description>
    <link>https://dev.to/marouaboud</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4099228%2F50bbd1bf-67c6-4c18-b458-135df3871a04.png</url>
      <title>DEV Community: MarouaB</title>
      <link>https://dev.to/marouaboud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/marouaboud"/>
    <language>en</language>
    <item>
      <title>Exactly-Once: Your agent shouldn't pay the same invoice twice</title>
      <dc:creator>MarouaB</dc:creator>
      <pubDate>Sun, 30 Aug 2026 12:15:10 +0000</pubDate>
      <link>https://dev.to/marouaboud/exactly-once-your-agent-shouldnt-pay-the-same-invoice-twice-4jmd</link>
      <guid>https://dev.to/marouaboud/exactly-once-your-agent-shouldnt-pay-the-same-invoice-twice-4jmd</guid>
      <description>&lt;p&gt;&lt;em&gt;Wrap the payment. It runs once across retries, crashes, resumes, and replays.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;exactly-once&lt;/strong&gt; is a Python library that makes a side effect run a single time. Wrap the function that pays an invoice or sends an email, or submits a transaction and it executes once per key, then replays its stored result on every later call.&lt;/p&gt;

&lt;p&gt;Here is the whole integration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;exactly_once&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;once&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_key&lt;/span&gt;

&lt;span class="n"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqlite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;effects.db&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@once&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;inv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pay:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;inv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&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;pay_invoice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inv&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;payments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vendor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idempotency_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;current_key&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Call &lt;code&gt;pay_invoice(invoice)&lt;/code&gt; and it pays the vendor. Call it again from a retry, a resumed run, a replay, or a second worker and it returns the recorded result. The vendor is paid once.&lt;/p&gt;

&lt;h2&gt;
  
  
  The crash it's built for
&lt;/h2&gt;

&lt;p&gt;An agent pays an invoice. The transfer reaches the provider and succeeds. The process dies in the moment between the provider's &lt;code&gt;200 OK&lt;/code&gt; and the line that records the result. The agent restarts and reaches the same step again.&lt;/p&gt;

&lt;p&gt;exactly-once writes a record the instant the agent enters the call. &lt;code&gt;pay_invoice&lt;/code&gt; claims the key &lt;code&gt;pay:{invoice.id}&lt;/code&gt;, and the store marks it &lt;code&gt;IN_FLIGHT&lt;/code&gt;. When the result returns, the store marks it &lt;code&gt;COMMITTED&lt;/code&gt; and saves that result. After the crash the record reads &lt;code&gt;IN_FLIGHT&lt;/code&gt; with an empty result the library knows a payment started and holds no proof it finished.&lt;/p&gt;

&lt;p&gt;So it quarantines the key. The agent leaves that payment for a decision and moves on. You give &lt;code&gt;@once&lt;/code&gt; a prober that asks the payments API whether a transfer with that idempotency key exists: the library commits the key when the provider confirms the payment, and releases it when the provider confirms none. Until an answer arrives, the held payment stays in the ledger where you can see it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;in_flight&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# every payment awaiting a verdict
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How the guarantee holds
&lt;/h2&gt;

&lt;p&gt;Three states, one atomic operation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FRESH ──claim──▶ IN_FLIGHT ──commit──▶ COMMITTED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;claim(key)&lt;/code&gt; is an atomic check-and-set. The first caller to claim a key wins it and runs the effect; every other caller reads the record that already exists. The whole guarantee rests on that one operation, so it lives in the store you choose, and each store states the scope it enforces:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Store&lt;/th&gt;
&lt;th&gt;Guarantee&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;memory&lt;/td&gt;
&lt;td&gt;strong within one process&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQLite&lt;/td&gt;
&lt;td&gt;strong on one host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redis&lt;/td&gt;
&lt;td&gt;strong on a single instance; best-effort under failover&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Postgres &lt;code&gt;SERIALIZABLE&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;multi-writer correctness with transactional serialization&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The guarantee is one line: a guarded effect is entered &lt;strong&gt;at most once per key&lt;/strong&gt;. That is exactly-once &lt;em&gt;effect&lt;/em&gt; execution at most once, then replay and it holds across retries, concurrent workers, crashes, and replays. Passing &lt;code&gt;current_key()&lt;/code&gt; to the provider extends it end to end: your store keeps the agent from entering the call twice, and the provider's own idempotency key resolves a duplicate request to the one payment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key on the payment's identity
&lt;/h2&gt;

&lt;p&gt;The key is the identity of the effect. &lt;code&gt;pay:{invoice.id}&lt;/code&gt; binds the guard to the invoice, so the same invoice always resolves to the same guarded payment, and each separate invoice gets its own. Key on business identity an invoice id, an order id and the store dedupes every attempt that shares it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you get
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;@once&lt;/code&gt; decorator and a &lt;code&gt;with once(...)&lt;/code&gt; block sync and async, identical semantics.&lt;/li&gt;
&lt;li&gt;Stores for memory, SQLite, Redis, and Postgres, each with a documented atomicity and writer model.&lt;/li&gt;
&lt;li&gt;Quarantine on crash, with probers and optional worker leases for recovery.&lt;/li&gt;
&lt;li&gt;Passthrough of the provider's idempotency key through &lt;code&gt;current_key()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;An onchain adapter that keys a transaction on its nonce, so a resumed agent submits it once.&lt;/li&gt;
&lt;li&gt;Wrappers for LangGraph nodes and CrewAI tool runs, and any plain function, loop, or worker.&lt;/li&gt;
&lt;li&gt;An inspectable ledger: &lt;code&gt;store.list(state=...)&lt;/code&gt; feeds dashboards, audits, and reconciliation.&lt;/li&gt;
&lt;li&gt;Zero required dependencies, full typing, no LLM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Watch it hold a duplicate payment while an unguarded agent lets one through, side by side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python examples/crash_mid_payment.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then wrap the first irreversible call in your agent the payment whose duplicate would be hardest to explain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;exactly-once
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/swarmproof/exactly-once" rel="noopener noreferrer"&gt;github.com/swarmproof/exactly-once&lt;/a&gt; · MIT&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stripe.com/blog/idempotency" rel="noopener noreferrer"&gt;Stripe on idempotency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/powertools/python/latest/utilities/idempotency/" rel="noopener noreferrer"&gt;AWS Lambda Powertools idempotency utility&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bravenewgeek.com/you-cannot-have-exactly-once-delivery/" rel="noopener noreferrer"&gt;You cannot have exactly-once delivery&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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