When using ChatOpenAI.with_structured_output with method='json_schema' and streaming, the response_metadata headers (e.g., x-request-id) are missing from the streamed AIMessageChunk objects, unlike plain streaming or AzureChatOpenAI.
In langchain-openai's structured output streaming implementation for method='json_schema', the final AIMessageChunk constructed from parsed tool call arguments does not copy response_metadata from the raw OpenAI API chunks, resulting in loss of headers.
1. Set up ChatOpenAI with streaming=True and include_response_headers=True.
2. Define a Pydantic model and call llm.with_structured_output(SimpleAnswer, method='json_schema').stream('Say hello').
3. Observe that the streamed chunks' response_metadata lacks headers, while plain streaming (without structured output) includes them.
Fixing Code Block
from typing import Any, Iterator
from langchain_openai import ChatOpenAI
from langchain_core.messages import AIMessageChunk
class ChatOpenAIWithHeaderPropagation(ChatOpenAI):
"""Hotfix: preserve response_metadata headers in streamed structured output."""
def _stream(self, messages, stop=None, run_manager=None, **kwargs):
last_headers = getattr(self, "_last_headers", None)
for chunk in super()._stream(messages, stop=stop, run_manager=run_manager, **kwargs):
if chunk.response_metadata and "headers" in chunk.response_metadata:
last_headers = chunk.response_metadata["headers"]
elif last_headers and chunk.response_metadata is not None:
chunk.response_metadata["headers"] = last_headers
self._last_headers = last_headers
yield chunk
This subclass overrides _stream to capture headers from any chunk that contains them and reattach them to subsequent chunks that lack them. This ensures that the metadata is present on all streamed chunks, including those produced by the structured output wrapper, because the wrapper ultimately calls this _stream method.
Edge Case Audit
This hotfix only works if the structured output wrapper does not strip metadata after the chunks are yielded. If headers are still missing, a library-level fix is required in the structured output parser to copy response_metadata from raw chunks to the final parsed AIMessage. The monkey patch may break with future versions or if the _stream signature changes. Rollback: remove the subclass and use original ChatOpenAI.