Agent开发的核心不是框架,而是这五件事——两年实战总结

1. 做了近两年Agent开发,我先说结论:框架真的不值钱

先交代一下背景。我是做后端出身,后面转大模型应用开发,从某个还比较早期的阶段就开始碰Agent相关的东西。前后加起来差不多两年时间,主流的和不太主流的框架都试过,自己也在团队内部从零搭过两套Agent脚手架。一直以来在社区里最常见的问题就是:"做Agent开发到底要学什么?""Agent开发的学习路线是什么?"。

很多人的第一反应是:学LangChain、学AutoGen、学CrewAI,或者研究一下Hermes、Pi这样的新框架。不能说不对,但以我实际做项目的体感来说,这些东西恰恰是最不重要的。框架是流水线上的扳手,换个型号最多别扭两天。真正卡住项目进度、决定Agent能不能落地的东西,从来不是某一行API调用,而是下面这五件事——Agent的目标与任务拆解、工具(Skill)设计、记忆体系构建、多Agent协作模式、以及让整个系统稳定跑起来的评测与防错机制。

这篇文章不科普概念,我只讲在真实项目里踩过的坑、验证过的做法,以及不同方案之间到底怎么取舍。无论你是刚准备入门的开发者,还是已经在做Agent项目但总觉得"代码能跑、效果拉胯",这篇文章应该都能给你一些可以照抄的经验。

2. 第一件事:先搞清楚Agent的边界,再谈别的

2.1 单Agent任务本质上是"输入状态机"到"输出状态机"的映射

很多人做Agent开发一上来就设计Prompt,或者先选框架,这在我看来是顺序反了。做Agent的第一步,一定是把一个宽泛的用户需求,变成一个"可以用工具序列完成"的计算问题。

我习惯用一个比较土但有效的说法:Agent是一个接受"目标状态"和"当前状态"作为输入,输出"行动序列"的系统。中间怎么推理、怎么调用工具,反而不是本质。本质上,我们要解决的就是两件事:

  1. 理解当前状态:用户到底在什么背景下提问,手里有什么资源,限制条件是什么。
  2. 定义目标状态:什么样的输出算是"完成",哪些情况要停止并寻求人工介入。

举一个我做过的例子。一个纯客服Agent,表面上处理的是"用户退货申请"这个任务。如果不加边界,模型会尝试理解用户情绪、判断责任方、甚至开始跟用户道歉——这些都在消耗上下文、延长推理时间,而且大概率产出不稳定的结果。当我把任务边界改成"判断退货条件是否满足 + 提取必要订单信息 + 调用退货接口"三件事之后,系统的稳定率直接提升了近30%。

这背后的原理其实很简单:LLM在开放域的推理能力是统计性的,一旦任务边界模糊,它的输出方差就会指数级增加。把任务边界定义得越清晰,模型的推理路径越短,幻觉率越低。

2.2 任务拆解不是"分步骤",而是"分决策点"

这里有一个很常见的认知误区。新手做任务拆解,喜欢把任务拆成"第一步做什么、第二步做什么",这其实是流程拆解,不是任务拆解。真正的任务拆解,拆的是决策点。

什么意思呢?流程里的每一步执行,不一定需要Agent做判断;但每一个需要根据输入内容变化而选择不同路径的地方,才需要Agent介入。我举一个内部项目里的拆分案例:

子任务是否拆出独立决策点理由
提取用户订单时间否纯信息提取,正则或结构化输出即可
判断是否在退货期内是需要多条件组合判断,且存在边界情况
选择退货方案是根据用户地址、商品类型选择不同流程
生成退货回执否模板化输出,固定格式拼接即可

如果你接触过React Agent或者Swarm这类偏底层的框架,你会发现它们的核心能力之一就是"根据当前状态决定下一步动作"。这个动作的选择,本质上就是在决策点之间的跳转。所以任务拆解得越细,Agent的每个决策点越简单,整个系统就越接近"确定性程序+少量智能判断"的组合。这个组合越稳定,Agent越可靠。

2.3 给Agent立"规矩":什么时候必须停下来

这一点是我认为所有做Agent的人最容易忽略的。我们用LLM做Agent,天然有一种倾向是"让模型尽量处理所有情况",但实际项目里,设计"什么时候不做"比"怎么做"更重要。

我早期做的其中一个Agent,用户问什么我都想让模型硬接。结果就是:模型会编一个查询条件、会猜一个不存在的订单号、会把退款金额计算出负数。后来我总结了一个硬性规则:当置信度低于某个阈值或者关键信息缺失时,Agent必须调用一个"澄清工具"或者直接转人工,而不是继续推理。

这个规则怎么落地呢?不是靠一句Prompt里的"如果你不确定请询问用户"——那样模型会过度询问,体验极差。正确的做法是让Agent在决策点强制校验参数:比如查询订单号,必须匹配"数字+字母组合"的正则,否则就触发澄清分支。也就是说,把关键约束放到工具层的参数校验里,而不是放到模型层的自觉里。这个经验,回头我会在第5部分展开讲。

3. 第二件事:工具不是越多越好,重点是"能被模型调对"

3.1 Skill、Tool和Action的关系,别被各种框架绕晕

最近Agent开发社区里有一个讨论度很高的点:Skill和Agent的区别到底是什么?其实各家框架的命名不太一样,但底层逻辑是共通的。

  • Tool(工具):最小的可执行单元,比如"查询天气API""计算运费""生成图片"。
  • Skill(技能):一组围绕某个场景组织的"提示词+工具集合",比如"售后处理技能"里包含订单查询工具、退货判断规则、话术模板。
  • Agent:一个拥有目标、记忆和决策逻辑的运行时载体,它根据当前状态选择调用哪个Skill或Tool。

我见过不少人把Skill直接理解成"多个Prompt的集合",这有偏差。Skill的封装对象是能力,而不是文本。一个合格的Skill应该包含三部分:触发条件描述、工具清单、执行策略(包括边界规则和错误处理)。

举个例子。我给一个内容审核Agent封装过一个"图片安全审核"Skill,它里面包含:图片描述工具、安全策略判断规则、以及拒绝内容的回复模板。当用户上传一张图,Agent先判断"是否需要审核",再调用Skill,Skill内部再去调度具体的API。这样的分层方式,比让Agent直接在几十个工具列表里选要稳定得多。

3.2 工具定义的质量决定了Agent的"智商"

关于工具这里,我最想强调的一个点是:工具描述写得不好,等于没给模型导航。以OpenAI Function Calling的经验来说,模型是通过工具的description来理解"什么时候该用这个工具"的。结构化参数只是第二步。

我自己吃过亏。有一个项目里,我定义了一个"获取用户信息"的工具,description写了一句话:"获取用户基本信息。"结果模型在用户问订单问题的时候也调用它,因为模型的逻辑是"查订单之前得先知道用户是谁"。后来我把description改成:"当用户提供手机号或用户ID时调用,用于获取该用户的注册信息、会员等级和常用收件地址。该信息用于辅助售后判断,不能直接作为订单查询结果。"改完之后调用准确率明显提升。

所以给到读者一个非常实用的建议:写工具描述时,一定要交代清楚三件事——什么时候用、用之前需要哪些参数、用了之后返回什么结果能够接续什么决策。这比你在Prompt里写一百句"你要聪明一点"都管用。

3.3 我见过的工具设计最佳实践:按"业务能力域"收敛

早期我做一个功能,顺手定义了二十多个工具接口。结果每到关键决策的时候,模型选择工具的时间明显变长,而且经常选错。后来做了一次重构,把工具按业务能力域收敛成四个大工具,每个大工具内部自己负责路由和错误处理,整个系统的表现反而好了很多。

这个思路跟RPC框架里的BFF层有点相似:不要让模型面对数百个细粒度工具,而是给它提供几个"总闸门"。每个闸门内部,再通过参数区分具体操作。这不仅降低了模型的选择难度,也让工具的测试和Mock变得更加容易。

下面是当时重构前后的对比,非常直观地展示了为什么"少而粗"有时优于"多而细":

维度重构前(细粒度工具)重构后(能力域工具)
工具数量24个5个
工具调用准确率约82%约96%
单次决策延迟约2.1秒约0.9秒
mock和测试难度高,需要逐接口mock低,按域mock

4. 第三件事:记忆体系不是"聊天记录",而是结构化决策上下文

4.1 短期记忆、长期记忆、永久记忆到底怎么落地

