One 90-minute lab · Python · Restate

Durable Agents with Restate

Kill a running agent, read Restate's journal, and count the model calls the replay paid for — then fix it with one line.

1 module · about 2 hoursFreeHands-on labs

Python · Docker · no prior Restate.

A one-module sample course on durable execution for AI agents with Restate. You kill a running agent on purpose, read the journal Restate kept, and count the model calls the replay paid for. Then you watch the same bug turn into a journal mismatch (RT0016), fix the replay with one line, and kill the fixed agent mid-call to find the window that line cannot close. Every number on these pages comes from a recorded run.

Your Learning Path

One self-contained module, about 90 minutes, to work through from top to bottom.

1

The Model Call You Pay For Twice — What Restate's journal keeps across a crash, what a replay re-runs, and why RT0016 is the same bug

A weather agent on Restate is killed in the middle of a durable pause. When it comes back, Restate replays the journal: the tool result is recorded, but a model call made outside ctx.run is not, so the replay pays for it again. Let the model answer differently and the replay fails with RT0016; let it stay different and every retry pays again until the invocation pauses. One line — ctx.run_typed around the model call — fixes the replay bug behind all three. The last experiment kills the fixed agent mid-call and finds the window that line cannot close: until Restate records a result, the call can run again.

Free90 minVideo lectureReading materialHands-on lab (local)

Who this course helps

  • Engineers building AI agents that call models and tools and must survive a process dying
  • Backend engineers evaluating durable execution who want to see what a replay actually re-runs
  • Python practitioners new to Restate who are comfortable with async/await and Docker

A durable agent whose crash costs you can predict and count

  • Explain what Restate's journal records for an invocation, and what a replay re-runs after the process dies
  • Predict the extra model calls a crash costs with and without ctx.run, and verify the count
  • Recognize a journal mismatch (RT0016) as replayed code diverging from the recorded journal

One weather agent, killed five ways. Every claim is checked against the journal Restate kept and a counter of model calls, not a diagram.

About This Course

An agent is a loop that asks a model what to do, does it, and asks again. Kill the process in the middle and something has to remember how far it got. Restate keeps a journal of each invocation: the input, every durable step and its result, every timer. When the process comes back, Restate replays the handler against that journal, skipping the steps it already has.

Restate can only replay what went through its context. A model call made with a plain HTTP request never reaches the journal, so the replay runs it again, and you pay for it again. If the model answers differently on replay, the handler diverges from the recorded journal and that attempt fails with a journal mismatch (RT0016). Restate retries it under the handler's retry policy: a later attempt may take the recorded path and complete, or the retries run out and the invocation pauses. This module shows all of that on a real Restate server, with the call counts, the journals and the error text, and ends on the rule that prevents it and the window a journaled call still leaves open.

The lab runs locally: a Restate server in Docker, a small Python agent, and a stub standing in for the model so every call can be counted.

Course design original to SciMigo. Pages link to and paraphrase Restate's documentation (docs.restate.dev and restate.dev, as fetched 2026-09-16); no documentation text is reproduced. Every observed number comes from SciMigo's demo repository, run against restate-server 1.7.10 with restate-sdk 1.0.5. Restate is developed by Restate GmbH; this course is independent and not endorsed by Restate.

Prerequisites

  • Comfortable Python, including async/await basics
  • Docker installed locally; no prior Restate

What You Will Learn

  • Explain what Restate's journal records for an invocation, and what a replay re-runs after the process dies
  • Predict the extra model calls a crash costs with and without ctx.run, and verify the count, including the call a journaled agent still repeats when it dies mid-call
  • Recognize a journal mismatch (RT0016) as replayed code diverging from the recorded journal, and trace how an unrecorded model decision causes it
  • Choose how to get a stuck invocation out: resume it on a journal-compatible fix, or kill it and restart it as new

Terminology Mapping

How classic concepts map to the terminology used in this course.

ClassicThis Course (Python)
Invocationone call of a handler, e.g. POST /WeatherAgent/run/send; has an invocation id (inv_…)
Durable stepawait ctx.run_typed("call model", ask_model, messages=messages)
Durable timerawait ctx.sleep(timedelta(seconds=6), name="rate-limit pause")
Journalthe sys_journal table (admin API /query) or the Restate UI's invocation timeline
Deterministic helpersctx.random(), ctx.uuid(), await ctx.time()
Invocation retry policyrestate.Service(..., invocation_retry_policy=InvocationRetryPolicy(max_attempts=20, on_max_attempts="pause"))

Module 1: The Model Call You Pay For Twice

What Restate's journal keeps across a crash, what a replay re-runs, and why RT0016 is the same bug. About 90 minutes.

Start module 1 — free
Course interest

Help shape what we build next

Tell us what you want to learn. This records your interest; it does not enroll you or promise a launch email.

We use your address to identify duplicate responses and your note to decide what to build next.