1. 为什么 Agent 自进化必须靠工程闭环,而不是靠堆模型
做 Agent 开发这两年,我最大的感受是:模型能力只是起点,真正决定一个 Agent 能不能长期稳定干活的,是它背后那套评测、记忆、Skill 更新的工程闭环。很多人一上来就想着换个更强的模型、加更长的上下文,结果跑了两周发现,Agent 该犯的错还是犯,该忘的还是忘,Skill 该过时的还是过时。问题不在模型,在于你没有给它装上一套“自我进化”的机制。
所谓 Agent 自进化,说白了就是让 Agent 在真实使用过程中,能够自己发现问题、记住经验、更新技能,形成一个越用越顺的循环。这个循环拆开来看,核心就三块:评测负责判断“这次干得好不好”,记忆负责沉淀“哪些经验值得留”,Skill 更新负责把沉淀下来的经验固化成可复用的能力。三块缺一不可,缺了评测就是瞎进化,缺了记忆就是每次从零开始,缺了 Skill 更新就是永远在重复踩同一个坑。
我见过太多项目,评测靠人工看几条 case,记忆就是往向量库里塞聊天记录,Skill 全靠手写 prompt。这种搭法在 demo 阶段能跑通,一旦上量、一旦场景变复杂,立刻崩盘。原因很简单:没有闭环,就没有反馈;没有反馈,就没有进化。你的人工评测跟不上 Agent 的调用量,你的向量库塞满了噪声,你的 prompt 越写越长最后自己都维护不动。
这篇文章我想把这两年踩过的坑、试过的方案、最后跑通的架构完整讲一遍。适合谁看?如果你正在做 Agent 项目,不管是客服、代码助手、还是自动化工作流,只要你想让它“越用越聪明”,而不是“越用越乱”,那这套闭环思路你应该能用上。我会从整体设计讲到每个模块的具体实现,包括参数怎么定、阈值怎么设、坑在哪里,尽量让你看完能直接抄作业。
2. 整体架构设计:评测、记忆、Skill 三者怎么咬合
2.1 先想清楚“进化”到底进化什么
在动手搭之前,得先回答一个问题:Agent 自进化,进化的对象到底是什么?我的答案是三个层面。
第一层是行为策略,也就是 Agent 在什么情况下该调用什么工具、该走什么流程。比如一个代码助手,遇到报错时是先查文档还是先看堆栈,这就是策略。第二层是知识记忆,也就是那些一次学会、长期受用的领域知识,比如某个内部 API 的调用规范、某个业务的黑话映射。第三层是技能封装,也就是把高频、稳定的操作序列固化成一个个 Skill,让 Agent 不用每次重新推理。
这三层对应到工程上,就是评测系统、记忆系统、Skill 管理系统。它们不是并列关系,而是流水线关系:评测产生信号,记忆沉淀信号,Skill 固化信号。信号从评测流向记忆,再从记忆流向 Skill,最后 Skill 又反过来影响 Agent 的行为,行为再被评测捕捉,形成闭环。
我一开始犯的错就是把这三块当成独立模块来做,评测归评测,记忆归记忆,结果数据不通,评测出来的问题没法自动变成记忆,记忆里的经验也没法自动升级成 Skill。后来改成流水线之后,整个系统的“进化速度”明显上来了。
2.2 闭环的数据流长什么样
具体的数据流我画不出来图(这里也不方便用图),但可以用文字描述清楚。一次 Agent 调用结束后,会产生三类原始数据:输入上下文、执行轨迹、最终结果。这三类数据先进入评测层,评测层根据预设的指标打分,输出一个结构化的评测报告,里面包含“这次任务成功还是失败”“失败在哪个环节”“有没有更优解”。
评测报告里标记为“值得学习”的样本,会进入记忆层。记忆层不是无脑存,而是要做筛选、压缩、归类。筛选是去掉噪声,压缩是把长轨迹提炼成短经验,归类是把它放到合适的记忆分区里。记忆层输出的是一条条结构化的“经验条目”,每条都带元数据,比如适用场景、置信度、时间戳。
经验条目积累到一定数量、且置信度足够高时,触发 Skill 更新流程。Skill 更新不是简单地把经验拼成 prompt,而是要做抽象和泛化,把多条相似经验归纳成一个可复用的 Skill 定义,然后经过一轮回归测试,确认新 Skill 不会破坏已有能力,才正式上线。
这条流水线跑通之后,Agent 的每一次调用都在为下一次调用做贡献,这才是真正的自进化。
2.3 为什么不用“全自动”,而是“半自动 + 人工兜底”
这里我要泼一盆冷水:完全无人的自进化,目前阶段非常危险。我试过让系统自动把评测通过的经验直接写进 Skill,结果两周后 Skill 库里多了一堆互相矛盾的定义,Agent 行为开始漂移,排查了半天才发现是某几条错误经验被误判为“值得学习”。
所以我的建议是半自动 + 人工兜底。评测和记忆可以高度自动化,但 Skill 更新这一步,尤其是涉及核心能力的更新,一定要有人工审核环节。具体做法是:系统自动生成 Skill 候选,自动跑回归测试,测试通过后进入待审核队列,人工确认后才上线。这样既保证了进化速度,又守住了质量底线。
3. 评测系统:怎么让 Agent 自己知道自己干得好不好
3.1 评测集构建:别指望一套评测集打天下
评测集构建是很多人忽略的一环。我见过有人拿几十条手工 case 当评测集,跑完就宣称 Agent 准确率 90%+,这种数字没有任何意义。评测集必须分层,我一般分三层。
第一层是冒烟集,20 到 50 条,覆盖最核心的场景,每次代码改动都跑,要求秒级出结果,主要看有没有明显回归。第二层是回归集,200 到 500 条,覆盖主要业务路径和已知的边界情况,每天跑一次,看整体指标波动。第三层是挑战集,专门收集线上真实失败 case,持续更新,用来发现新问题。
这三层的构建方式也不一样。冒烟集靠人工精选,回归集靠历史 case 沉淀,挑战集靠线上监控自动捞。我特别想强调的是挑战集,它是自进化的燃料。线上每出现一次失败,就自动把这条 case 脱敏后加入挑战集,Agent 下次评测就会遇到它,逼着它学会。
3.2 评测指标:准确率只是冰山一角
只盯准确率是新手最容易犯的错。Agent 的评测指标至少要覆盖四个维度。
| 维度 | 指标 | 说明 | 建议阈值 |
|---|---|---|---|
| 效果 | 任务成功率 | 端到端完成目标的比例 | 核心场景 > 85% |
| 效果 | 召回率 | 该找到的信息有没有找到 | > 90% |
| 效率 | 平均步数 | 完成任务消耗的推理步数 | 越低越好,设上限 |
| 效率 | 平均耗时 | 端到端响应时间 | 按场景定,一般 < 30s |
| 稳定 | 方差 | 同一 case 多次跑的波动 | 越小越好 |
| 安全 | 越界率 | 调用未授权工具或输出敏感内容 | 必须为 0 |
我实测下来,召回率和平均步数是最能反映 Agent 健康度的两个指标。召回率掉了,说明记忆或检索出了问题;步数涨了,说明策略在退化。这两个指标比单纯的准确率敏感得多。
3.3 自动评测的实现:LLM-as-Judge 怎么用才靠谱
自动评测现在主流做法是 LLM-as-Judge,就是用一个强模型来给 Agent 的输出打分。这个方案好用,但坑也多。
第一个坑是评分标准太模糊。你如果只告诉 Judge“给这次回答打分”,它给的分基本没法用。必须给它结构化的评分维度,比如“信息准确性 1-5 分”“完整性 1-5 分”“是否调用正确工具 是/否”,每个维度都要有明确的评分说明。
第二个坑是位置偏见。Judge 容易偏向它先看到的内容。解决办法是交换顺序跑两次,取平均分,或者用多个 Judge 投票。
第三个坑是成本。全量用强模型评测,成本扛不住。我的做法是分层评测:冒烟集用规则匹配 + 小模型,回归集用中等模型,只有挑战集和争议 case 才动用强模型。
# 一个简化的 LLM-as-Judge 评分 prompt 结构 judge_prompt = """ 你是一个严格的评测员。请根据以下维度给 Agent 的回答打分: 1. 信息准确性(1-5分):回答中的事实是否正确,有无编造 2. 任务完整性(1-5分):是否完整解决了用户的问题 3. 工具使用(是/否):是否调用了正确的工具,有无多余调用 用户问题:{question} Agent 回答:{answer} 参考答案:{reference} 请以 JSON 格式输出:{{"accuracy": int, "completeness": int, "tool_correct": bool, "reason": str}} """这段 prompt 我调了很多版,关键点是维度要少而精,每个维度要有明确定义,输出要结构化。维度太多 Judge 会顾此失彼,定义模糊 Judge 会自由发挥,输出不结构化你后面没法自动处理。
3.4 人工评测怎么和自动评测配合
自动评测再强,也替代不了人工。我的经验是自动评测负责筛,人工评测负责校准。具体做法是:自动评测每天跑全量,把分数处于“中间地带”的 case(比如成功率 60% 到 80% 之间的)挑出来,人工重点看这些。分数特别高和特别低的反而不用看,高的说明稳,低的说明明显有问题,直接进挑战集。
人工评测的结果要反哺自动评测,用来校准 Judge。比如人工发现某条 case 其实是对的,但 Judge 打了低分,那就要调整 Judge 的 prompt 或评分标准。这个校准过程要持续做,不然 Judge 会越来越偏。
4. 记忆系统:长短期记忆怎么分层,怎么防止越记越乱
4.1 双网络记忆模型:短期和长期各管什么
记忆系统我踩过最大的坑就是什么都往一个库里塞,结果检索出来的东西又杂又乱,Agent 反而被带偏。后来改成双网络模型,短期记忆和长期记忆分开管,效果立竿见影。
短期记忆管的是当前会话或最近几次会话的上下文,特点是容量小、更新快、时效性强。它主要解决“刚才说到哪了”的问题,比如用户上一句提到的偏好、当前任务的中间状态。短期记忆一般放在内存或高速缓存里,会话结束就衰减。
长期记忆管的是跨会话的稳定知识,特点是容量大、更新慢、置信度高。它解决的是“这个用户/这个场景长期来看是什么样”的问题,比如用户的固定习惯、某个业务领域的通用规则。长期记忆要持久化,而且要定期做压缩和整理。
两者之间的桥梁是记忆晋升机制:短期记忆里反复出现、且被评测确认有效的经验,才晋升到长期记忆。这样既保证了长期记忆的质量,又不会让短期记忆无限膨胀。
4.2 记忆的写入策略:不是所有对话都值得记
新手最容易犯的错是把每一轮对话都写进记忆库。这样做的后果是,记忆库里 90% 是噪声,检索的时候真正有用的信息被淹没。
我的写入策略是三重过滤。第一重是价值过滤,只有包含新信息、新偏好、新规则的对话才值得记,纯寒暄、纯确认的直接丢弃。第二重是置信度过滤,用户明确陈述的事实置信度高,Agent 自己推理出来的结论置信度低,后者要谨慎写入。第三重是去重过滤,写入前先检索一下,如果已有相似记忆,就做合并或更新,而不是新增。
def should_write_to_memory(turn, existing_memories): # 价值过滤:是否包含新信息 if not contains_new_info(turn): return False # 置信度过滤:来源是否可靠 if turn.source == "agent_inference" and turn.confidence < 0.8: return False # 去重过滤:是否与已有记忆高度相似 similar = find_similar(turn, existing_memories, threshold=0.9) if similar: update_memory(similar, turn) return False return True这段逻辑看着简单,但阈值怎么定很关键。相似度阈值我试过 0.85、0.9、0.95,最后定在 0.9。太低会误合并,把不同信息当成同一个;太高会漏合并,导致记忆库冗余。这个值要根据你的 embedding 模型和业务特点调,没有万能值。
4.3 记忆的检索策略:怎么在正确的时候想起正确的事
记忆检索的核心矛盾是召回率和精确率的平衡。召回率低了,Agent 想不起该想的事;精确率低了,Agent 被无关记忆干扰。
我的做法是多路召回 + 重排序。多路召回包括:向量相似度召回、关键词召回、时间衰减召回。向量召回负责语义相关,关键词召回负责精确匹配,时间衰减召回负责让近期记忆有更高权重。三路结果合并后,再用一个重排序模型精排,取 top-k 注入上下文。
这里有个细节:记忆的分数不能只看相似度,还要看时间。我用的公式是score = 相似度 * 时间半衰期因子,时间半衰期因子随时间指数衰减。这样既保证了相关性,又让新鲜记忆有优势。半衰期设多长要看场景,客服场景可能 7 天,知识库场景可能 30 天。
4.4 记忆的压缩与遗忘:该忘的必须忘
记忆系统最反直觉的一点是:遗忘和记忆同样重要。一个只记不忘的系统,最后一定会被自己的历史压垮。
我的压缩策略是定期聚类 + 摘要。每周跑一次,把长期记忆里的条目做聚类,同一类的多条记忆合并成一条摘要记忆。比如用户提过五次“喜欢简洁的回答”,就合并成一条“该用户偏好简洁风格,置信度 0.95”。
遗忘策略是置信度衰减 + 容量上限。长期没被检索到的记忆,置信度会缓慢衰减,衰减到阈值以下就归档或删除。同时给每个记忆分区设容量上限,超了就淘汰置信度最低的。这样保证记忆库始终是“精华”,而不是“垃圾场”。
5. Skill 更新:从经验到可复用能力的最后一公里
5.1 Skill 到底是什么:和 prompt、工具的区别
很多人搞不清 Skill 和 prompt、工具的区别。我的理解是:prompt 是给模型的指令,工具是模型能调用的函数,Skill 是封装好的、可复用的能力单元。一个 Skill 通常包含一段 prompt、一组工具调用逻辑、以及一些前置条件和后置校验。
举个例子,“查询订单状态”这个能力,如果只写 prompt,模型每次都要自己推理该调哪个 API、怎么解析参数;如果封装成 Skill,模型只需要判断“用户想查订单”,然后调用这个 Skill,剩下的参数填充、API 调用、结果解析都由 Skill 内部完成。Skill 的价值在于把高频、稳定的操作序列固化下来,减少模型的推理负担和出错概率。
5.2 Skill 的生成:从记忆条目到 Skill 定义
Skill 的生成不是拍脑袋写,而是从记忆条目里归纳。具体流程是:先筛选出高置信度、高频出现的经验条目,然后对这些条目做聚类,同一类的经验归纳成一个 Skill 候选。
归纳的过程可以用 LLM 辅助。给 LLM 一批相似的经验条目,让它总结出“这些经验共同描述了一个什么能力”“这个能力的输入输出是什么”“执行步骤是什么”。LLM 输出的结果就是 Skill 定义的初稿,然后人工审核、补充边界条件、写测试用例。
skill_generation_prompt = """ 以下是一批相似的经验条目,请归纳出一个可复用的 Skill 定义: {experience_entries} 请输出 JSON 格式: {{ "skill_name": "技能名称", "description": "技能描述", "input_schema": {{"参数名": "类型和说明"}}, "output_schema": {{"返回值": "类型和说明"}}, "steps": ["执行步骤1", "执行步骤2"], "preconditions": ["前置条件"], "edge_cases": ["边界情况处理"] }} """这个 prompt 的关键是要求结构化输出,而且要把边界情况单独列出来。我见过太多 Skill 定义只写了 happy path,一遇到异常就崩。边界情况必须显式定义,这是 Skill 能不能上生产的关键。
5.3 Skill 的回归测试:新 Skill 不能破坏老能力
Skill 更新最大的风险是新 Skill 和已有 Skill 冲突,或者新 Skill 上线后导致某些场景退化。所以每次 Skill 更新,必须跑回归测试。
回归测试分两部分。第一部分是新 Skill 自身的测试,用专门为它写的测试用例,验证它在各种输入下都能正确工作。第二部分是全量回归,把整个评测集跑一遍,对比更新前后的指标,确认没有明显退化。
我设的回归门槛是:核心场景成功率不能下降超过 1%,整体平均步数不能上升超过 5%。超过这个门槛,更新就打回,人工排查原因。这个门槛看着严,但实测下来是必要的,因为 Skill 之间的相互影响往往很隐蔽,不严格卡就会慢慢累积成大问题。
5.4 Skill 的版本管理与灰度上线
Skill 一定要做版本管理。每次更新都生成新版本,旧版本保留,出问题可以快速回滚。版本号我一般用skill_name@v1.2.3这种格式,主版本号表示不兼容变更,次版本号表示新增能力,修订号表示 bug 修复。
上线要走灰度。先在小流量上跑,观察指标,没问题再逐步放量。灰度期间要重点看新 Skill 的调用频率、成功率、以及它对其他 Skill 的影响。我遇到过新 Skill 上线后,因为它的触发条件太宽,把原本该走另一个 Skill 的请求抢过来了,导致那个 Skill 的成功率下降。这种问题只有灰度才能发现。
6. 常见问题与排查技巧实录
6.1 评测分数忽高忽低怎么办
这是最常见的问题。原因通常有三个:评测集本身不稳定、Judge 有随机性、Agent 输出有随机性。
排查顺序是:先固定 Agent 的随机性(temperature 设 0),再固定 Judge 的随机性(同样设 0,或者多次采样取平均),最后看评测集。如果固定了随机性分数还是波动,那就是评测集里有歧义 case,需要人工清洗。
我一般会维护一个稳定性监控,同一批 case 每天跑,记录分数的方差。方差突然变大,说明系统某处出了问题,要立刻排查。
6.2 记忆检索总是召回无关内容
这个问题八成是embedding 模型和业务不匹配。通用 embedding 模型在垂直领域往往表现不好,因为领域术语的语义它理解不了。解决办法是用领域数据微调 embedding 模型,或者至少做一轮领域适配。
另一个原因是记忆条目太长。一条记忆如果几百字,embedding 会把它压缩成一个模糊的向量,检索时自然不准。解决办法是记忆条目要短,一条记忆只讲一件事,长内容拆成多条。
6.3 Skill 更新后 Agent 行为漂移
行为漂移通常是Skill 之间的优先级没定义清楚。多个 Skill 都能处理同一个请求时,Agent 不知道该用哪个,就会随机选,表现就是行为不稳定。
解决办法是给 Skill 定义优先级和互斥规则。比如“查询订单”和“查询物流”有重叠,就明确“如果用户明确提到物流,优先用查询物流”。这些规则要写进 Skill 的元数据里,Agent 决策时参考。
6.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方向 | 解决手段 |
|---|---|---|---|
| 评测分数波动大 | 随机性未固定 | 检查 temperature | 设 0 或多次采样 |
| 记忆召回不准 | embedding 不匹配 | 看召回样本 | 微调 embedding |
| 记忆库膨胀 | 写入无过滤 | 看写入量 | 加三重过滤 |
| Skill 冲突 | 优先级未定义 | 看调用日志 | 定义优先级规则 |
| 行为漂移 | Skill 更新未回归 | 对比更新前后 | 严格回归门槛 |
| 响应变慢 | 记忆注入过多 | 看上下文长度 | 限制 top-k |
6.5 几个我踩过的坑
第一个坑是过早追求全自动。我一开始想让整个闭环全自动跑,结果 Skill 库被污染,花了整整一周清理。后来改成半自动,效率反而更高。
第二个坑是评测集一成不变。评测集不更新,Agent 就会过拟合评测集,线上表现和评测分数脱节。必须持续往评测集里加线上 case。
第三个坑是记忆只增不减。记忆库涨到几十万条之后,检索延迟飙升,而且噪声越来越多。后来加了压缩和遗忘机制才稳住。
第四个坑是Skill 粒度过细。一开始我把每个小操作都封装成 Skill,结果 Skill 数量爆炸,Agent 选择困难。后来合并成粗粒度 Skill,效果好很多。Skill 的粒度应该以“用户意图”为单位,而不是以“操作步骤”为单位。
7. 我个人的一些实操体会
这套闭环我前后迭代了大半年,从最开始的手工评测、单库记忆、硬编码 Skill,到现在半自动评测、双网络记忆、版本化 Skill,中间踩的坑能写一本书。如果让我给正在做 Agent 的朋友几条建议,我会说这几条。
先把评测做扎实,再谈自进化。评测是闭环的入口,入口不准,后面全白搭。我见过太多项目评测都没做明白,就急着上记忆和 Skill,最后做出来的东西自己都不敢信。
记忆系统的核心是“筛选”而不是“存储”。存储谁都会,难的是判断什么该存、什么该忘。把筛选逻辑做对,记忆系统就成功了一大半。
Skill 更新一定要有人工兜底。至少在现阶段,完全自动的 Skill 更新风险太大。人工审核不是拖慢速度,而是保证质量,长期看反而更快。
闭环的每一环都要有监控。评测的分数、记忆的命中率、Skill 的调用分布,这些指标要实时看。任何一个环节异常,都要能第一时间发现。
最后分享一个小技巧:给闭环设一个“进化速率”指标,比如每周新增多少条有效记忆、每月更新多少个 Skill。这个指标能直观反映你的 Agent 是不是真的在进化。如果这个数字长期是零,那你的闭环大概率是断的,得回去查哪一环没跑通。