如果你点进来是因为“自进化”这三个字,我猜你想看的不是科幻片,而是一套系统到底怎么把“越用越强”落到工程上。Hermes Agent 是我一直在打磨的一套智能体项目代号,它不做模型参数重训练,也不是什么端到端魔法,而是把“进化”翻译成一组可以观察、可以回滚、可以测试的代码管道。这篇内容就是我对 Hermes Agent 技术架构的完整拆解:它拆成了哪些模块,每一条数据怎么流动,评估器如何打分,更新器如何决定要不要“改自己”,以及在实测中哪些地方最容易翻车。
这套东西适合两类人看:一类是正在做 Agent 应用、想引入“经验沉淀/自动优化”能力的开发者,另一类是纯粹好奇所谓“自进化”在工程上到底是什么的人。我不会复制官方文档,只讲我在真实搭建和维护过程中验证过的思路、代码片段和踩坑记录。
1. 别被“自进化”骗了:它只是一组带反馈的管道
1.1 从黑话到工程语言:自进化等于执行、记录、评估、更新
很多人一听到“自进化”就觉得是模型自己写代码、自己改权重,其实在工程实现上完全不是这回事。Hermes Agent 的自进化,本质是把“人怎么复盘”这件事迁移到代码里:做完一个任务,留下记录,判断这次做得好不好,然后把做得好的部分沉淀成下次可复用的东西。
整个过程拆成四个环节,缺一不可。
- 执行:Agent 接到目标,完成规划、调用工具、生成回答。
- 记录:把执行过程的每一步都结构化落盘,形成轨迹(trace)。
- 评估:根据任务结果、用户反馈和安全性指标,给这次执行一个得分。
- 更新:得分显著优于历史均值时,把新的技能、记忆或配置吸收进系统。
如果这四个环节是互相断开的,那就谈不上进化,只能叫“能跑的 Demo”。而 Hermes Agent 的架构重点,就是让这四个环节形成闭环,并且每一步都可观测、可干预。
我常用的一个类比是健身房训练:你练完一组动作是执行,录像回放是记录,教练点评是评估,调整下一组计划是更新。没有录像和教练,光靠“练得多”并不会变得更标准,反而可能固化错误动作。Agent 系统也一样,没有轨迹和评估器,执行多少次都是在原地打转。
1.2 为什么不重训模型:要区分“参数进化”和“配置进化”
在设计 Hermes Agent 的初期,我最先确认的一件事是:不碰模型权重。原因很现实,重训一个大模型的人力、数据、算力成本,绝大多数团队根本承受不起,而且一旦训练过程没控制好,模型行为会整体漂移,连原本能正常使用的任务都崩掉。
所以 Hermes Agent 的“进化”被严格限定在三个可管控的层面:技能库、记忆内容、路由与评估配置。技能库是“怎么做事的模板”,记忆是“具体任务的事实与偏好”,配置是“用什么策略选择工具、达到多少分才更新”。这三个层面都改的是文本、结构体和参数,而不是神经网络里的浮点数。
这样做有两个明显好处:第一,任何变更都能用传统软件工程手段管控,比如版本对比、回滚、A/B 测试;第二,每次更新的影响范围小,最坏情况只是某个技能退步,而不是整个模型不可用。你可以把模型权重想象成一个人的大脑结构,Hermes 只负责给这个人更换工具和操作手册,不直接开颅。
架构上,Hermes Agent 不是一个单体的“模型调用壳”,而是一条数据管道:用户目标和环境状态进入,经过规划器、执行器、记忆层、评估器,最后到达更新器。我习惯把它描述成两条互相嵌套的循环:
- 快循环:当前任务内,规划-执行-观察不断迭代,目标是完成客户请求。
- 慢循环:跨任务维度,评估-更新-验证不断迭代,目标是提升后续任务的整体质量。
两条循环共享轨迹数据,但写入和读取的节奏完全不同。快循环强调低延迟,慢循环强调低风险。后面的章节会分别拆开讲。
2. 拆开 Hermes Agent 的心脏:五大模块与两条循环
2.1 模块职责:谁在干活、谁在打分、谁在改自己
Hermes Agent 的代码组织严格按职责分模块,不是一个大文件里塞满回调函数。我按五个核心模块来划分边界:规划器、执行器、记忆层、评估器、更新器。下面这个表是我在实际开发中用来对齐团队认知的版本,每个模块都有明确产物和失败影响。
| 模块 | 核心职责 | 关键产物 | 最常见的出错影响 |
|---|---|---|---|
| 规划器 | 把用户目标拆成可执行的动作序列 | Plan(结构化步骤) | 步骤拆错,后续全跑偏 |
| 执行器 | 调用大模型和外部工具,完成单步操作 | Observation / Tool Result | 工具参数错误或超时 |
| 记忆层 | 存储和检索任务事实、历史轨迹、技能模板 | Retrieved Context | 检索出无关信息,误导规划 |
| 评估器 | 对执行结果打分,判断好坏 | Score 与评估报告 | 打分失真,更新器被带偏 |
| 更新器 | 根据得分生成新技能/记忆补丁,管理版本 | Patch / New Skill Version | 过度更新,系统行为漂移 |
这五个模块不是串行工作的。规划器产生计划后,执行器会一边执行一边把结果写回记忆层,评估器在任务结束后读取所有轨迹来打分,更新器则在分数足够高且稳定时决定是否合并一个新版本技能。
我踩过的一个坑是:一开始把评估逻辑写在执行器内部,导致每执行一步都在跑评估,不仅时延高,还会让执行器为了“当前这一步看起来好”而牺牲整个任务的最终目标。后来改成评估器独立成模块,只在任务边界触发,整个世界都安静了。
2.2 记忆层不是数据库,而是分层缓存
记忆层是 Hermes Agent 里最容易被误解的模块。很多初版设计会把所有历史消息塞进一个向量库,美其名曰“长期记忆”,结果 token 消耗暴涨,检索质量还差。后来我把记忆分成三层,每一层的生命周期和写入条件都不一样。
第一层是工作记忆,只在单个任务内生效,保存当前目标、最近几步的观察和中间结果。它相当于你的草稿纸,任务结束就清空,不进入持久化。第二层是情景记忆,按任务维度保存历史轨迹摘要,用于相似任务检索。这一层是有时效性的,超过一定时间或重复多少次没有命中后,会被压缩或清理。第三层是语义记忆,也叫技能库,保存经过提炼的通用操作流程、提示词模板和工具调用规则,这层才真正承担“积累经验”的功能。
这样分层的核心原因是成本和噪声控制。工作记忆只保留必要上下文,避免大模型被无关历史干扰;情景记忆帮助“记得上次是怎么做的”,但每个条目都需要摘要化,不能整段轨迹往里塞;技能库只接受“经过评估器验证过的经验”,宁缺毋滥。
写入规则也很重要。我在项目里明确规定:工作记忆的写入不受限,情景记忆必须等任务完成且评估分超过阈值才能写,技能库则必须经过候选验证流程。没有这套门槛,记忆会被大量低质量轨迹污染,越记越笨。
2.3 工具路由与技能库的边界:什么该让模型决定,什么不该
Agent 离不开工具调用,但是“让大模型自己选工具”在高频场景下并不可靠。Hermes Agent 的做法是:先注册工具到工具路由表,路由表不仅包含函数签名,还包含成本、成功率、平均耗时、可并发度。规划器只负责“需要完成什么能力”,工具路由则负责“具体用哪个实现”。
比如用户请求“查询天气”,规划器知道需要调用天气查询能力,而不是直接指定“用某个第三方天气 API”。工具路由会根据路由表里的历史成功率、响应速度和费用,选出最合适的工具。如果最便宜的工具最近成功率下降了,路由会自动切换到备选工具,这个过程不需要模型参与。
技能库和工具路由的边界也比较清楚。技能是“完成一类任务的多步骤模板”,比如“生成周报”可以包含检索任务记录、调用汇总模型、格式化输出三个步骤,其中每一步会引用具体工具能力。所以技能库是更高一层的抽象,工具路由是底层的选择器。
这个设计的含义是:自进化可以发生在两个层级——要么生成更好的技能模板,要么调整工具路由的优先级。更新器在大多数时候只动这两个层级,不会去动规划器的核心推理逻辑。这大大降低了进化风险,因为即使某个技能改错了,工具路由和历史技能还在,可以快速回退。
3. 把“变得更强”写成代码:从轨迹回放到参数更新
3.1 轨迹文档格式:让每次行动都可复盘
闭环的第一步是记录,而记录最忌讳的是一堆非结构化的日志。Hermes Agent 从第一天起就定义了统一的轨迹格式,采用 JSON Lines 形式,每个任务一个文件,每行一个事件。这个选择看起来朴素,但实际带来很大便利:既方便追加写入,又方便后续用脚本离线分析,还能直接导入评估器做批量回放。
下面是一个简化版的事件结构,我在项目里要求所有执行路径都必须遵守这套 schema。
{ "task_id": "task_20250514_001", "ts": "2025-05-14T10:23:11Z", "agent_step": 3, "event_type": "tool_call", "payload": { "tool": "web_search", "query": "Hermes Agent self-evolution", "result_summary": "found 42 results", "duration_ms": 832, "cost": 0.0042 }, "trace_id": "trace_abc123" }事件类型我至少区分这几种:plan、model_call、tool_call、observation、user_feedback、evaluator_score。每一种都有固定字段。很多人会觉得这很繁琐,但实际到排查问题时,你会发现结构化轨迹是救命稻草。
我强烈建议把评估器的打分结果也写成轨迹事件,并且带上打分模型或人工标注的来源。这样后期分析时,你能看到“某个工具调用之后,评估分数发生了什么变化”。没有这种细粒度记录,所有优化都是盲人摸象。轨迹仓库我习惯按天分目录,文件名以任务号开头,方便做并发重放和统计。
3.2 评估器:如何量化“这次更好”
评估器是自进化闭环里最核心、也最容易自欺的模块。Hermes Agent 不把“更好”定义成一个模糊感觉,而是拆成可计算的加权分数。我这个项目里的默认评估维度有四个。
- 任务成功率:关键动作是否完成、最终产物是否满足硬性断言。
- 效率得分:步数、耗时、token 消耗与历史基线对比。
- 安全得分:是否触发禁止动作、是否泄露敏感信息、是否符合工具调用规范。
- 用户反馈:显式点赞/点踩,或任务后的自然语言评价的情感倾向。
综合得分公式可以写成:
def compute_score(task_result, baselines): success = task_result.hard_assertions_passed() efficiency = baseline_ratio(task_result.duration_ms, baselines.duration_ms) safety = 1.0 if task_result.policy_violations == 0 else 0.3 user_rating = task_result.user_star_rating / 5.0 score = 0.4 * success + 0.2 * efficiency + 0.2 * safety + 0.2 * user_rating return round(score, 3)这个权重不是拍脑袋定的,而是根据业务场景调出来的。如果当前阶段更关注合规,就把 safety 权重提高;如果更关注成本,就把 efficiency 权重提高。需要注意的是,权重本身也是一种配置,它可以被更新器优化,但必须留人工审批入口。
评估器最容易犯的毛病是完全信任大模型裁判。在我自己的实测中,让模型当裁判确实省人力,但会出现系统性偏好,典型的如“回答越长分数越高”“引用来源越多分数越高”。所以 Hermes Agent 的评估器必须有多种信息源交叉验证。
我建议至少三种信号:硬性规则断言、模型裁判打分、人工抽检。人工抽检比例不用很高,但必须保留。每产生一批新技能,至少要抽检 20 条历史任务,计算自动评分和人工评分的相关性。相关性格外低的时候,说明评估器已经失真,更新器必须暂停。
3.3 版本化更新与安全回滚:进化不是替换,而是候选池竞争
更新器是“进化”的执行者,但我在设计时反复提醒自己:不能一有高分就立刻覆盖线上技能。正确的做法是让候选技能先进入影子模式,与线上版本并行运行一段时间,用数据决定去留。
具体流程我把它分成四步:
- 更新器从高分的任务轨迹中提炼出一个候选技能,写入技能库的 pending 区。
- 候选技能不直接服务正式流量,而是复制一份配置,在影子环境里跑离线测试集。
- 如果离线测试通过,候选技能进入金丝雀阶段,只对 5% 到 10% 的真实请求生效。
- 统计候选技能和线上技能的评估分数差值,只有差值大于阈值且样本量足够时,才全量切换。
这个“影子模式 + 金丝雀”的流程,本质上是用工程方式对抗自进化系统最危险的问题:单次偶然高分带来的过度自信。我曾经遇到过一个候选技能在 30 次测试里表现很好,全量上线后却因为一次罕见的输入模式翻车。后来我把最小样本量从 20 提高到 50,并要求连续两个评估周期的得分都超过线上版本才放行。
更新器生成的补丁也不是直接修改文件。每一条变更都记录为带版本号的 diff,可以理解为给整个智能体状态做 Git 管理。以下是我项目里使用的版本状态表:
| 状态 | 含义 | 可进行的操作 |
|---|---|---|
| pending | 已生成,未验证 | 离线测试 |
| shadow | 影子模式,与线上并行 | A/B 统计 |
| active | 全量生效 | 持续监控 |
| rejected | 未通过验证 | 归档,不再使用 |
| rolled_back | 线上回退后的旧版本 | 保留,可重新激活 |
这份表看起简单,但实际执行时最容易被忽略的是“rolled_back”版本的管理。很多团队把回退当成失败,直接把旧版本删了,结果新版本再次翻车时连退路都没有。我的建议是:回滚不是失败,它是进化系统正常的负反馈调节。至少保留最近十个有效版本,并且每个版本的评估指标摘要都要随版本一起存档。
4. 实测中最容易翻车的四个环节
4.1 评估器自欺:分数上涨,业务却在变差
自进化系统上线后,最后一个让人措手不及的问题,就是评估分数一路走高,但用户实际体验明显变差。我遇到过一个典型案例:模型裁判喜欢详细解释,Agent 就学会了把每次回答都拉得很长,单次任务 token 消耗翻了三倍,任务成功率却基本没变。因为评估器的效率指标用的是“相对历史均值”,而历史均值被长回答拉高了,所以系统反而觉得“正常”。
这个问题的根源是评估指标之间存在耦合,且缺少绝对基准。排查时我会分两步:第一步,把评估分数和业务核心指标放在同一个看板上,比如完成率、日均任务数、客诉率;第二步,定期用一批固定不变的人工标注样本集来校准评估器。如果自动分数在涨,但人工标注得分在跌,那就该怀疑“评估器被进化过程污染了”。
这套校准样本我习惯称之为“锚定集”。锚定集不参与训练,只用来打穿评估器。我每次盘点自进化系统时,会先跑一遍锚定集,并计算自动得分和人工得分的皮尔逊相关系数。相关系数低于 0.6 的时候,我基本会停掉自动更新,先修评估器。
4.2 记忆污染:错误经验固化后,越改越难
另一类高频事故来自记忆层。技能库一旦收录了一个错误技能,后续执行会不断把它检索出来,并因为“检索到了足够上下文”而给出更高分,错误经验就被不断自我强化。要打破这个循环,光靠“以后不写入”是不够的,因为已经污染的历史轨迹还会继续参与评估和检索。
我在 Hermes Agent 里给记忆条目增加了三个元字段:来源任务号、置信度、最近验证时间。置信度不是一成不变的,每次被成功调用会加一点,每次被显式纠正会大幅降低。这个机制简单但有效,能让错误记忆的优先级在多次失败后自然下沉。
另外,记忆层必须支持“手动纠偏”。我在管理后台加了一个功能:允许把某一条记忆或技能强制置为“需重新验证”状态。这个状态会阻断它参与检索,并要求更新器为它生成替代版本。没有这个开关,自进化系统就会变成一台没人刹车的车,方向歪了还在加速。
4.3 版本爆炸与回归测试:进化速度不等于迭代速度
自进化听起来越自动越好,但版本管理的噩梦会随之而来。我的项目在一次长假后积累了上百个候选技能,其中绝大部分是同一能力在微小参数上的差异。这种版本爆炸会让回归测试的维护成本直线上升,也会让系统行为变得难以解释。
我后来给更新器设了“冷却时间”:同一技能模板,24 小时内最多产生一个新候选版本;候选池里超过 20 个待验证项时,不再接受新的候选技能。这个限制看着简单,却能逼更新器去提炼更通用的经验,而不是反复微调。
回归测试套件也要区分层级。我用三类测试:单元级的轨迹断言、场景级的模拟任务、线上金丝雀统计。新技能至少要过前两类,才允许进入第三类。这样能过滤掉绝大多数“局部优化、全局破坏”的问题。
4.4 工具误调用与成本失控:进化出的“省事”不等于“省钱”
Agent 在进化过程中非常擅长走捷径,但这种捷径不一定对平台友好。典型问题是:明明有免费且足够用的内置解析函数,Agent 却偏要调用一个昂贵的第三方大模型接口去“理解”一段简单文本。原因很简单,评估器只看到了它能完成任务,没有把成本权重拉高到足够抑制这种行为。
我做的成本控制主要有两层。第一层是工具路由的硬性约束:每个工具都配置单次最大调用量和单任务累计预算。第二层是评估器的惩罚项:一旦某类工具调用次数超过基线,效率得分直接打折。我甚至给高频工具专门加了“工具调用序列指纹”,能自动发现“绕道调用”模式。
这类问题不能在每次更新后靠人工审查,因为量太大了。必须把它变成评估器和路由层的默认规则,让进化过程本身就知道:同样的功能,更便宜的方案优先,否则视为不合格。
5. 后续还能往哪走:自进化的上限与边界
5.1 从单机自进化到群体进化
Hermes Agent 当前架构解决的是单个智能体实例如何变强。但我在实际中感受到,更吸引人的方向是“群体进化”:多个 Agent 实例在执行不同任务,共享各自提炼出的技能,同时由中心评估器统一把关。这有点像开源社区,每个人提交 PR,维护者做 code review,合入主干前还要跑 CI。
群体进化的好处是经验复用率更高,A 场景总结的技能可以直接在 B 场景里做适配。风险是容易形成“信息茧房”,即所有实例共享了同一套错误偏见。我的建议是,在共享技能库之外,每个实例必须保留一块私有记忆区域,只有在那里被验证多次的经验,才有资格提交到共享库。
5.2 评估器独立成服务:把“裁判”从“运动员”里拆出来
在 Hermes Agent 的演进路线图里,我越来越倾向于把评估器做成分离服务。理由是,当技能库越来越丰富,更新器需要验证的候选越来越多,评估逻辑也会越来越复杂,继续内嵌在 Agent 主进程里,会成为性能和可靠性瓶颈。
独立评估服务可以统一接收所有 Agent 的轨迹,集中跑规则、模型裁判、抽样人工复核,并输出统一的得分报告。这样做的附加好处是,红线规则可以集中管理,例如“某些敏感操作无论完成得多好,安全得分直接归零”。这个机制让自进化有了边界,而边界恰恰是系统可信的前提。
5.3 我个人的实操体会:进化要快,但开关要慢
这套架构前后改了很多个版本,最大的感受是:自进化系统最怕的不是学得慢,而是乱学得快。工程实现里真正费心思的不是让更新器更聪明,而是给聪明加装足够多的刹车和仪表盘。每一次自动变更都要回答三个问题:能不能回滚?评估指标会不会骗我?这次改变是不是真的比旧版本好?
如果你想在自己的项目里引入类似机制,我的建议是先从一个闭环开始:只记录轨迹,只做离线评估,先不自动更新。等跑通两周、积累了几百条轨迹以后,再手动挑选几条经验写入技能库。等手动流程顺手了,再逐步开放自动更新。这个顺序看起来慢,但比一上来就全自动可靠得多。
少即是多。真正稳定的“自进化”,其实是由很多次“不进化”组成的。