Keep Your Agent Framework, Add Durable Execution
Add durable execution to LangGraph, CrewAI, ADK, or Strands agents with one package and a wrapper. See how Diagrid Catalyst keeps your framework intact.
Jani Janakiram, MSV
Guest Author
The post before this one ended with evidence that step-level traces and tool-call records enabled a platform team to explain what an agent did at two in the morning. Across the five posts in this series before this one, durability, cost control, identity, and observability all turned out to be platform properties. None of them belong to the framework the agent was written in.
An engineering lead reading that lands on one question. Does adopting the platform mean rewriting the agents that already work? The answer is no, and the change occurs at the import statement level, where Catalyst attaches to an existing agent via a package and a wrapper class. The graph, the crew, the tools, and the prompts stay exactly as they are.
Think of the arrangement as a device driver. An application maintains its own logic and API. The underlying driver handles everything that interacts with hardware, and replacing the driver never requires rewriting the application. Catalyst occupies that position for agents, where the framework maintains the reasoning loop and the runtime handles checkpointing, failure detection, and recovery.
What the Frameworks Already Do, and Where They Stop
The agent frameworks solved a genuine problem. LangGraph gave developers explicit graph orchestration with conditional routing. CrewAI gave them role-based crews and tool orchestration. Google ADK brought a hierarchical agent tree with tight Gemini integration, Pydantic AI brought typed structured outputs, and Strands brought a model-driven loop. None of that work needs to be undone.
Several of them also persist state. That is the part most teams point to when they argue they already have durability. But persistence and recovery are different jobs, and the harder of the two is failure detection.
Consider what happens when an agent running inside a Kubernetes pod dies at step four of a seven-step agent run. Someone has to notice the process is gone and decide that the run is recoverable rather than merely slow. It then has to find the persisted history and restart the run on a healthy instance, without a second instance picking up the same work. Diagrid's own reading of the framework landscape puts the gap in each one. LangGraph checkpoints save state but do not detect failures or recover automatically. CrewAI offers task replay without automatic failure detection. Google ADK uses event sourcing while leaving failure detection to the caller. Strands persist messages, and restoring a session restarts the event loop from the beginning.
Managed runtimes from the framework vendors narrow some of this, but they do not close it. A hosted service that stores graph state still leaves two questions open. Who notices the crash, and who decides the run is safe to resume? In most cases, the answer is an operator, or a supervisor processes what the team wrote itself.
A checkpoint is a save point that something still has to detect and reload. A retry does nothing for steps that have already been completed and have already cost money. What is missing across the category is the runtime that owns detection, resumption, and coordination across instances.
Catalyst supplies that runtime on top of Dapr Workflow, the CNCF project underneath the product. The integration packages exist so that developers new to Dapr never have to learn it first.
The Integration Mechanism
An expense-approval agent makes the mechanism concrete, and this example carries the rest of the chapter. The agent receives a submitted claim and fetches the current reimbursement policy. It then validates the attached receipt against that policy and posts the approved amount to the payments ledger. Three activities, one of which moves money.
In LangGraph, those three activities are nodes on a compiled graph. Making the agent durable with a Diagrid Catalyst package takes an install and a wrapper.
pip install "diagrid[langgraph]"
from diagrid.agent.langgraph import DaprWorkflowGraphRunner
graph = StateGraph(ExpenseState)
graph.add_node("fetch_policy", fetch_policy)
graph.add_node("validate_receipt", validate_receipt)
graph.add_node("post_reimbursement", post_reimbursement)
runner = DaprWorkflowGraphRunner(
graph=graph.compile(),
name="expense-approval",
)
runner.start()Behind the scenes, each node becomes a durable Dapr Workflow activity. The workflow engine records which activities are completed and stores their results. A crash after validate_receipt brings the agent back to post_reimbursement, with the receipt result replayed from the persisted history rather than recomputed. The recovery resumes from the last completed durable step, so an activity that was mid-execution when the process died runs again.
The same shape holds across the rest of the supported frameworks, with only the class name changing. CrewAI, Strands, OpenAI Agents, Google ADK, Pydantic AI, and the Claude Agent SDK all wrap in DaprWorkflowAgentRunner. The import comes from the matching module, such as diagrid.agent.crewai or diagrid.agent.adk. LangChain Deep Agents uses DaprWorkflowDeepAgentRunner, and each sub-agent in a supervisor pattern runs as its own independent workflow.
.NET teams get the same capability through a different package. The Microsoft Agent Framework path uses Diagrid.AI.Microsoft.AgentFramework, registers agents with AddDaprAgents(), and wraps each invocation through IDaprAgentInvoker with no explicit workflow registration in application code.
builder.Services.AddDaprAgents()
.WithAgent(sp => chatClient.CreateAIAgent(
instructions: "Approve expense claims against current policy.",
name: "ExpenseApprovalAgent",
tools: tools));Agents built without a framework take the workflow SDK directly. The developer defines the orchestration function and registers each tool call as an activity. That is more code than the wrapper path, and it gives complete control over where the activity boundaries fall. Teams with an unusual control loop or a framework for which Catalyst does not yet ship an integration land here.
Teams starting fresh still have a shorter path. Dapr Agents are durable by default with no wrapper at all, since state, memory, and failure recovery are configured on the agent itself. Diagrid makes the case for that route in the tiniest durable agent. It remains the most compact way to ship a production agent when there is no framework investment to protect.
The Boundary of the Guarantee
Durable execution recovers steps that have completed and persisted. It does not make a side effect safe to repeat. Say post_reimbursement writes to the payments ledger, and the process dies after the write lands but before the result is recorded. The activity runs again on recovery.
The third activity in the expense agent therefore takes an idempotency key derived from the claim identifier. The ledger rejects a duplicate key rather than posting twice. Activities that charge cards, post ledgers, or send mail need an idempotency key or an outbox pattern regardless of what the runtime does. The workflow engine handles orchestration, and the safety of every side effect stays with the application that wrote it.
One Provider Abstraction for Every LLM Call
The second integration point sits at the model boundary. In the Catalyst quickstarts, the LLM is not addressed by the provider SDK. It is addressed by component name through DaprChatClient(component_name="llm-provider"), and the component resolves to a YAML file.
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: llm-provider
spec:
type: conversation.openai
metadata:
- name: model
value: gpt-4.1-2025-04-14Changing conversation.openai to conversation.anthropic and updating the model value points the same agent at a different provider. The application never imports a vendor SDK, so the switch touches configuration rather than code.
The Dapr conversation API also carries prompt caching and PII obfuscation at that boundary. Both serve the cost argument and the audit argument from previous posts.
The First Thirty Minutes
Adoption decisions are made in the first half hour, before anyone reads the architecture page. Two pieces of the local experience carry that window.
The first is diagrid dev run, which runs the agent process on the developer's own machine while connecting it to the Catalyst workflow engine. Application code never leaves the laptop, and only the workflow state is stored in Catalyst. That separation is also what makes the crash demonstration work locally, since the engine tracking completed steps is not the process that just died.
The second is the Diagrid Dev Dashboard, a free and open source single binary. It lists workflow executions for every running application and shows the event history, including the input and output of each step. A developer can terminate or purge a stuck instance. Discovery is automatic for applications started with dapr run, Docker Compose, Testcontainers, and .NET Aspire AppHosts. The dashboard is scoped to local development, and Catalyst covers the same need for shared environments.
For .NET teams, the Catalyst Aspire integration closes the loop. A few lines in the AppHost provision the Catalyst project and configure the sidecars. The inner loop is defined in code rather than in YAML managed by hand.
Where the State Actually Lives
The last question an engineering lead asks before committing is where the workflow history is written. Catalyst offers managed pub/sub, key-value, and workflow stores per project for teams that want nothing to provision. Teams that need the data in their own accounts connect their own state stores, message brokers, and secret stores as components. Secrets can come from AWS Secrets Manager, Azure Key Vault, or HashiCorp Vault. Chapter 9 takes up what that choice means for sovereignty and lock-in.
For a platform team, the value of this arrangement is that the choice of framework is no longer a platform decision. Application teams pick LangGraph, CrewAI, or the Microsoft Agent Framework on the merits of the reasoning model. Behind all of them, the platform team runs one control plane, one identity model, and one set of workflow operations. Standardization moves down a layer, where it costs the application teams nothing.
Comparing the Adoption Paths
The choice between these paths depends on what the team has already built and which language ecosystem it lives in.
| Scenario | Path to take | What to weigh |
|---|---|---|
| An existing Python agent on LangGraph, CrewAI, ADK, Strands, OpenAI Agents, or Pydantic AI | Install the matching diagrid extra and wrap the agent | Agent logic is untouched, though activities with external side effects still need idempotency keys |
| A .NET codebase on the Microsoft Agent Framework | The Diagrid.AI.Microsoft.AgentFramework package | Keeps the familiar dependency injection experience. |
| A greenfield durable agent with no framework commitment | Dapr Agents | Simple and durable with no wrapper, at the cost of adopting a newer framework with a smaller community than LangGraph |
| An agent framework based on Catalyst for writing a workflow | Use the workflow SDK directly | Full control over activity boundaries, and more code to write and maintain than the wrapper path |
Most deployments end up mixing these paths. A platform team running Python agents on LangGraph and .NET services on the Microsoft Agent Framework uses two integration packages that connect to a single control plane. That combination is the practical test of whether a platform is framework-agnostic or only framework-tolerant.
In Summary
Adoption without migration is the design goal, and the mechanism is small enough to inspect. Install a package and wrap the agent. The framework's own execution now runs on Dapr Workflow durable execution, with failure detection and recovery owned by the runtime rather than by application code. Everything the framework was good at survives the change.
A single durable agent is the easy win. The next installment in this series focuses on the coordination between agents, where one delegates to another and either side can fail mid-handoff. That is the case in which identity, state, and governance all come together.