Hermes Agent 自动学习与成长原理深度解读

Nous Research 推出的 Hermes Agent 是 2026 年增长最快的开源 AI Agent,其核心差异化能力是内置学习循环(Learning Loop)——它能从经验中自动创建技能、在使用中自我改进、主动持久化知识,实现跨 Session 的能力累积。本文从源码层面深度拆解其原理。


架构总览:学习循环的四阶段

Hermes Agent 的学习循环遵循 Observe → Distill → Reuse → Refine 四个阶段,运行在 agent loop 的主循环之上:

User Message
    │
    ▼
┌─────────────────────────────────┐
│   Agent Loop                    │
│   (run_conversation)            │
│                                 │
│   while budget_remaining:       │
│     response = LLM.call(...)    │
│     if tool_calls:              │
│       execute tools             │
│       append results            │
│     else:                       │
│       return response           │
│                                 │
│   ┌─────────────────────────┐   │
│   │ Self-Evaluation         │   │
│   │ Checkpoint              │   │
│   │ (每 15 次 tool call)     │   │
│   └─────────┬───────────────┘   │
│             ▼                   │
│   ┌─────────────────────────┐   │
│   │ Skill Creation / Update │   │
│   │ Memory Nudge            │   │
│   └─────────────────────────┘   │
└─────────────────────────────────┘

核心洞察:这不是模型权重层面的训练,而是结构化的经验记录与检索系统。LLM 的权重从未被改变,改变的是围绕 LLM 的”知识层”——提示词、技能文档、记忆文件。

主线 Agent Loop

Hermes 的核心驱动在 run_agent.py 中的 AIAgent 类(约 13,700 行)。其主循环逻辑如下:

def run_conversation(self):
    while (api_call_count < self.max_iterations
           and self.iteration_budget.remaining > 0) \
           or self._budget_grace_call:

        if self._interrupt_requested:
            break

        # 1. 构建系统提示(含 skills 索引、记忆)
        system_prompt = self._build_system_prompt()

        # 2. 调用 LLM(支持多种 provider)
        response = client.chat.completions.create(
            model=model,
            messages=messages,
            tools=tool_schemas
        )

        # 3. 解析响应
        if response.tool_calls:
            for tool_call in response.tool_calls:
                result = handle_function_call(
                    tool_call.name, tool_call.args, task_id
                )
                messages.append(tool_result_message(result))

                # ★ 自评价检查点
                if self._should_evaluate():
                    self._learning_checkpoint(messages)

            api_call_count += 1
        else:
            self._flush_memory()
            return response.content

关键设计:

  • self.iteration_budget:追踪父子 agent 的预算消耗,防止无限循环
  • _should_evaluate():基于 tool call 计数判断是否需要触发学习检查点
  • _flush_memory():在上下文丢失前将关键信息写入持久化文件

技能系统:学习循环的核心载体

SKILL.md 格式

技能以 Markdown 文件存储在 ~/.hermes/skills/ 下,通过 YAML frontmatter 声明元数据:

---
name: code-review
description: 执行标准代码审查工作流
version: 1.2.0
platforms: [macos, linux]
metadata:
  hermes:
    tags: [code-review, github, ci]
    related_skills: [github-pr-workflow]
    config:
      - key: review.strictness
        description: 审查严格程度
        default: "medium"
---

# 代码审查技能

## 触发条件
当用户说"审查这个 PR"时自动加载。

## 步骤
1. 读取 PR 的变更文件列表
2. 对每个文件运行 linter 检查
3. 生成变更摘要报告

## 已知陷阱
- 超过 500 行变更的 PR,先要求作者拆分

渐进式加载

prompt_builder.py 实现了三层缓存加载策略:

层级 内容 Token 开销 触发时机
L0 技能名称 + 描述索引 ~3K(总) Session 启动(自动注入 system prompt)
L1 完整 SKILL.md 内容 按需 Agent 调用 skill_view(name)
L2 附属文件(references/templates/scripts) 按需 Agent 调用 skill_view(name, file_path)
def build_skills_system_prompt(available_tools=None):
    """构建紧凑的技能索引,注入 system prompt"""

    index_lines = []
    for category in sorted(skills_by_category):
        for name, desc in sorted(...):
            if desc:
                index_lines.append(f"    - {name}: {desc}")

    result = (
        "## Skills (mandatory)\n"
        "Before replying, scan the skills below. "
        "If a skill matches your task, you MUST load it. "
        "<available_skills>\n"
        + "\n".join(index_lines) + "\n</available_skills>\n"
    )
    return result

