mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-07-27 17:49:22 +00:00
Three defects, two raised in review and one found while verifying them. 1. Learned-behaviour caches ignored the endpoint (CodeRabbit). Both _LEARNED_TOOLS_REASONING_EFFORT_CONFLICTS and, from #6656, _LEARNED_RESPONSES_ONLY_MODELS were keyed on the model name alone. Two instances using the same model string against api.openai.com and an OpenAI-compatible proxy shared the cache, so one endpoint's 400 silently degraded the other. Both are now keyed by (endpoint, model) via _model_cache_key(). 2. A recovered call still reported a failure (CodeRabbit). _handle_completion / _ahandle_completion log "OpenAI API call failed" and emit LLMCallFailedEvent for anything they catch, including the errors the retry wrappers exist to recover from. That printed a user-visible "LLM Error" panel for a call that then succeeded. Both handlers now re-raise early for errors _call_completions will retry, via _is_recoverable_completion_error() so the suppressing and retrying sides can't drift apart. 3. Dropping reasoning_effort didn't actually fix the request. Measured against the live endpoint while testing the above: gpt-5.6-sol tools, no reasoning_effort -> 400 (same error) gpt-5.6-sol tools, reasoning_effort=none -> OK gpt-5.5 tools, no reasoning_effort -> OK gpt-5.4 tools, no reasoning_effort -> OK gpt-5.6-* apply a server-side default, so omitting the parameter fails exactly like sending "high". The retry and the fast path now send an explicit "none" instead of removing the key. Without this the whole retry was a no-op for the family that prompted the fix. Also made error parsing tolerant of both body shapes the SDK produces: the live BadRequestError carries "message"/"param" at the top level of .body, while a synthetic one nests them under "error". The original code only read the nested form, so detection returned False against real API errors and the retry never fired. Shared _error_param_and_message() now handles both. Verified live -- real Agent + Task + Crew().kickoff() on gpt-5.6-sol with the fast path disabled so the runtime retry is exercised: AGENT RESULT: 391 tool calls : [(17, 23)] spurious LLMCallFailedEvent: 0 spurious failure ERROR logs: 0 Tests: 153 passed, 1 skipped in tests/llms/openai. New cases for endpoint-scoped learning on both caches, recoverable-error classification, and the forced-"none" behaviour with the measured API results recorded. Ruff + mypy clean.