Files
semantic-kernel/python/tests/unit
f034ed1d4c Python: fix: ChatHistoryTruncationReducer orphans TOOL role messages (#13608)
## 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()`:

```python
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.

---------

Co-authored-by: giulio-leone <[email protected]>
Co-authored-by: Evan Mattson <[email protected]>
Co-authored-by: Copilot <[email protected]>
2026-03-24 02:00:04 +00:00
..