-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can't go to a node in the parent graph using Command.PARENT #3570
Comments
Thanks for reporting -- the issue seems to come from using import random
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import StateGraph
from langgraph.graph import END, START
from langgraph.types import Command
from typing import Literal, Annotated, TypedDict
from langgraph.graph.message import AnyMessage
from langgraph.graph.message import add_messages
import operator
class State(TypedDict):
messages: Annotated[list[AnyMessage], add_messages]
personal_data: dict
dialog_state: Annotated[list[str], operator.add]
def node_a_child(state):
return {"dialog_state": ["b_child_state"]}
def node_b_child(state) -> Command[Literal["node_c_child", "node_d_child"]]:
value = random.choice([0, 1])
return Command(
goto="node_c_child"# if value == 0 else "node_d_child"
)
def node_c_child(state):
return Command(
graph=Command.PARENT,
goto="node_sibling",
)
def node_d_child(state):
return {"dialog_state": ["d_child_state"]}
sub_builder = StateGraph(State)
sub_builder.add_node("node_a_child", node_a_child)
sub_builder.add_edge(START, "node_a_child")
sub_builder.add_node("node_b_child", node_b_child)
sub_builder.add_edge("node_a_child", "node_b_child")
sub_builder.add_node("node_c_child", node_c_child)
sub_builder.add_edge("node_c_child", END)
sub_builder.add_node("node_d_child", node_d_child)
sub_builder.add_edge("node_d_child", END)
# adding checkpointer=True causes the issue
sub_graph = sub_builder.compile()#checkpointer=True)
def node_a_parent(state):
return {"dialog_state": ["a_parent_state"]}
def node_b_parent(state):
return {"dialog_state": ["pop"]}
def node_sibling(state):
return {"dialog_state": ["sibling"]}
main_builder = StateGraph(State)
main_builder.add_node("node_a_parent", node_a_parent)
main_builder.add_edge(START, "node_a_parent")
main_builder.add_node("subgraph", sub_graph)
main_builder.add_edge("node_a_parent", "subgraph")
main_builder.add_node("node_b_parent", node_b_parent)
main_builder.add_edge("subgraph", "node_b_parent")
main_builder.add_edge("node_b_parent", END)
main_builder.add_node("node_sibling", node_sibling)
main_builder.add_edge("node_sibling", END)
checkpointer_temp = MemorySaver()
main_graph = main_builder.compile(checkpointer_temp, name="parent")
config = {
"configurable": {
"thread_id": 1,
}
}
result = main_graph.invoke(input={"dialog_state": ["init_state"]}, config=config, subgraphs=True) |
Reduced further to just this example illustrating the issue: from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import StateGraph, START
from langgraph.types import Command
from typing import Literal, Annotated, TypedDict
import operator
class State(TypedDict):
dialog_state: Annotated[list[str], operator.add]
def node_a_child(state):
return {"dialog_state": ["a_child_state"]}
def node_b_child(state):
return Command(
graph=Command.PARENT,
goto="node_b_parent",
update={"dialog_state": ["b_child_state"]}
)
sub_builder = StateGraph(State)
sub_builder.add_node(node_a_child)
sub_builder.add_node(node_b_child)
sub_builder.add_edge(START, "node_a_child")
sub_builder.add_edge("node_a_child", "node_b_child")
# adding checkpointer=True causes the issue
sub_graph = sub_builder.compile()#checkpointer=True)
def node_b_parent(state):
return {"dialog_state": ["node_b_parent"]}
main_builder = StateGraph(State)
main_builder.add_node(node_b_parent)
main_builder.add_edge(START, "subgraph_node")
main_builder.add_node("subgraph_node", sub_graph, destinations=("node_b_parent",))
checkpointer_temp = MemorySaver()
main_graph = main_builder.compile(checkpointer_temp, name="parent")
config = {
"configurable": {
"thread_id": 1,
}
}
result = main_graph.invoke(input={"dialog_state": ["init_state"]}, config=config, subgraphs=True) |
Thank you for your quick response. Yes, removing the
Ideally, yes, as I want to store the states of subgraphs. Currently, as a workaround, I'm planning to use a new |
Hey @vbarda I am using langgraph-supervisor library. I attached two of my agent I created (Not using agents created from Right now, When I am trying to send message to the supervisor like Note: Both of my agents have different state. Supervisor code snippet
Langsmit trace: https://smith.langchain.com/public/2b8077fa-54ca-4888-b3cf-44e41c7f013c/r |
@rahilvora please open issue in the supervisor repo for this |
Checked other resources
Example Code
Error Message and Stack Trace (if applicable)
Description
I am trying to implement a handoff where a subgraph transfers the user to another node in the parent graph (a sibling node in this case) using a Command, but I keep encountering an error. There is no difference whether the graph and subgraph share the same state or only a single key, whether a reducer function is applied or not—the transition simply doesn’t occur. To me, this seems somewhat illogical. I have experimented with various target nodes (e.g., node_a_parent), but the result remains the same—a ParentCommand exception.”
System Info
System Information
Package Information
Optional packages not installed
Other Dependencies
The text was updated successfully, but these errors were encountered: