<?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: wang vince</title>
    <description>The latest articles on DEV Community by wang vince (@wang_vince_bcb7d8b8c1d33e).</description>
    <link>https://dev.to/wang_vince_bcb7d8b8c1d33e</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%2F2699642%2F94a19e66-2854-4495-9450-e00a2c6a58d9.png</url>
      <title>DEV Community: wang vince</title>
      <link>https://dev.to/wang_vince_bcb7d8b8c1d33e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wang_vince_bcb7d8b8c1d33e"/>
    <language>en</language>
    <item>
      <title>What should an AI agent do when a tool may have succeeded before a crash?</title>
      <dc:creator>wang vince</dc:creator>
      <pubDate>Mon, 21 Sep 2026 15:52:22 +0000</pubDate>
      <link>https://dev.to/wang_vince_bcb7d8b8c1d33e/what-should-an-ai-agent-do-when-a-tool-may-have-succeeded-before-a-crash-203p</link>
      <guid>https://dev.to/wang_vince_bcb7d8b8c1d33e/what-should-an-ai-agent-do-when-a-tool-may-have-succeeded-before-a-crash-203p</guid>
      <description>&lt;p&gt;The familiar agent loop is model → tool → result. It is a useful sketch, but it hides a failure window: the tool may change the outside world, then the agent process may die before it records the result.&lt;/p&gt;

&lt;p&gt;After a restart, “I did not receive a result” does not mean “nothing happened.” Repeating the call might duplicate a payment, an API request, or a file operation. Treating it as successful might skip work that never happened. A language model cannot recover this fact by reasoning over a transcript that does not contain it.&lt;/p&gt;

&lt;p&gt;I ran into this while building Kiso, an open-source TypeScript runtime for AI agents. I initially wanted to make a smaller, more token-efficient agent than Pi. Reading Pi closely made me realize that shaving a few tools or prompt tokens was less interesting than defining what an agent is allowed to treat as a fact after a crash.&lt;/p&gt;

&lt;h2&gt;
  
  
  Record the boundaries, not just the conversation
&lt;/h2&gt;

&lt;p&gt;Kiso writes an append-only event log. For a tool call that may have an effect, the relevant order is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;complete model response
    ↓
durable turn commit
    ↓
approval decision
    ↓
durable execution start
    ↓
tool runs and may change the outside world
    ↓
durable success or failure receipt
    ↓
result is shown to the model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The turn commit matters. A streamed model response can contain the beginning of a tool call and then fail or end incompatibly. Until the whole response has completed cleanly, that tool call is only a draft; it has no authority to change anything.&lt;/p&gt;

&lt;p&gt;The execution start matters for a different reason. It is written before the tool handler runs, so recovery can distinguish a call that never started from one whose outcome is now unknown.&lt;/p&gt;

&lt;h2&gt;
  
  
  What recovery can actually know
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Last durable fact&lt;/th&gt;
&lt;th&gt;What recovery knows&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;No committed turn&lt;/td&gt;
&lt;td&gt;The incomplete model output cannot authorize a tool call. It may be generated again.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Committed call, no execution start&lt;/td&gt;
&lt;td&gt;The tool handler has not run.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Execution start, no receipt&lt;/td&gt;
&lt;td&gt;The tool may or may not have changed the outside world. Its outcome is uncertain.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Success or failure receipt&lt;/td&gt;
&lt;td&gt;The recorded result can be reused; a confirmed success is not run again.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The third row is the hard one. Kiso stops there and asks a person to decide whether to rerun or abandon that execution. For a remote API, that person might first inspect the remote system. If the API offers idempotency keys or a way to query the result, those are better sources of evidence than a guess from the model.&lt;/p&gt;

&lt;p&gt;This does &lt;strong&gt;not&lt;/strong&gt; claim exactly-once effects in an external system. A local event log cannot prove what happened inside a bank or another service after the connection was lost. The useful guarantee is narrower: Kiso will not silently turn an unknown outcome into a success or automatically repeat an effect it cannot prove failed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this belongs in the runtime
&lt;/h2&gt;

&lt;p&gt;A normal “continue” prompt works when someone deliberately stops an agent and the host can tell the model what happened. It is weaker when the whole process disappears in the middle of an action. The new process needs durable execution evidence, not a plausible story assembled from the surviving conversation.&lt;/p&gt;

&lt;p&gt;Kiso includes a TUI coding agent, kiso-code, to exercise this design in a real tool loop. The repository has an end-to-end test that kills the agent process group during a shell call and resumes the same trajectory in a fresh process. The test checks that the interrupted execution is marked uncertain and requires a decision before the run continues.&lt;/p&gt;

&lt;p&gt;The design has costs. An unfinished model generation may need to be requested again, and an uncertain external action requires investigation. I think making those costs visible is preferable to hiding them behind an automatic retry.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/vincemakes/kiso" rel="noopener noreferrer"&gt;Kiso repository&lt;/a&gt; includes the runnable coding agent, &lt;a href="https://github.com/vincemakes/kiso/blob/main/docs/durability.md" rel="noopener noreferrer"&gt;durability contract&lt;/a&gt;, and the real &lt;code&gt;kill -9&lt;/code&gt; test. I would be interested in how other agent runtimes handle this window, especially for tools without idempotency support.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: This English article was drafted with AI assistance from my original Chinese writing. The technical claims were checked against the Kiso repository.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>architecture</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
