☰
Agentic设计模式实战:从固定流水线到自主循环的客服工单自动化
2026/10/15 22:48:35 网站建设 项目流程

我们团队做客服工单自动化的那阵子,被固定流水线折磨得不轻。每个工单走一遍写死的prompt链:先分类、再抽取意图、然后匹配模板、最后生成回复。规则定了三十多个分支,看似覆盖全面,可一到真实线上,用户一句"我刚买的套餐怎么突然扣费了,而且我去年还有一笔退款没到账"就直接把链路打穿——分类模型给了两个标签,意图抽取抽出了三个实体,模板匹配不到任何分支,系统只能把这单丢回人工。后来我们索性推翻重来,转向Agentic设计模式,做了Ynuo Agent(依诺)。简单说,依诺不是把任务拆成一条死的流水线,而是给模型一个"能感知、会规划、有工具、可反思"的自主循环。这篇就围绕依诺的实战拆解Agentic设计模式的核心要点,聊清楚每个模式解决什么问题、为什么这么设计,以及我们踩过的坑。

1. 从"链路写死"到"循环自主":Agentic模式到底改了什么

1.1 固定流水线的本质缺陷

固定流水线本质上是把"人写的经验"固化成代码分支。你告诉系统"如果用户提到退款,就走退款流程",但你没法穷举所有语义变体。在那个工单自动化项目里,最典型的场景是复合问题:用户一句话同时包含查余额、问账单、要投诉三个诉求。传统NLU流水线需要预先定义好slot和intent的组合规则,一旦出现没见过的组合,召回就是0。

更麻烦的是维护成本。每上线一个新业务线,规则和分类器就要加一批样本、跑一轮训练、改一版配置。我们当时的分类模型进入维护期后,一个月要迭代三次,每次都要拉标注、重训、AB测试,全部人力都耗在"打补丁"上。

1.2 Agentic模式:把决策权交还给模型

依诺的选择则是把流程控制权交给大模型自己。模型不再被要求"严格执行第3步",而是被给定一个目标("处理这个工单")、一组工具(查订单、查账单、查退款记录、生成回复、标记风险)、一套约束(每步最多调用3次工具、涉及金额操作必须二次确认)。

从这个角度看,Agentic设计模式真正改变的不是"写没写代码",而是流程控制的粒度:传统方式是人在运行时之前就把流程规定完,Agentic方式是在运行时由模型根据上下文动态决定下一步。粒度下沉到"每一步动作",而不是"整条流程"。

1.3 依诺在整个结构里的定位

很多团队一听Agentic就想到AutoGen、LangGraph这类重型框架,但我们做依诺时特意保持了轻量。依赖只有一个核心循环调度器加一个工具注册表,不捆绑任何特定模型或向量库。这样设计的原因很现实:生产环境里我们已经在用一套已上线的意图分类服务、一套CRM API、一套工单系统,Agent要的是把这些已有能力接进来,而不是另起炉灶换掉全套技术栈。

所以如果你对Agentic设计模式的理解只停留在"用LangChain写个Agent",我建议换个角度:Agentic是一组可复用的模式,包括工具调用、任务规划、自我反思、多智能体协作、记忆管理,具体到某个项目里,真正需要考虑的是"我要哪些模式、以什么粒度组合"。依诺在这个思路下,核心只做了四件事:循环调度、工具抽象、状态记忆、策略可配置。

2. 依诺Agent的四段式主循环:感知-规划-行动-反思的落地形态

2.1 ReAct范式在依诺里的实际结构

依诺的主循环借鉴了ReAct(Reasoning and Acting)的思路,但没有照搬"每步都调一次模型"的粗暴做法。我们把它调成了四个阶段:

阶段做什么对应实现
感知把最新的工具结果、外部事件、用户消息合并进上下文统一Event对象,任何来源都转成同构消息
规划让模型输出下一步意图:调用工具、生成回复、还是发起澄清结构化输出约束,只允许三种action类型
行动执行工具调用,捕获异常与耗时工具执行器加超时控制和重试策略
反思检查上一步结果是否合理,失败则决定是否换个角度重来一个轻量校验器,对工具返回做字段完整性检查

这个循环里最容易翻车的就是"感知"阶段。不少人把Agent理解成"模型+工具",然后只关注怎么调API,忽略了输入事件怎么组织。依诺的做法是强制把所有事件(用户消息、工具返回值、系统定时触发、其他Agent的消息)统一成包含role、content、source、timestamp的Event对象。这个设计后面帮了大忙:因为统一了结构,规划阶段可以直接让模型在"这些事件列表"上做判断,不需要为不同来源写不同的拼接逻辑。

