Skip to content

fix: wire _extract_tool_name into codebase and add regression tests for #5244#5245

Open
devin-ai-integration[bot] wants to merge 2 commits intomainfrom
devin/1775170555-fix-tool-name-collision-regression
Open

fix: wire _extract_tool_name into codebase and add regression tests for #5244#5245
devin-ai-integration[bot] wants to merge 2 commits intomainfrom
devin/1775170555-fix-tool-name-collision-regression

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot commented Apr 2, 2026

Summary

Addresses issue #5244 by ensuring _extract_tool_name() and check_native_todo_completion() (restored in #5243) cannot be silently removed as "dead code" again. The key changes:

Production code (agent_executor.py):

  • New _resolve_original_tool() method — centralizes the duplicated tool-lookup logic (check _tool_name_mapping first, fall back to scanning original_tools) that was previously copy-pasted in two places.
  • _should_parallelize_native_tool_calls() now routes through _extract_tool_name() instead of the standalone extract_tool_call_info(). This is the critical wiring that makes _extract_tool_name a live call site rather than dead code.
  • _execute_single_native_tool_call() now calls _resolve_original_tool() instead of repeating the 10-line inline lookup, reducing duplication.

Tests (test_agent_executor.py): 20 new regression tests across 5 classes:

  • TestExtractToolName — all provider formats (OpenAI, Gemini, Anthropic, dict, unknown)
  • TestToolNameCollisionResolutionconvert_tools_to_openai_schema deduplication
  • TestResolveOriginalTool — mapping lookup, fallback, collision-renamed, unknown
  • TestToolErrorHandlingRegression — error injection, result_as_answer, max_usage_count with renamed tools
  • TestShouldParallelizeUsesExtractToolName — verifies _extract_tool_name is called and result_as_answer blocks parallelization

Review & Testing Checklist for Human

  • Behavioral equivalence of the _should_parallelize refactor: the old code used extract_tool_call_info() which returns (id, name, args) or None; the new code uses _extract_tool_name() which returns the name or "unknown". Verify these are equivalent for the parallelization decision (only the name was used before).
  • _resolve_original_tool edge cases: uses getattr(self, "_tool_name_mapping", None) defensively. Confirm this is safe across all code paths where the method might be called before _setup_native_tools() populates the mapping.
  • Manual smoke test: create a crew with two tools that have identical names (e.g., two "Search" tools) and verify that both tools execute correctly via native tool calling, collision suffixes are applied, and result_as_answer / max_usage_count work on the renamed variants.

Notes

  • All 20 new tests pass locally alongside the existing 79 tests in the file (99 total).
  • The uv.lock on main has a parse error (missing version field at line 1126); this is a pre-existing issue unrelated to this PR. Tests were run after regenerating the lock locally.

Link to Devin session: https://app.devin.ai/sessions/99afc2d07f9743aebb44a9c547f8db25


Note

Medium Risk
Touches native tool execution/parallelization decisions and tool lookup, which can affect runtime behavior for function-calling providers and collision-renamed tools; mitigated by extensive new regression tests.

Overview
Fixes native tool-call handling to avoid tool-name collisions and "unknown" name ambiguity by adding _resolve_original_tool() (centralized lookup via _tool_name_mapping with fallback), wiring _should_parallelize_native_tool_calls() through _extract_tool_name(), and updating _extract_tool_name() to return None for unrecognized formats.

Adds a large regression test suite covering tool-name extraction across provider formats, collision deduplication in convert_tools_to_openai_schema, original-tool resolution, native-tool error handling/usage limits/result-as-answer with collision-renamed tools, and ensuring parallelization logic calls _extract_tool_name().

Written by Cursor Bugbot for commit e40b29b. This will update automatically on new commits. Configure here.

#5244

- Add _resolve_original_tool() to centralize tool lookup via _tool_name_mapping
- Refactor _should_parallelize_native_tool_calls() to use _extract_tool_name()
- Refactor _execute_single_native_tool_call() to use _resolve_original_tool()
- Add 20 regression tests covering:
  - Tool name extraction (OpenAI, Gemini, Anthropic, dict formats)
  - Tool name collision resolution with _tool_name_mapping
  - _resolve_original_tool() with mapping, fallback, and unknown tools
  - Error handling with collision-renamed tools
  - result_as_answer and max_usage_count with renamed tools
  - _should_parallelize_native_tool_calls integration with _extract_tool_name

Closes #5244

Co-Authored-By: João <joao@crewai.com>
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

Prompt hidden (unlisted session)

@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Addresses Cursor Bugbot feedback: the string 'unknown' could collide
with a tool legitimately named 'unknown'. Now _extract_tool_name
returns None for unrecognised formats, and _should_parallelize checks
'is None' instead of '== "unknown"'.

Co-Authored-By: João <joao@crewai.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants