✅Hermes Agent的Skill自进化机制



这几天(4月初级到四月中旬),Nous Research开源的Hermes Agent突然火起来了,github的star数在疯涨,热度高到有超越open claw的势头了。



为什么他这么火呢?主要是因为他解决了open claw中的这样一个痛点:



在使用 OpenClaw 完成一个任务后,无论过程中走了多少弯路、犯了多少错误,这些宝贵的经验都不会沉淀下来,都是用后即焚的。即使下次再遇到相同的任务,他还会从头再来一遍,把踩过的坑再踩一遍。即使你让它记录Memory,他也只是会记录一些简要的重点事项和用户习惯,并不会记录太多执行细节。



Hermes则引入了一种Skill自进化机制,来解决这个问题。



说的简单点,就是引入了一种动态的Skill沉淀的能力。在Hermes Agent中,每次完成复杂任务后,Hermes不会简单地丢弃对话历史,而是会启动一个“复盘”流程。它会回过头来审视整个执行轨迹,提取其中的关键步骤,特别是那些“踩过的坑”、有效的纠错手段以及人工验证过的最佳实践。



随后,系统将这套经验总结、抽象为一个结构化的Skill技能文件包。这就带来了一个根本性的转变:Skill 从“静态调用”变成了“动态生成”。



总结一下:Skill 自进化是指 AI Agent 能够在执行任务的过程中自动创建新的技能,并在后续使用中持续改进这些技能的能力。



在Hermes中,Skill生成的触发时机包括:



1
# agent/prompt_builder.py 第 164-171 行SKILLS_GUIDANCE = (    "After completing a complex task (5+ tool calls), fixing a tricky error, "    "or discovering a non-trivial workflow, save the approach as a "    "skill with skill_manage so you can reuse it next time.\n"    "When using a skill and finding it outdated, incomplete, or wrong, "    "patch it immediately with skill_manage(action='patch') — don't wait to be asked. "    "Skills that aren't maintained become liabilities.")
Field Value
触发条件 说明
复杂任务成功完成后 任务使用了 5+ 个工具调用
克服错误后 在解决错误后形成可复用的方法
用户纠正的方法奏效后 用户指导的方法被验证有效
发现非平凡的工作流 发现了复杂的工作流程
用户明确要求记住某个流程 用户主动要求保存为 Skill



触发原则

  • 在困难/迭代任务后,Agent 会主动提议保存为 Skill

  • 简单的一次性任务跳过

  • 创建/删除前需要用户确认



入口函数:skill_manage()



1
2
def skill_manage(    action: str,           # "create", "edit", "patch", "delete", "write_file", "remove_file"    name: str,             # Skill 名称    content: str = None,   # SKILL.md 完整内容(create/edit 时需要)    category: str = None,  # 可选分类(如 "devops", "mlops")    ...) -> str:



Skill 创建的核心步骤(_create_skill 函数)



1
def _create_skill(name: str, content: str, category: str = None) -> Dict[str, Any]:



Skill的创建有多种触发机制:



自动触发机制



自动触发完全依赖 LLM 的自主决策。通过在系统提示中植入指导文本,让 LLM 自己判断何时应该创建或更新 Skill。



在 Hermes Agent 中,系统会在每次对话开始时给 AI 发送一段”指导语”,告诉它什么情况下应该创建 Skill。AI 在工作的过程中,会自主决定什么时候调用创建工具。



首先,系统提示词注入:



1
# agent/prompt_builder.py 第 164-171 行SKILLS_GUIDANCE = (    "After completing a complex task (5+ tool calls), fixing a tricky error, "    "or discovering a non-trivial workflow, save the approach as a "    "skill with skill_manage so you can reuse it next time.\n"    "When using a skill and finding it outdated, incomplete, or wrong, "    "patch it immediately with skill_manage(action='patch') — don't wait to be asked. "    "Skills that aren't maintained become liabilities.")



  • 完成一项复杂任务(涉及5次以上工具调用)

  • 修复一个棘手的错误

  • 发现一种复杂且有效的工作流程后

  • 使用某项技能时,若发现它已过时、不完整或存在错误,立即修正



系统提示组装:



1
2
# run_agent.py 第 3374-3383 行
def _build_system_prompt(self, system_message: str = None) -> str: # ... # Tool-aware behavioral guidance: only inject when the tools are loaded tool_guidance = [] if "memory" in self.valid_tool_names: tool_guidance.append(MEMORY_GUIDANCE) if "session_search" in self.valid_tool_names: tool_guidance.append(SESSION_SEARCH_GUIDANCE) if "skill_manage" in self.valid_tool_names: # ← 检查 skill_manage 是否可用 tool_guidance.append(SKILLS_GUIDANCE) # ← 注入 Skill 指导 if tool_guidance: prompt_parts.append(" ".join(tool_guidance))



关键点

  • 只有在 skill_manage 工具可用时才注入指导

  • 指导文本成为系统提示的一部分

  • LLM 每次响应都会”看到”这个指导



工具Schema强化:

1
2
3
# tools/skill_manager_tool.py 第 683-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.\n\n" "After difficult/iterative tasks, offer to save as a skill. " "Skip for simple one-offs. Confirm with user before creating/deleting." ), ...
}



