<?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: Piotr Wachowski</title>
    <description>The latest articles on DEV Community by Piotr Wachowski (@piotrwachowski).</description>
    <link>https://dev.to/piotrwachowski</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%2F3959978%2Fbba188ba-8761-4580-93fd-241376310e4a.png</url>
      <title>DEV Community: Piotr Wachowski</title>
      <link>https://dev.to/piotrwachowski</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/piotrwachowski"/>
    <language>en</language>
    <item>
      <title>Your AI Agent Just Crashed at Step 9 of 12. Here's How to Make That Not Matter.</title>
      <dc:creator>Piotr Wachowski</dc:creator>
      <pubDate>Sat, 30 May 2026 14:47:43 +0000</pubDate>
      <link>https://dev.to/piotrwachowski/your-ai-agent-just-crashed-at-step-9-of-12-heres-how-to-make-that-not-matter-1ijb</link>
      <guid>https://dev.to/piotrwachowski/your-ai-agent-just-crashed-at-step-9-of-12-heres-how-to-make-that-not-matter-1ijb</guid>
      <description>&lt;p&gt;&lt;em&gt;How to build crash-proof, resumable AI agents with Temporal's durable execution: a DeepAgents-style developer experience where killing the process doesn't kill the run.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;If you've built an AI agent that does real work (calling tools, delegating to sub-agents, looping until a task is done), you've probably felt this particular kind of pain:&lt;/p&gt;

&lt;p&gt;The agent is nine steps into a twelve-step job. It has searched the web, written three files, and delegated to a sub-agent. Then the process dies. A deploy, an OOM kill, a dropped network connection, a transient &lt;code&gt;500&lt;/code&gt; from your model provider. Whatever the cause, the result is the same: &lt;strong&gt;the entire run is gone.&lt;/strong&gt; All that state lived in process memory, and process memory just evaporated.&lt;/p&gt;

&lt;p&gt;Durability usually isn't the first thing you reach for when prototyping an agent, and for good reason: it's plumbing, not the fun part. But once an agent starts doing real work, it's worth taking seriously. This article is about a mental model that makes that durability almost free, &lt;strong&gt;an agent is not an object in memory, it's a durable workflow&lt;/strong&gt;, and how you can build agents that survive crashes, restarts, and infrastructure failures by running them on &lt;a href="https://temporal.io" rel="noopener noreferrer"&gt;Temporal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'll also show you a small open-source library I've been building, &lt;a href="https://github.com/piotrwachowski/durable-agents" rel="noopener noreferrer"&gt;&lt;code&gt;durable-agents&lt;/code&gt;&lt;/a&gt;, that packages this pattern so you don't have to write the plumbing yourself. But the ideas matter more than the library: you can apply them with raw Temporal, and you'll learn something even if you never touch my repo.&lt;/p&gt;




&lt;h2&gt;
  
  
  The core insight: an agent run is a workflow
&lt;/h2&gt;

&lt;p&gt;Here's the whole idea in one sentence:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Stop storing your agent's state in RAM. Store it in an append-only event&lt;br&gt;
history that survives any crash.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's exactly what Temporal's &lt;strong&gt;durable execution&lt;/strong&gt; gives you. Temporal is a system for running &lt;em&gt;workflows&lt;/em&gt;, functions whose every step is persisted to an event history as it happens. If the worker process dies, Temporal replays that history on a new worker and your function continues from precisely where it left off. No checkpoint code. No "resume from step N" logic. It just continues.&lt;/p&gt;

&lt;p&gt;Map an agent onto that model and everything clicks into place:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent concept&lt;/th&gt;
&lt;th&gt;Temporal primitive&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The agent run&lt;/td&gt;
&lt;td&gt;A &lt;strong&gt;workflow&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;An LLM call (plan / execute / synthesize)&lt;/td&gt;
&lt;td&gt;An &lt;strong&gt;activity&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A tool invocation&lt;/td&gt;
&lt;td&gt;An &lt;strong&gt;activity&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A sub-agent&lt;/td&gt;
&lt;td&gt;A &lt;strong&gt;child workflow&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The agent's memory&lt;/td&gt;
&lt;td&gt;The workflow's &lt;strong&gt;event history&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The split between &lt;em&gt;workflow&lt;/em&gt; and &lt;em&gt;activity&lt;/em&gt; is the key. Workflow code is &lt;strong&gt;deterministic&lt;/strong&gt;: it's the orchestration logic, and it must replay identically every time. Anything non-deterministic or with side effects (an HTTP call to OpenAI, reading a file, running a tool) happens in an &lt;strong&gt;activity&lt;/strong&gt;. Activities are retried automatically on failure, and their results are recorded in history so they never re-run after they've succeeded.&lt;/p&gt;

&lt;p&gt;This is why a crash is survivable: when the worker comes back, Temporal replays the workflow up to the last recorded event and resumes. The plan you already generated, the three files you already wrote, the sub-agent results you already collected, all still there. Only the &lt;em&gt;in-flight&lt;/em&gt; step retries.&lt;/p&gt;




&lt;h2&gt;
  
  
  What this looks like in practice