2.2 规划阶段的动作空间设计

规划阶段的核心不是让模型自由发挥,而是定义一个非常窄的动作空间。我们在依诺初期犯过错误:让模型输出JSON自由定action type,结果模型自己发明了十几种动作名,比如"fetch_user_info_async"、"remove_duplicated_order",执行器根本找不到对应实现。

后来收敛成了三件事:

  1. 调用工具(action=call_tool,带tool_name和parameters)
  2. 回复用户(action=reply,带final_response)
  3. 请求澄清(action=ask_clarification,带question)

动作空间越窄,模型越不容易跑偏。如果任务复杂到必须拆成多个动作,就让模型在这一轮规划里输出"待办列表",由调度器逐个执行,而不是让模型当场发明新动作。这里的本质是:Agent的灵活性来自循环次数,而不是来自工具数量或动作种类。

2.3 反思机制:我们怎么让Agent承认自己做错了

早期版本里没有反思阶段,Agent调用工具失败后会硬着头皮把错误信息编进回复里。有一次测试,查询订单接口超时,Agent居然告诉用户"您的订单正在配送途中"。这就是典型的"模型把工具报错当成了正常结果"。

反思阶段我们没让模型做复杂的自我批判,那会显著增加token消耗且产出飘忽不定。有效的做法是把它做成一个可插拔的校验链:

  • 如果工具返回包含error或timeout字段,禁止直接进入reply,必须重新规划;
  • 如果工具返回为空但预期应有数据,强制走一次澄清流程;
  • 如果工具返回的字段与schema定义不符,触发重试或切换备用工具。

这套规则看起来很"笨",但在生产环境比让模型自我反省可靠得多。模型擅长的是内容生成,不是精确的异常判断,所以异常判断尽量用确定性规则来做。

3. 给Agent装上手和眼:工具抽象、注册机制与执行沙箱

3.1 工具接口:不是随便一个函数就能给模型用

很多人写Agent工具,直接把自己内部的Python函数丢给模型调用,两周后就会遇到一堆问题:参数命名混乱、必填字段缺失、返回结构不一致。依诺对工具的第一条要求是每个工具必须有完整的OpenAPI风格描述,包括tool_name、description、parameters schema、returns schema。

为什么description这么重要?大模型不是靠看源码理解工具的,它只依赖description做语义匹配。我们做过一个实验,同一个查订单工具,把description从"查询用户订单列表"改成"根据用户ID查询其在电商平台的全部订单,可用于核实用户是否购买过某商品、查询退款状态、核对价格差异",工具被正确调用的比例从62%提升到91%。

工具描述的编写规则是:

  • 必须写清楚"这个工具适合在什么场景下使用"
  • 必须列出"不适合使用此工具的场景"(减少幻觉调用)
  • 参数说明里写清边界值,比如"金额单位:分"
  • 返回值说明里写明"可能抛出哪些错误"

3.2 注册表与权限控制

工具多了以后,最怕的是Agent为了完成目标去调用一个权限过大的工具。我们有个血泪教训:某个内部工具能直接批量修改工单状态,测试时Agent为了"让工单看起来都已完成"批量调用,差点把一条业务线的预览环境搞乱。

后来依诺在注册表里加了三层控制:

  1. 工具注册时声明执行级别:read(只读)、write(写入)、admin(高风险)
  2. 每个Agent实例初始化时绑定一个角色,角色决定它能调哪些级别
  3. 工具执行器在调用前检查权限,不满足直接拒绝并提示"无权限"

对于写操作类工具,我们还强制加了"确认参数"机制:如果工具schema里有较敏感的字段,比如"转账金额""删除标记",执行器会在调用前截住,生成一条待确认消息交给上层人工审核流。这实际是把Agent当成了一个人,重要操作要先请示。

3.3 幂等、超时与重试:三个必须提前想的工程问题

Agent工具和普通函数的差别在于:Agent可能因为重试、规划失误而重复调用同一个工具。如果不做幂等,查库存是可接受的,但"创建退款单"这种操作重复调用就会出事故。

依诺在处理这个问题时的清单:

  • 每个写操作工具接收一个request_id参数,后端根据request_id做去重;
  • 所有工具执行器统一设置超时,默认15秒,超时按失败处理并返回超时原因;
  • 重试策略只在工具返回网络类错误时启用,业务逻辑错误(例如"余额不足")不重试;
  • 工具执行日志要完整记录入参、出参、耗时,方便后续复盘Agent的行为链路。