Agent 自管理技能:skill_manage 工具

这是学习循环的关键工具——Agent 可以在运行时创建、更新、删除自己的技能文件:

def skill_manage(action, name, content=None, category=None,
                 old_string=None, new_string=None, replace_all=False,
                 file_path=None, file_content=None):
    if action == "create":
        return _create_skill(name, content, category)
    elif action == "patch":
        return _patch_skill(name, old_string, new_string,
                            replace_all, file_path)
    elif action == "edit":
        return _edit_skill(name, content)
    elif action == "delete":
        return _delete_skill(name)
    elif action == "write_file":
        return _write_file(name, file_path, file_content)
    elif action == "remove_file":
        return _remove_file(name, file_path)

_patch_skill 的模糊匹配引擎

def _patch_skill(name, old_string, new_string,
                 replace_all=False, file_path=None):
    content = target.read_text(encoding="utf-8")

    # 8 策略模糊匹配引擎
    # 处理:空白标准化、缩进差异、块锚点匹配
    from tools.fuzzy_match import fuzzy_find_and_replace

    new_content, match_count, _strategy, match_error = \
        fuzzy_find_and_replace(content, old_string, new_string, replace_all)

    if match_error:
        preview = content[:500] + ("..." if len(content) > 500 else "")
        return {"success": False, "error": match_error, "file_preview": preview}

    err = _validate_content_size(new_content)
    if err:
        return {"success": False, "error": err}

    _atomic_write_text(target, new_content)  # 原子写入,失败回滚
    return {"success": True, "message": f"Patched skill '{name}' ({match_count} replacements)."}

_create_skill 完整流程

def _create_skill(name, content, category=None):
    # 1. 解析 YAML frontmatter
    frontmatter, body = _parse_frontmatter(content)
    skill_name = frontmatter.get("name", name)

    # 2. 安全检查
    if _detect_injection(content):
        return {"success": False, "error": "注入检测失败"}
    err = _validate_content_size(content)
    if err:
        return {"success": False, "error": err}

    # 3. 确定目标路径
    skill_dir = SKILLS_DIR / category / skill_name if category else SKILLS_DIR / skill_name
    skill_dir.mkdir(parents=True, exist_ok=True)

    # 4. 原子写入
    _atomic_write_text(skill_dir / "SKILL.md", content)
    return {"success": True, "message": f"Skill '{skill_name}' created."}

System Prompt 中的技能引导

# agent/prompt_builder.py
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."
)

这不是硬编码规则,而是通过 System Prompt 引导 LLM 自主决策:

  • 5+ 次 tool call → 判定为”复杂任务”
  • 成功完成 + 发现更好方法 + 用户纠正 → 分别是创建/更新/修正技能的触发条件

这意味着学习能力来自于 LLM 自身的推理能力,而非预设规则

技能生命周期管理:Curator

Curator 是 Hermes 的”技能管家”,自动管理技能的完整生命周期:

class SkillCurator:
    def run(self):
        usage = self._load_usage_stats()  # ~/.hermes/skills/.usage.json

        for skill in self._get_agent_skills():
            state = usage.get(skill.name, {})

            if self._is_stale(skill, state):
                self._archive_skill(skill)     # 30 天未使用 → 归档
            elif self._is_frequently_used(skill, state):
                self._pin_skill(skill)          # 高频使用 → 固定

            if self._needs_review(skill, state):
                review = self._llm_review_skill(skill)
                if review.suggested_improvements:
                    self._apply_review(skill, review)

    def _archive_skill(self, skill):
        """移到 .archive/ 目录,永不删除"""
        shutil.move(str(skill.dir), str(SKILLS_DIR / ".archive" / skill.name))

Curator 的不变量:

  • 仅操作 created_by: "agent" 的技能,内置 + Hub 安装技能不受影响
  • 永不删除,最多归档到 .archive/
  • Pinned 技能豁免所有自动操作

记忆系统:跨 Session 知识持久化

提示记忆:MEMORY.md + USER.md

class MemoryManager:
    def flush(self, conversation_history):
        insights = self._extract_insights(conversation_history)

        # MEMORY.md:工作相关的记忆
        with open(HERMES_HOME / "MEMORY.md", "a") as f:
            for insight in insights.work_memories:
                f.write(f"- {insight}\n")

        # USER.md:用户画像
        with open(HERMES_HOME / "USER.md", "a") as f:
            for insight in insights.user_insights:
                f.write(f"- {insight}\n")

