Files
langchain/libs/core/langchain_core
Sydney Runkle 1cf08abd92 feat(core)!: auto-assign UUID to BaseMessage.id at creation
Change the `id` field from `default=None` to
`default_factory=lambda: str(uuid.uuid4())` so every message receives a
stable, unique id from birth rather than being id-less until a reducer
or `add_messages` assigns one.

## Motivation

LangGraph's `DeltaChannel` stores pending writes (the raw message
objects) as serialized blobs **before** `update()` is called. Any id
assigned inside the reducer (e.g. a random UUID in
`_messages_delta_reducer`) only exists in the in-memory channel state;
it never reaches the stored write. On checkpoint replay the same
id-less message gets a fresh random UUID, so an eviction/update Command
that references the runtime-assigned id cannot match the replayed
message — both the original and the update land in state as separate
messages.

The root fix is here: if messages already carry a stable id when they
are first constructed (before any serialization boundary), the stored
write and any subsequent Command that updates that message by id will
always agree on the id, making `DeltaChannel` replay fully correct.

## Breaking change

`HumanMessage(content="x") == HumanMessage(content="x")` is now
`False` because auto-assigned UUIDs differ. Previously both had
`id=None` and compared equal. Code that relies on content-based message
equality must be updated (compare `.content` / `.model_dump(exclude={'id'})`
directly, or set an explicit shared `id`).

129 unit tests in langchain-core fail; all are due to this equality
change. Options the team can consider:
- Fix tests to use explicit ids or field-level comparisons
- Override `BaseMessage.__eq__` to exclude `id` (preserves backward
  compat for equality; DeltaChannel dedup uses id-keyed dict, not ==)
- Introduce a `__eq__` that only uses `id` when both sides have a
  non-None id, otherwise falls back to content comparison

Explicitly passing `id=None` still produces a message with `id=None`
(default_factory is not invoked for explicitly-supplied values).
2026-05-12 07:38:45 -07:00
..
2026-05-05 15:00:01 -04:00