How Do You Make a CrewAI Agent Survive a Crash? A developer demonstrated a durable-execution wrapper for CrewAI agents that converts each tool call into a Dapr workflow activity, so a crashed or redeployed process resumes from the last completed call instead of restarting the task. The DaprWorkflowAgentRunner class replaces crew.kickoff() and persists tool inputs and outputs in the workflow history, with a fixed run ID preventing duplicate runs on restart. The approach still re-executes any activity that was mid-flight at crash time, so the developer recommends idempotency keys for tools that send email or write records. Run it under a durable workflow, so every tool call is saved as it completes. For CrewAI durable execution, that's one wrapper class around the agent you already have: DaprWorkflowAgentRunner turns each tool call into a Dapr workflow activity, and after a crash the run continues from the last completed one instead of starting over. What happens without it crew.kickoff runs the whole task inside your Python process. The tool results the agent has gathered and its place in the reasoning loop live in that process's memory. If a deploy or an OOM kill takes the process out halfway, the task starts again from the top, and every tool it already called gets called again. The change pip install "diagrid crewai " dapr init python from crewai import Agent, Task from crewai.tools import tool import dapr.ext.workflow as wf from diagrid.agent.crewai import DaprWorkflowAgentRunner @tool "Search the web for information" def search web query: str - str: return f"Results for: {query}" swap in your real search tool agent = Agent role="Research Analyst", goal="Analyse market trends", backstory="A careful analyst who cites sources", tools= search web , llm="openai/gpt-4o-mini", task = Task description="Research Q4 trends in durable execution for AI agents", expected output="Five bullet points with sources", agent=agent, runner = DaprWorkflowAgentRunner agent=agent, name="market-research", max iterations=10 runner.start run id = "q4-trends" client = wf.DaprWorkflowClient if client.get workflow state run id is None: out = runner.run sync task=task, session id=run id, workflow id=run id, timeout=600 print out.final response else: state = client.wait for workflow completion run id, timeout in seconds=600 print state.serialized output runner.shutdown dapr run --app-id market-research -- python crew app.py The Agent and Task are the same objects you'd hand to a Crew. The runner takes the place of kickoff . What gets saved Each tool call runs as a workflow activity. When it finishes, its input and output go into the workflow history in your state store. If the process dies, the Dapr runtime reactivates the workflow and replays it. Completed activities return their saved results, and execution continues from the first one that hadn't finished, with the agent's local state restored. The fixed run id is there so a restarted script finds the unfinished run and waits on it, rather than starting a second copy of the same task. Where it stops An activity that was mid-flight when the process died runs again from its start, because nothing recorded its result. For a search tool that costs you one extra search. For a tool that sends an email or writes a record, pass an idempotency key made from the run ID and the step, and let the receiving system drop the repeat. Takeaway If a CrewAI agent runs longer than the gap between your deploys, wrap it, give each run a stable ID, and make a list of which of its tools write to something. The CrewAI page has the rest: https://www.diagrid.io/learn/crewai-durable-execution https://www.diagrid.io/learn/crewai-durable-execution Give it a spin and lmk what breaks 👀