State 是什么?LangGraph 里最重要的不是节点 📅 2026/7/19 22:46:20 上一篇文章里我们讨论了从 Chain 到 Graph 的变化。一个重要结论是当 AI 应用开始出现分支、循环、重试和人工介入时线性流程就会变得吃力。LangGraph 用图结构把复杂 Agent Workflow 显式组织起来。但学习 LangGraph 时很多人第一反应是我要写哪些 Node每个 Node 调哪个模型Edge 怎么连这些问题当然重要。但在 LangGraph 里真正决定系统是否清晰、稳定、可维护的往往不是节点而是 State。这篇文章就讨论State 到底是什么为什么它是 LangGraph 里最重要的设计之一State 不是普通变量很多人会把 State 理解成一个普通变量集合。比如query answer history这样理解只对了一部分。在 LangGraph 里State 更像是整个图运行过程中的共享上下文。它记录了当前流程知道什么、做到哪一步、下一步判断需要依据什么。一个 Agent Workflow 可能需要的 State 包括用户输入 消息历史 任务类型 当前步骤 检索结果 工具调用结果 失败次数 中间分析结论 是否需要人工确认 最终答案Node 读取 State。Node 执行任务后更新 State。Edge 根据 State 决定下一步。所以 State 不是附属品。它是图运行的核心。为什么 State 很重要一个 Agent 流程能不能稳定取决于系统能不能清楚回答几个问题现在用户想做什么 系统已经完成了哪些步骤 当前有哪些可用信息 哪些工具已经调用过 哪些结果可信 是否需要继续执行 是否应该结束这些答案都来自 State。如果 State 设计混乱就会出现很多问题。比如节点之间传递信息不清楚 重复调用工具 检索结果被覆盖 错误信息丢失 分支判断没有依据 循环无法正确结束 人工介入后无法恢复很多 LangGraph 项目后期难维护不是因为 Node 不会写。而是因为 State 从一开始就没有设计好。State 决定节点边界Node 应该做什么往往取决于 State 怎么设计。比如你有一个检索节点。它读取query tenant_id permission_context然后写入retrieval_results retrieval_scores sources这样节点边界就很清楚。如果 State 没有定义这些字段节点就容易把结果塞到任意位置。后面的 Rerank 节点、生成节点、日志节点也不知道该读哪里。所以 State 是节点之间的契约。它告诉每个节点你可以依赖什么 你应该产出什么 你不要随便改什么这对工程化非常重要。State 和 Prompt 不是一回事有些人会把所有上下文都塞进 Prompt。比如用户问题 历史对话 工具结果 检索结果 失败记录 任务目标全部拼成一个大 Prompt。这样做在小 Demo 里能跑。但它有几个问题。第一结构不清楚。你很难知道哪些内容是任务状态哪些内容是用户上下文哪些内容是工具结果。第二成本高。所有信息都塞给模型会浪费 token。第三不利于分支判断。流程判断最好基于结构化 State而不是让模型在大段文本里自己猜。第四不利于调试。出问题时你很难复盘是哪部分状态导致了错误。更好的做法是State 结构化保存信息。Prompt 只拿当前节点真正需要的部分。State 应该包含哪些内容不同项目的 State 不一样。但可以从几个维度思考。第一用户输入。user_query original_input第二对话上下文。messages conversation_summary第三任务状态。task_type current_step plan progress第四检索状态。rewritten_query retrieval_results rerank_results sources第五工具状态。tool_calls tool_results tool_errors retry_count第六控制状态。need_human_review should_continue final_answer error_message这些字段不一定都要有。关键是根据业务需要设计。不要一开始就把 State 做得特别大。也不要只放一个 messages把所有东西都混进去。State 过小的问题State 过小最常见的表现是所有信息都临时传递。比如节点 A 返回一个结果 节点 B 临时接收 节点 C 又重新包装这种方式一开始看起来简单。但流程一复杂就会出现问题。比如某个节点想知道前面工具失败了几次却没有地方记录。某个条件边想判断是否继续检索却不知道检索结果质量如何。人工介入后想恢复流程却不知道之前停在哪一步。这些都是 State 过小带来的问题。State 太小流程就没有记忆。图看起来在运行但上下文是断的。State 过大的问题State 过大也麻烦。有些人会把所有内容都塞进 State完整文档 完整日志 所有中间 Prompt 所有模型原始输出 所有外部系统响应这样会带来几个问题。第一状态难理解。字段太多没人知道哪个字段真的重要。第二节点耦合变强。每个节点都可能随便读写很多字段。第三存储和恢复成本变高。如果后续使用 Checkpoint过大的 State 会影响性能和成本。第四隐私风险增加。敏感数据如果无脑进入 State日志和持久化都会变危险。所以 State 要够用但不要无限膨胀。State 要服务于路由判断LangGraph 里很多 Edge 会根据 State 判断下一步。比如如果 retrieval_results 为空进入 rewrite_query。 如果 risk_level 为 high进入 human_review。 如果 retry_count 超过 3进入 fallback。 如果 final_answer 已生成进入 END。这意味着 State 字段要能支持决策。不要让条件边依赖一段模糊文本。更好的方式是让节点输出结构化字段。比如is_answerable: true risk_level: low need_more_context: false retry_count: 1这些字段非常适合做路由。Agent Workflow 的可控性很大一部分来自这些结构化状态。State 要服务于可观测性State 还有一个价值帮助排查问题。当某次运行结果不对时你需要知道用户原始问题是什么 问题有没有被改写 检索到了哪些资料 Rerank 后留下了哪些内容 工具调用结果是什么 为什么进入这个分支 最终答案基于哪些信息这些信息如果都在 State 里有清晰记录排查会容易很多。当然生产环境不能把敏感信息无脑写进日志。但从设计上State 应该支持流程复盘。否则系统越复杂越只能靠猜。一个简单 State 示例假设我们做一个带 RAG 的问答 Agent。State 可以先设计成这样messages user_query rewritten_query retrieval_results rerank_results need_more_context answer sources error对应流程可能是接收问题 ↓ 改写问题 ↓ 检索 ↓ 判断资料是否足够 ├─ 不足继续改写或追问 └─ 足够生成答案这里每个字段都有明确用途。rewritten_query给检索节点使用。retrieval_results给 Rerank 节点使用。need_more_context给条件边使用。answer和sources给最终输出使用。这就比把所有东西塞到一个字符串里清楚得多。常见误区第一个误区是只关注 Node不设计 State。Node 是执行单元State 才是流程上下文。第二个误区是把所有内容都放进 messages。messages 适合保存对话但不适合承载全部任务状态。第三个误区是 State 字段没有边界。每个字段都应该知道由谁写、被谁读。第四个误区是 State 过大。状态不是垃圾桶不应该无脑塞所有原始数据。第五个误区是 State 不能支持路由。如果条件判断依赖模糊文本流程就不稳定。总结LangGraph 里最重要的概念之一是 State。因为 State 决定了节点之间如何传递信息流程如何判断下一步系统如何恢复问题如何复盘。Node 是做事的地方。Edge 是连接路径。但 State 是整个图的上下文和记忆。一个好的 LangGraph 项目不是节点越多越好而是 State 设计清楚。State 要足够表达任务进度、工具结果、检索结果和控制信号。但也不能无限膨胀变成难维护的大杂烩。下一篇文章可以继续讨论 Node 怎么设计。因为有了清晰的 State才能进一步决定每个节点应该承担什么职责。