乐于分享
好东西不私藏

Hermes Agent源码解析,读懂AI自我进化闭环

Hermes Agent源码解析,读懂AI自我进化闭环

👇 点击左下角 关注 → 获取大厂最新技术动态

Hermes Agent源码解析,读懂AI自我进化闭环

OpenRouter 排行榜上,Hermes Agent 增速 +204%,登顶 Top Coding Agents 第一。上线不到半年,GitHub 从 0 冲到 106k+ Star。它做了一件 OpenClaw 架构上做不到的事:Agent 干完活之后,自动把踩坑经验提炼成可复用的 Skill,用得越久,能力越强。本文拆开源码,看看这个 Self-Improving 闭环到底怎么跑的。

AI Agent 正在经历一场从「工具」到「伙伴」的范式转变

区别在哪?OpenClaw 的 Skill 是手写的 Markdown 文件——你写多少它会多少,你不写它就不会。Hermes 做了一件更彻底的事:Agent 干完活之后,会自动把踩坑经验提炼成可复用的 Skill,下次遇到同类问题直接调用。用得越久,能力越强。

这不是功能差异,是设计哲学的分野——一个静态配置,动态进化。这篇文章拆开 Hermes 的源码,看看这个 Self-Improving 闭环到底怎么跑的。

总览:三个子系统,一个闭环

绝大多数 Agent 在会话结束后就失去了一切上下文。Hermes 的解决思路是在内部构建一个持续学习的闭环,由三个子系统共同支撑:

Memory 相当于 Agent 的长期记忆,记录用户偏好和环境信息;Skill 是 Agent 积累的操作指南,记录经过验证的工作流程;Nudge Engine 则是一个定时器,定期触发 Agent 对自身工作进行回顾和总结。

🏗️ Hermes Self-Improving 系统架构

🧠 Memory
环境事实 / 用户偏好
◀▶
📚 Skill
可复用操作手册
⏰ Nudge Engine
定时触发反思
◀▶
🔄 自进化闭环
越用越强

Memory:越用越懂你

两个文件,就是 Agent 对你的全部认知

Memory 系统的实现非常精简——仅用两个纯文本文件,条目之间用 § 分隔:

~/.hermes/memories/
├── MEMORY.md # Agent 的个人笔记(环境事实、项目约定、工具怪癖)
└── USER.md # Agent 对用户的认知(偏好、沟通风格、工作习惯)
tools/memory_tool.py:116-122
classMemoryStore:
def__init__(self, memory_char_limit=2200, user_char_limit=1375):
self.memory_entries: List[str] = []
self.user_entries: List[str] = []
self.memory_char_limit = memory_char_limit
self.user_char_limit = user_char_limit
self._system_prompt_snapshot: Dict[str, str] = {"memory": "", "user": ""}
tools/memory_tool.py:124-140
defload_from_disk(self):
mem_dir = get_memory_dir()
self.memory_entries = self._read_file(mem_dir / "MEMORY.md")
self.user_entries = self._read_file(mem_dir / "USER.md")
# 会话开始时冻结快照,之后不再变动
self._system_prompt_snapshot = {
"memory": self._render_block("memory", self.memory_entries),
"user": self._render_block("user", self.user_entries),
}

字符上限设置得非常严格:MEMORY 上限 2200 字符,USER 上限 1375 字符。这种设计迫使 Agent 必须筛选高价值信息,低质量内容会被自然淘汰。

这与 OpenClaw 形成鲜明对比——OpenClaw 的 MEMORY.md 采用追加模式,几个月后就会膨胀到数万行,检索历史内容只能逐行扫描。Hermes 通过容量限制倒逼 Agent 进行信息压缩,自动淘汰过时内容,保留的都是高价值信息。

超限之后怎么办?让模型自己决定

Hermes 不会静默删除旧条目,也不做自动压缩,而是让 add 操作返回失败,同时将当前所有条目返回给模型:

