上篇咱们把 LangGraph 的骨架State / Node / Edge搭起来了。这篇老哥带你把两个最容易被新手忽视、却决定你写得好不好的核心机制啃透State和Command。用大白话讲State 决定了一张图里能流动什么数据、节点之间怎么协作Command 让节点能在更新状态的同时顺便决定下一步去哪。一、State图里能流动什么数据全看它State 不是随便写个 dict它是图运行过程中的状态快照有三个作用定义数据结构、在节点间传递数据、控制执行逻辑条件边、Command、Send 都靠它。先记一个容易踩坑的点State 是共享快照不是普通全局变量。节点不要直接原地改 state而是返回一个更新让 LangGraph 帮你合并回全局。写法的差别是def node(state): # ❌ 不要原地改 # state[messages].append(...) # ✅ 返回更新 return {messages: [new_msg]}三种定义方式怎么选表格Schema 类型特点适合场景TypedDict简单、轻量、最常见大多数项目、学习dataclass支持默认值需要默认值的状态Pydantic运行时校验、限字段范围强约束、外部输入复杂我的建议很直接先用 TypedDict 把状态结构设计清楚确实需要运行时校验时再上 Pydantic。别一上来就追求 高级。二、Reducer多个节点同时写一个字段怎么办这是 State 机制里最重要的部分。设想两个节点并行执行都往reports这个字段里写东西如果字段没有 reducerLangGraph 直接报错 —— 因为它不知道该怎么合并。解决办法就是给字段指定一个Reducer合并规则。写法是配合Annotatedfrom typing import Annotated import operator class State(TypedDict): reports: Annotated[list, operator.add] # 列表用 add 拼接Reducer 本质上就是一个函数接收旧值和新值返回合并后的值。常见套路给你整理好了表格字段类型推荐 reducer说明list[str]operator.add列表拼接messagesadd_messages聊天消息合并带 ID 语义set自定义 union集合合并dict自定义 merge字典合并计数器自定义 sum数字累加特别提醒聊天消息别用operator.add要用add_messages。因为消息有 ID、类型Human/AI/Tool/Systemadd_messages会追加新消息、同 ID 更新原消息这个语义是普通列表拼接给不了的。三、Input/Output Schema 和 Private State两个进阶法宝Input / Output Schema默认图的输入、内部状态、输出是同一个 schema但复杂项目里你肯定不想让调用方传一堆intent、docs这种内部字段。拆分出入口 schema 能隐藏内部状态、让 API 边界清晰、保护私有数据输出里不出现的字段不暴露、方便测试。Private State私有状态这是理解 LangGraph 状态体系的关键我给你打个比方 ——**公共 State 就像班级团建的公共账户大家兑钱进去买大家都吃的东西。如果只有两个同学想吃臭豆腐拿公共账户的钱买就不合适。这时候这两个人就该自己兑钱搞个私有账户。对应到代码如果你的图有 100 个 node每两个 node 之间传的临时变量都塞进公共 State字段会爆炸既不便于阅读也拖累 checkpoint。私有 State 就是节点之间临时的内存管道不进全局 State、不持久化、不对外暴露用完就扔只在声明它的节点之间流转。四、Command让节点 一边更新状态一边跳转前几章里节点和边是各司其职的节点更新 State条件边读 State 决定下一步。但有个别扭的地方 ——分类结果明明是在classify节点里算出来的却还要再写一个路由函数读一遍。Command 就是为这个痛点而生的。它的核心是两个参数表格参数作用update把数据写入 State和返回字典等价goto指定接下来执行哪个节点两者可以一起用也可以单独用。一个节点可以这样返回from langgraph.types import Command def classify(state): category decide(state[user_input]) # 算出分类 return Command(update{category: category}, gotocategory)一条 return 同时完成了 写状态 和 选下一站不用再单独写路由函数少写一半代码。五、用 Command 的三个铁律新手必看只更新状态、不控制流程时直接返回字典别为了用 Command 而用 Command。goto的目标节点必须真实存在拼错名字运行时会报 找不到目标节点。⚠️ 最坑的一条goto不会自动取消静态边。如果一个节点用Command(goto...)负责路由就不要再给它配其他出边否则那两个节点会并行执行容易撞上 一个 key 一步只能接收一个值 的报错。规则是用了 goto 路由的节点别给它再加边。六、完整案例客服问题分流把这套知识串起来就是客服分流用户输入问题 → 分类节点判断是order订单 / 物流、refund退款还是general其他→ 分类节点用Command同时写入category并跳到对应处理节点。这正是Command(update..., goto...)的经典场景分类结果和路由强相关用 Command 一气呵成比 条件边 独立路由函数 更直观。七、老哥的收尾把这套学完你已经从 会用 LangGraph 画图 进阶到 能设计出好图 了。给你留个记忆锚点State 管数据怎么流动Reducer 管并行怎么写Private State 管临时变量放哪Command 管节点写完状态直接去哪。下一步就可以去挑战真正的 Agent 循环了 —— 记住循环设计必须带退出条件文本达标或尝试次数到上限否则你的图会跑到天荒地老。有问题随时回来问老哥咱们下篇见。