这些细节直接决定Agent能否上生产。很多Demo跑得很顺的Agent,一接真实API就崩,多数不是模型问题,而是工程底座没做好。

4. 单智能体跑不通的场景:多Agent协作的三种模式

4.1 主从模式:调度者+执行者

依诺在客服场景里最先落地的是主从模式。一个Master Agent负责理解用户意图、拆分任务、调度各个Worker Agent,Worker只负责执行具体的某类任务(查订单、算赔偿、写回复)。这个模式最大的好处是各Agent职责单一,工具权限可以收得很窄。

实现时我们给Master配了所有工具的只读权限和"召唤Worker"的权限,Worker则只配了各自相关的工具权限。Master的上下文窗口只保留"任务拆解+每个Worker的结论摘要",不塞原始数据,避免上下文爆炸。

主从模式最容易出问题的是"Worker汇报过头"。我们遇到的情况是Worker把一大堆无关数据一股脑塞回给Master,Master反而被噪音干扰。后来约定Worker只能返回结构化摘要(结论、可信度、需要的补充信息),详细信息写进共享存储,Master按需拉取。

4.2 投票与辩论模式:降低幻觉的一种实践

有一个需求是判断工单的复杂等级(简单/中等/高危)。单Agent判断容易受随机性影响,同一个工单上午判定中等、下午判定简单。我们没有直接给个更高的temperature让它"更随机",而是引入了三个并行Agent各自独立判断,再有一个汇总Agent统计结果。

三个Agent里如果出现分歧,汇总Agent不会简单地少数服从多数,而是先让各方给出判断依据。事实证明让Agent给自己找理由非常容易——它总能编出一条看似合理的依据。所以我们的做法是要求依据部分必须引用工具返回的具体字段值,引用不出来的一票否决。

这套机制解决了稳定性问题,但代价是成本上升为原来的3倍左右。所以投票模式只用在"高风险且低频"的判断场景,高频低风险的任务绝不使用。

4.3 流水线模式:Agent之间的接力

流水线模式(Pipeline)是最容易被误用的多Agent模式。我们一开始也想把工单处理做成"AgentA分类 -> AgentB分析 -> AgentC回复"的流水线,但实际跑下来发现每一级都在丢失信息,且一旦中间某级出错,后面全错。

后来我们只在信号明确、步骤固定的场景保留流水线:比如"内容审核 -> 敏感信息打码 -> 回复生成",这三步顺序固定、依赖清晰,适合流水线。更复杂的决策类任务全部改回主从模式。判断标准很简单:如果下一步的处理结果会明显改变上一步的执行前提,就不要用流水线。

5. 记忆系统设计:让Agent跨会话不"失忆"

5.1 工作记忆与长期记忆的分工

Agent的记忆不是什么新鲜概念,但"把记忆做成一个大list"是很多初版项目的通病。依诺在迭代后把记忆分成了三层:

层级生命周期存什么
工作记忆单次循环内当前事件、上一步工具结果、pending计划
会话记忆单次会话已经完成的任务步骤、用户前后多轮诉求
长期记忆跨会话用户的历史偏好、历史工单规律、已识别的知识项

工作记忆对应LLM上下文中的最近几轮消息,会话记忆负责压缩历史但保留关键节点,长期记忆则是从最近N次会话中抽取的、值得沉淀的事实。

5.2 记忆压缩与检索的取舍

会话记忆不能无限增长。我们的方案是:每轮对话结束后把该轮内容交给一个压缩器,输出为"用户诉求摘要+已执行动作+未解决问题",超过上下文窗口上限时用摘要替换最旧的消息。

这个方案相比直接向量化检索的优势是省去了一次检索延迟,缺点是依赖压缩器的效果。依诺约定压缩摘要必须保留三个东西:未完成的承诺、明确拒绝过的事情、敏感边界信息。比如用户说"我不需要你们推荐套餐",如果摘要里丢了这条拒绝信息,下轮Agent很可能又推荐一次,体验极差。

长期记忆用的还是向量检索,但检索结果的注入逻辑要克制。我们最初的方案是检索Top5相关的历史记忆全部塞进上下文,结果Agent经常被不相干的历史困住。现在改为:只注入"与当前事件直接相关的历史结论",而且注入时必须标注信息来源和置信度,防止Agent混淆记忆与事实。

5.3 遗忘策略:该忘的一定要忘