"Agent记忆"这个话题最近逐渐热起来了,相关的框架也越来越多。很多人问我记忆体系到底怎么设计。我先说一个最核心的认知:记忆的本质,是让Agent在做决策时拥有上下文,而上下文的形式远不止"聊天记录"一种。

按时间粒度和用途,我把记忆体系分成三层:

  • 短期记忆(工作记忆):当前对话轮次中需要临时保存的信息,比如"用户刚才说订单编号是A12345"。这一层通常存在于上下文窗口内,用完就丢。
  • 长期记忆(场景记忆):跨对话持续有效的业务信息,比如"用户偏好顺丰快递""该用户是企业级会员"。通常存储在处理后的向量库里,按需检索注入。
  • 永久记忆(知识记忆):几乎不变的数据资产,比如商品的售后规则、退货政策、渠道费率表。它们不太需要向量化的语义检索,更适合用结构化存储加规则引擎。

这三层记忆分开建,不要混在一个Redis或者向量库里。否则就会出现一个经典问题:用户刚聊完的事情,下次对话被错误地当成了历史偏好,甚至污染了政策判断。

4.2 记忆检索里的时效性是大多数项目翻车的根源

我一直有一种观点:Agent的记忆检索,难点不在"如何存进去",而在"什么情况下应该忘掉"。以长期记忆为例,在向量检索时如果不加时间衰减,会出现这样的窘境:用户三个月前问过某型号的维修方法,三个月后他问"现在这个机器出问题了怎么办",Agent反而把三年前的旧方案检索了出来,因为新对话里没有更相关的文本片段。

我的做法比较朴素但有效:在每条记忆入库时打上last_access_time和hit_count两个标签。查询的时候,除了语义相似度,还要计算一个"时效得分",两者做加权和。具体公式大致是:

final_score = 0.7 * cosine_similarity + 0.3 * time_decay_factor

其中time_decay_factor按天递减,比如pow(0.99, days_since_last_access)。这样新近的记忆会得到额外加成,旧记忆慢慢淡出检索结果。效果上,实测能让"记忆串味"的问题减少一半以上。对于很多中小型团队的Agent项目,这个简单方案已经足够用了。

4.3 从选型角度聊聊:哪种记忆框架适合什么项目

最近社区里有很多记忆框架和选型相关的讨论,比如Mem0、MemGPT、Letta,还有Zep。我统一说一下我的选型感受:

框架/方案优势适合场景
自建结构化存储(MySQL/Redis)可控性最强,适合业务规则稳定的系统企业应用、数据敏感场景
自建向量库(Milvus/pgvector)灵活,支持语义检索需要跨场景召回记忆的项目
Mem0 / MemGPT 等框架开发快,社区活跃快速原型、研究项目
混合方案(结构化标签 + 向量检索)兼顾精确与语义我推荐的生产级方案

我自己目前在生产环境用的,是混合方案:结构化标签(时间、场景、业务类型)负责精确过滤,向量库负责候选召回。框架的话,早期用过几轮之后最终还是抽了出来,因为业务里没有哪个现成框架的记忆衰减策略能完全匹配我的需求。这也是想提醒大家的一点:框架可以帮你把轮子转起来,但记忆这东西,还是得结合自己的业务场景去修改底层策略,否则上线跑一周你会积累一堆低质量的"记忆垃圾"。

5. 第四件事:多Agent协作的真相——先单Agent,再谈编排

5.1 多Agent不是"多个大模型开会",而是"拆解后的职责分配"

在聊多Agent之前,我想先泼一盆冷水:如果你连单Agent的任务边界都没想清楚,直接上手多Agent协作,大概率会得到一个"华丽但失控"的系统。多Agent协作的中文翻译其实就是"多个职责明确的程序模块,通过消息传递完成一个共同目标"。

为什么需要多Agent而不是一个超级Agent?主要有三个原因:

  1. 上下文隔离:不同领域的信息不混在同一个上下文里,减少相互干扰。
  2. 权限控制:某些Agent可以访问敏感数据,另一些则不能。
  3. 容错与降级:某个子Agent出错时,不会拖垮整个主流程。