&lt;/h2&gt;

&lt;p&gt;Let me make it concrete. Here's a complete research agent. The thing to notice is how little ceremony there is, and that the durability is invisible. You write ordinary &lt;code&gt;async&lt;/code&gt; Python.&lt;/p&gt;

&lt;p&gt;First, a tool. A tool is just an &lt;code&gt;async&lt;/code&gt; function with a decorator; the JSON schema the model needs is generated from your type hints and docstring:&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;durable_agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;

&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;web_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&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;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Search the web for information about the given query.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# ... call your search API ...
&lt;/span&gt;    &lt;span class="k"&gt;return&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;Results for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: ...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the agent. This lives on the &lt;strong&gt;worker&lt;/strong&gt;, the process that does the work:&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;durable_agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;create_durable_agent&lt;/span&gt;

&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_durable_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai:gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;web_search&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 are a helpful research assistant.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;task_queue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;research-agent&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="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_worker&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;   &lt;span class="c1"&gt;# blocks; serves the task queue
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And triggering it. Here's a detail worth pausing on: &lt;strong&gt;the client is thin&lt;/strong&gt;. It imports no tools, knows no schemas. It only knows a task-queue name:&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;durable_agents&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DurableAgentClient&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DurableAgentClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_queue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;research-agent&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="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&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 is quantum entanglement?&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;p&gt;The agent definition (model, tools, prompt, sub-agents) lives &lt;strong&gt;only on the worker&lt;/strong&gt;. The worker &lt;em&gt;is&lt;/em&gt; the agent. A web handler, a cron job, or another service can trigger an agent without depending on its implementation, and your tool code and credentials never leave the worker. Tool schemas are never sent over the wire.&lt;/p&gt;




&lt;h2&gt;
  
  
  The detail that changes how you think about agents: two retry layers
&lt;/h2&gt;

&lt;p&gt;This is the part that reframes a problem every agent builder hits. Agents fail in two completely different ways, and they need two completely different recovery strategies:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Infrastructure faults.&lt;/strong&gt; The network blips. The model API returns a &lt;code&gt;503&lt;/code&gt;. The worker is redeployed. These are transient and &lt;em&gt;not the agent's fault&lt;/em&gt;. The right response is: retry the exact same operation, with backoff, until it works. Temporal does this for you, automatically, at the activity level. You write zero retry code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Semantic faults.&lt;/strong&gt; The model returns malformed JSON. It calls a tool that doesn't exist. A tool raises an exception. Retrying the identical call won't help: the &lt;em&gt;input&lt;/em&gt; needs to change. The right response is to feed the failure back to the model as an &lt;strong&gt;observation&lt;/strong&gt; and let it correct itself on the next step.&lt;/p&gt;

&lt;p&gt;It's tempting to collapse these into one mechanism, usually a &lt;code&gt;try/except&lt;/code&gt; that crashes the loop on bad output. Keeping them separate is what makes the loop resilient:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A tool that raises does &lt;strong&gt;not&lt;/strong&gt; crash the agent. The exception is caught and returned to the model as &lt;code&gt;ERROR calling tool 'x': ...&lt;/code&gt;, an observation it can reason about.&lt;/li&gt;
&lt;li&gt;Malformed model output (often just a truncated response) becomes an empty result the model sees and retries differently.&lt;/li&gt;
&lt;li&gt;Meanwhile, underneath all of that, Temporal is transparently retrying any activity that failed for &lt;em&gt;infrastructure&lt;/em&gt; reasons.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bad model output is &lt;strong&gt;data, not an exception.&lt;/strong&gt; That single reframing makes agents dramatically more robust.&lt;/p&gt;




&lt;h2&gt;
  
  
  Watching it work: a multi-agent pipeline
&lt;/h2&gt;

&lt;p&gt;To show this with something more interesting than a single agent, here's the example I use: a &lt;strong&gt;Code Archaeologist&lt;/strong&gt;, a four-agent pipeline that modernises legacy Python on disk.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;strong&gt;orchestrator&lt;/strong&gt; plans the work and delegates each phase. It has no tools of its own; it only coordinates.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;archaeologist&lt;/strong&gt; reads the legacy code and reports what's wrong (missing type hints, &lt;code&gt;%&lt;/code&gt;-formatting, global state).&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;modernizer&lt;/strong&gt; rewrites the files: annotations, f-strings, &lt;code&gt;pathlib&lt;/code&gt;,
context managers.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;documenter&lt;/strong&gt; adds docstrings and writes a &lt;code&gt;README&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each sub-agent runs as a &lt;strong&gt;child workflow&lt;/strong&gt; on its own task queue, with its own isolated, independently-visible history. The orchestrator delegates by handing each child a self-contained task that carries forward the previous stage's findings; the child never inherits the parent's full message history, so context stays clean and scoped.&lt;/p&gt;

