用 LangChain 1.0 做一次真正可落地的 Agent-to-Agent 协作(携程 + 美团 + 滴滴)
基于 LangChain 1.0 实现携程 + 美团 + 滴滴出行场景的 Agent-to-Agent 协作,摒弃全能 Agent 模式,拆分为机票、酒店、打车专属子 Agent + 总协调 Agent。子 Agent 仅绑定单一工具、输出格式标准化,协调层统一调度并增加工具兜底逻辑,解决了工具调用混乱、排错难等问题。该分层结构兼顾稳定性与可维护性,是更适配真实业务落地的工程化方案。总结
在做大模型项目时,很多人一开始都会写一个“全能 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 都通过“总协调层”调度,相当于建立了一个单点控制中心。
优点是:
-
流程清晰
-
日志好打
-
错误好定位
这更像传统后端里的服务编排,而不是“让模型自己玩”。
六、顺序执行还是并行?
在这个案例里我选择了顺序执行:
-
机票
-
酒店
-
打车
从工程角度看,顺序更稳定。
当然理论上机票和酒店可以并行。
但在真实系统里,优先保证可控,再考虑性能。
如果以后要优化,可以用异步 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 更有效。
这套结构不仅适用于出行场景,
电商下单、金融审批、多系统数据整合,其实都可以复用同样思路。
技术本身不复杂,
关键在于结构是否清晰。
更多推荐

所有评论(0)