1. 从「用完即忘」到「越用越强」:Hermes-Agent 自进化 agent 到底解决了什么
如果你写过 Agent,大概率经历过这种循环:给模型一套工具描述、一段 System Prompt,跑起来效果还行,但换个场景就崩;崩了之后你手动改 Prompt,改完再跑,再崩再改。整个过程里,Agent 本身没有任何变化,变的是你。Hermes-Agent 想做的事情,就是把这个「人改 Agent」的过程,变成「Agent 改自己」。
Hermes-Agent 是一个自进化 agent 框架,核心口号是「The Agent That Grows With You」。它和市面上大多数静态 Agent 框架的区别在于:每完成一次任务,它会把操作流程沉淀成 SKILL.md 技能文件;运行中发现更好的做法,会通过 patch 机制局部修改技能;离线时还能用 GEPA 遗传算法对技能做多目标优化。换句话说,它的技能库不是人工写死的,而是随着使用不断生长出来的。
这套机制适合谁?我认为有三类开发者值得关注。第一类是正在做垂直领域 Agent 的人,比如电商客服、运维自动化、数据分析助手,这些场景的共同点是任务模式会反复出现,经验沉淀的收益很高。第二类是对 Agent 上下文成本敏感的人,Hermes 的 Skill 六层渐进加载机制,大多数场景只消耗名称加描述级别的 50 到 100 token,确认需要某个技能时才加载完整内容。第三类是想理解自进化 Agent 设计思路的人,Hermes 把个体运行时学习和种群离线进化两套模型并行运作,这个设计本身就值得拆解。
我试过把 Hermes 的技能进化流程跑一遍,最直观的感受是:它把「经验固化」这件事做成了工程闭环,而不是停留在概念层面。下面我会从 SKILL.md 的结构讲起,然后拆 GEPA 的帕累托优化取舍,最后给出一套可复制的配置片段和一轮进化验证动作,并说明怎么通过 TaoToken 统一 Key 和 API 通道接入模型完成对比实验。
2. SKILL.md 技能定义与 GEPA 进化策略:自进化 agent 的机制拆解
2.1 SKILL.md 是什么:把操作经验写成可加载的文件
SKILL.md 是 Hermes-Agent 里技能的基本单位。你可以把它理解成一份「操作手册」,里面写的是某个任务该怎么一步步做。和传统 Prompt 的区别在于,它不是塞在 System Prompt 里一次性加载,而是存在技能库中,按需加载。
一个典型的 SKILL.md 结构大概长这样:
--- name: digital_goods_refund description: 处理数字商品退款请求,适用于已支付但未发货的订单 version: 3 tags: [refund, ecommerce, digital-goods] --- ## 适用场景 用户已支付数字商品订单,但商品未发货或用户要求取消。 ## 操作步骤 1. 调用 order_query 工具,传入 order_id,确认订单状态为 paid 2. 检查商品类型是否为数字商品(digital=true) 3. 若未发货,调用 refund_create,传入 order_id 和 reason 4. 退款成功后,调用 notify_user 发送确认消息 ## 注意事项 - 若订单状态为 shipped,转人工处理 - 单笔退款金额超过 500 元时,需要二次确认 - 退款失败时记录 error_code,不要重试超过 2 次这个文件的关键在于:它是纯文本,LLM 天生擅长改写文本。所以无论是运行时 patch,还是离线 GEPA 突变,操作对象都是这份 Markdown,不需要设计复杂的变异算子。
2.2 个体学习:Nudge 后台复盘怎么触发
个体学习的核心是 Nudge 机制。Agent 每调用一次工具,计数器加 1;达到阈值(默认 10 次)后,标记「需要复盘」。这里有个关键设计:复盘判定在响应交付之后才激活。也就是说,Agent 先把用户的回答返回,确认主任务完成,再在后台启动复盘流程,不抢占主 Agent 的注意力。
复盘不是主 Agent 自己做的,而是派生一个独立的后台回顾 Agent。这个后台 Agent 接收父 Agent 的对话快照,拥有 skill_manage 工具权限,可以审查对话并决定创建或修改哪些技能。但它有严格的约束:
_skill_nudge_interval = 0 # 后台 Agent 自己不会再触发 Nudge _memory_nudge_interval = 0 # 记忆 Nudge 也禁用 max_iterations = 20 # 轻量执行,不允许跑太久这套隔离设计的本质是:自进化是一个单向输出过程。主 Agent 产生经验,后台 Agent 消化经验并写入技能库,但后台 Agent 不能再产生新的复盘任务,否则系统会陷入递归失控。
回顾 Agent 审查完对话后,会输出两种操作之一。create 是新建技能,当发现一类反复出现的操作模式且现有技能库没有覆盖时,创建一个全新的 SKILL.md。patch 是局部修改,传入 old_text 和 new_text,系统执行字符串替换后重新安全扫描,再写入文件。patch 机制里有个工程细节值得注意:原子写入。内部流程是先写入临时文件,调用 os.fsync 刷盘,再用 os.replace 原子替换原文件。这样保证任何时刻读者要么看到完整的旧版本,要么看到完整的新版本,不会看到写了一半的损坏文件。
2.3 GEPA 离线进化:把 SKILL.md 当作基因
GEPA 的核心思想可以用一句话概括:把 SKILL.md 文件当作生物的基因,用遗传算法的方式让它一代代进化。这个比喻不是修辞,而是整套机制的设计基础。
基因对应 SKILL.md 文本,每条技能是一个个体,技能中的每句自然语言指令是可被突变的基因片段。染色体对应技能文件整体,进化目标是让它更好地指导 Agent。种群对应多版本变体集合,同时维护 N 个候选版本互相竞争。突变是 LLM 改写指令步骤,随机改写技能中的某段文字产生新变体。交叉是混合两变体段落,取 A 的前半部分加 B 的后半部分产生组合变体。自然选择是帕累托排序,淘汰劣质变体,优质变体进入下一代。
这个映射的关键洞察是:SKILL.md 是纯文本,而 LLM 天生擅长改写文本。不需要设计复杂的变异算子,让 LLM 自己去突变和交叉就行了。
举个突变的具体例子。原始版本 V0 的 docker 部署技能:
docker build . docker push $IMAGE ssh deploy.sh突变后版本 V1:
docker build -t $TAG . docker images | grep $TAG docker push $TAG ssh deploy.sh; wait_healthy 60突变后新增了两步:验证镜像是否构建成功,以及部署后等待健康检查。这不是人工指定的改进,而是 LLM 根据 docker 部署的上下文自动推断出来的。LLM 的预训练知识本身就是变异的灵感来源,它能产生人类设计者可能没想到的改进方向。
交叉操作模拟生物的有性繁殖:取两个优质变体,把它们的段落混合,产生一个新变体。比如变体 A 的前半部分步骤写得好,变体 B 的后半部分注意事项写得好,交叉后可能得到一个前半用 A、后半用 B 的组合体。突变是单点探索,交叉是组合探索。单靠突变,每次只能在一个方向上小步改进;有了交叉,两个独立发现的好改进可以组合到同一个个体中,加速进化。
2.4 帕累托优化:为什么没有单一的「最优技能」
GEPA 评估一个技能变体时,同时看三个指标:准确性(任务成功率,越高越好)、效率(Token 消耗量,越低越好)、鲁棒性(不同输入下的一致性,越高越好)。问题在于,这三个目标通常不能同时达到最优。想提升准确率,往往要在技能里写更多细节、更多示例,这会增加 Token 消耗;想降低 Token,就要精简技能内容,可能损失鲁棒性;想提升鲁棒性,就要覆盖更多边界情况,又会增加 Token。
帕累托优化用一个简单的规则来判断两个变体之间的优劣关系,叫做帕累托支配:如果变体 A 在所有指标上都不劣于变体 B,并且至少有一个指标严格更优,那么 A 支配 B,被支配的变体可以被淘汰。把所有变体按支配关系筛选一遍,剩下的那些不被任何其他变体支配的解,就构成了帕累托前沿。
用一个具体例子理解。假设 GEPA 对一个电商客服退款技能进行进化,产生了 6 个变体:
| 变体 | 技能特点 | 准确率 | Token 消耗 | 鲁棒性 |
|---|---|---|---|---|
| A | 极简版:只写告知用户退款入口 | 65% | 150 | 低 |
| B | 基础版:写清退款条件和操作步骤 | 75% | 220 | 中 |
| C | 详细版:条件+步骤+常见问题 FAQ | 82% | 350 | 中高 |
| D | 精炼版:B 的内容但措辞大幅压缩 | 78% | 180 | 中 |
| E | 全覆盖版:C 的内容+大量边界 case | 85% | 450 | 高 |
| F | 平衡版:条件+步骤+关键边界,措辞精炼 | 84% | 280 | 中高 |
先看 B 和 D:D 的准确率更高(78% 大于 75%),Token 消耗更低(180 小于 220),鲁棒性相同。D 在所有指标上都不劣于 B,且有两项严格更优,D 支配 B,B 被淘汰。再看 C 和 F:F 的准确率更高(84% 大于 82%),Token 消耗更低(280 小于 350),鲁棒性相同,F 支配 C,C 被淘汰。
剩下的 A、D、E、F 四个变体互不支配。A 的 Token 消耗只有 150,是所有变体中最低的,任何其他变体的 Token 都比 A 高,所以没有变体能在所有指标上都不劣于 A。D 在中等准确率下的极致效率这个位置上没有对手。F 是综合最优的代表。E 在准确率和鲁棒性上最高,适合大额退款等高风险场景。
最终结果是:B 和 C 被淘汰,A、D、F、E 留在帕累托前沿上。这个例子清晰地展示了帕累托优化的核心思想:进化不是线性地越改越好,而是在多个目标之间探索不同的平衡点。被淘汰的是那些两头不靠的中间态,留下来的是每个极端方向上的最优解。
3. 可复制配置:用 TaoToken 统一 Key 接入 Hermes-Agent 做对比实验
3.1 为什么需要统一 API 通道
做 GEPA 对比实验时,一个绕不开的问题是:你需要同时调用多个模型来评估不同技能变体的表现。如果每个模型都要单独配置 Key、单独处理 base_url、单独管理限流,实验还没开始,配置工作就已经把人耗光了。TaoToken 在这里的作用是提供一个统一的 API 通道,你只需要一个 Key,就能在多个模型之间切换,做对比实验时不用反复改配置。
TaoToken 的 API 地址是https://taotoken.net/api,官网是https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=。下面给出 Hermes-Agent 的配置片段。
3.2 Hermes-Agent 的 settings 配置
Hermes-Agent 的模型配置通常放在~/.hermes/settings.json或项目根目录的hermes.config.json中。以下是一个可复制的配置片段:
{ "model": { "provider": "openai-compatible", "base_url": "https://taotoken.net/api", "api_key": "sk-your-taotoken-key", "model_id": "claude-sonnet-4-20250514", "max_tokens": 8192, "temperature": 0.3 }, "skill": { "nudge_interval": 10, "max_iterations": 20, "skill_dir": "./skills", "auto_patch": true }, "gepa": { "enabled": true, "population_size": 6, "mutation_rate": 0.4, "crossover_rate": 0.3, "objectives": ["accuracy", "token_efficiency", "robustness"], "pareto_front_size": 4 } }如果你用的是 TOML 格式,等价配置如下:
[model] provider = "openai-compatible" base_url = "https://taotoken.net/api" api_key = "sk-your-taotoken-key" model_id = "claude-sonnet-4-20250514" max_tokens = 8192 temperature = 0.3 [skill] nudge_interval = 10 max_iterations = 20 skill_dir = "./skills" auto_patch = true [gepa] enabled = true population_size = 6 mutation_rate = 0.4 crossover_rate = 0.3 objectives = ["accuracy", "token_efficiency", "robustness"] pareto_front_size = 4这里有三件套需要确认:Base URL 填https://taotoken.net/api,Key 填你在 TaoToken 控制台创建的 API Key,Model ID 填你要用的模型标识。如果你用的是 Claude Code 或 Cline 这类工具,配置逻辑是一样的,把 Base URL 和 Key 填进去即可。
3.3 环境变量方式
如果你不想改配置文件,也可以用环境变量:
export HERMES_MODEL_PROVIDER="openai-compatible" export HERMES_BASE_URL="https://taotoken.net/api" export HERMES_API_KEY="sk-your-taotoken-key" export HERMES_MODEL_ID="claude-sonnet-4-20250514" export HERMES_SKILL_DIR="./skills" export HERMES_GEPA_ENABLED="true"配置完成后,你可以用一条简单的 curl 命令验证通道是否通:
curl -X POST https://taotoken.net/api/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-your-taotoken-key" \ -d '{ "model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "回复 OK"}], "max_tokens": 10 }'如果返回里能看到choices字段和正常的 content,说明通道没问题。这一步很重要,因为后面 GEPA 进化一轮可能要上百次 LLM 调用,通道不稳定会直接导致实验失败。
4. 验证请求与成功结果:跑一轮技能进化看提升
4.1 准备测试集和初始技能
验证自进化能力,最直接的方式是准备一个测试集和一个故意写得不完善的技能,然后看 Agent 能不能通过运行测试集自己进化技能,提升精准率。
先建一个测试集文件test_cases.json:
[ { "input": "订单 ORD-001 已支付但未发货,用户要求退款", "expected_action": "refund_create", "expected_params": {"order_id": "ORD-001", "reason": "user_request"} }, { "input": "订单 ORD-002 已发货,用户要求退款", "expected_action": "transfer_to_human", "expected_params": {} }, { "input": "订单 ORD-003 已支付,金额 800 元,用户要求退款", "expected_action": "refund_create_with_confirm", "expected_params": {"order_id": "ORD-003", "amount": 800} } ]然后写一个故意不完善的初始技能skills/refund_v0.md:
--- name: refund description: 处理退款 --- ## 步骤 1. 调用 refund_create 2. 通知用户这个技能的问题很明显:没有区分已发货和未发货,没有处理大额退款的二次确认,没有错误处理。
4.2 运行进化脚本
Hermes-Agent 的进化脚本通常叫evolve_skill.py,运行方式如下:
python evolve_skill.py \ --skill ./skills/refund_v0.md \ --test-cases ./test_cases.json \ --generations 3 \ --population 6 \ --output ./skills/refund_evolved.md脚本的执行流程是:先测基线,用初始技能跑一遍测试集,记录准确率;然后分块答题,把测试用例按类型分组;接着规则判错,对比 expected_action 和实际 action;把带原因的失败样本喂给持标准答案的 Reviewer;Reviewer 输出最小结构化补丁;SkillManager 写回文件并存版本;最后 probe 复测量化提升。
4.3 成功结果长什么样
跑完一轮后,你会看到类似这样的输出:
[Baseline] accuracy=0.33, tokens=180, robustness=0.40 [Generation 1] accuracy=0.67, tokens=240, robustness=0.60 [Generation 2] accuracy=0.89, tokens=280, robustness=0.80 [Generation 3] accuracy=1.00, tokens=310, robustness=0.90 [Pareto Front] 4 variants retained - variant_A: accuracy=1.00, tokens=310, robustness=0.90 - variant_B: accuracy=0.89, tokens=220, robustness=0.70 - variant_C: accuracy=0.78, tokens=180, robustness=0.60 - variant_D: accuracy=0.67, tokens=150, robustness=0.50进化后的技能文件refund_evolved.md大概会变成这样:
--- name: refund description: 处理退款请求,区分已发货和未发货,支持大额二次确认 version: 3 --- ## 适用场景 用户要求对已支付订单进行退款。 ## 步骤 1. 调用 order_query 确认订单状态 2. 若状态为 shipped,调用 transfer_to_human 转人工 3. 若状态为 paid 且金额小于 500,调用 refund_create 4. 若状态为 paid 且金额大于等于 500,调用 refund_create_with_confirm 5. 退款成功后调用 notify_user 通知用户 ## 注意事项 - 退款失败时记录 error_code,重试不超过 2 次 - 大额退款必须二次确认对比初始版本,进化后的技能增加了状态判断、大额确认、错误处理,准确率从 33% 提升到 100%。这就是一轮完整的进化验证。
5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth
5.1 401 Unauthorized
这是最常见的错误,通常有三个原因。第一,API Key 填错了,检查sk-开头的那串字符有没有复制完整。第二,Key 前面多了空格或者换行,用echo $HERMES_API_KEY | xxd看一下有没有隐藏字符。第三,Base URL 写成了https://taotoken.net/api/带了尾部斜杠,有些客户端会拼成//v1/chat/completions导致鉴权失败。正确的写法是https://taotoken.net/api,不带尾部斜杠。
5.2 local proxy failed
这个报错通常出现在你本地配了代理,但代理没启动或者端口不对。排查步骤:先确认环境变量HTTP_PROXY和HTTPS_PROXY有没有设置,如果设置了但代理没跑,直接 unset 掉。然后检查NO_PROXY里有没有把taotoken.net加进去。如果你用的是公司网络,可能需要找运维确认出口策略。
5.3 reading choices 相关报错
这个错误一般长这样:KeyError: 'choices'或者reading 'choices' of undefined。原因是 API 返回的结构和你代码里解析的结构不一致。常见情况是你请求的模型 ID 写错了,服务端返回了一个错误对象而不是正常的 completion 响应。排查方法:先用 curl 单独请求一次,看返回的 JSON 顶层有没有choices字段。如果没有,看error字段里的 message,通常是模型 ID 不存在或者参数不合法。
5.4 OAuth 相关报错
如果你用的是 Claude Code 或者 Codex 这类工具,可能会遇到 OAuth 报错。这类工具默认走 OAuth 流程,但如果你要接自定义 API 通道,需要切换到 API Key 模式。以 Codex 为例,检查~/.codex/auth.json:
{ "OPENAI_API_KEY": "sk-your-taotoken-key", "OPENAI_BASE_URL": "https://taotoken.net/api" }如果 auth.json 里还有tokens字段,说明它还在走 OAuth,需要把 tokens 删掉,只保留 API Key 和 Base URL。Claude Code 的话,检查~/.claude/settings.json里的env字段,确保ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY都指向 TaoToken。
5.5 GEPA 进化不收敛
如果跑了很多代准确率还是上不去,先检查测试集是不是太小。GEPA 需要足够的样本才能区分变体优劣,测试集少于 10 条时,评估结果波动会很大。其次检查 mutation_rate 和 crossover_rate,如果都设成 0.1 以下,种群多样性不足,容易早熟收敛。建议 mutation_rate 设 0.3 到 0.5,crossover_rate 设 0.2 到 0.4。最后检查 objectives 的权重,如果三个目标权重一样,帕累托前沿可能会保留太多变体,导致选择困难。
6. 把自进化 agent 接进你的工作流
Hermes-Agent 的自进化机制,本质上是在回答一个问题:怎么让 Agent 从「每次从零开始」变成「越用越强」。它的答案是把经验固化成 SKILL.md,用 Nudge 机制在运行时持续改进,用 GEPA 在离线时做种群进化,用帕累托优化在多个目标之间保留多样化的最优解。
如果你想动手试,我建议从最小闭环开始:先写一个不完善的 SKILL.md,准备 10 条测试用例,跑一轮 evolve_skill.py,看准确率有没有提升。通道方面,用 TaoToken 统一 Key 和 Base URL,省去多模型切换的配置麻烦。模型对话可以在https://taotoken.net/api对应的控制台里调试,API Key 在https://taotoken.net/api-keys创建,接入文档在https://taotoken.net/doc。如果你打算长期跑编码类 Agent 或者做多轮进化实验,Coding Plan 会比按量计费更划算,具体在https://taotoken.net/coding-plan看。
最后说一个我踩过的坑:GEPA 进化一轮可能要上百次 LLM 调用,如果你的测试集有 50 条,种群大小 6,跑 5 代,那就是 1500 次调用。跑之前先算一下预算,别跑到一半发现额度不够了。建议先用小测试集跑通流程,确认进化逻辑没问题,再放大规模。