&lt;p&gt;In the Temporal Web UI you can &lt;em&gt;see&lt;/em&gt; the whole thing: the orchestrator spawning three child workflows in sequence, each one's plan-then-execute loop, every LLM call and tool call as a discrete, inspectable event. The question "what did my agent actually do?" has a precise, visual answer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmernav4igk5lzs1o56rg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmernav4igk5lzs1o56rg.png" alt="Temporal Web UI: the orchestrator and its three sub-agent child workflows" width="800" height="81"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The orchestrator plus its three child workflows: archaeologist, modernizer, and documenter, each running as its own Temporal workflow.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The money shot: I killed the worker, and the agent didn't care
&lt;/h2&gt;

&lt;p&gt;Here's the test that proves the whole thesis.&lt;/p&gt;

&lt;p&gt;I started the pipeline and let it run. The three sub-agents finished their work: the analysis, the rewritten files, the documentation were all done and recorded. Then, while the orchestrator was on its &lt;strong&gt;final&lt;/strong&gt; step (&lt;code&gt;synthesize_result&lt;/code&gt;, writing up the summary), &lt;strong&gt;I killed the worker.&lt;/strong&gt; &lt;code&gt;Ctrl-C&lt;/code&gt;. Dead process.&lt;/p&gt;

&lt;p&gt;In an in-memory framework, that's a total loss. Three agents' worth of completed work, gone. Start over.&lt;/p&gt;

&lt;p&gt;Here's what actually happened:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcd2fuckvh37dk0l6ytp9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcd2fuckvh37dk0l6ytp9.png" alt="Temporal UI showing the synthesize_result activity retrying after the worker was killed" width="799" height="341"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Worker killed mid-run: &lt;code&gt;synthesize_result&lt;/code&gt; sits in &lt;code&gt;Attempt 2 / ∞&lt;/code&gt;, while the plan and all three child workflows stay Completed. Nothing re-ran.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;synthesize_result&lt;/code&gt; activity went into a retry loop, patiently attempting against an empty task queue. Crucially, &lt;strong&gt;none of the completed work re-ran.&lt;/strong&gt; The plan, the three child workflows, all still marked completed in history. Only the single in-flight activity was pending.&lt;/p&gt;

&lt;p&gt;Then I restarted the worker. The instant it reconnected:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqr7dmj08cxnvl6kyeq7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqr7dmj08cxnvl6kyeq7.png" alt="Temporal UI showing the workflow completed successfully after the worker restarted" width="800" height="372"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The instant the worker reconnected, the pending activity finished and the workflow completed. Total wall-clock includes the dead time, but no work was lost or repeated.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It picked up the pending activity, completed it, and the client that submitted the task got its result as if nothing had happened, no work lost, none repeated.&lt;/p&gt;

&lt;p&gt;That's durable execution. The agent's state lived in Temporal's event history, not in the process I killed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where to start, and what's honest about this
&lt;/h2&gt;

&lt;p&gt;If you want to try the pattern, you don't need my library: you can wire LLM calls and tools as Temporal activities directly. The &lt;a href="https://docs.temporal.io" rel="noopener noreferrer"&gt;Temporal docs&lt;/a&gt; are excellent, and the workflow / activity split is the only concept you really need.&lt;/p&gt;

&lt;p&gt;If you want the DeepAgents-style ergonomics (&lt;code&gt;@tool&lt;/code&gt;, &lt;code&gt;@skill&lt;/code&gt;, sub-agent&lt;br&gt;
delegation, the plan-then-execute loop) on top of that durability,&lt;br&gt;
&lt;a href="https://github.com/piotrwachowski/durable-agents" rel="noopener noreferrer"&gt;&lt;code&gt;durable-agents&lt;/code&gt;&lt;/a&gt; packages it.&lt;br&gt;
Let me be straight about its status: it's &lt;strong&gt;alpha&lt;/strong&gt;, and currently OpenAI-only.&lt;br&gt;
The core loop, sub-agents, skills, and filesystem tools work today; things like persistent memory, human-in-the-loop, and more model providers are on the roadmap. I'm sharing it mainly because the &lt;em&gt;idea&lt;/em&gt; is worth sharing; the code is just one small, runnable example of wiring it up, and you might wire it differently.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;This is the first piece in a series. Durable execution is the foundation, but it's also what &lt;em&gt;unlocks&lt;/em&gt; the features that are genuinely hard to do well in memory-bound agents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Human-in-the-loop&lt;/strong&gt;: pausing an agent for days waiting on human approval, with &lt;em&gt;no process held open&lt;/em&gt;, by parking the workflow on a Temporal signal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent memory&lt;/strong&gt;: facts and preferences that outlive a single run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deeper observability&lt;/strong&gt;: tracing and streaming on top of the event history.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll write each of those up as I build them.&lt;/p&gt;

&lt;p&gt;If the "agent is a workflow" framing was useful, I'd love to hear how you're thinking about durability in your own agents, and if you want to poke at the code, the repo and the runnable crash-test are linked below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/piotrwachowski/durable-agents" rel="noopener noreferrer"&gt;https://github.com/piotrwachowski/durable-agents&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Reproduce the crash test:&lt;/strong&gt; see the &lt;em&gt;Durability test&lt;/em&gt; (crash the worker and watch it resume) section in &lt;code&gt;docs/09-examples.md&lt;/code&gt;.&lt;/p&gt;

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