在做大模型项目时,很多人一开始都会写一个“全能 Agent”。
用户一句话进来,模型自己判断、自己调工具、自己输出结果。

Demo 阶段没问题,但一旦业务变复杂,很快就会发现几个问题:

  • 工具越来越多,模型经常选错

  • Prompt 越写越长,修改一次牵一发动全身

  • 出错时很难定位是模型问题还是工具问题

这次我用 LangChain 1.0 做了一个简单但完整的场景:
“北京飞上海 → 订浦东机场酒店 → 预约机场到酒店打车”。

实现过程中最大的收获不是“跑通流程”,而是对 A2A(Agent-to-Agent)协作结构有了更清晰的理解。


一、为什么不再用单 Agent?

一开始我也尝试过把三个工具都绑定在一个 Agent 上:

  • 机票工具

  • 酒店工具

  • 打车工具

理论上模型可以根据语义自动选择。

但实际运行时经常出现:

  • 调错工具

  • 参数混乱

  • 输出多余解释文本

  • 调用成功但格式不统一

问题本质在于:
让一个 Agent 同时承担决策、业务执行、流程编排,是职责过重的。

于是我改成拆分结构。


二、结构调整:三个专属 Agent + 一个协调 Agent

整体结构变成:

  • 携程 Agent:只负责机票

  • 美团 Agent:只负责酒店

  • 滴滴 Agent:只负责打车

  • 总协调 Agent:按顺序调用它们

每个子 Agent 只绑定一个工具,而且 Prompt 写得非常“死”:

  • 只能调用指定工具

  • 必须传入固定参数格式

  • 调用后直接返回工具字符串结果

  • 不允许输出任何额外内容

这么做的好处很明显:

  • 不存在工具混淆

  • 输出格式统一

  • 排错非常清晰

如果机票出问题,只需要看携程 Agent,不会影响其他模块。


三、LangChain 1.0 带来的变化

这套结构在 1.0 版本里写起来其实比 0.x 清晰很多。

核心在于统一的 Runnable 结构:

Prompt | LLM | OutputParser

每个子 Agent 都是一个标准 Runnable,对外只暴露:

invoke({"input": ...})

这种统一接口让协调层写起来非常干净。

相比旧版本各种 AgentExecutor 混合写法,
1.0 的链式结构更容易维护。


四、一个很关键的设计:工具兜底

这是我觉得整套方案里最实用的一点。

模型不是 100% 稳定的,有时会:

  • 返回空字符串

  • 工具没被正确触发

  • 输出格式异常

如果直接依赖模型输出,流程就会中断。

所以我在协调层增加了一层兜底逻辑:

  • 如果子 Agent 返回为空

  • 或者抛异常

  • 直接调用 tool.func 原始函数

这相当于给系统加了一个“保险丝”。

在真实业务场景中,这是必须的。
否则一次模型波动,就会导致整条业务链失败。


五、为什么协调层统一调度?

很多人会问:
能不能让 Agent 之间互相调用?

理论上可以,但我没有这么做。

原因很简单:

  • 调试困难

  • 状态难追踪

  • 容易出现循环调用

让所有子 Agent 都通过“总协调层”调度,相当于建立了一个单点控制中心。

优点是:

  • 流程清晰

  • 日志好打

  • 错误好定位

这更像传统后端里的服务编排,而不是“让模型自己玩”。


六、顺序执行还是并行?

在这个案例里我选择了顺序执行:

  1. 机票

  2. 酒店

  3. 打车

从工程角度看,顺序更稳定。

当然理论上机票和酒店可以并行。
但在真实系统里,优先保证可控,再考虑性能。

如果以后要优化,可以用异步 Runnable 或 LangGraph 来管理状态流。


七、一些真实踩坑

1. 工具 description 不写清楚,模型会乱传参

必须在 description 里写明:

  • 参数名

  • 参数类型

  • 日期格式

否则模型会自己发挥。


2. Prompt 不够强硬,模型会多输出解释

如果不明确写:

“调用后直接返回工具结果,不能有其他内容”

模型经常会加解释文本。


3. 版本不对会直接报错

LangChain 1.0 和 0.x 差别非常大。

一定要锁版本:

langchain==1.0.0

否则 Runnable 接口不兼容。


八、A2A 的实际价值

写完这个案例之后,我的理解是:

A2A 并不是“多个 Agent 聊天”,
而是把复杂业务拆成可维护的模块。

更像是:

  • 子 Agent = 智能微服务

  • 总协调 Agent = 编排层

这样做的好处是:

  • 易扩展

  • 易替换真实 API

  • 易调试

  • 易控制风险

如果以后要加“高铁票 Agent”或“餐饮推荐 Agent”,
只需要新增模块,不需要重写全部逻辑。


九、总结

这次实现让我最大的体会是:

单 Agent 更像是实验室结构,
A2A 更像是工程结构。

真正落地时,稳定性和可维护性比“模型有多聪明”更重要。

LangChain 1.0 提供的 Runnable 抽象,让这种结构实现起来非常自然。

如果要一句话总结这套方案:

子 Agent 专注业务,总协调 Agent 专注流程,工具层保证稳定。

当业务复杂度上来时,这种分层思路会比堆 Prompt 更有效。

这套结构不仅适用于出行场景,
电商下单、金融审批、多系统数据整合,其实都可以复用同样思路。

技术本身不复杂,
关键在于结构是否清晰。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