diff --git a/libs/partners/openai/langchain_openai/chat_models/base.py b/libs/partners/openai/langchain_openai/chat_models/base.py index 52dc6f9ba29..8fc35ea47d9 100644 --- a/libs/partners/openai/langchain_openai/chat_models/base.py +++ b/libs/partners/openai/langchain_openai/chat_models/base.py @@ -236,6 +236,26 @@ def _convert_dict_to_message(_dict: Mapping[str, Any]) -> BaseMessage: return ChatMessage(content=_dict.get("content", ""), role=role, id=id_) # type: ignore[arg-type] +def _sanitize_chat_completions_content(content: str | list[dict]) -> str | list[dict]: + """Sanitize content for chat/completions API. + + For list content, filters text blocks to only keep 'type' and 'text' keys. + """ + if isinstance(content, list): + sanitized = [] + for block in content: + if ( + isinstance(block, dict) + and block.get("type") == "text" + and "text" in block + ): + sanitized.append({"type": "text", "text": block["text"]}) + else: + sanitized.append(block) + return sanitized + return content + + def _format_message_content( content: Any, api: Literal["chat/completions", "responses"] = "chat/completions", @@ -368,7 +388,9 @@ def _convert_message_to_dict( elif isinstance(message, ToolMessage): message_dict["role"] = "tool" message_dict["tool_call_id"] = message.tool_call_id - + message_dict["content"] = _sanitize_chat_completions_content( + message_dict["content"] + ) supported_props = {"content", "role", "tool_call_id"} message_dict = {k: v for k, v in message_dict.items() if k in supported_props} else: diff --git a/libs/partners/openai/tests/unit_tests/chat_models/test_base.py b/libs/partners/openai/tests/unit_tests/chat_models/test_base.py index fe87233572a..2297f428363 100644 --- a/libs/partners/openai/tests/unit_tests/chat_models/test_base.py +++ b/libs/partners/openai/tests/unit_tests/chat_models/test_base.py @@ -1264,6 +1264,23 @@ def test__get_request_payload() -> None: assert payload == expected +def test_sanitize_chat_completions_text_blocks() -> None: + messages = [ + ToolMessage( + content=[{"type": "text", "text": "foo", "id": "lc_abc123"}], + tool_call_id="def456", + ), + ] + payload = ChatOpenAI(model="gpt-5.2")._get_request_payload(messages) + assert payload["messages"] == [ + { + "content": [{"type": "text", "text": "foo"}], + "role": "tool", + "tool_call_id": "def456", + } + ] + + def test_init_o1() -> None: with warnings.catch_warnings(record=True) as record: warnings.simplefilter("error") # Treat warnings as errors