我比较常见的落地方式,是"主管-工人"模式:一个协调者Agent负责理解用户目标和任务拆解,然后分发给多个工具型Agent执行,最后做结果整合。这其中的关键点在于,协调者Agent的决策尽量简单化——它不需要自己做具体业务判断,而是根据规则或少量分类结果,决定把任务交给谁。

5.2 协作的基础不是聊天,是结构化消息协议

很多入门者会把多Agent协作理解为"多个Agent互相发消息聊天",这是大坑。如果Agent之间用自然语言来回对话,不仅延迟翻倍,而且消息内容难以追踪和回放。我建议的做法是定义一套结构化消息协议——即消息就是一个JSON对象,包含task_id、sub_task_type、payload、status、callback这几个字段。Agent之间只传结构,不传废话。

举个例子,假设有一个数据处理Agent收到了上游发来的sub_task_type: "validate_email",它处理完直接返回:

{ "task_id": "task_0001", "sub_task_type": "validate_email", "status": "success", "payload": { "valid": true, "normalized_email": "user@example.com" } }

下游Agent只需解析这个JSON,就能决定下一步。不需要上游Agent写一段"我已经验证完邮箱了,它是有效的"这种自然语言来传递信息,这样既省Token又便于排查。

5.3 编排模式选型的核心思路:脉络优先,工具其次

当前主流的Agent编排框架,功能其实都大同小异。很多人在朋友圈看到某个新框架发布,就觉得"技术又要重构了",实际上没必要。我在谈框架选型时,关注以下几个核心命题,无论框架叫什么名字,只要这些维度符合项目需求,它就能用:

  1. 是否支持可观测性(能不能看到每个子任务的执行状态)。
  2. 是否支持异步消息(避免阻塞式同步调用造成的资源浪费)。
  3. 是否支持降级策略(子模块失败时能否走备选路径)。
  4. 是否容易接入自定义Skill/工具。

如果满足这四点,无论框架是LangGraph、AutoGen、CrewAI还是自己写的状态机,都能支撑项目跑起来。我甚至见过有人在生产环境里用纯消息队列加一个聪明的调度器就实现了不错的多Agent编排。做得太重,反而让团队陷入"为了用框架而用框架"的困境。

这里补充一个我很认同的观点,来自吴恩达的Agent教程:多Agent模式的第一步,永远是"思考你需要并行还是串行"。串行场景适合长流程制造,并行场景适合信息收集。框架只是把这些模式实现成代码结构,真正定方向的,仍然是你对业务流程的理解。

6. 第五件事:评测、防错与可观测性,是Agent开发不被炒鱿鱼的底线

6.1 没有评测体系的Agent开发,等于瞎开车

如果让我从近两年经验里挑一个对团队价值最大的技术方向,我会说:评测(Eval)和可观测性。几乎所有Agent做不好落地的团队,问题不是出在"模型能力不够",而是出在"无法证明模型能力足够好、也无法及时发现它变差"。

早期我们开发Agent时,评测全靠人工试几条用例。后来发现,模型版本一升级,一些功能就悄悄退化,但代码和环境都没变。那个阶段踩了不少坑。后来总结出来的教训是:Agent评测不能只看"最终回复是否正确",还得看工具调用序列是否正确、是否及时停止、是否产生幻觉等。

我目前在生产环境维护的评测体系包括:

  • 回归评测集:按业务场景整理几十条典型输入,每次Agent改版后自动化跑一遍。
  • 工具调用审计:记录每个工具的触发条件、入参、出参,做离线分析。
  • 用户反馈闭环:线上真实用户点"踩"或者转人工的数据回流到评测集。
  • 延迟与Token成本监控:这些指标很多时候比"答案正确"更能反映系统健康度。

有读者可能觉得麻烦,但我的建议是:哪怕最开始只整理20条真实业务场景做回归测试,也比完全靠感觉和手工验证好。做Agent开发,没有评测体系的加持,上线后就会陷入"修好一个bug引入三个bug"的循环。

6.2 Agent执行错误:别只盯着traceback,要分层定位

标题相关热词里有一条是"agent execution terminated due to error.",这让我想起很多人在社区里问这种报错怎么处理。实际上这个报错信息,通常出现在使用某些Agent框架时——当一个内部工具或子任务失败,框架就把整个流程终止,并抛出这么一条笼统的信息。只盯着这条报错看,没有任何意义。