tools/memory_tool.py:248-259
if new_total > limit:
current = self._char_count(target)
return {
"success": False,
"error": (
f"Memory at {current:,}/{limit:,} chars. "
f"Adding this entry would exceed the limit. "
f"Replace or remove existing entries first."
),
"current_entries": entries,
}

错误提示中的 “Replace or remove existing entries first” 引导模型执行替换或删除操作。返回的 current_entries 让模型能够看到现有内容,自主判断哪些需要删除、哪些可以合并。

模型不是被动执行淘汰逻辑,而是主动进行信息筛选——这个过程本身就是一种自我反思。

冻结快照:保护前缀缓存

每次会话开始时,Memory 加载完成后立即生成一份快照,后续系统提示词都使用这份快照。注入后,Agent 在处理用户消息前就已经了解了用户环境和偏好设置。

采用冻结快照而非实时更新的原因是:系统提示词保持不变可以利用前缀缓存(Prefix Cache)机制,避免重复计费。新写入的内容仅更新磁盘,下次会话时才会加载。

什么该记、什么不该记?

通过 Prompt 进行引导。系统提示词中的 MEMORY_GUIDANCE 部分明确规定:

agent/prompt_builder.py:144-162
"Write memories as declarative facts, not instructions to yourself."
"User prefers concise responses" ✓# 声明式事实
"Always respond concisely" ✗# 命令式指令

Memory 要求记录声明式事实(如 “User prefers concise responses”),而非命令式指令(如 “Always respond concisely”)。前者是用户偏好,可以被上下文覆盖;后者是固定规则,会降低 Agent 的灵活性。

Tool Schema 中还定义了一条关键边界:“If you’ve discovered a new way to do something, save it as a skill.” —— Memory 负责存储事实信息,Skill 负责存储操作步骤。这条规则清晰划分了两个系统的职责。

Skill:把做过的事变成会做的事

Memory 记录的是事实知识,Skill 记录的是操作方法

每个 Skill 是一个目录,核心是 SKILL.md 文件:

~/.hermes/skills/
├── devops/
│ └── flask-k8s-deploy/
│ ├── SKILL.md # 主指令
│ ├── references/ # 参考文档
│ └── templates/ # 模板文件
└── software-development/
└── fix-pytest-fixtures/
└── SKILL.md

典型的 SKILL.md 包含使用场景、操作步骤和注意事项。需要注意的是 Pitfalls 部分并非预先编写,而是 Agent 在实际操作中遇到问题后补充的——这就是 Skill 的自我改进机制。

什么时候创建 Skill?

Agent 不需要用户主动要求创建 Skill。触发条件定义在 skill_manage 工具的 schema 中:

tools/skill_manager_tool.py:681-701
SKILL_MANAGE_SCHEMA = {
"name": "skill_manage",
"description": (
"Manage skills (create, update, delete). Skills are your procedural "
"memory — reusable approaches for recurring task types.\n\n"
"Create when: complex task succeeded (5+ calls), errors overcome, "
"user-corrected approach worked, non-trivial workflow discovered, "
"or user asks you to remember a procedure.\n"
"Update when: instructions stale/wrong, OS-specific failures, "
"missing steps or pitfalls found during use. "
"If you used a skill and hit issues not covered by it, "
"patch it immediately with skill_manage(action='patch') "
"— don't wait to be asked.\n\n"
"After difficult/iterative tasks, offer to save as a skill. "
"Skip for simple one-offs."
),
}

创建门槛设定明确:工具调用超过 5 次才值得创建(简单任务无需记录)、经过问题修复的经验具有价值、用户纠正过的做法需要记录。

OpenClaw 同样具备 Skill 系统,采用 SKILL.md + YAML frontmatter 格式,但 Skill 的来源只有两种:手写或社区安装。手写成本高且维护困难;社区安装的 Skill 不一定适配你的具体环境。核心问题在于:Agent 无法从实际工作中积累经验——即使执行了一百次部署操作,第一百零一次仍可能犯同样的错误。

