-
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
Branch Conditions Limited to Preceding Node's Input Schema Instead of Full Graph State #3657
Comments
The ProblemIn your code, the
But it's missing Solutionyou can work around it by ensuring your router function only depends on properties that are either:
Here's a modified version of your code that works around the issue: from libs.langgraph.langgraph.graph import StateGraph, START, END
from typing import TypedDict, Literal
class OverallState(TypedDict):
property_in_input: str
property_not_in_input: str
property_control: str
class InputState(TypedDict):
property_in_input: str
property_not_in_input: str # Added this to ensure it's available in the router
def node1(input: OverallState):
print("node1 overall state" , input)
return {
"property_control": "route_to_node2",
}
def intermediate(input: InputState):
print("intermediate node with input state" , input)
return {
"property_control": "route_to_end",
}
def node2(input: OverallState):
print("node2 overall state" , input)
return {
"property_control": "completed",
}
def router(state: OverallState) -> Literal["node2", "END"]:
print("Router function state:", state)
if state["property_control"] == "route_to_node2":
return "node2"
else:
return END
graph_builder = StateGraph(OverallState)
graph_builder.add_node("node1", node1)
graph_builder.add_node("intermediate", intermediate, input=InputState)
graph_builder.add_node("node2", node2)
graph_builder.add_edge(START, "node1")
graph_builder.add_edge("node1", "intermediate")
graph_builder.add_conditional_edges("intermediate", router, {
"node2": "node2",
END: END
})
graph_builder.add_edge("node2", END)
graph = graph_builder.compile()
result = graph.invoke({
"property_in_input": "value",
"property_not_in_input": "value",
"property_control": "initial_value"
}) The key change is adding |
Hi, @YassinNouh21 I understand and this quick fix is what I am currently doing but this bug could always result in unexpected behavior and hurts observability in langsmith. |
Yes it is more about workaround. But in my opinion, I think that u miss use the Input state as it supposes to be at the start node not in the intermediate nodes |
Thanks for your thoughts! Hmm, Input Nodes would act as a filter to what each node sees, drawing a line of separation on inputs required for each node. I find this idea helpful in long workflows beginning or amid the workflow and is essential for me in Langsmith instead of seeing key states from overall states I can see the relevant input to each node instead, so I am not sure why you think that. But still applying it only at the start node and then having a router function after it that should use the full schema will have the same problem, so I don't think that's a relevant discussion. |
I believe the issue is that InputState should only apply at the start node. Using it mid-workflow filters out important properties (like property_not_in_input), leaving the router with an incomplete state. This behavior not only breaks the expected full-state propagation but also hurts observability in LangSmith. Wouldn't it be better if we kept the full OverallState for intermediate nodes and router functions? as you can see in this docs. it is explicity stated that
|
Using input states doesn't inherently lose information, it's only when using router functions as stated in my issue, even in subsequent nodes the nodes still can access overallstate normally.
This doesn't say that I shouldn't define private schemas amid the graph. Refer to the docs 1 , 2 here of using internal schemas in midst of graph, here called "private" states. this doesn't break propagation.
This causes problems for other people aswell, like here. |
Checked other resources
Example Code
Error Message and Stack Trace (if applicable)
Description
Description
When using a branch condition in LangGraph, the branch condition function only has access to fields defined in the source node's input schema, not the full graph schema. This breaks the expected behavior where branch conditions should have access to the complete state.
Reproduction Example
Current Behavior
The router function only receives properties that are defined in the source node's input schema, plus any updates from that node. In this example, property_not_in_input is lost when the router is called, despite the router function expecting the complete OverallState.
Output:
node1 overall state {'property_in_input': 'value', 'property_not_in_input': 'value', 'property_control': 'initial_value'}
intermediate node with input state {'property_in_input': 'value'}
Router function state: {'property_control': 'route_to_end', 'property_in_input': 'value'}
Expected Behavior
The router function should receive the complete graph state (all properties in OverallState), regardless of what fields the source node uses or updates.
System Info
System Information
Package Information
Optional packages not installed
Other Dependencies
The text was updated successfully, but these errors were encountered: