Using Google ADK with Catalyst's Durable Execution
Google ADK can replay a stopped agent from its event history, but only if something outside the framework notices the crash and re-invokes it. See how pairing ADK with Diagrid Catalyst adds that missing piece, so agents recover automatically without re-running completed steps.
Your Google ADK agent has been running a multi-tool task for four minutes. It has called two tools successfully, written the results into the event history, and started on the third. Then the pod gets evicted. When it restarts, nothing happens.
The event history is still there. Every completed step is on record. ResumabilityConfig is set correctly. The invocation_id is valid. The agent just doesn't come back. It's waiting. Specifically, it's waiting for something outside the framework to notice the crash, retrieve the original invocation_id, and re-invoke.
That's the gap. Google ADK has the primitives for durability: event sourcing, immutable events, and replay-based resumption. What it doesn't have is the automation that turns those primitives into durable execution. Resumability in ADK is something the caller has to orchestrate, not something the framework does on your behalf.
This article walks through that gap, why it exists, and what it takes to close it. All this without abandoning ADK's event-sourced model.
What ADK gets right, and where the primitives stop
Give ADK its due. The event-sourced architecture is a genuinely good foundation for resumability. Every interaction, which includes user message, LLM response, tool call, tool result, and state change, is recorded as an immutable Event with a unique ID and an invocation_id that ties it to the overall run. Turn on ResumabilityConfig(is_resumable=True) and completed tool results are returned from the event history on replay. Function tools that have already succeeded are not re-executed. Only the failing tool re-runs. If you re-invoke with the original ID, the workflow picks up where it stopped.
That's real work, and it solves the state problem correctly. The state you need to resume is already captured.
But the state isn't the whole problem.

Fig 1: The state to resume is intact. What's missing is a system that notices and acts on it.
Failure detection isn't part of the framework. If an ADK agent crashes, nothing inside ADK notices. There's no supervisor. No watchdog. No lease that expires and triggers a takeover. The runtime doesn't know the difference between an agent that finished, an agent blocked on a slow tool call, and an agent whose process was killed. From ADK's perspective, all three look the same: an invocation that isn't producing new events.
The Google ADK documentation is explicit. The caller must detect workflow interruption and re-invoke. In practice, that means whoever built the calling system has to write and operate the monitoring, health-checking, and retry logic that watches every in-flight ADK invocation and decides when to resume. If that logic is missing or wrong, the agent sits in a failed state until someone reads the logs.
That same architectural gap introduces a secondary issue: scaling ADK across multiple replicas has no coordination layer built in. Without external locking, two runners can pick up the same task and produce duplicate work.
None of this is a bug in ADK. It's a scope choice. ADK gives you an agent framework with strong replay primitives and leaves the surrounding production plumbing for someone else to provide.
What durable execution adds that manual resumability doesn't
Two words that sound similar mean different things.
Replay is the ability to resume. It's the guarantee that if you feed a completed history back in, execution picks up correctly from the last completed step. ADK does this.
Durable execution is the guarantee that resumption actually happens, automatically, when it's needed. That requires something outside the process. Specifically, a runtime that owns the workflow's identity. One that notices when the process running it has stopped making progress. And one that picks up execution elsewhere, without a human or an external caller getting involved.
A workflow engine is what does this. Each tool call is modeled as an activity, which is a discrete unit of work with a durable input and a durable output. When an activity completes, the engine checkpoints the result before moving on. If the process running the workflow disappears, whether from a crash, eviction, or network partition, the runtime detects the interruption. It then reactivates the workflow on a healthy replica. The workflow resumes from the last completed activity. Anything that has already run isn't re-executed. Results are replayed from the log.

