Open
Description
Checked other resources
- This is a bug, not a usage question. For questions, please use GitHub Discussions.
- I added a clear and detailed title that summarizes the issue.
- I read what a minimal reproducible example is (https://stackoverflow.com/help/minimal-reproducible-example).
- I included a self-contained, minimal example that demonstrates the issue INCLUDING all the relevant imports. The code run AS IS to reproduce the issue.
Example Code
from typing import Annotated, TypedDict
from typing_extensions import Literal
from langgraph.graph import END, StateGraph
from langgraph.types import Command
def my_reducer(a: str, b: str | None) -> int:
if b is not None:
return b
return a
class State(TypedDict):
# node_name: Annotated[list[str], add]
node_name: Annotated[str, my_reducer]
foo: str
def subgraph_node_1(state: State) -> Command[Literal["subgraph_node_2"]]:
return Command(
goto="subgraph_node_2",
update={
"node_name": "subgraph_node_1",
"foo": "Update at subgraph_node_1!",
},
)
def subgraph_node_2(state: State) -> Command:
return Command(
goto="node_3",
update={"node_name": "subgraph_node_2"},
graph=Command.PARENT,
)
subgraph_builder = StateGraph(State)
subgraph_builder.add_node(subgraph_node_1)
subgraph_builder.add_node(subgraph_node_2)
subgraph_builder.set_entry_point("subgraph_node_1")
subgraph = subgraph_builder.compile()
# Define main graph
def node_1(state: State) -> Command[Literal["node_2"]]:
return Command(
goto="node_2",
update={"node_name": "node_1"},
)
def node_3(state: State) -> Command[Literal["__end__"]]:
return Command(
goto=END,
update={"node_name": "node_3"},
)
main_builder = StateGraph(State)
main_builder.add_node("node_1", node_1)
main_builder.add_node("node_2", subgraph)
main_builder.add_node("node_3", node_3)
main_builder.set_entry_point("node_1")
main_graph = main_builder.compile()
# Build subgraph
with open("graph_use_command.md", "w") as file:
file.write(f"\n{main_graph.get_graph(xray=1).draw_mermaid()}")
initial = {"node_name": "__start__"}
for chunk in main_graph.stream(initial, stream_mode="values", subgraphs=True):
print(chunk)
Error Message and Stack Trace (if applicable)
Description
This issue is related to #3115.
Problem
When using Command in both the parent graph and the subgraph, running the stream method does not display the output of the final node in the subgraph.
Below is a diagram of the graph from the example code:
%%{init: {'flowchart': {'curve': 'linear'}}}%%
graph TD;
__start__([<p>__start__</p>]):::first
node_1(node_1)
node_2_subgraph_node_1(subgraph_node_1)
node_2_subgraph_node_2(subgraph_node_2)
node_3(node_3)
__end__([<p>__end__</p>]):::last
__start__ --> node_1;
node_1 --> node_2_subgraph_node_1;
node_2_subgraph_node_2 --> node_3;
node_3 --> __end__;
subgraph node_2
node_2_subgraph_node_1 --> node_2_subgraph_node_2;
end
classDef default fill:#f2f0ff,line-height:1.2
classDef first fill-opacity:0
classDef last fill:#bfb6fc
Below is the output from the example code. Notice that the result for the subgraph node subgaph_node_2
is not displayed:
((), {'node_name': '__start__'})
((), {'node_name': 'node_1'})
(('node_2:5198e6fe-5d96-32e1-6f68-ce104abdea04',), {'node_name': 'node_1'})
(('node_2:5198e6fe-5d96-32e1-6f68-ce104abdea04',), {'node_name': 'subgraph_node_1', 'foo': 'Update at subgraph_node_1!'})
((), {'node_name': 'subgraph_node_2', 'foo': 'Update at subgraph_node_1!'})
((), {'node_name': 'node_3', 'foo': 'Update at subgraph_node_1!'})
Expected Behavior
It is expected that the output of the final node in the subgraph is displayed.
Note that when using add_edge instead of Command, the expected behavior is achieved. Below is the example code rewritten using add_edge:
from typing import TypedDict
from langgraph.graph import END, START, StateGraph
class State(TypedDict):
node_name: str
foo: str
def subgraph_node_1(state: State):
return {
"node_name": "subgraph_node_1",
"foo": "Update at subgraph_node_1!",
}
def subgraph_node_2(state: State):
return {"node_name": "subgraph_node_2"}
subgraph_builder = StateGraph(State)
subgraph_builder.add_node(subgraph_node_1)
subgraph_builder.add_node(subgraph_node_2)
subgraph_builder.add_edge(START, "subgraph_node_1")
subgraph_builder.add_edge("subgraph_node_1", "subgraph_node_2")
subgraph_builder.add_edge("subgraph_node_2", END)
subgraph = subgraph_builder.compile()
# Define main graph
def node_1(state: State):
return {"node_name": "node_1"}
def node_3(state: State):
return {"node_name": "node_3"}
main_builder = StateGraph(State)
main_builder.add_node("node_1", node_1)
main_builder.add_node("node_2", subgraph)
main_builder.add_node("node_3", node_3)
main_builder.add_edge(START, "node_1")
main_builder.add_edge("node_1", "node_2")
main_builder.add_edge("node_2", "node_3")
main_builder.add_edge("node_3", END)
main_graph = main_builder.compile()
# Build subgraph
with open("graph_use_edge.md", "w") as file:
file.write(f"```mermaid\n{main_graph.get_graph(xray=1).draw_mermaid()}```")
initial = {"node_name": "__start__"}
for chunk in main_graph.stream(initial, stream_mode="values", subgraphs=True):
print(chunk)
Below is the output, where the result for the subgraph node subgraph_node_2
is correctly displayed:
((), {'node_name': '__start__'})
((), {'node_name': 'node_1'})
(('node_2:0cf73922-e372-fc29-ef53-ba1c568bb221',), {'node_name': 'node_1'})
(('node_2:0cf73922-e372-fc29-ef53-ba1c568bb221',), {'node_name': 'subgraph_node_1', 'foo': 'Update at subgraph_node_1!'})
(('node_2:0cf73922-e372-fc29-ef53-ba1c568bb221',), {'node_name': 'subgraph_node_2', 'foo': 'Update at subgraph_node_1!'})
((), {'node_name': 'subgraph_node_2', 'foo': 'Update at subgraph_node_1!'})
((), {'node_name': 'node_3', 'foo': 'Update at subgraph_node_1!'})
System Info
System Information
------------------
> OS: Linux
> OS Version: #44~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Jun 18 14:36:16 UTC 2
> Python Version: 3.12.5 | packaged by Anaconda, Inc. | (main, Sep 12 2024, 18:27:27) [GCC 11.2.0]
Package Information
-------------------
> langchain_core: 0.3.28
> langchain: 0.3.7
> langchain_community: 0.3.5
> langsmith: 0.1.136
> langchain_aws: 0.2.10
> langchain_fireworks: 0.2.1
> langchain_openai: 0.2.11
> langchain_text_splitters: 0.3.0
> langgraph_sdk: 0.1.48
Optional packages not installed
-------------------------------
> langserve
Other Dependencies
------------------
> aiohttp: 3.10.5
> async-timeout: Installed. No version info available.
> boto3: 1.35.90
> dataclasses-json: 0.6.7
> fireworks-ai: 0.15.7
> httpx: 0.27.0
> httpx-sse: 0.4.0
> jsonpatch: 1.33
> numpy: 1.26.4
> openai: 1.56.2
> orjson: 3.10.9
> packaging: 24.1
> pydantic: 2.9.2
> pydantic-settings: 2.6.1
> PyYAML: 6.0.2
> requests: 2.32.3
> requests-toolbelt: 1.0.0
> SQLAlchemy: 2.0.34
> tenacity: 8.2.3
> tiktoken: 0.8.0
> typing-extensions: 4.11.0
LangGraph Version
pip list | grep langgraph
> langgraph 0.2.70
> langgraph-checkpoint 2.0.12
> langgraph-sdk 0.1.48
Activity