HN 上有一篇讨论指出「Data Is the Final Moat」——当模型能力和 Agent 框架都变得容易获取时,真正的竞争优势来自 Agent 在实际工作中积累的领域知识。OpenClaw 的 Skill 是静态的手写配置,使用一年后仍然是最初的手写内容;Hermes 的 Skill 则是不断积累的经验资产——每次问题解决都在增强系统能力。

Skill 的自我修补

当 Agent 按照现有 Skill 执行任务时,如果发现步骤不完整或遇到新问题,会在任务完成后对 Skill 进行修补。采用精确的局部 patch 而非全量重写:

tools/skill_manager_tool.py:397-485
def_patch_skill(name, old_string, new_string, file_path=None, replace_all=False):
"""Targeted find-and-replace within a skill file."""
new_content, match_count, _, match_error = fuzzy_find_and_replace(
content, old_string, new_string, replace_all
)
if match_error:
return {"success": False, "error": match_error}
original_content = content
_atomic_write_text(target, new_content)
scan_error = _security_scan_skill(skill_dir)
if scan_error:
_atomic_write_text(target, original_content) # 不通过就回滚
return {"success": False, "error": scan_error}

关键设计包括:fuzzy_find_and_replace 实现模糊匹配,容忍 Agent 提供的 old_string 与原文之间的格式差异。每次修改后执行 _security_scan_skill() 安全扫描,未通过则自动回滚。

渐进式加载:先看目录再翻全文

随着 Skill 数量增加,无法全部放入系统提示词。Hermes 采用轻量索引机制,默认只包含 Skill 名称和简要描述:

系统提示词中的 Skill 索引
Available skills:
devops:
- flask-k8s-deploy: Deploy a Flask app to Kubernetes with health checks
- nginx-reverse-proxy: Configure Nginx reverse proxy with SSL
software-development:
- fix-pytest-fixtures: Debug and fix pytest fixture scope issues

Agent 仅在判断某个 Skill 与当前任务相关时,才通过 skill_view 加载完整内容。按需加载机制有效避免了上下文膨胀问题。

Nudge Engine:谁来提醒 Agent「该学习了」

Memory 和 Skill 作为存储系统,需要触发机制来执行写入操作。Nudge Engine 就是这个触发器,通过维护两个计数器定期提醒 Agent 进行工作回顾。

两个计数器,两种粒度

📊 Nudge 计数器设计

计数器 触发粒度 默认阈值
Memory 计数器 按用户回合计 每 10 回合
Skill 计数器 按工具迭代计 每 10 次迭代

两种计数器的粒度差异基于不同的信息来源:Memory 的信息来自用户对话,按回合统计;Skill 的经验来自工具调用过程,按迭代统计。达到阈值后触发审查,如果 Agent 已经主动使用了 memory 或 skill_manage 则重置计数器。

后台 fork:不打扰用户的静默审查

Nudge 触发后的处理方式是在后台启动一个独立的 Agent 实例,使用主对话的快照进行审查,避免在主对话中插入提示信息影响用户体验:

run_agent.py:2665-2711
def_spawn_background_review(self, messages_snapshot,
review_memory=False, review_skills=False):
def_run_review():
review_agent = AIAgent(
model=self.model, max_iterations=8,
quiet_mode=True
)
review_agent._memory_store = self._memory_store
review_agent._memory_nudge_interval = 0# 禁用,防无限递归
review_agent._skill_nudge_interval = 0
review_agent.run_conversation(
user_message=prompt,
conversation_history=messages_snapshot,
)
thread = threading.Thread(target=_run_review, daemon=True)
thread.start()

关键实现细节包括:输出重定向到 /dev/null,用户完全无感知;限制最多 8 次工具调用,控制 API 消耗;禁用 review agent 的 nudge 机制,防止无限递归;与主 agent 共享 Memory 实例,写入操作立即生效。

