fix(openai): always use string content for tool messages#1878
fix(openai): always use string content for tool messages#1878notowen333 merged 4 commits intostrands-agents:mainfrom
Conversation
OpenAI-compatible endpoints (e.g., Kimi K2.5, vLLM, Ollama) only correctly parse string-format content for tool role messages. When content was sent as an array of content blocks, models would fail to parse the tool result and hallucinate the answer instead. Changed format_request_tool_message() to always join text/json content blocks into a single newline-separated string. Image and document blocks are preserved in array format so _split_tool_message_images() can still extract them into a separate user message. Closes #1696
a808007 to
4bdd547
Compare
|
Friendly ping — ensures OpenAI tool messages always use string |
notowen333
left a comment
There was a problem hiding this comment.
This is in the right direction, but has some logic polish and testing coverage issues.
Address review feedback from @notowen333: - Replace bulk text separation with adjacent-text-only merging to preserve the original order of interleaved text/image/document blocks - Add tests for mixed text+image, adjacent text merging, image-only, and text+document mixed content - Restore accidentally deleted test_split_tool_message_images_with_image function definition
notowen333
left a comment
There was a problem hiding this comment.
Just a small logical nit
The merging loop already joins adjacent text blocks with newlines, so in the all-text case there is always a single merged entry. Extract it directly instead of redundantly re-joining.
|
/strands review |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
As suggested in review — verify that an empty content list produces an empty string instead of crashing.
|
Thanks @notowen333 for the thorough review and approval! All feedback has been addressed:
Is there anything else needed for merge? |
|
Once the macOS unit tests pass, this will be merged! |
|
That's great to hear, thanks @notowen333! 🎉 Let me know if anything else is needed on my end. |
…nts#1878) Co-authored-by: giulio-leone <giulio.leone@users.noreply.github.com>
Summary
Fixes #1696
format_request_tool_message()sent tool resultcontentas an array of content blocks. While the OpenAI API accepts both formats, many OpenAI-compatible endpoints (Kimi K2.5, vLLM, SGLang, Ollama) only correctly parse string content for tool messages. Array format causes the model to ignore the tool result and hallucinate the answer.Changes
openai.py: Changedformat_request_tool_message()to always join text/json content blocks into a single newline-separated string. Image and document blocks are preserved in array format so_split_tool_message_images()can still extract them into a user message.test_openai.py: Updated multi-content test to expect string output. Added a dedicated regression test for the multi-content string join behavior.Root Cause
format_request_tool_message()produced array-format content:{"content": [{"text": "72°F", "type": "text"}], "role": "tool", ...}OpenAI-compatible endpoints expect string-format:
{"content": "72°F", "role": "tool", ...}Before / After
Before (array → model ignores result, hallucinates):
After (string → model uses result correctly):
Testing
All 72 OpenAI model tests pass.