Skip to content

Python: fix: ChatHistoryTruncationReducer orphans TOOL role messages#13608

Open
giulio-leone wants to merge 1 commit intomicrosoft:mainfrom
giulio-leone:fix/truncation-reducer-orphaned-tool-messages
Open

Python: fix: ChatHistoryTruncationReducer orphans TOOL role messages#13608
giulio-leone wants to merge 1 commit intomicrosoft:mainfrom
giulio-leone:fix/truncation-reducer-orphaned-tool-messages

Conversation

@giulio-leone
Copy link

Summary

Fixes #12708

ChatHistoryTruncationReducer.reduce() can orphan TOOL role messages by truncating the preceding assistant message that contains the tool_calls, causing OpenAI to reject the history with:

messages with role 'tool' must be a response to a preceding message with 'tool_calls'

Root Cause

locate_safe_reduction_index() uses contains_function_call_or_result() to detect tool-related messages during its backward scan. This function only checks msg.items for FunctionCallContent/FunctionResultContent instances.

However, TOOL role messages can contain only text content (no FunctionResultContent in items), which causes the backward scan to treat them as regular messages. The truncation point then lands between the tool_calls assistant message and its TOOL responses, orphaning the tool results.

Fix

Added AuthorRole.TOOL check to contains_function_call_or_result():

if msg.role == AuthorRole.TOOL:
    return True

This ensures any TOOL role message is recognized as part of a tool call/result pair, regardless of whether it has FunctionResultContent in its items.

Test

Added test_locate_safe_reduction_index_tool_role_without_function_result_content that verifies TOOL role messages with only text content are not separated from their tool call.

…without FunctionResultContent

The locate_safe_reduction_index backward scan only checked msg.items
for FunctionCallContent/FunctionResultContent to avoid splitting tool
call/result pairs. However, TOOL role messages that contain only text
content (no FunctionResultContent in items) were not recognized as
part of a tool pair, causing the truncation to split tool_calls from
their tool responses.

Fix: Include AuthorRole.TOOL check in contains_function_call_or_result
so that any TOOL role message is treated as part of a tool call/result
pair, regardless of its items content.

Fixes microsoft#12708
@giulio-leone giulio-leone requested a review from a team as a code owner February 28, 2026 17:55
@moonbox3 moonbox3 added the python Pull requests for the Python Semantic Kernel label Feb 28, 2026
@giulio-leone
Copy link
Author

Friendly ping — CI is green and this is ready for review. Happy to address any feedback. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Pull requests for the Python Semantic Kernel

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: Bug: ChatHistoryTruncationReducer cuts off TOOL_CALLS role message making the following TOOL role messages orphan in AgentThread history

2 participants