每个审查 prompt 都以 “If nothing is worth saving, just say ‘Nothing to save.’ and stop.” 结尾,防止 review agent 为了完成任务而强行记录低价值信息。

完整案例:从「不会」到「精通」的三次会话

用一个 K8s 部署场景串一下三个子系统的协同。

第 1 次会话:冷启动

初始状态下 Memory 和 Skills 均为空,Agent 依赖基座模型知识进行操作,共进行了 12 次工具调用,遇到两个问题

iter 1-4:确认集群版本 → 读取代码 → 创建 Dockerfile → 构建镜像 → iter 5:编写部署文件 → iter 6:💥 ImagePullBackOff!忘记推镜像到 registry → iter 7-8:推镜像 + 重新部署 → iter 9-10:编写 Service + 部署 → iter 11:💥 CrashLoopBackOff!livenessProbe 路径不对 → iter 12:修改配置 → ✅ 成功

12 次迭代触发了 Skill Review 机制,Review Agent 分析了两次报错和修复过程,自动创建了一个 Skill,包含完整的操作步骤和注意事项。整个过程对用户透明。

第 2 次会话:Skill 复用 + 自我修补

第二次会话中,系统提示词已包含 Skills 索引,Agent 加载 flask-k8s-deploy Skill 后按照步骤执行:工具调用次数从 12 次减少到 9 次,已知问题被避免,但遇到了 Django 特有的 DisallowedHost 错误。

Review Agent 同时完成了三项工作:更新用户画像、记录 registry 地址、patch Skill 补充 ALLOWED_HOSTS 注意事项

第 3 次会话:零错误,一次搞定

第三次会话中,Agent 已经掌握了用户信息、registry 地址和集群配置,Skill 中也包含了 ALLOWED_HOSTS 的注意事项——仅 6 次调用,零错误

📊 三次会话对比

维度 会话 1
冷启动
会话 2
Skill 复用
会话 3
全协同
工具调用 12 次 9 次 6 次
错误数 2 1 0
Memory 触发写入 系统提示词注入
Skill 触发创建 + 修补 复用已修补版本

开源版本中,这些经验数据存储在用户本地的 ~/.hermes/ 目录。RDSHermes 将 Skill 存储迁移到云端——单个 DBA 遇到的问题,团队中所有 Agent 都能避免。经验积累从个人行为转变为组织级能力。

安全机制:进化也需要约束

Agent 具备自我写入能力,同时也引入了安全风险。Hermes 采用两层防护机制。

tools/memory_tool.py:65-81
_MEMORY_THREAT_PATTERNS = [
(r'ignore\s+(previous|all|above|prior)\s+instructions', "prompt_injection"),
(r'do\s+not\s+tell\s+the\s+user', "deception_hide"),
(r'system\s+prompt\s+override', "sys_prompt_override"),
(r'curl\s+[^\n]*\$\{?\w*(KEY|TOKEN|SECRET|PASSWORD)', "exfil_curl"),
...
]

第一层,Memory 内容扫描:由于 Memory 内容会注入系统提示词,如果包含 “ignore all previous instructions” 等恶意内容,会导致会话劫持。因此在写入前会扫描 prompt_injection、deception_hide、sys_prompt_override、exfil_curl 等威胁模式。

第二层,Skill 安全扫描:自创 Skill 和从 Hub 安装的 Skill 使用相同的安全扫描流程,未通过则自动回滚。

设计取舍一览

📊 源码中的设计决策及其背后的考虑因素

设计决策 表面效果 背后的考量
Memory 限 2200 chars 迫使 Agent 挑重要的记 低质量 Memory 注入系统提示词 = 每次 API 调用都带噪声
声明式事实 vs 操作步骤 分离 Memory 和 Skill 两者的更新频率、触发条件、安全风险完全不同
冻结快照模式 系统提示词会话内不变 保护前缀缓存,避免每轮 API 调用重新计费
后台 fork 审查 用户感知不到 review 过程 自省不应占用用户任务的 attention budget
patch 优先于全量重写 局部修复 Skill 保留已验证的稳定部分,只改需要改的