Fig 2: Replay makes resumption possible. Durable execution makes it automatic.
The mechanics of Dapr Workflows, like how the engine uses actors, placement, and reminders to make this durable under the hood, are covered in more depth in the durable agents article. The shape of the guarantee is what matters here. The caller doesn't have to notice a crash. The runtime does.
This isn't ADK versus Diagrid Catalyst. Diagrid Catalyst runs underneath ADK. The agent code, the tools, the prompts, the model configuration, and the event-sourced runtime stay exactly as they were.
The integration: what changes in the code
Almost nothing.
The ADK agent definition stays the same: the same LlmAgent, the same FunctionTool, the same Gemini model, the same instructions, the same tool functions. If you already have an ADK agent running, you don't rewrite it. Everything you know about how to author agents in ADK still applies.
What changes is one import and one wrapper. Instead of driving the agent with ADK's default Runner, you wrap it in DaprWorkflowAgentRunner:
from google.adk.agents import LlmAgent
from diagrid.agent.adk import DaprWorkflowAgentRunner
agent = LlmAgent(
name="event_planner",
model="gemini-2.5-flash",
tools=[...],
instruction="Plan an event by calling the three tools in sequence.",
)
runner = DaprWorkflowAgentRunner(
name="event-planner",
agent=agent,
max_iterations=10,
)That's the entire code change. Each tool call the agent makes at runtime is scheduled as a Dapr workflow activity. The workflow engine checkpoints the activity's input, output, and status after it runs.
The runtime behaviour is worth being precise about. Under DaprWorkflowAgentRunner, recovery does not go through ADK's invocation_id-based replay path. It goes through Dapr's own workflow log, the record of completed activities and their results. ADK's event history still gets written during normal execution (the agent is still an ADK agent). Still, if the process crashes, resumption is driven by Dapr's checkpoint, not by ADK's history.
That distinction is what removes the caller from the recovery loop. Nobody needs to detect the crash. Nobody needs to look up the invocation_id. The workflow engine notices that the lease on the workflow instance has stopped being renewed, reactivates the workflow on a healthy replica, and starts replaying from Dapr's log. Completed activities return their checkpointed results. The workflow arrives at the failed step and re-runs it, with the same input it had the first time.
Before we cover what the wrapper unlocks, one product note. Diagrid Catalyst is a reliable and secure platform for running agentic workloads in production, with the Dapr runtime, state stores, and message brokers managed for you. DaprWorkflowAgentRunner is the client-side wrapper in your code; Diagrid Catalyst is the platform it talks to.

Fig 3: Your ADK code stays the same. The runner is the seam.
For a full end-to-end walkthrough, including a crash test that shows Diagrid Catalyst resuming a workflow mid-execution without re-running completed steps, see the Diagrid ADK quickstart.
What the developer gets in return
Four things change once the wrapper is in place, and they connect directly back to the gaps the article opened with.
- Automatic failure recovery. No more waiting for a caller to notice a crash. When the process running the workflow disappears, the Dapr runtime detects the interruption via a durable reminder that fires when the activity doesn't complete and reactivates the workflow on a healthy replica. Recovery timing is measured in seconds to minutes, depending on the timeout configuration; not in however long it takes an on-call engineer to read a Slack alert.
- Single-instance execution across replicas. Dapr's placement service assigns each workflow instance to exactly one replica at a time via a distributed hash table of active workflow actors. Scaling the ADK app horizontally no longer risks two runners picking up the same task. If the replica hosting a workflow goes down, placement reassigns the workflow to another one, but never to two at once.
- Vendor-neutral, per-step tracing. ADK already emits OpenTelemetry traces for LLM calls and tool executions. Diagrid Catalyst adds traces for the durable execution lifecycle itself: activity checkpoints, workflow reactivation, and the replay path recovery takes, which ADK can't emit because it doesn't have those events. Combined with deterministic replay of any past workflow instance from persisted state, you can see not just what the agent did, but what recovery had to do to keep it going. When something fails halfway through a chain of tool calls, you can see exactly which one, with what input, producing what output.
- Framework-agnostic underneath. The same durability layer works with LangGraph, Strands, OpenAI Agents, Microsoft Agent Framework, Pydantic AI, and CrewAI. A team standardizing on Diagrid Catalyst doesn't have to standardize on a single agent framework. If part of your system uses ADK and another part uses LangGraph, both get the same durable execution guarantees, on the same infrastructure, with the same operational model.
Together, they shift the failure model from something your calling code manages to something the runtime handles, and the agent code doesn't change to get any of it.
Where to go next
ADK's event sourcing gives you the primitives for resumability. Diagrid Catalyst adds the automation that turns those primitives into durable execution in practice. Pairing them is a one-import, one-wrapper change to your code. Your agent definitions and tool logic stay put.
The next question is usually about coordination. Once individual ADK agents recover automatically, how do multiple agents talk to each other reliably across a longer-running system? What happens when one agent's output is another's input, and either can crash mid-conversation? That's where multi-agent orchestration patterns come in, and where durable execution stops being a nice-to-have and starts being what holds the system together.
To go deeper on the concepts behind durable agents, work through the Dapr University lesson on Dapr Agents. It covers how workflow engines model activities, how state is checkpointed, and how replay stays deterministic. It's the fastest way to build the mental model for what Diagrid Catalyst is doing underneath your framework of choice.