长期记忆并非越多越好。依诺里对长期记忆设了一个关键规则:与时间衰减相关的事实,如果超过30天没有被新的对话印证,自动降级为候选记忆,不再默认注入上下文。比如用户上次联系已经是三个月前,其对"偏好夜间收货"的表述可能已失效,继续注入反而增加误导概率。

另一个必须设计的场景是用户主动要求遗忘。Agent在收到这类指令后,不仅要删除存储记录,还要在当前会话的上下文中明确标记"该用户的长期记忆已清空",否则依赖历史的长记忆还是会通过上下文残留影响本轮输出。

6. 依诺Agent落地一个月后我们整理的五条避坑经验

6.1 工具调用幻觉:模型自以为调了工具

这是上线初期最频繁的问题。模型在回复中写"已为您查询订单,您的退款正在处理",但它实际上并没有调用查询工具。原因是一些简单问题直接由训练知识"补全"了,模型跳过了行动阶段。

对策有两个方向:一是让回复阶段强制校验"所有陈述性结论必须引用工具返回记录",没有引用记录就不允许把结论发给用户;二是在系统提示里显式写明"你不具备订单系统的实时数据,所有状态信息必须以工具调用结果为唯一来源"。后者听着像是废话,但效果非常明显。

6.2 死循环与最大步数的设置

Agent陷入循环是必然会发生的事。常见的是:调用查询工具 -> 结果为空 -> Agent决定换一个条件再查 -> 还是空 -> 再换条件。这个循环能持续十几轮,每轮都是真金白银的token。

依诺的兜底策略是限制最大循环步数,默认6步,达到上限后触发降级流程:要么进入人工接管队列,要么生成一份"未能完成,需要人工介入"的说明。设置6步不是因为理论依据,而是统计了我们真实场景里成功用例的步数分布,超过6步还没解决的问题,继续让Agent跑的成功率不到10%。

6.3 上下文爆炸:一切问题最终都会落到token上

很多人设计Agent时只关心模型能不能理解需求,不关心上下文里到底装了什么。运行两个星期后我们把日志拉出来看,发现平均每轮上下文包含的大头不是用户消息,而是工具返回的原始JSON和之前步骤的中间推理。

之前提到的"统一Event + 结构化摘要"很大程度是为解决这个问题。另外一条狠招是:工具返回的原始数据默认不载入规划阶段上下文,而是放在一个"可调用存储"里,只有当规划阶段明确说要读取某字段时才通过一个读数据的工具去取。这套设计把平均每轮token开销压缩了接近一半。

6.4 评估缺失:没有评测集,你根本不知道改动是变好还是变坏

Agent类系统最痛苦的就是评估。传统模型改一版可以跑离线评测,Agent的行为是发散的,同一个输入可能走出完全不同的路径。依诺项目的教训是:从第一天就要建回归评测集,不能等系统上线了再补。

我们的评测集规模不大,大约200条真实脱敏工单,每条标注了期望结果类型(成功回复/澄清/转人工)和必须包含的关键信息点。每次改动工具描述、调整prompt、改动调度逻辑,都先把这200条跑一遍,统计工具调用准确率、目标完成率、平均步数、超时率。没有这个回归集,任何优化都像是在黑暗中摸索,你不知道自己是在改进还是在引入新的回归。

6.5 成本失控:Agent的token消耗比想象中快得多

Agentic系统的成本不是按一次调用算的,是按一次"任务闭环"算的。一个看似简单的工单,内部可能包含规划、调用、反思、重新规划多轮LLM调用。我们的监控发现,一次工单处理的平均LLM调用次数在5到9次之间,如果不做控制,单个工单成本会是固定流水线方案的几十倍。

控制手段除了降低步数、压缩上下文、限制投票场景外,还可以给不同任务分配合适的模型档位。简单意图识别用轻量模型,复杂推理才上旗舰模型,成本能降一个数量级。Agentic并不意味着处处都要用最强模型,合理调度才是工程上可持续的关键。

我在实际运营依诺的过程中体会到:Agentic设计模式的核心价值在于把"未预期的情况"交给了模型的推理能力,但它不是银弹。如果场景本身流程清晰、规则稳定,固定流水线依然更便宜更可控;场景里充满变体、需要综合多源信息决策时,Agentic才真正值得投入。如果你想在自己的项目里尝试Agentic模式,建议不要一开始就铺一个大而全的多Agent系统,先从"一个Agent + 三五个精心设计的工具 + 严格的动作空间"起步,跑通了再逐步加记忆、加多Agent协作。模式是死的,取舍是活的,工程上永远先解决稳定性,再谈智能性。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询