Skill 自动进化的下一步

自动创建和自我修补机制已经实现,未来还有几个值得探索的方向:

生命周期管理:当前 YAML frontmatter 仅包含 name、description、version 字段。增加 last_used、use_count、success_rate 等字段后,可以实现 Skill 的自动降权、归档和过时检测。

技能组合:当前 Skill 之间相互独立。如果系统能够自动识别经常组合使用的 Skill 并生成工作流(例如 flask-k8s-deploy + nginx-reverse-proxy → full-stack-deploy),系统将具备更高层次的推理能力。

创建透明度:当前 Skill 创建过程是静默的,用户无法感知。增加创建通知机制后,用户可以审核和纠正新创建的 Skill。

团队治理:个人使用场景下问题不大,但团队部署需要追踪操作来源。RDSHermes 要求写操作经过二次确认,所有会话可追溯和审计——Agent 可以自我进化,但所有操作都在审计范围内。

RDSHermes:从「开发者工具」到「团队都能用」

Self-Improving 机制是 Hermes 的核心优势,但开源版本主要面向开发者用户——需要编写 config.yaml 配置文件、配置 API Key 和 Gateway、通过日志排查问题。对于非技术背景的团队成员来说,使用门槛仍然较高。

RDSHermes 的目标是解决这个问题:将 Hermes 的自我进化能力封装为开箱即用的服务。

📊 开源 Hermes vs RDSHermes 对比

维度 开源 Hermes Agent RDSHermes
开始使用 命令行安装,手写 config.yaml 控制台一键开通,零配置
对话界面 终端 CLI 内置 WebUI,打开浏览器就能对话
数据库连接 手动配连接串,密码明文写配置 一键接入 RDS 实例,密码自动加密
云凭证管理 AK/SK 写进环境变量或配置文件 加密托管,网关代理鉴权,密钥不落盘
技能管理 Agent 自动创建,磁盘文件 Skill Hub 预装专业技能

简单来说:开源 Hermes 提供底层引擎,RDSHermes 提供完整解决方案。在 Self-Improving 能力基础上,RDSHermes 补充了四个方面的能力:

  • 数据库安全纳管:MySQL、PostgreSQL、SQL Server、MariaDB 多引擎一键接入,密码提交瞬间加密。可以设只读模式——Agent 能查但不能改,生产环境安全有底线。
  • 身份认证托管:AK/SK 加密托管,Agent 调用云 API 时由网关代理鉴权,密钥不暴露给 Agent 也不暴露给用户。
  • 内置数据库专业技能:Skill Hub 预装智能巡检、慢 SQL 诊断、索引优化等技能。DBA 说一句「帮我巡检一下 prod-mysql」,Agent 连着你的库做真实分析。
  • 全链路监控审计:写操作需确认才执行,会话可追溯,Token 消耗可监控,安全事件有告警。

总结

Hermes Agent 的 Self-Improving 机制依赖于三个组件的协同:Memory 记录用户信息,Skill 记录操作方法,Nudge Engine 维持学习循环。使用时间越长,Agent 的工作效率越高,遇到的问题越少。

OpenClaw 在 AI Agent 的推广方面做出了重要贡献。但需要详细配置指南的工具、升级后容易出问题的系统、记忆文件随使用时间增长而变慢的架构——这些限制正在推动行业向前发展。开发者的选择反映了真实需求。Hermes 的核心优势不在于功能数量,而在于实现了一个关键能力:系统能力随使用时间增长而提升。

如果当前还在手动编写 Skill、维护 MEMORY.md 文件、每次升级前进行充分准备——值得思考的是:投入时间进行 Agent 运维,还是让 Agent 具备自主学习能力?


END


📚 参考文章

github.com/NousResearch/hermes-agent

🔥 感谢点赞 · 分享 · 喜欢,您的支持即动力

👇 点击左下角 关注 → 大厂技术动态早知道