Curriculum › Agentic Architecture & Orchestration · 27% of the exam

Session state and resumption

What you'll be able to do

  • Identify what must be externalized beyond conversation history for a resumable agent
  • Design idempotent steps so a resumed session can't double-execute a side effect
  • Use checkpoints to make resumption resume from the right point, not the start
  • Explain why conversation history alone is not durable state

What you’ll be able to do

  • Identify what must be externalized beyond conversation history for a resumable agent
  • Design idempotent steps so a resumed session can’t double-execute a side effect
  • Use checkpoints to make resumption resume from the right point, not the start
  • Explain why conversation history alone is not durable state

What you need to know

Conversation history is not the same as state

It's tempting to treat an agent's conversation transcript as the record of what's happened — after all, every tool call and result is right there in the messages. But a transcript is a record of what was said, not a durable, queryable record of what was done in the outside world. If a process crashes mid-run, the transcript up to that point tells you what the agent had decided to do, not reliably whether the last action actually completed.

A resumable architecture needs state that lives outside the model's context: a record, in a durable store, of which steps have started, which have completed, and what their results were — independent of whether the conversation that produced them is still in memory.

What has to be externalized

  • Task progress — which stage of a multi-step workflow the run is currently at, stored durably, not just implied by "wherever the transcript left off."
  • Side-effect status — whether a specific side-effecting action (an email sent, a payment charged, a record written) has already happened, keyed so it can be checked before retrying.
  • External resource handles — IDs or references to things created mid-run (a ticket ID, a file handle) that a resumed session needs to continue working with the same resource rather than creating a duplicate.

Idempotency is what makes resumption safe

before — resuming can double-send
def send_confirmation_email(order): email_client.send(order.customer_email, template="confirmation") # a crash right after this line, followed by a naive resume-from-start, # sends the email again
after — idempotency key prevents the double-fire
def send_confirmation_email(order): if already_sent(order.id, action="confirmation_email"): return email_client.send(order.customer_email, template="confirmation") mark_sent(order.id, action="confirmation_email")

The "before" version has no way of knowing, on resume, whether the email already went out — so a naive replay sends it again. The fix isn't a smarter retry policy; it's recording, durably, that the action happened, and checking that record before acting. This is the same idempotency-key pattern used anywhere a system needs "at-most-once" behavior over an unreliable process.

Checkpoint from the right point, not from zero

Resuming a crashed run by starting the whole task over is wasteful and, if any step has side effects, dangerous — it's exactly what produces double-fires. A well-architected resumable agent checkpoints its durable progress record after each meaningfully sized step, so resumption means "read the last checkpoint, continue from there," not "replay everything and hope idempotency checks catch the duplicates." Idempotency is the safety net; checkpointing is what keeps you from needing to rely on it for the entire run.

Key concept

Conversation history tells you what was said. Durable, externalized state tells you what was actually done. Resumption is only safe when side-effecting steps are idempotent and progress is checkpointed outside the model’s context.

When a scenario describes a duplicate action after a crash and restart, the fix is an idempotency key on the side-effecting step — not a change to how the agent decides what to do next.

Practice scenario

ScenarioAn order-processing agent charges a customer's card, then writes an order record, then sends a confirmation email. A process crash between the charge and the order-write causes the resumed run to charge the card a second time.
Work it through, then open this

The charge step has no idempotency key, so the resumed run has no way to know a charge already succeeded for this order. Fix it with an idempotency key tied to the order ID, passed to the payment provider — most payment APIs support this directly — so a retried charge request for the same order ID is recognized as a duplicate and not processed twice. Pair it with a durable checkpoint after each step so resumption picks up at the order-write stage rather than replaying the charge at all.

Build exercise — Add idempotency and checkpoints to a multi-step flow

Intermediate · 25 min

What you’ll learn

  • Distinguishing conversation history from durable state
  • Adding an idempotency key to a side-effecting step
  • Placing checkpoints so resumption starts from the right stage
  1. Take a multi-step flow with at least one side-effecting action and identify what currently tells the system whether that action already ran.

    • Why: If the answer is “nothing, we’d just run it again,” that’s the gap this lesson is about.
    • You should see: Either an existing idempotency mechanism, or a clear gap.
  2. Design an idempotency key for the side-effecting step, tied to something stable like an order ID or request ID.

    • Why: The key is what lets a resumed run recognize “this already happened” instead of re-executing blindly.
    • You should see: A specific key scheme, not a general intention to “add deduplication later.”
  3. Add a durable checkpoint after each stage and define what “resume” means in terms of the last checkpoint reached.

    • Why: Checkpointing is what prevents needing to rely on idempotency to survive a full replay from the start.
    • You should see: A resume path that starts from the last completed stage, not from stage one.

Exam traps

Treating the conversation transcript as the system’s durable state

A transcript records what was said, not a verified record of what was done — it can’t tell you reliably whether a crashed step completed.

Resuming a session by replaying from the start instead of from a checkpoint

Full replay without idempotency is exactly what produces duplicate side effects.

Building a side-effecting step with no idempotency key

Without a key, a resumed run has no way to distinguish “already done” from “needs doing.”

Assuming a crash mid-step means the step definitely didn’t complete

A crash can happen after the side effect fired but before the result was recorded — treating it as “definitely didn’t happen” is exactly how double-charges occur.

Storing progress only in memory, with nothing surviving a process restart

If progress isn’t externalized, a restart has nothing to resume from and no way to know what already happened.

Sources

Quick check

A subagent tasked only with summarizing a single document is invoked by forwarding the entire parent conversation history, including several unrelated prior tasks. What is the main risk?