自动触发工作流程:



1
用户输入    │    ▼┌─────────────────────────────────────┐│  系统提示包含 SKILLS_GUIDANCE        ││  "After completing a complex task   ││   (5+ tool calls)..."               │└─────────────────────────────────────┘    │    ▼LLM 处理任务    │    ├─── 工具调用 1 ────┐    ├─── 工具调用 2 ────┤    ├─── 工具调用 3 ────┤  LLM 自主计数    ├─── 工具调用 4 ────┤  和判断    ├─── 工具调用 5 ────┘    │    ▼LLM 判断:"这是一个复杂任务,应该保存为 Skill"    │    ▼主动调用 skill_manage(action="create")    │    ▼创建 Skill 文件



后台审查机制



除了自动触发外,还有一种后台审查机制的触发,即系统跟踪工具调用次数,达到阈值后自动启动后台审查,无需 LLM 主动决策。



在 Hermes Agent 中,系统会默默计数——每次 AI 使用工具(比如查资料、运行命令、读取文件)都会 +1。当累计达到 10 次后,系统会在后台自动启动一个”审查员”(另一个 AI 实例),让它回顾刚才的对话历史,判断是否需要创建或更新 Skill。这个审查是在后台悄悄进行的,不会打扰用户,如果发现值得保存的内容,会发送一个通知。



计数器初始化:



1
# run_agent.py 第 1219 行 (AIAgent.__init__)self._iters_since_skill = 0  # 自上次 skill 操作以来的迭代计数器



配置加载:



1
# run_agent.py 第 1340-1346 行# Skills config: nudge interval for skill creation remindersself._skill_nudge_interval = 10  # 默认每 10 次工具调用触发一次try:    skills_config = _agent_cfg.get("skills", {})    self._skill_nudge_interval = int(skills_config.get("creation_nudge_interval", 10))except Exception:



迭代计数(核心):



1
2
# run_agent.py 第 8642-8646 行# 在每次工具调用迭代后执行
# Track tool-calling iterations for skill nudge.# Counter resets whenever skill_manage is actually used.if (self._skill_nudge_interval > 0 # 功能已启用 and "skill_manage" in self.valid_tool_names): # 工具可用 self._iters_since_skill += 1 # ← 计数器 +1



计数器重置条件:



1
2
# run_agent.py 第 7416-7417 行# 当实际调用 skill_manage 时重置计数器
elif function_name == "skill_manage": self._iters_since_skill = 0 # ← 重置计数器



触发判断:



1
2
# run_agent.py 第 11338-11344 行# 在响应用户完成后执行
# Check skill trigger NOW — based on how many tool iterations THIS turn used._should_review_skills = Falseif (self._skill_nudge_interval > 0 # 1. 功能已启用 and self._iters_since_skill >= self._skill_nudge_interval # 2. 达到阈值 and "skill_manage" in self.valid_tool_names): # 3. 工具可用 _should_review_skills = True self._iters_since_skill = 0 # ← 重置计数器



