工作流与多 Agent 协作:LangGraph、MCP 和 A2A 的应用分层
当大模型应用从单轮问答发展到复杂任务,系统复杂度会迅速上升。一个请求可能需要意图识别、查询改写、工具调用、数据库查询、结果摘要、人工确认和跨服务协作。如果所有逻辑都堆在一个函数里,代码会很快失控。
这时需要把系统拆成不同层次:应用内部用工作流管理状态,外部工具用标准协议接入,多个 Agent 之间用任务协议协作。LangGraph、MCP 和 A2A 可以分别从这三个角度理解。
1. 为什么链式调用不够
简单应用可以写成:
text
Prompt -> Model -> Parser
稍复杂一点是:
text
Retriever -> Prompt -> Model -> Parser
但真实任务常常不是直线:
- 用户意图不同,流程要分支。
- 信息不足,要追问。
- 工具失败,要重试或降级。
- 生成结果不合格,要重新生成。
- 多个子任务可以并行。
- 某些步骤需要人工确认。
- 不同能力由不同服务提供。
这些场景需要显式建模状态和流程,而不是不断增加嵌套 if/else。
2. LangGraph:应用内部的状态图编排
状态图适合描述"节点如何修改状态,状态如何驱动下一步"。它的基本元素包括:
- State:流程中共享的数据结构。
- Node:一个处理步骤,例如分类、检索、生成、评估。
- Edge:节点之间的连接。
- Conditional Edge:根据状态选择分支。
- Checkpointer:保存状态,支持恢复。
可以把一次复杂任务看成状态不断变化:
text
初始状态 -> 意图识别 -> 检索状态 -> 生成状态 -> 评估状态 -> 最终状态
相比普通链式调用,状态图更适合长期维护,因为每个节点职责清楚,流程结构可视化,也便于插入中断、重试和日志。
3. 分支、循环、并行与子图
工作流的价值主要体现在四类控制结构。
分支用于不同意图走不同路径:
text
天气查询 -> 天气工具
票务查询 -> 票务工具
闲聊问题 -> 普通回答
循环用于质量不达标时重新执行:
text
生成草稿 -> 评估 -> 不合格 -> 按反馈重写
并行用于互不依赖的任务:
text
查询天气 + 查询票务 -> 汇总结果
子图用于封装可复用流程,例如把"查询并格式化结果"封装成独立模块,再嵌入主流程。
并行场景要特别注意状态合并。如果两个节点同时更新同一个字段,系统需要明确合并规则,否则结果可能不确定。
4. 人机协同:中断和恢复比全自动更可靠
很多业务不适合完全自动执行,例如下单、删除、审批、发送通知等。工作流应支持在关键节点中断,等待用户或人工系统输入,然后恢复执行。
典型流程:
text
生成操作建议 -> 请求确认 -> 用户确认 -> 执行工具 -> 返回结果
这种设计比"模型直接执行"更安全,也更符合真实业务流程。人机协同不是降低智能化,而是把风险放在正确的位置。
5. MCP:工具接入层的标准化
MCP 可以理解为工具服务化和标准化接入。工具提供方把能力包装成 MCP 服务,应用通过 MCP 客户端调用工具。
它解决的问题是工具生态碎片化:
- 每个工具都有不同 SDK。
- 每个服务都有不同鉴权和调用方式。
- 工具升级会影响主应用。
- 多个应用重复集成同一工具。
通过工具协议化,主应用可以用统一方式发现和调用工具。数据库查询、天气服务、票务服务、文件读取、搜索服务等,都可以包装成工具服务。
但 MCP 不等于 Agent。MCP 更偏工具层,负责"能力如何暴露和调用";Agent 负责"什么时候调用什么能力"。
6. A2A:多个 Agent 的任务协作层
当系统中存在多个具备独立能力的 Agent 时,需要一种任务级通信方式。A2A 类架构通常包含:
- Agent Card:描述 Agent 名称、地址、版本、能力。
- Skill:说明 Agent 能处理什么任务。
- Task:一次任务请求。
- Task Status:任务完成、失败或需要补充输入。
- Artifact:任务产物。
一个主控 Agent 或前端应用可以根据用户意图,将不同子任务路由给不同 Agent:
text
用户请求
-> 意图识别
-> 路由到专业 Agent
-> 接收任务状态和产物
-> 汇总成最终答复
这种模式适合能力边界清楚、服务需要独立部署、团队分工明确的系统。
7. 多 Agent 不等于更先进
多 Agent 会带来额外成本:
- 服务部署更复杂。
- 调用链路更长。
- 延迟更高。
- 日志排查更难。
- 上下文传递更容易丢失。
- 错误恢复更复杂。
因此,不应为了"架构高级"而拆 Agent。判断是否需要多 Agent,可以看:
- 子任务是否有清晰边界。
- 是否需要独立扩缩容。
- 是否由不同数据源或权限控制。
- 是否需要独立发布和维护。
- 是否存在明显的能力复用价值。
如果只是两个函数能完成的任务,用单 Agent 加工具就足够。
8. 三者的分层关系
可以把三者放在一个层次模型里:
text
LangGraph:应用内部流程编排
MCP:外部工具接入协议
A2A:Agent 之间任务协作协议
它们不是互相替代,而是可以组合:
text
一个 Agent 内部用 LangGraph 管理流程;
流程节点通过 MCP 调用工具;
主 Agent 通过 A2A 调用其他专业 Agent。
这样的分层能让复杂系统更清楚:流程归流程,工具归工具,协作归协作。
9. 架构设计中的关键问题
设计工作流和多 Agent 系统时,需要提前回答:
- 状态由谁维护?
- 子任务失败如何反馈?
- 哪些操作需要用户确认?
- 工具返回的数据是否可信?
- Agent 之间传递多少上下文?
- 是否需要任务 ID 和追踪 ID?
- 如何记录每一步执行轨迹?
- 是否存在权限和数据隔离要求?
这些问题比"用了几个 Agent"更重要。
10. 可观测性与链路追踪
工作流和多 Agent 系统一旦拆分,排错难度会明显上升。必须记录任务链路:
- 主任务 ID。
- 子任务 ID。
- 路由到哪个 Agent。
- 调用了哪些工具。
- 每个节点输入和输出摘要。
- 任务状态变化。
- 失败原因和重试次数。
- 最终产物。
如果缺少链路追踪,一个复杂请求失败时,很难判断是意图识别错、路由错、子 Agent 失败、工具失败,还是最终汇总错。
11. 从单体到多 Agent 的演进建议
更稳妥的演进路径是:
- 先把单体应用中的工具和流程边界写清楚。
- 再用状态图管理内部复杂流程。
- 把可复用工具服务化。
- 当某类能力需要独立部署或独立维护时,再拆成 Agent。
- 最后引入 Agent 间任务协议。
这样架构是随需求长出来的,而不是一开始就被概念推着走。
12. 小结
复杂大模型应用的演进路径可以概括为:
text
单次模型调用
-> 工具调用
-> Agent 执行循环
-> 状态图工作流
-> 多 Agent 协作网络
每一步都增加能力,也增加复杂度。成熟的应用架构不是追求最复杂,而是在任务真正需要时,把状态、工具和协作边界拆清楚。
用一句话总结:
text
LangGraph 让流程可控,MCP 让工具可接入,A2A 让 Agent 可协作。
当这三层关系清晰后,大模型应用才更容易从单体 demo 走向可维护、可扩展的工程系统。