Problem
The ToolCallAdvisor is currently using a hardcoded check to detect tool calls:
isToolCall = chatResponse != null && chatResponse.hasToolCalls();
This approach works fine in some cases but it doesn't consider how certain models (like Anthropic or Bedrock) detect tool calls. For example models like Anthropic also check the "finish reason" (e.g., tool_use) along with tool calls to determine if a tool is being used. Because ToolCallAdvisor ignores this additional check it might miss important tool call detection when working with such models.
Fix
To solve this problem a ToolExecutionEligibilityPredicate has been added to ToolCallAdvisor. This predicate is used in the tool call detection process instead of the hardcoded hasToolCalls() check.
The new approach involves:
-
Adding the ToolExecutionEligibilityPredicate to the ToolCallAdvisor which defaults to a basic predicate (DefaultToolExecutionEligibilityPredicate).
-
Using this predicate in both the non streaming method (adviseCall) and the streaming method (handleToolCallRecursion).
-
Allowing customization: A toolExecutionEligibilityPredicate() method has been added to the Builder class so users can inject their own custom predicates if needed.
Why?
This change ensures that ToolCallAdvisor behaves consistently with how different models (like AnthropicChatModel) detect tool calls. By using a customizable predicate the tool call detection process can now be aligned with the specific behavior of various models making it more accurate and flexible.
Problem
The ToolCallAdvisor is currently using a hardcoded check to detect tool calls:
isToolCall = chatResponse != null && chatResponse.hasToolCalls();
This approach works fine in some cases but it doesn't consider how certain models (like Anthropic or Bedrock) detect tool calls. For example models like Anthropic also check the "finish reason" (e.g., tool_use) along with tool calls to determine if a tool is being used. Because ToolCallAdvisor ignores this additional check it might miss important tool call detection when working with such models.
Fix
To solve this problem a ToolExecutionEligibilityPredicate has been added to ToolCallAdvisor. This predicate is used in the tool call detection process instead of the hardcoded hasToolCalls() check.
The new approach involves:
Adding the ToolExecutionEligibilityPredicate to the ToolCallAdvisor which defaults to a basic predicate (DefaultToolExecutionEligibilityPredicate).
Using this predicate in both the non streaming method (adviseCall) and the streaming method (handleToolCallRecursion).
Allowing customization: A toolExecutionEligibilityPredicate() method has been added to the Builder class so users can inject their own custom predicates if needed.
Why?
This change ensures that ToolCallAdvisor behaves consistently with how different models (like AnthropicChatModel) detect tool calls. By using a customizable predicate the tool call detection process can now be aligned with the specific behavior of various models making it more accurate and flexible.