langchain - 💡(How to fix) Fix fix(openrouter): merge fragmented reasoning_details in streaming multi-turn conversations [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
langchain-ai/langchain#36399Fetched 2026-04-08 01:57:53
View on GitHub
Comments
1
Participants
2
Timeline
3
Reactions
0
Author
Timeline (top)
closed ×1commented ×1labeled ×1

Root Cause

During streaming, each chunk wraps its reasoning_details as a list in additional_kwargs. When chunks are merged via AIMessageChunk.__add__, LangChain's merge_lists concatenates these lists, fragmenting a single reasoning_details entry into many separate entries.

When _convert_message_to_dict() serializes the conversation history back to the OpenRouter API for the next turn, these fragmented entries are passed through as-is. The API rejects the malformed payload with BadRequestResponseError.

Non-streaming (invoke()) is unaffected — it returns complete entries in a single response.

Code Example

from langchain_openrouter import ChatOpenRouter
from langchain_core.messages import AIMessage, HumanMessage

model = ChatOpenRouter(
    model="anthropic/claude-sonnet-4-6",
    api_key="...",
    reasoning={"effort": "high", "summary": "auto"},
)

# Turn 1 — streaming
msgs = [HumanMessage(content="What is 2+2? Think step by step.")]
chunks = list(model.stream(msgs))
merged = chunks[0]
for c in chunks[1:]:
    merged = merged + c

# Inspect: reasoning_details is fragmented (e.g. 6 entries instead of 1)
details = merged.additional_kwargs.get("reasoning_details", [])
print(f"reasoning_details count: {len(details)}")  # Expected: 1, Actual: 6

# Turn 2 — fails
ai_msg = AIMessage(
    content=merged.content,
    additional_kwargs=merged.additional_kwargs,
    response_metadata=merged.response_metadata,
)
msgs.append(ai_msg)
msgs.append(HumanMessage(content="Now what is 3+3?"))

# This raises BadRequestResponseError
chunks2 = list(model.stream(msgs))
RAW_BUFFERClick to expand / collapse

Bug Description

When using ChatOpenRouter with streaming and reasoning enabled, multi-turn conversations fail with BadRequestResponseError on the second turn.

Root Cause

During streaming, each chunk wraps its reasoning_details as a list in additional_kwargs. When chunks are merged via AIMessageChunk.__add__, LangChain's merge_lists concatenates these lists, fragmenting a single reasoning_details entry into many separate entries.

When _convert_message_to_dict() serializes the conversation history back to the OpenRouter API for the next turn, these fragmented entries are passed through as-is. The API rejects the malformed payload with BadRequestResponseError.

Non-streaming (invoke()) is unaffected — it returns complete entries in a single response.

Reproduction

from langchain_openrouter import ChatOpenRouter
from langchain_core.messages import AIMessage, HumanMessage

model = ChatOpenRouter(
    model="anthropic/claude-sonnet-4-6",
    api_key="...",
    reasoning={"effort": "high", "summary": "auto"},
)

# Turn 1 — streaming
msgs = [HumanMessage(content="What is 2+2? Think step by step.")]
chunks = list(model.stream(msgs))
merged = chunks[0]
for c in chunks[1:]:
    merged = merged + c

# Inspect: reasoning_details is fragmented (e.g. 6 entries instead of 1)
details = merged.additional_kwargs.get("reasoning_details", [])
print(f"reasoning_details count: {len(details)}")  # Expected: 1, Actual: 6

# Turn 2 — fails
ai_msg = AIMessage(
    content=merged.content,
    additional_kwargs=merged.additional_kwargs,
    response_metadata=merged.response_metadata,
)
msgs.append(ai_msg)
msgs.append(HumanMessage(content="Now what is 3+3?"))

# This raises BadRequestResponseError
chunks2 = list(model.stream(msgs))

Expected Behavior

Multi-turn streaming conversations should work without errors. Fragmented reasoning_details entries should be merged back into single entries before serialization.

Environment

  • langchain-openrouter: 0.2.1
  • langchain-core: 1.2.21+
  • Python: 3.11 / 3.12

extent analysis

TL;DR

Modify the merge_lists function in LangChain to correctly handle the merging of reasoning_details entries.

Guidance

  • Identify the merge_lists function in LangChain and modify it to concatenate lists of reasoning_details into a single list with merged entries, rather than fragmenting them.
  • Inspect the additional_kwargs dictionary after merging chunks to verify that reasoning_details is correctly merged into a single entry.
  • Consider adding a custom serialization step before passing the conversation history to the OpenRouter API to ensure that reasoning_details is properly formatted.
  • Review the ChatOpenRouter implementation to ensure that it correctly handles the merged reasoning_details entries.

Example

def merge_lists(lists):
    # Custom implementation to merge reasoning_details entries
    merged_list = []
    for lst in lists:
        if lst:
            if merged_list:
                # Merge the current list with the existing merged list
                merged_list[0].update(lst[0])
            else:
                merged_list = lst
    return merged_list

Notes

The provided code snippet assumes that the reasoning_details entries can be merged by updating the first entry with the subsequent entries. This may need to be adjusted based on the actual structure and requirements of the reasoning_details data.

Recommendation

Apply a workaround by modifying the merge_lists function to correctly handle the merging of reasoning_details entries, as this will allow multi-turn streaming conversations to work without errors.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING