mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-07-12 10:25:14 +00:00
fix(agent): recognize OpenAI Responses API tool-call shape in native tool loop
is_tool_call_list() and extract_tool_call_info() only recognized
Chat-Completions-style ({"function": {...}}), Anthropic-style
({"name", "input"}), and Gemini-style tool-call shapes. The Responses
API's function_call output items are flat dicts shaped
{"id", "name", "arguments"} with no nested "function" key and no
"input" key, so they matched none of the checks.
This caused is_tool_call_list() to misclassify a genuine tool call as
a plain text answer, so the native tool loop returned the raw
tool-call list as the agent's final output instead of executing the
tool. Even after recognizing the shape, extract_tool_call_info() would
have passed an empty arguments dict, since it only read "input" for
the dict fallback.
Verified against LLM(api="responses") with tools attached: the agent
now correctly executes the tool with the parsed arguments instead of
returning the unexecuted tool-call JSON as its answer.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1228,7 +1228,14 @@ def extract_tool_call_info(
|
||||
)
|
||||
func_info = tool_call.get("function", {})
|
||||
func_name = func_info.get("name", "") or tool_call.get("name", "")
|
||||
func_args = func_info.get("arguments") or tool_call.get("input") or {}
|
||||
# OpenAI Responses API function_call items are flat dicts using
|
||||
# "arguments" (not "input") with no nested "function" key.
|
||||
func_args = (
|
||||
func_info.get("arguments")
|
||||
or tool_call.get("arguments")
|
||||
or tool_call.get("input")
|
||||
or {}
|
||||
)
|
||||
return call_id, sanitize_tool_name(func_name), func_args
|
||||
return None
|
||||
|
||||
@@ -1260,6 +1267,13 @@ def is_tool_call_list(response: list[Any]) -> bool:
|
||||
# Bedrock-style
|
||||
if isinstance(first_item, dict) and "name" in first_item and "input" in first_item:
|
||||
return True
|
||||
# OpenAI Responses API-style (flat dict, no nested "function" key)
|
||||
if (
|
||||
isinstance(first_item, dict)
|
||||
and "name" in first_item
|
||||
and "arguments" in first_item
|
||||
):
|
||||
return True
|
||||
# Gemini-style
|
||||
if hasattr(first_item, "function_call") and first_item.function_call:
|
||||
return True
|
||||
|
||||
Reference in New Issue
Block a user