情节记忆:SQLite FTS5

-- 10ms 内跨 10,000+ 文档检索
CREATE VIRTUAL TABLE session_history USING fts5(
    content, metadata, tokenize='porter'
);

SELECT snippet(session_history, 1, '<b>', '</b>', '...', 32)
FROM session_history
WHERE session_history MATCH ?
ORDER BY rank
LIMIT 5;

Memory Nudge

每 10 次交互或会话结束时,Hermes 会问自己:”这次对话中有哪些值得记住的信息?”

Nudge 类型 触发条件 目的
会话结束 对话关闭 总结关键收获
模式检测 3+ 次类似请求 持久化偏好
用户声明 “记住这个” 立即存储
周期检查 每 10 轮交互 检查有价值信息

完整的技能自改进循环

第一次请求:”帮我审查这个 PR”

# 1. Agent 收到请求
# 2. 扫描 skills_list  → 没有匹配技能 → 从头推理
# 3. 执行 7 次 tool call(gh pr view, gh pr diff, lint...)
# 4. 成功完成 ✓
# 5. ★ 自评价检查点触发(7 > 5)
# 6. Agent 判断这是可复用的工作流
skill_manage(action='create', name='code-review', content=...)
# → 文件写入 ~/.hermes/skills/code-review/SKILL.md

第二次请求:”再审查 PR #58″

# 1. 扫描 skills_list → 发现 code-review 技能匹配
skill_view("code-review")  # → 加载完整 SKILL.md
# 2. 按步骤执行,遇到新问题:PR 包含二进制文件
# 3. 完成审查后,自动修补技能:
skill_manage(action='patch', name='code-review',
    old_string="1. 读取 PR 的变更文件列表",
    new_string="1. 读取 PR 的变更文件列表\n"
               "2. 过滤二进制文件,仅审查文本文件")
# → 技能从 5 步变成了 6 步

第 N 次:技能成熟

经过 20-30 次使用后,技能文档已从简单的指令集演化为经过实战锤炼的操作手册:

指标 第 1 周 第 6 周
每次审查的 tool call 数 25 8-10
错误率 高(经常遗漏步骤) 低(边界情况已被覆盖)
需要的人工干预 频繁 几乎不需要

RL 强化学习管道:Atropos 集成

class AtroposRLPipeline:
    def train_from_trajectories(self, trajectories_dir):
        trajectories = self._load_trajectories(trajectories_dir)
        compressed = trajectory_compressor.compress(trajectories)

        for trajectory in compressed:
            reward = self._compute_reward(trajectory)
            # RLHF: 用户反馈作为奖励信号
            # DPO: 偏好对比训练
            self._training_step(trajectory, reward)

        self._export_for_finetuning(compressed)  # ShareGPT 格式

但需注意:RL 管道是可选的、离线的。日常学习循环不需要权重更新,在用户使用过程中实时发生。

“自改进”的真实含义

维度 Hermes 的学习 传统 ML 训练
作用对象 提示词、技能文档、记忆文件 模型权重
范围 特定用户的工作流 全局能力
频率 实时(每次任务后) 周期性(训练阶段)
存储 文件系统(明文 Markdown) 模型参数(二进制)
可解释性 完全透明(可读可编辑) 黑盒
回滚 删文件或 git revert 重新训练

结论:Hermes 的”自改进”不是模型变聪明了,而是围绕模型的辅助层——过程性记忆(Skills)和陈述性记忆(MEMORY.md/USER.md)在持续累积经验。但这恰恰是实用层面最重要的改进:一个更了解你工作流的 Agent,比一个参数更多的通用模型更有价值。

极简学习循环演示代码

"""极简版学习循环实现(原理演示)"""
from pathlib import Path

SKILLS_DIR = Path.home() / ".demo-skills"
TOOL_CALL_THRESHOLD = 3

