下面我们来深入拆解这段 LangGraph 代码中出现的 四种 State状态形式并结合执行流程说明它们各自的作用、约束与数据流转方式。1. 四种 State 的定义与角色① InputState输入状态pythonclassInputState(TypedDict):user_input:str角色定义外部调用者向图Graph发起请求时必须传入的数据结构。使用位置在创建 StateGraph时通过 input_schemaInputState指定。特点仅描述“入口数据”不包含图内部产生的中间或最终结果。调用 graph.invoke({“user_input”: “My”})时参数必须兼容 InputState。与本例关系初始全局状态中只有 user_input: “My”。② OutputState输出状态pythonclassOutputState(TypedDict):graph_output:str角色定义图执行完毕后返回给外部的结果结构。使用位置在创建 StateGraph时通过 output_schemaOutputState指定。特点对全局状态进行“裁剪”最终只保留此处声明的字段。示例中返回 {‘graph_output’: ‘My name is Lance’}。与本例关系即使全局状态还包含 foo、bar、user_input输出时也被过滤得只剩 graph_output。③ OverallState总体状态pythonclassOverallState(TypedDict):foo:struser_input:strgraph_output:str角色定义整个图内部维护的完整全局状态即“总状态”。使用位置作为 StateGraph的第一个类型参数StateGraph(OverallState, …)。特点理论上应囊括所有节点需要读写的状态字段本例为了演示故意没放 bar。各节点函数的输入/输出可以只是它的子集LangGraph 负责合并。初始时由 InputState注入user_input随后被各个节点逐步填充。与本例关系初始{“user_input”: “My”}foo、graph_output暂缺node_1 写入 foo→ {“user_input”: “My”, “foo”: “My name”}node_3 写入 graph_output→ 最终全局状态含三个键外加临时的 bar④ PrivateState私有/局部状态pythonclassPrivateState(TypedDict):bar:str角色定义某两个或多个相邻节点之间传递的临时数据结构不属于全局状态的正式 schema。使用位置仅作为某些节点的输入输出类型标注非图级配置。特点用于封装中间计算结果避免污染 OverallState。LangGraph 允许节点返回未在 OverallState中声明的字段并传递给下一节点只要下一节点标注接收该结构。最终不会被 OutputState输出。与本例关系node_2返回 {“bar”: “My name is”}写入私有状态node_3接收 PrivateState读取 bar并生成最终输出。2. 数据流转全过程结合代码python graph.invoke({user_input:My})步骤节点接收的状态类型标注实际可访问的字段返回的状态全局状态变化START→node_1node_1InputStateuser_input“My”{“foo”: “My name”} foonode_1→node_2node_2OverallStateuser_input, foo{“bar”: “My name is”} bar(私有)node_2→node_3node_3PrivateStatebar{“graph_output”: “My name is Lance”} graph_outputnode_3→END输出OutputState——仅保留 graph_output最终输出python{graph_output:My name is Lance}3. 核心设计思想总结关注点分离InputState对外契约调用方知道传什么OutputState对外契约调用方知道收什么OverallState对内全景图作者管理全量状态PrivateState节点间临时契约解耦中间逻辑类型驱动LangGraph 利用 Python 类型标注TypedDict在编译期/运行期做状态校验与自动补全提示。渐进式状态构建全局状态从输入开始经各节点返回的部分状态不断合并最后按输出 schema 剪裁。代码此代码取自官方给的demofromtypingimportTypedDictfromlanggraph.graphimportEND,START,StateGraphclassInputState(TypedDict):user_input:strclassOutputState(TypedDict):graph_output:strclassOverallState(TypedDict):foo:struser_input:strgraph_output:strclassPrivateState(TypedDict):bar:strdefnode_1(state:InputState)-OverallState:# Write to OverallStatereturn{foo:state[user_input] name}defnode_2(state:OverallState)-PrivateState:# Read from OverallState, write to PrivateStatereturn{bar:state[foo] is}defnode_3(state:PrivateState)-OutputState:# Read from PrivateState, write to OutputStatereturn{graph_output:state[bar] Lance}builderStateGraph(OverallState,input_schemaInputState,output_schemaOutputState)builder.add_node(node_1,node_1)builder.add_node(node_2,node_2)builder.add_node(node_3,node_3)builder.add_edge(START,node_1)builder.add_edge(node_1,node_2)builder.add_edge(node_2,node_3)builder.add_edge(node_3,END)graphbuilder.compile()graph.invoke({user_input:My})# {graph_output: My name is Lance} 实践中为了避免混淆通常建议把所有会被多个节点使用的字段都放进OverallState而将PrivateState视为可选的精细化工具。本例特意将bar放在PrivateState是为了演示四种形态的共存与区别。