Some agent tasks finish in a second. Others run for minutes, hours, or days — a deep research job, a multi-step pipeline, a workflow that pauses to wait on a human. The trouble is that the way we usually call an agent — one request, wait for the response — falls apart the moment a task runs long.
Long-running AI workflows need a different foundation. This is Part 5 of the Designing AI-Native Applications series. Part 4 was about coordinating many agents; this post is about keeping a single long job alive when things crash, time out, or wait.
By the end you’ll know why request/response breaks, what durable execution does instead, and how to keep retries from doing real-world damage.
- A request/response call can’t survive a long job. One timeout or crash loses every step of progress.
- Durable execution fixes it: checkpoint after every step and resume from the last one instead of restarting. In 2026 it’s baseline infrastructure, not a nice-to-have.
- Anything that touches the outside world needs an idempotency key — or a replay will double-charge, double-send, or double-create.
Why Long-Running AI Workflows Outgrow Request/Response#
A normal web request has seconds to live. It runs, returns, and the server forgets everything. That’s fine for a quick answer, but an agent doing real work doesn’t fit in that box. It might call ten tools, wait on an API, or pause for a human to approve a step — far longer than any request timeout allows.
And when the process dies mid-task — a deploy, a crash, an out-of-memory kill — everything in memory goes with it.
Look at the left side. A single long call that crashes at step three doesn’t lose step three — it loses all three, because none of it was ever saved. The work wasn’t durable, so the crash erased it. Re-running from zero is slow, expensive, and on a paid model, you pay for every redone step. This is the wall every long-running agent hits.
Durable Execution: Resume, Don’t Restart#
The fix is durable execution: save the workflow’s state after each step, store it outside the process, and on restart replay that history to pick up exactly where it failed. The right side of the diagram shows it — each step is checkpointed, so a crash resumes at the next step instead of the first.
| Request / response | Durable workflow | |
|---|---|---|
| State on crash | Lost — restart from zero | Saved — resume from last step |
| Lifespan | Seconds (until timeout) | Minutes to days |
| Retry | Re-run everything | Re-run only the failed step |
| Side effects | Can duplicate on retry | Idempotency keys dedupe |
| Triggered by | A synchronous call | An event, queue, or schedule |
In code, the unit of work becomes a checkpointed step rather than one long function:
# Each step is saved when it returns; a crash resumes here, not at the top.
@workflow
def research(topic):
plan = step(make_plan, topic) # saved
docs = step(gather, plan) # crash here? plan is NOT re-run
return step(write_report, docs) # external writes carry idempotency keysThis isn’t niche anymore. Temporal raised at a $5B valuation in early 2026, and LangGraph, Pydantic AI, and the OpenAI Agents SDK have all made durable execution first-class. You’ll meet it either as a dedicated engine (Temporal, Inngest, Restate, AWS Step Functions, DBOS) or baked into a framework’s checkpointer — the build-versus-buy call is mostly about how much orchestration you want to own.
Checkpointing is the same idea you met in Part 3’s memory — saved state — applied to the run instead of the agent’s knowledge. (Use a real store for it: SQLite or Postgres in production, not an in-memory saver.)
Event-Driven, Not Call-and-Wait#
Once a workflow can outlive a single call, you stop waiting on it. Instead of holding a connection open, you trigger the workflow and let it run: a webhook fires it, a queue feeds it, a schedule wakes it, or a human approval resumes it. The caller gets an ID and moves on; the result arrives later.
This event-driven shape is what makes long jobs practical. A workflow can sleep for three days waiting on a signature and cost nothing while it waits, then continue the instant the event arrives.
It’s also how these systems scale — work piles into a queue and gets processed as capacity allows, rather than every request blocking a thread. The same shape powers scheduled agents: a nightly report or a recurring check that wakes on a cron trigger, runs, and goes back to sleep. When you’re ready to run one for real, deploying an agent to Cloud Run or Fly.io and the FastAPI deploy in the build series cover the hosting side.
Two choices decide whether an event-driven system behaves. Delivery semantics: most queues are at-least-once, so a message can arrive twice — the deeper reason every side effect needs an idempotency key, not just crash-replay. Coordination: with orchestration, a central workflow tells each step when to run; with choreography, each service reacts to events on its own. Orchestration is easier to trace and debug — the same reason the supervisor won in Part 4 — so prefer it unless you truly need the looser coupling.
Where Long-Running Workflows Break#
Durability solves the crash problem but introduces its own:
- Duplicate side effects. This is the big one. On replay, a step that sent an email or charged a card will do it again unless it carries an idempotency key — the safe-retry guarantee from Part 1, now mandatory.
- Non-deterministic replay. If a step’s logic isn’t reproducible (it reads the clock, calls a random API), replay can diverge from history. Keep side effects in steps and the orchestration deterministic.
- Zombie and stuck runs. A workflow waiting on an event that never comes sits forever. You need timeouts and dead-ends.
- State bloat. Histories grow; long or chatty workflows need pruning and size limits.
The rule for durable workflows: every step that changes the outside world must be safe to run twice. If a replay would send a second email, you have a bug, not a workflow.
When You Don’t Need This#
Durable execution is real infrastructure, and most requests don’t need it. If a task finishes in a second or two and writes nothing externally, a plain request/response is simpler, cheaper, and easier to reason about.
Reach for a durable, event-driven workflow when:
- The task runs long — beyond a request timeout, or it waits on people or slow systems.
- A crash mid-way would hurt — losing progress is expensive or unacceptable.
- It retries or writes to the world — so you need idempotency and resumability.
If none of those hold, don’t stand up a workflow engine for a function call — the same “simplest thing that works” rule from Part 1.
Ask how long the task lives and what it would cost to lose it halfway. If the answer is “seconds” and “nothing,” skip durability. If it’s “hours” and “a lot,” make it durable.
Quick Recap#
- Request/response dies on long jobs — a crash loses all progress.
- Durable execution checkpoints each step and resumes from the last, instead of restarting.
- Event-driven triggers (webhooks, queues, schedules) let workflows run and wait cheaply.
- Idempotency keys keep replays from duplicating real-world side effects.
- Skip it for short, side-effect-free tasks; use it when work runs long or must survive crashes.
Conclusion#
Long-running AI workflows are less about the agent and more about the runtime around it. Treat a long job as a series of checkpointed, idempotent steps you can replay — not one fragile call you hope finishes — and the hard problems (crashes, timeouts, retries, long waits) turn into routine recovery. In 2026 that durable, event-driven foundation has quietly become the default for any agent that does serious work.
What’s the longest-running job you’d want an agent to own — and what would it cost you if it died halfway? Tell me in the comments.
The architecture pattern under those event-driven triggers is event-driven architecture — decoupling through events, with a replayable log so a long job can resume after a crash.
Read next: Human-in-the-Loop Architecture — Part 6 of Designing AI-Native Applications, on pausing a workflow for human approval without grinding it to a halt.

