mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-08-10 16:32:28 +00:00
Two findings, and the first was a documented feature that never worked. `resolve_tool_failure_policy` consulted a crew, and the docs advertised crew as a scope, but `Crew` had no `tool_failure_policy` field at all -- and even with one it was unreachable, because `BaseAgent` defaulted the policy to `WARN` rather than `None`, so resolution always stopped at the agent. Crew-level configuration was silently ignored. Fixed by making "inherit" the default everywhere instead of baking `warn` into one layer: `Crew` gains the field, and `BaseAgent`/`LiteAgent` default to `None` like `Task` and `BaseTool` already did. The resolver owns the single fallback, so the chain is genuinely tool > task > agent > crew > warn and the effective default with nothing configured is still `warn`. Reading `agent.tool_failure_policy` now returns `None` (meaning "inherit") rather than `WARN`. The other: `StepExecutor` re-raised `ToolExecutionFailedError` from its outer handler, but the nested handler around the native-to-text tooling fallback still caught it and returned `StepResult(success=False)`. An agent whose LLM lacked native tool calling would therefore not abort under `raise`. That is the third distinct place this exception was being downgraded; it now re-raises there too. Testing: 8 further tests, 60 total, including the full precedence chain walked one level at a time and crew-scoped `raise`/`ignore` driven end-to-end through `kickoff()` rather than only through the resolver -- the gap that let the original crew bug pass review. Full suite matches baseline exactly at 377 pre-existing failures; mypy clean on every changed file. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ETacm2dMASfpMAYUiDu5YG