启动后台审查:



1
# run_agent.py 第 11356-11366 行# Background memory/skill review — runs AFTER the response is delivered# so it never competes with the user's task for model attention.if final_response and not interrupted and (_should_review_memory or _should_review_skills):    try:        self._spawn_background_review(            messages_snapshot=list(messages),            review_memory=_should_review_memory,            review_skills=_should_review_skills,  # ← 触发 Skill 审查        )    except Exception:        pass  # Background review is best-effort



后台审查执行:



1
2
3
4
5
6
7
8
9
10
# run_agent.py 第 2371-2469 行def _spawn_background_review(    self,    messages_snapshot: List[Dict],    review_memory: bool = False,    review_skills: bool = False,) -> None:    """Spawn a background thread to review the conversation for memory/skill saves."""    import threading
# 选择审查提示词 if review_memory and review_skills: prompt = self._COMBINED_REVIEW_PROMPT el
if review_memory: prompt = self._MEMORY_REVIEW_PROMPT else: prompt = self._SKILL_REVIEW_PROMPT # ← Skill 专用提示词
def _run_review(): review_agent = None try: with contextlib.redirect_stdout(_devnull), \ contextlib.redirect_stderr(_devnull): # ===== 创建 Fork 的 Review Agent ===== review_agent = AIAgent( model=self.model, max_iterations=8, # 限制迭代次数 quiet_mode=True, # 静默模式 platform=self.platform, provider=self.provider, ) # 禁用嵌套触发(避免无限循环) review_agent._memory_nudge_interval = 0 review_agent._skill_nudge_interval = 0
# 执行审查 review_agent.run_conversation( user_message=prompt, conversation_history=messages_snapshot, )
# ===== 扫描审查结果 ===== actions = [] for msg in getattr(review_agent, "_session_messages", []): if msg.get("role") != "tool": continue data = json.loads(msg.get("content", "{}")) if not data.get("success"): continue message = data.get("message", "") if "created" in message.lower() or "updated" in message.lower(): actions.append(message)
# ===== 通知用户 ===== if actions: summary = " · ".join(dict.fromkeys(actions)) self._safe_pr
int(f" 💾 {summary}") # 终端显示 if self.background_review_callback: self.background_review_callback(f"💾 {summary}")
finally: if review_agent: review_agent.close()
# 启动后台线程 threading.Thread(target=_run_review, daemon=True, name="bg-review").start()



Skill 审查专用提示词:



1
# run_agent.py 第 2347-2355 行_SKILL_REVIEW_PROMPT = (    "Review the conversation above and consider saving or updating a skill if appropriate.\n\n"    "Focus on: was a non-trivial approach used to complete a task that required trial "    "and error, or changing course due to experiential findings along the way, or did "    "the user expect or desire a different method or outcome?\n\n"    "If a relevant skill already exists, update it with what you learned. "    "Otherwise, create a new skill if the approach is reusable.\n"    "If nothing is worth saving, just say 'Nothing to save.' and stop.")



后台审查触发工作流程:



1
用户输入    │    ▼工具调用循环    │    ├─── 每次迭代后 ───► _iters_since_skill += 1    │    ▼响应用户完成    │    ▼检查触发条件    │    ├─── _iters_since_skill >= 10? ─── 否 ─── 继续等待    │    └─── 是 ───► _should_review_skills = True                  │                  ▼         调用 _spawn_background_review()                  │                  ▼         创建 Fork Review Agent                  │                  ▼         执行 _SKILL_REVIEW_PROMPT                  │                  ▼         LLM 审查对话历史                  │    ┌─────────────┴─────────────┐    ▼                           ▼ Nothing to save.           调用 skill_manage    │                           │    ▼                           ▼   结束                    创建/更新 Skill                               │                               ▼                          显示 💾 通知