class LearningAgent:
    def __init__(self):
        self.tool_call_count = 0
        self.conversation_history = []
        SKILLS_DIR.mkdir(exist_ok=True)

    def run(self, user_input):
        self.conversation_history.append(
            {"role": "user", "content": user_input}
        )
        response = self._call_llm(self._build_prompt())

        if response.get("tool_calls"):
            for tc in response["tool_calls"]:
                result = self._execute_tool(tc)
                self.conversation_history.append(
                    {"role": "tool", "content": result}
                )
                self.tool_call_count += 1

            if self.tool_call_count >= TOOL_CALL_THRESHOLD:
                self._learning_checkpoint()  # ★ 自评价

            return self.run(user_input)
        else:
            return response["content"]

    def _learning_checkpoint(self):
        steps = self._extract_steps()
        if not steps:
            return

        task_type = self._classify_task(steps)
        existing = self._find_skill(task_type)

        if existing:
            new_steps = self._find_new_steps(existing, steps)
            if new_steps:
                self._patch_skill(existing, new_steps)
                print(f"  → 技能 '{task_type}' 已更新 (+{len(new_steps)} steps)")
        else:
            self._create_skill(task_type, steps)
            print(f"  → 新技能 '{task_type}' 已创建 ({len(steps)} steps)")

    def _create_skill(self, name, steps):
        content = f"""---
name: {name}
description: 自动创建的技能
---

# {name}

## 步骤
"""
        for i, step in enumerate(steps, 1):
            content += f"{i}. {step}\n"

        skill_dir = SKILLS_DIR / name
        skill_dir.mkdir(exist_ok=True)
        (skill_dir / "SKILL.md").write_text(content)
# 运行示例
agent = LearningAgent()
agent.run("帮我设置 CI/CD 流水线")
# → 执行 5 次 tool call → 自评价触发 → 创建技能 'ci-cd-pipeline' (8 steps)

agent.run("再设置一个前端项目的 CI/CD")
# → 技能匹配!加载 ci-cd-pipeline 技能
# → 发现缺少 npm install 步骤 → 自动 patch
# → 技能更新为 9 steps

总结

机制 技术实现 学习效果
技能创建 将复杂任务的执行轨迹抽象为 SKILL.md 从”不知道怎么做”到”有标准方法”
技能修补 模糊匹配引擎 patch 技能文件 从”有标准方法”到”方法越来越完善”
技能渐进加载 L0 索引 + L1 内容 + L2 附属文件 数百技能不增加 token 开销
记忆持久化 MEMORY.md / USER.md + SQLite FTS5 跨 Session 知识不丢失
Curator 生命周期 自动归档 + LLM 审查 技能库保持健康
Honcho 用户建模 辩证主义演进式用户画像 Agent 越来越了解你
Atropos RL 轨迹压缩 + DPO/RLHF 训练 可选深度优化模型行为

Hermes 的学习循环本质上是将 LLM 的推理能力与文件系统的持久性结合:LLM 负责判断”什么值得学”和”如何改进”,文件系统负责”记住”和”检索”。这种架构让 Agent 在使用中不断累积领域知识,从第 1 天的通用助手,进化为第 30 天的专属工作伙伴。

正如 Nous Research 所说:”这不是一个更聪明的模型,这是一个更聪明的包装器。”
The LLM is a replaceable component; the real engineering work happens in the layers around it.

 

u2

Related Posts

本地AI时代来临:Ollama + MemPalace工作流深度指南

本地优先(Local-First)正在重塑AI开发范式。当O…

Read more

担心Todesk,向日葵有漏洞和数据泄露?跟我来体验下完美开源替代工具:RustDesk!

除了使用vpn访问公司内网外,很多公司员工为了操作上的便利,…

Read more

发表回复

You Missed

Hermes Agent 自动学习与成长原理深度解读

  • u2
  • 5月 14, 2026
  • 16 views

Agent Memory + Skills 双轮驱动 Memori Labs × Anthropic Dreaming 执行记忆 vs 会话记忆,如何构建持续进化的 Agent

  • u2
  • 5月 11, 2026
  • 50 views
Agent Memory + Skills 双轮驱动 Memori Labs × Anthropic Dreaming 执行记忆 vs 会话记忆,如何构建持续进化的 Agent

基于大模型的测试用例生成解决方案

  • u2
  • 5月 10, 2026
  • 64 views

从0到1搭建一个AI Token中转站:技术架构与实战指南

  • u2
  • 5月 2, 2026
  • 550 views

本地AI时代来临:Ollama + MemPalace工作流深度指南

  • u2
  • 4月 21, 2026
  • 227 views

Raycast深度解析:这个让Mac效率重装升级的东西,到底值不值?

  • u2
  • 4月 14, 2026
  • 166 views