Description
When a CrewAI task fails and is retried — via max_retry_limit, exception handling, or external re-trigger — any @tool decorated function that already executed runs again. There's no mechanism to detect that a specific tool call already completed.
Steps to Reproduce
- Create a CrewAI agent with a @tool that calls an external API (payment, email, etc.)
- Have the tool execute successfully
- Simulate a failure after tool execution but before the agent receives confirmation
- Task retries
- The tool fires again — duplicate side effect
Expected behavior
A retry of the same logical tool call should return the original result without re-executing the side effect.
Screenshots/Code snippets
@tool
def send_payment(amount: float, recipient: str) -> str:
"""Send a payment to recipient"""
stripe.charge(amount, recipient) # fires twice on retry
return "payment sent"
Operating System
Windows 11
Python Version
3.10
crewAI Version
latest
crewAI Tools Version
lates
Virtual Environment
Venv
Evidence
See LangGraph Cloud issue #7417 for the same failure pattern documented in production: langchain-ai/langgraph#7417
Two independent parties confirmed the exact failure mode — in-memory dedup doesn't survive worker re-dispatch, and the fix requires durable external storage keyed before execution starts.
Possible Solution
Derive a stable request_id from tool arguments before execution, claim it in durable external storage, return the cached result on any retry with the same ID. The claim must happen outside the agent execution context so a retry on a new process hits the guard immediately.
Reference implementation: SafeAgent (pip install safeagent-exec-guard) — happy to contribute a CrewAI integration example.
Additional context
Same pattern documented in LangGraph Cloud issue #7417. The fix requires durable storage outside the framework, not in-memory or graph state.
Description
When a CrewAI task fails and is retried — via max_retry_limit, exception handling, or external re-trigger — any @tool decorated function that already executed runs again. There's no mechanism to detect that a specific tool call already completed.
Steps to Reproduce
Expected behavior
A retry of the same logical tool call should return the original result without re-executing the side effect.
Screenshots/Code snippets
@tool
def send_payment(amount: float, recipient: str) -> str:
"""Send a payment to recipient"""
stripe.charge(amount, recipient) # fires twice on retry
return "payment sent"
Operating System
Windows 11
Python Version
3.10
crewAI Version
latest
crewAI Tools Version
lates
Virtual Environment
Venv
Evidence
See LangGraph Cloud issue #7417 for the same failure pattern documented in production: langchain-ai/langgraph#7417
Two independent parties confirmed the exact failure mode — in-memory dedup doesn't survive worker re-dispatch, and the fix requires durable external storage keyed before execution starts.
Possible Solution
Derive a stable request_id from tool arguments before execution, claim it in durable external storage, return the cached result on any retry with the same ID. The claim must happen outside the agent execution context so a retry on a new process hits the guard immediately.
Reference implementation: SafeAgent (pip install safeagent-exec-guard) — happy to contribute a CrewAI integration example.
Additional context
Same pattern documented in LangGraph Cloud issue #7417. The fix requires durable storage outside the framework, not in-memory or graph state.