正确的排查方式,是把错误分层来看:

对不起,不能用Mermaid。我改用文字描述:排查Agent执行错误时,按照"意图理解层 → 工具调用层 → 编排执行层 → 模型推理层"逐层定位。

  • 意图理解层:用户输入是否被正确分类,是否错误触发某个Skill。
  • 工具调用层:工具入参是否合法,API返回是否失败,超时设置是否合理。
  • 编排执行层:多Agent协作时,消息协议是否有误,子任务状态流转是否卡死。
  • 模型推理层:LLM是否幻觉、是否拒绝执行、是否上下文过长导致截断。

我自己碰到过最典型的一个情况是:某个工具,偶尔会因为上游接口超时而返回空数据,Agent拿到空数据后没有走"数据缺失"分支,反而生成了错误的业务结论。从表面看,就是一句泛泛的execution terminated due to error,实际根因是工具层没有对空结果做防御性验证。把校验加进工具层之后,这类错误就几乎消失了。

6.3 稳定性工程:sleep、重试、降级三板斧

说句稍微得罪人的话:很多Agent开发者在写代码时,没有把稳定性工程当成一回事。模型调用(LLM API)是有网络波动、有速率限制、有偶发超时的。如果你的代码不处理这些,生产环境一定出问题。

我处理LLM异常和工具异常时,有一套固定的思路:

  1. 所有外部调用统一加超时和重试(例如:超时10秒,重试3次,指数退避)。
  2. 关键路径上加降级策略,模型挂了就切规则引擎,规则引擎挂了就切人工。
  3. 每次外部调用记录耗时和返回码,方便事后复盘。

这套思路不是老生常谈。Agent项目由于链路长,任何一环出问题,最终表现都是"整体不可用"。而这种不可用的代价,比传统后端应用大得多,因为用户感知到的不再是"某个接口报错",而是"这个AI助手好像变蠢了"。

6.4 架构选型时,多问一句:这个框架坑不坑

最后闲聊一下框架选型的心态。前面讲到Hermes、Pi这些新名词,其实在很多热搜词里频繁出现。我的看法是:AI Agent领域现在处于一个高速迭代期,几乎每个季度都有新的框架出来,不值得为了追新而追新。选框架之前,先把下面这些问题过一遍:

  • 框架的维护活跃度如何?有没有人解决Issues?
  • 社区案例是否覆盖了与你类似的生产场景?
  • 框架的抽象层级是否和你的业务复杂度匹配?
  • 如果框架一年内不再更新,你的代码还能不能继续维护?

我用过好几个框架,有些项目后来因为框架迭代太激进,团队被迫频繁改代码,痛不欲生。后来我们的策略变成了:核心Agent逻辑尽量自己写,框架只负责外围的消息分发和状态管理。这样一来,无论框架底层怎么变,我们的核心业务逻辑都相对稳定。这也是为什么我前面一直强调"少依赖框架做理解,多依赖框架做基建"。

7. 沉淀一下这两年我最常用的落地核查清单

这算是给急着上手项目的读者一个可以直接抄的清单。我每次接手一个新的Agent项目,不管业务领域是什么,都会按这个顺序过一遍:

  1. 目标边界:用户一句话输入时,Agent能识别多少种意图?哪些场景明确不处理?
  2. 决策点清单:把核心业务流拆成决策点,确认每个决策点有对应的规则或工具。
  3. 工具描述:逐条检查工具描述是否包含"什么时候用、用什么参数、返回怎么接续"。
  4. 记忆分层:确认短期、长期、永久记忆的存储介质和时效策略是否分开。
  5. 协作消息协议:如果有多Agent,确认消息结构是否稳定、可追踪。
  6. 回归评测集:至少准备20条真实场景用例,自动跑完并记录结论。
  7. 稳定性预案:确认超时、重试、降级、人工接管四件事都写进了代码。

写到这里差不多把我这两年的核心经验都掏出来了。要说做Agent开发有什么天赋型选手,我是不太信的。这个方向说白了就是"想法 + 工程 + 数据验证"三件套一直转。你要是能把这五件事真正想明白、做扎实,哪怕不追任何新框架,也能做出一个能稳定交付价值的系统。这也是我做Agent开发到现在,最想传达的一句话。