架构设计这事,很多团队第一步就绕错了。不少朋友跟我聊Agent系统时,开口就是“我该用哪个框架”“LangChain还是自研”,其实框架只是表面问题,真正决定系统上限的,是你把Agent工作流编排成什么形状。今天这篇我把Agent工作流里三种最核心的架构模式掰开揉碎讲一遍——增强型、链式、路由式,从设计思路到落地的关键细节,再到我实操中踩过的一系列坑,全部摊开说。
先泼一盆冷水:如果你把Agent当成一个“万能黑盒节点”,所有任务一股脑塞进去让它自由发挥,那你大概率会在交付前夜被不稳定的输出折腾到崩溃。Agent本身是模型,模型天然带随机性,工作流设计的第一价值,就是用结构去约束随机性。三种架构不是谁替代谁的关系,而是像积木一样可以组合嵌套的关系。搞懂它们各自解决什么问题、擅长什么场景、有哪些致命缺陷,你才能像搭积木一样搭出稳定可控的系统。这篇文章适合正在做Agent应用落地的开发者、技术负责人,也适合刚接触LLM应用架构、想建立全局认知的同学。
1. 三种Agent工作流架构到底在解决什么问题
1.1 单节点Agent的失控与低效
先聊一个最常见的原始形态:一个Prompt,一个Agent,自动决定做什么、用什么工具、输出什么。听起来很美好,但现实中这种“自由Agent”很容易变成“失控Agent”,原因有三个层面。
一是输出不稳定。模型每次推理都有概率偏差,同一种语义的表达方式可能完全不同,直接导致下游解析程序没法稳定工作。二是上下文失管。自由Agent调用工具时,每轮工具结果都往上下文里塞,多轮下来上下文膨胀,模型开始遗忘早期关键信息,幻觉率直线上升。三是效率低下。一个复杂任务,比如“查一个客户的历史订单并生成售后处理建议”,如果让单个Agent从零自由发挥,它可能花大量tokens在自我对话上,编排步骤不固定,响应时间和成本双双失控。
这里有个很好的生活类比:把整个餐厅后厨交给一个大厨,让他一个人决定配菜、炒菜、摆盘、上菜顺序。遇到熟客家常菜没问题,但一到高峰期,菜品一多,这个大厨就开始手忙脚乱,出品质量大打折扣。工作流架构,本质上就是给后厨划分工位:切配归切配,热炒归热炒,传菜归传菜——用明确的职责边界去替代“一个人扛所有事”的不确定性。
1.2 三种架构的定义与选型边界
增强型架构(Augmented Workflow),核心是“让单个Agent变强”。在Agent外层包裹上下文检索、记忆管理、工具注册、结果校验等一系列机制。模型还是那个模型,但外围设备让它不裸奔。典型形态像RAG应用,Agent在回答前会先检索知识库,把相关内容作为上下文注入,再让模型生成答案。增强型的价值在于就近解决“单点能力不足”,实施成本相对低,对现有系统改造小。
链式架构(Sequential Chaining / Pipeline),核心是“把一个大任务拆成多个子Agent接力”。上一个Agent的输出解析、过滤后,作为下一个Agent的输入。典型场景是信息提取流水线:原始文档先交给Agent A做要素抽取,抽出的结构化数据交给Agent B做分类打标签,再交给Agent C生成摘要报告。每级只做一件事,输入输出有明确接口约束,问题定位起来非常方便。
路由式架构(Routing Workflow),核心是“先分类、再分派”。一个入口路由Agent接收用户请求,判断任务类型,把请求转发给不同的下游Agent或固定流程。典型形态是智能客服系统的主入口:用户问“我的订单怎么还没到”——路由到订单查询流程;用户骂“你们产品质量有问题”——路由到售后维权流程。路由式架构擅长处理意图分支明确的场景,能把不同类型的任务隔离到各自的处理流程中,避免“一个Agent干所有活”带来的指令冲突。
选型边界其实挺清晰的,我归纳成一张表:
| 架构类型 | 核心目标 | 适合场景 | 落地复杂度 | 典型风险 |
|---|---|---|---|---|
| 增强型 | 提升单Agent能力 | 问答、代码辅助、知识密集型任务 | 低 | 上下文成本高、检索质量不稳 |
| 链式 | 稳定流水线、可定位 | 信息提取、内容生成、多步处理 | 中 | 错误传播、前级输出影响后级 |
| 路由式 | 意图分流、任务隔离 | 多业务入口、客服、门户型系统 | 中高 | 分类错误、边界模糊导致分发失败 |
1.3 为什么选型比写代码更重要
我在一些项目里见过一句话式的技术决策:“先跑通再说,后面优化”。这句话在MVP阶段没问题,但到了Agent系统这里,很容易变成灾难。因为Agent工作流的改型成本,不是改一段代码,而是整个链路的数据形态、上下文策略、运维观测体系全部推倒重来。
举个例子,某团队一开始做了个增强型Agent,所有任务都在一个大Agent里完成。后来业务方提出要支持“先提取用户意图,再分流到不同处理流程”,团队被迫在现有大Agent外面套路由层,但原来大Agent里塞满了各种业务prompt,互相干扰,最后不得不拆成多个小Agent重新编排。估算下来,重构工时是当初“先跑通”版本的3倍不止。
所以我有个习惯:动工前,先花半天把“任务类型清单”列出来。数一数系统到底有多少种不同的用户意图、多少种上游输入、多少种下游输出。如果不超过两种类型,增强型就够了;如果超过五种且有明确的分支条件,路由式不可避免;如果任务本身是一条明确的生产线,比如“解析、分类、摘要、入库”,链式才是正确选择。选型错了,后面每一步都是在还债。
2. 架构设计的核心细节与关键参数
2.1 协议先行:三种架构共同的基础
聊任何架构细节之前,必须先说“协议”。这个词听起来硬核,实际含义就是:你系统里传递的数据长什么样,必须提前定死。很多Agent系统崩就崩在这里——Agent A输出的字段叫“summary”,Agent B期待的字段叫“result”,两边对不上,链式架构直接断链,路由式架构直接分错类。
我在实操中会把每个Agent之间的消息体统一成三层结构:
- 第一层
meta,放消息ID、产生时间、来源Agent标识、链路追踪ID。这层负责运维观测,排查问题全靠它。 - 第二层
payload,放业务主数据。比如工单标题、用户描述、历史订单列表。 - 第三层
context,放链路内的临时状态。比如处理进度、已执行步骤、路由决策依据。
再来一个版本号字段,描述这套结构的schema版本。这样后面要加字段,老的处理节点看到版本不匹配,可以走降级逻辑,而不是直接解析报错。整体结构类似这样:
{ "version": "1.2", "meta": { "message_id": "msg_8f3a...", "created_at": "2024-05-12T10:30:00Z", "source_node": "router", "trace_id": "trace_0f2e..." }, "payload": { "ticket_id": "TKT-20240512-001", "user_message": "我的订单三天没更新物流了", "user_id": "U-10086", "order_ids": ["ORD-20240501-A"] }, "context": { "route_decision": "logistics_query", "route_confidence": 0.87, "attempts": 0 } }这个契约一旦确定,三种架构的拼装就变得非常顺滑。路由式看context.route_decision,链式处理payload里的业务数据,增强型Agent只用关心payload和检索回来的辅助上下文。所有架构差异都被隔离在“数据处理逻辑”之外。
2.2 增强型架构的设计重点:上下文、记忆与工具
增强型架构的设计重点,不是模型选型,而是“在模型之外围了些什么”。我排一下优先级。
上下文工程是排第一位的。一个常见误区是“把能搜到的全塞给模型”。实际情况是,模型输入越长,注意力分配越稀疏,关键信息反而容易被淹没。我实测过一组数据:上下文从2k tokens涨到8k tokens时,召回率明显下降的case不在少数。正确做法是做“压缩-排序-匹配”三步:压缩指把检索回来的长文档截断成与问题相关的段落;排序指按语义相似度从高到低排列;匹配指从压缩后的语料里挑出Top-K条注入,K值的黄金区间通常在3到5条之间。
记忆管理排在第二位。短期记忆可以理解为对话窗口里的消息历史,这个直接控制——超过一定轮次就做摘要压缩,不然全量塞进去必然爆上下文。长期记忆用向量库存储,但要注意写入时机:不是每轮都写,而是等一个任务单元结束后,把关键结论抽取出来持久化。否则你库里塞的全是中间状态,检索时噪声极大。
工具注册与失效降级排在第三位。每个工具都该有四个元信息:名称、描述、入参schema、调用地址。描述写得好不好直接决定模型调用工具的准确率——描述模糊,模型就会张冠李戴。实测下来,描述越具体越带范例,调用准确率越高,比如“查询订单物流状态,参数为订单号,形如ORD-20240501-A”就比“订单查询”好很多。
工具还得配降级策略。工具临时不可用时,不能直接把错误抛给用户,要设计“降级链”:主工具挂了,按顺序尝试备选工具,最后兜底返回预设话术。关键是要在响应里带上“工具异常”标记,方便后续补单处理。
2.3 链式架构的衔接时机与失败传播
链式架构的核心不在“怎么调用下一个Agent”,而在“怎么保证上一个Agent的输出可靠地成为下一个Agent的输入”。有四个细节必须抠。
第一,单一职责。每个环节只做一件事,而且这件事必须能被“一句话说清”。比如“把原始工单文本里的地址抽取出来”是一个职责;“抽取地址并判断该地址是否在配送范围并给出运费预估”就串了三个职责,任何一步出错你都定位不到是哪一步出的错。
第二,中间产物持久化。链条上一环的结果不能只存在内存里,必须在每一步完成后落盘(数据库或对象存储)。这既是数据审计的需要,也是失败恢复的抓手——很多时候不是重跑整条链,而是从失败节点恢复重新执行。
第三,幂等设计。链式系统里同一环节被重复执行的情况非常常见,比如网络超时后客户端自动重试。如果这个环节是“写库”或“调对外接口”,重复执行就会产生脏数据或重复扣费。所以每个环节的入参里必须带唯一事件ID,处理前先查重,做不了幂等的环节,至少要做到可对账。
第四,失败传播策略得提前定。链式里有三种失败方式——前级输出为空、解析失败、模型超时。我的做法是每个环节都配置一个“失败出口”:要么终止整链并通知上游,要么走一个降级子流程,要么把异常信息追加到消息体里继续往后传。注意,没有兜底策略的链式架构,等于没有安全气囊的汽车。
2.4 路由式的分类质量与兜底策略
路由式架构的门面是入口,核心是决策质量。如果你的入口分类不准,后面的流程再精妙也没用。
分类实现有两种路线。一种是用LLM做语义分类,比如让Agent判断“这个请求属于订单查询、售后投诉、建议反馈中的哪一类”。一种是用Embedding相似度匹配,把用户请求向量化,跟预置的各类别样本向量比相似度。各有各的问题,我给出的建议是混合使用:先用相似度匹配拿到Top-2候选,再用LLM在候选里做最终判定。这样既避免LLM在太多类别里犯选择困难,又能弥补相似度匹配对语义深层理解不足的缺陷。
路由置信度阈值也是个关键参数。阈值太高,很多请求会掉进“无法分类”的兜底流程里;阈值太低,各种不相干的请求被硬塞进某个流程,后患无穷。我的经验是从0.7起步,根据线上日志动态调整:如果A类任务被误分到B类的比例高于5%,就该上调B类阈值,同时补A类样本。
设计兜底流程时有个容易踩的坑。不少人觉得兜底就是“找不到就道歉抱歉”,但实际兜底应该做成“澄清-重试-转人工”三级。第一级:告诉用户“我没太理解,您是想要XX还是YY”,给出选项引导用户重新表述;第二级:用另一种分类策略重新判一次,比如换Embedding模型或者换Prompt;第三级:转到人工或预设的通用FAQ流程。三级的兜底结构,能极大降低路由系统的不可用率。
3. 实操过程:从一个具体项目看三种架构落地
3.1 场景设定:某智能客服工单系统的改造
理论讲了一堆,下面用一个模拟项目把三种架构串起来。场景是“某电商平台的智能客服工单系统”,业务背景是每天收到几千条用户消息,需要自动分类、提取关键信息、生成处理摘要、派发到对应业务组。
原系统是一个巨大的增强型Agent,一条Prompt包打天下。结果就是客服团队天天抱怨:有时候把抱怨当成了咨询,有时候把退换货请求当成了物流查询,处理摘要格式不统一,业务组接单后还要重看原始消息才能理解上下文。于是我们做了架构改造,整体设计成“路由式入口 + 增强型处理Agent + 链式子流程”的混合架构。
改造后的整体流程是这样的:用户消息先进入路由层,判定为“物流咨询”“退换货请求”“建议反馈”“无法识别”四个大类。其中“物流咨询”走一个增强型Agent,查订单系统、查物流接口,OR备选查询方案,生成答复建议。“退换货请求”走链式流程:先做信息抽取,把订单号、商品ID、问题描述抽出来;再做退款计算;最后生成售后处理摘要,输出给业务组。“建议反馈”则直接入库存留,定期汇总。“无法识别”进入兜底流程,先澄清再转人工。
3.2 第一步:把需求拆成可路由的意图树
动手前我们做的第一件事,是把所有客服会话历史翻出来,统计高频意图。这里有个很核心的经验:意图树不是拍脑袋定的,是拿真实数据喂出来的。
我们拉了一个月的工单数据,按人工客服的归类方式做聚类,最终收敛出四级意图树。注意不需要无限细分,只要分到“能对应到不同处理流程”这个粒度就够了。比如“退换货请求”下级还拆了“仅退款”“退货退款”“换货同款”,但这三个走的是同一套链式流程,只是参数不同,所以路由层只分到“退换货请求”这一层。
每个意图路由目标都预置了“样本示例”,比如“物流咨询”的示例有“我的快递不发怎么办”“都三天了还没更新物流”“能帮我催一下快递吗”等等。每个意图至少预置了十条示例,样本数量直接影响Embedding匹配的准确度,太少根本匹配不准。
3.3 第二步:实现路由层与增强型单Agent
路由层的实现,我们选了“Embedding召回 + LLM判定”的混合策略。具体来说,用户消息先转化为向量,在所有意图样本里取相似度Top-2。然后构造一个精简Prompt,让模型在这两个候选中选一个,并输出置信度,全程使用较低温度保证稳定性,温度参数我通常设在0.1以下。
这里有个实际参数:Embedding召回的相似度阈值是0.55,低于这个值直接判定为“无法识别”,不再进LLM二次判定。LLM的置信度阈值是0.75,低于0.75也归入“无法识别”。两个阈值配合使用,最终“无法识别”的比例大约在8%左右,这个比例是可接受的,因为还有三级兜底在撑。
物流咨询子流程的增强型Agent,我们做了三个增强点。一是接入了订单信息检索接口,先把用户关联的订单信息查回来做上下文。二是接了物流查询工具,并设计了备用方案:A方案调物流平台API,B方案调缓存中最近一次物流快照。三是建了一个“客服安全边界”规则库,比如遇到“要求补偿”“要求加急”时Agent只能记录不能承诺,这个规则以指令形式注入系统提示词。
3.4 第三步:在子流程中用链式串联多个子Agent
退换货请求的链式流程是这个项目里最复杂的部分。链路总共四段:信息抽取、条件校验、动作决策、摘要生成。
信息抽取段:Agent把用户原始消息转为结构化数据,包括用户ID、订单号、商品ID、问题类型、诉求描述。这里用到了严格模式输出,要求模型只输出JSON,任何多余文字都被视作失败。
条件校验段:这里不是模型处理的,是传统代码在处理。拿到结构化数据后,查订单系统核对订单是否真实存在、是否在售后期内、是否已发起过售后。这块用传统代码的原因是,规则是刚性的,不需要模型做模糊判断,用代码更稳定。
动作决策段:根据校验结果决定“自动退款”“转人工审核”“拒绝并说明原因”三类动作。这里也用了增强型Agent来写“拒绝并说明原因”的话术,因为这种场景需要模型生成语气合适的解释文案,同时保持信息准确。
摘要生成段:把前面的结构化数据和处理动作摘要成一段自然语言描述,推给业务组。摘要格式有严格的字段要求,包括处理结果、建议、风险标记等,确保业务组能直接看摘要干活,不用返回原文。
3.5 第四步:观测与迭代
整个系统上线前,我们还做了几件观测层面的准备。第一是给每个消息都生成了完整的链路追踪ID,从入口路由到最后摘要生成,每个节点的耗时、token消耗、状态码都记录成结构化日志。第二是搭了一个“评估集”机制:每个工作日抽样50条历史消息,人工标注路由分类是否正确、链式各段输出是否达标,算出一个“架构健康分”。这个分数直接反映系统在真实分布上的表现,比看几个演示案例靠谱得多。
在迭代节奏上,有一个反直觉的经验:不要每天调Prompt。Prompt调整一次,你至少要给它一周的线上数据来验证效果,否则很容易被噪声样本带偏。我们现在的节奏是每两周做一次集中调优,平时只修明显的case级错误。
4. 常见问题排查与避坑实录
4.1 典型故障:路由误判、链路中断、上下文污染、工具超时
做这套系统以来,遇到最多的问题集中在四个地方。
路由误判的典型案例:用户说“你们这个洗衣液是不是有问题,用了之后手上起红疹”,系统分成了“产品效果咨询”,而不是“投诉维权”。原因是我们预设的投诉样本太偏向“情绪化表达”了,忽略了很多理性陈述的投诉。解决方法是去真实投诉工单里补充样本,而不是拍脑袋写示例。
链路中断的典型案例:信息抽取段全部字段都成功解析,但条件校验段发现订单号格式不对,导致链路断裂。查日志发现,用户消息里写的订单号是“OR D2024”这种带空格的,Embedding检索没问题,但严格正则匹配挂了。这类问题的核心不是正则写不好,而是链式架构缺少“数据清洗前置节点”。
上下文污染的典型案例:增强型Agent在处理物流咨询时,把前一个用户的历史投诉记录也检索进来当作上下文,导致回答风格突然变得非常防御性。这个问题说明了“检索范围隔离”的重要性——业务A的工单记录不能让处理业务B的Agent随意检索。
工具超时的典型案例:物流平台API晚间高峰期响应要5秒以上,Agent等待期间整个链路超时。解决方式其实很简单:给工具调用设独立较短超时指标,超时就走降级缓存方案,不让模型干等。这个优化之后,整个系统的P95响应时间下降明显。
4.2 常见问题速查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 路由分类结果跳来跳去 | 温度过高、样本相似度接近 | 将分类温度降到0.1以下,给相似样本差异化描述 |
| 链式下一环节经常解析失败 | 上一环节输出格式不稳定 | 使用严格结构化输出范式,并加一轮格式校验重试 |
| 多个会话互相干扰 | 全局上下文混用 | 为每轮会话建立独立隔离的上下文存储区 |
| 工具调用频繁报错 | 工具描述与实际参数不符 | 在描述里加入参数示例,预置参数校验环节 |
| Agent重复执行相同操作 | 网络超时导致客户端重试 | 为操作节点设置唯一事件ID,实现幂等控制 |
| 增强检索结果质量差 | 检索范围过大、噪声多 | 增加元数据过滤,缩小检索范围,提高相似度阈值 |
| 输出内容出现冲突信息 | 上下文里新旧信息矛盾 | 在注入上下文前做时间戳筛选,过期信息降权 |
| 系统成本突然飙升 | 链式环节无节制的全量重跑 | 为每个重试场景设置最大次数上限,失败走降级流程 |
4.3 我踩过的坑与经验心得
最后分享几条可能是文档里永远找不到的实操经验。
第一,路由目标宁少勿多。同一个系统,路由目标从4个扩到9个之后,分类准确率没有提升反而下降。原因是目标越多,样本边界越难划清,相邻意图互相污染。如果需要很细的分类,试着把它们拆到路由之后的子流程里去判断,而不是全部押在路由层一次搞定。
第二,链式架构里的“中间人”要克制。有些环节看着可以“顺便”做点别的,比如信息抽取环节顺便生成个标题、顺便做个情绪判断。但一旦加了“顺便”,这个节点的输出就不能被其他环节稳定预期了,排查问题的难度直线上升。
第三,增强型架构最怕过度增强。一开始我们往Agent里塞了超长系统指令、历史对话摘要、知识库Top-5、工具描述十几条,结果模型输出变得犹豫、话痨、频繁自我纠正。后来做减法,把系统指令压到一屏以内,删除低价值工具,上下文清清爽爽,输出质量反而上来了。
第四,架构是动态演进的。我们的系统上线时是“路由 + 增强型”,运营一个月后才发现退换货场景需要稳定流水线,才补上了链式子流程。所以不用指望一次选型终身正确,关键是让系统具备“演进能力”——消息契约先行、各节点解耦、观测体系完整,这三点做到位,从一种架构演进到另一种架构的成本就会小很多。
做Agent工作流架构这件事,我最大的体会是:它的本质不是“把模型接进来”,而是“把不可控的模型关进可控的笼子里”。三种架构是三种笼子——增强型是把笼子加固,链式是给笼子隔间,路由式是把不同的鸟分到不同的笼子。理解这一点,很多设计决策都不用纠结了。