Skip to content

fix(langgraph): Make Overwrite survive JSON roundtrips#8127

Open
Sydney Runkle (sydney-runkle) wants to merge 1 commit into
mainfrom
fix/overwrite-json-roundtrip
Open

fix(langgraph): Make Overwrite survive JSON roundtrips#8127
Sydney Runkle (sydney-runkle) wants to merge 1 commit into
mainfrom
fix/overwrite-json-roundtrip

Conversation

@sydney-runkle

@sydney-runkle Sydney Runkle (sydney-runkle) commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Add a type: Literal["__overwrite__"] discriminator field to Overwrite and teach _get_overwrite() to recognise the dataclass-erased {"value": ..., "type": "__overwrite__"} form. This keeps Overwrite semantics intact across JSON boundaries that strip dataclass types (e.g. langgraph-api.serde.json_dumpb), without requiring callers to switch to the dict sentinel form.

This was an oversight in the initial Overwrite implementation, it should be json serializable out of the box.

Fixing langchain-ai/deepagents#3789

@sydney-runkle Sydney Runkle (sydney-runkle) changed the title Make Overwrite survive JSON roundtrips Make Overwrite survive JSON roundtrips Jun 17, 2026
@sydney-runkle Sydney Runkle (sydney-runkle) changed the title Make Overwrite survive JSON roundtrips fix(langgraph): Make Overwrite survive JSON roundtrips Jun 17, 2026

@open-swe open-swe Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open SWE Review found 1 potential issue.

Open in WebView Open SWE trace

Comment on lines +49 to +50
if value.get("type") == OVERWRITE and "value" in value:
return True, value["value"]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Extra-key dicts bypass reducers

This now treats any channel update dict with type == "__overwrite__" and a value key as an overwrite, even when the dict has additional application data. For example, a BinaryOperatorAggregate(dict, operator.or_) update of {"type": "__overwrite__", "value": 2, "b": 3} now replaces the channel with 2 instead of passing the dict to the reducer/merging it. The JSON-erased Overwrite shape produced by the new dataclass field is exactly {"value": ..., "type": "__overwrite__"}, so the discriminator check should be constrained to that exact shape to avoid hijacking legitimate dict values that happen to carry the same reserved-looking fields.

(Refers to lines 49-50)


Your feedback helps Open SWE learn. React with 👍 or 👎 to tell us if this review comment was useful.

Suggested change
if value.get("type") == OVERWRITE and "value" in value:
return True, value["value"]
if len(value) == 2 and value.get("type") == OVERWRITE and "value" in value:
return True, value["value"]

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's fine

value: Any
"""The value to write directly to the channel, bypassing any reducer."""

type: Literal["__overwrite__"] = "__overwrite__"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cursor said we can use type: Literal["__overwrite__"] = OVERWRITE

not sure that is true

Recognises three forms:

* The typed `Overwrite` dataclass instance.
* The sentinel-keyed `{"__overwrite__": value}` dict form.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add more details where this is from -- seems like from user hand writing the return from a node?

Christian Bromann (christian-bromann) added a commit to langchain-ai/langgraphjs that referenced this pull request Jun 17, 2026
#2553)

## Summary
- JS `Overwrite` already survives JSON serialization because
`Overwrite.toJSON()` emits the canonical `{ "__overwrite__": value }`
sentinel, which `_getOverwriteValue` recognizes.
- This adds recognition of the discriminator form `{ "type":
"__overwrite__", value }` that results when a typed `Overwrite` from
another runtime (notably a Python dataclass, post
langchain-ai/langgraph#8127) is serialized through a JSON boundary and
its type is erased.
- Brings JS to full parity with Python's three-form `_get_overwrite`
(instance, sentinel dict, discriminator dict), so `Overwrite`
round-trips both directions across the JS↔Python API boundary.
Delta-channel APIs remain Beta.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants