kmail.at
← learning

langchain · difficulty ◆◆

_convert_to_message and the Constructor-Envelope Wire Shape

Round-trip your serialized messages without the cryptic ValueError.

Messages are the currency of every chain. Learn the one wire shape that used to break the round-trip and how 1.4.1 finally fixes it.

2026-06-08 · 6 min read

$ pip install -U langchain-core>=1.4.1

What it does

_convert_to_message is an internal LangChain core helper that turns raw API output (like an LLM response chunk) into a proper Message object: AIMessage, HumanMessage, SystemMessage, or ToolMessage. In langchain-core==1.4.1 a bug was fixed where messages serialized with LangChain’s own Serializable envelope format (the id, type, data wire shape) could not be correctly round-tripped back through this function. Before, only plain dict shapes were accepted; now both the native wire format and LangChain’s own constructor envelope work.

Why it matters

Anyone building pipelines that serialize and deserialize messages is affected: caching LLM responses to a database, passing messages across process boundaries, or replaying conversation history. Before the fix, a message saved using LangChain’s own serialization would fail to load when replayed, causing cryptic ValueError or AttributeError exceptions. This was especially painful with tool-augmented chains where AIMessage.tool_calls and ToolMessage objects are interleaved. After the fix, the full round-trip works reliably.

Example

$ Envelope round-trip demo
Type:   AIMessage
Content: The capital of France is Paris.
ID:      msg-001

Tool calls after round-trip: [{'name': 'search', 'args': {'query': 'capital of France'}, 'id': 'call-abc123'}]

The envelope_payload dict with id, type=constructor and data is now handled directly by _convert_to_message.

$ Serialize then restore via to_dict
Hello, world!
weather

Use convert_to_messages([json.loads(serialized)]) and preserve tool_calls through the round-trip.

Common flags

--constructor-envelope
Accept the id/type/data Serializable wire shape when converting to a message
--plain-dict
Legacy plain-dict shapes continue to be accepted for backwards compatibility

History

Origin

langchain-core==1.4.1 (published June 5, 2026) carried the fix; the changelog landed on June 8 via GitHub PR #37456.

Evolution

Earlier versions only handled plain dict payloads. The 1.4.1 fix teaches _convert_to_message to recognize LangChain’s own Serializable constructor-envelope wire format so internally-produced serializations load cleanly.

Fun facts

Pros & cons

pros

  • + Reliable message persistence
  • + Tool calls survive serialization
  • + Backwards compatible with plain dicts

cons

  • − Internal API, not a public contract
  • − Requires upgrading core to >=1.4.1

Takeaways

  1. 1Use convert_to_messages to rebuild Message objects from serialized dicts.
  2. 2Upgrade langchain-core to >=1.4.1 to fix constructor-envelope round-tripping.
  3. 3Tool calls (AIMessage.tool_calls) now survive the round-trip cleanly.

Related commands

← all learning