在用 LangGraph 构建多 Agent 系统时,你是否经常遇到这样的场景:

  • Researcher Agent 辛辛苦苦输出了一大段自然语言总结;
  • 下一个 Critic Agent 或 Writer Agent 却完全“看不懂”,无法提取关键信息,导致整个流程卡死;
  • Supervisor 反复把同一个任务扔回给子 Agent,陷入无限循环;
  • 或者下游节点期望结构化数据,却收到杂乱的字符串,解析失败、Tool Calling 无法触发。

这就是 LangGraph(尤其是多 Agent 协作)中最常见、也最让人头疼的问题之一——输出格式不一致

本文将深入剖析这个问题产生的根本原因,并重点介绍 2026 年最推荐的解决利器:llm.with_structured_output() + Pydantic Model。掌握这个技巧后,你的 Agent 间协作将从“经常卡住”变成“像调用 API 一样稳定可靠”。

一、为什么输出格式不一致如此致命?

LangGraph 的核心是状态化图(StateGraph),节点之间通过共享 State 传递数据。每个节点(通常是一个 Agent)执行后,需要把结果更新到 State 中,供下一个节点使用。

然而,大模型(LLM)默认是“聊天模式”:

  • 它擅长生成自然语言,却不擅长严格遵守格式。
  • 上一个 Agent 可能输出“以下是我的研究总结:……(一大段自由文本)”,而下一个 Agent 或 Coordinator 期望的是 { "summary": "...", "key_findings": [...], "next_action": "critic" } 这样的结构化 JSON。

常见表现形式

  1. 解析失败:下游 Agent 无法从自然语言中可靠提取字段,导致决策错误。
  2. 路由卡死:Supervisor 依赖 next 字段决定路由,但收到的输出没有这个字段。
  3. 上下文膨胀:反复让模型“重新格式化”,token 消耗暴增,成本上升。
  4. 无限循环:模型输出不符合预期,Supervisor 不断重试同一 Agent。

在多 Agent 系统中,这个问题会被成倍放大。因为不像单 Agent 只需最终输出自然语言,多 Agent 需要Agent 之间像模块一样精确通信

二、根本原因分析

  1. LLM 输出本质是概率性的:即使你在 Prompt 中写“请用 JSON 输出”,模型仍可能添加多余文字、遗漏字段、或格式错误。
  2. LangGraph 依赖结构化状态更新:节点返回的 dict 需要符合 State Schema,否则 Reducer 无法正确合并,或下游节点无法读取。
  3. Tool Calling 与自由输出冲突:ReAct Agent 同时支持 Tool Calling 和自由回复时,模型容易混淆输出格式。
  4. 层次化架构放大问题:子图(Subgraph)返回的私有字段如果不是父图定义的 Key,就会被默默丢弃,进一步加剧格式不一致的影响。

社区 2025-2026 年的反馈显示,这个问题占多 Agent 项目调试时间的 30%-50% 以上。

三、最佳解决方案:强制使用 .with_structured_output()

LangChain / LangGraph 提供了强大且可靠的结构化输出机制——with_structured_output()。它会自动:

  • 将 Pydantic Model 转换为模型可理解的 JSON Schema;
  • 在 Prompt 中注入格式指令;
  • 使用 JSON Mode 或 Function Calling 强制模型严格遵守;
  • 如果输出不符合,自动重试(部分模型支持)。
3.1 核心代码示例
from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from typing import List

# 定义每个 Agent 的输出结构(强烈推荐为每个 Agent 单独定义)
class ResearcherOutput(BaseModel):
    reasoning: str = Field(..., description="你的思考过程")
    summary: str = Field(..., description="研究总结,控制在 200 字以内")
    key_findings: List[str] = Field(..., description="3-5 个关键发现,用列表形式")
    gaps: List[str] = Field(..., description="还需要补充的信息或疑问")
    next_agent: str = Field(..., description="下一步应该交给哪个 Agent:critic / writer / done")
    confidence: float = Field(..., ge=0, le=1, description="输出置信度")

# 绑定结构化输出(核心一步)
llm = ChatOpenAI(model="gpt-4o", temperature=0.2)
structured_llm = llm.with_structured_output(ResearcherOutput)

# 创建 Researcher Agent
researcher_agent = create_react_agent(
    model=structured_llm,      # 使用结构化 LLM
    tools=research_tools,
    # 可选:进一步强化 Prompt
    state_modifier=lambda state: [
        ("system", "你是一个严谨的研究员,必须严格按照指定的 JSON Schema 输出,不要添加任何额外文字。")
    ] + state["messages"]
)
3.2 在多 Agent 协作中的应用
  • Coordinator / Supervisor 也使用结构化输出定义 Router Model,专门决定 next_agent
  • Critic Agent 可以定义 CritiqueOutput,包含 quality_scoresuggestions 等字段,专门校验上游输出。
  • 在 State 中增加对应字段(如 research_output: ResearcherOutput | None),让状态更新更清晰。

四、配套最佳实践

  1. Prompt 强化:永远不要只依赖结构化输出,Prompt 中仍需明确说明“必须严格遵守以下 Schema,不要添加多余文字”。
  2. State Schema 配合:在 MultiAgentState 中为每个 Agent 的输出预留专用字段,避免所有信息都塞进 messages
  3. 调试神器:打开 LangSmith,查看每个 Agent 的输入输出对比,快速定位格式问题。
  4. 防退化:为重要节点设置 temperature=00.1,降低随机性。
  5. 生产建议:结合 langgraph-supervisor 或自定义 Coordinator Node,让路由决策也结构化。

总结
在 LangGraph 多 Agent 开发中,输出格式不是“提示词问题”,而是工程契约问题。把 .with_structured_output() + Pydantic 当成每个 Agent 的“输出 API 规范”,你的系统就会从脆弱的“聊天系统”升级为可靠的“Agent 流水线”。

如果觉得这篇有用,欢迎点赞和关注,一起玩转 LangGraph!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