Hermes Agent 深度技术调研:自我进化的开源 AI Agent

基于源码阅读的深度分析 | 仓库: NousResearch/hermes-agent | MIT License | v0.7.0 (2026-04-03)

一、项目概述

Hermes Agent 是 Nous Research 推出的自我进化开源 AI Agent。它不是一个 IDE 绑定的 Copilot,而是一个持久化的自主任务执行框架,核心卖点是闭环学习循环 (Closed Learning Loop) —— Agent 能从经验中自主创建技能、改进技能、持久化知识、搜索历史会话,并跨会话构建用户画像。

关键数据:

  • GitHub Stars: ~30,000+ | Contributors: 242+ | Releases: 7 (5周内)
  • 核心文件: run_agent.py (9,423行) | cli.py (8,615行)
  • 内置工具: 47个 | 内置技能: 70+ | 消息平台: 14+
  • 执行后端: 6种 | 支持 LLM Provider: 18+

二、架构设计(源码视角)

2.1 三层架构

┌─────────────────────────────────────────────────┐
│              User Interface Layer                │
│  CLI (cli.py) │ Gateway (gateway/run.py) │ ACP   │
│  Batch Runner │ Cron Scheduler │ API Server      │
├─────────────────────────────────────────────────┤
│              Core Agent Layer                    │
│  AIAgent (run_agent.py) — 核心编排引擎           │
│  ├── _build_system_prompt()  系统提示词组装      │
│  ├── run_conversation()      主对话循环          │
│  ├── _spawn_background_review() 后台记忆/技能审查│
│  ├── ContextCompressor       上下文压缩          │
│  └── IterationBudget         迭代预算控制        │
├─────────────────────────────────────────────────┤
│           Tool & Execution Layer                 │
│  ToolRegistry (tools/registry.py)               │
│  47个工具 × 6种执行后端                          │
│  (Local/Docker/SSH/Modal/Daytona/Singularity)   │
└─────────────────────────────────────────────────┘

2.2 核心循环: run_conversation() (run_agent.py:6882)

这是整个系统的心脏。阅读源码后,我总结出以下执行流程:

用户消息 → 代理编码清理 (surrogate sanitization)
         → 恢复主 runtime (若上轮发生了 fallback)
         → 系统提示词组装 (缓存,仅首次构建)
         → 预飞行上下文压缩 (若历史超阈值)
         → 插件 pre_llm_call hook
         → 外部记忆 provider prefetch
         ╔══════════════════════════════╗
         ║    主循环 (while budget > 0) ║
         ║  1. 检查中断请求             ║
         ║  2. 消费 iteration budget    ║
         ║  3. 注入临时上下文到用户消息  ║
         ║  4. 应用 Anthropic 缓存控制  ║
         ║  5. 清理孤立的 tool_call     ║
         ║  6. API 调用 (含重试逻辑)    ║
         ║  7. 处理 tool_calls          ║
         ║  8. 工具结果追加到消息        ║
         ║  9. 检查是否需要压缩上下文    ║
         ╚══════════════════════════════╝
         → 外部记忆 sync + queue_prefetch
         → 后台记忆/技能审查 (_spawn_background_review)
         → 插件 on_session_end hook
         → 返回结果

源码中几个值得注意的设计细节:

  1. 迭代预算是线程安全的 (IterationBudget 使用 threading.Lock),父 Agent 默认 90 次,子 Agent 默认 50 次
  2. 系统提示词只构建一次,缓存在 _cached_system_prompt 上,后续轮次复用,最大化 Anthropic 前缀缓存命中
  3. 工具结果超过 100K 字符时自动写入临时文件,只保留 1,500 字符预览 (_save_oversized_tool_result)
  4. 并行工具执行有严格的安全检查 —— _should_parallelize_tool_batch() 会检查工具是否在 _PARALLEL_SAFE_TOOLS 白名单中,且路径级工具(read_file/write_file/patch)需要确认路径不重叠

三、四层记忆架构(核心创新)

3.1 架构全景

层级存储方式特性角色
Prompt MemoryMEMORY.md + USER.md每次注入系统提示词,上限 3,575 字符语义记忆 (what matters)
Session SearchSQLite FTS5按需检索,LLM 摘要后注入情景记忆 (what happened)
Skills~/.hermes/skills/ 目录渐进式披露,按需加载全文程序记忆 (how to do it)
Honcho外部辩证引擎被动用户建模,12层身份画像关系记忆 (who you are)

3.2 Prompt Memory 实现 (tools/memory_tool.py)

这是最核心的记忆层。关键设计决策:

python
class MemoryStore:
    def __init__(self, memory_char_limit=2200, user_char_limit=1375):
        # 总上限 3,575 字符 ≈ 约 900 tokens
        # 这是一个刻意的设计约束:强制策展而非累积

冻结快照模式 (Frozen Snapshot Pattern):

  • 会话开始时加载 MEMORY.md/USER.md,捕获快照注入系统提示词
  • 会话中的写入立即持久化到磁盘,但不修改系统提示词
  • 原因:保持前缀缓存稳定。这是一个在成本效益和实时性之间的精妙权衡

安全扫描:

python
_MEMORY_THREAT_PATTERNS = [
    (r'ignore\s+(previous|all|above|prior)\s+instructions', "prompt_injection"),
    (r'curl\s+[^
]*\$\{?\w*(KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL|API)', "exfil_curl"),
    (r'authorized_keys', "ssh_backdoor"),
    # ... 更多模式
]

每次写入记忆前都会扫描注入/渗透模式 —— 因为记忆内容会被注入到系统提示词中,这是一个关键的安全边界。

3.3 Session Search (tools/session_search_tool.py)

使用 SQLite FTS5 全文搜索引擎索引历史会话。检索流程:

FTS5 搜索匹配消息 → 按 session 分组 → 取 top 3 unique sessions
→ 加载每个 session 对话 → 截取匹配点附近 ~100K 字符
→ 发送给辅助 LLM 做聚焦摘要 → 返回结构化摘要

这种 检索+摘要 的模式避免了把原始对话直接塞进上下文窗口。

3.4 周期性记忆/技能审查机制

源码中的 nudge 机制是学习循环的关键:

python
# run_agent.py:1027
self._memory_nudge_interval = 10  # 每10轮用户消息触发一次记忆审查
self._skill_nudge_interval = 10   # 每10次工具迭代触发一次技能审查

当触发条件满足时,_spawn_background_review() 会:

  1. 创建一个完整的 AIAgent 分支(共享记忆存储)
  2. 把当前对话历史作为上下文
  3. 追加审查提示词作为"用户消息"
  4. 在后台线程中运行(daemon=True),不阻塞用户交互
  5. 审查 Agent 有权使用 memory 和 skill_manage 工具
  6. 完成后向用户显示简要摘要(如 "💾 Memory updated · Skill created")

四、技能系统(程序记忆)

4.1 技能结构

~/.hermes/skills/
├── systematic-debugging/
│   └── SKILL.md          # YAML frontmatter + Markdown 指令
├── software-development/
│   ├── test-driven-development/
│   │   └── SKILL.md
│   └── subagent-driven-development/
│       └── SKILL.md
└── category/skill-name/
    ├── SKILL.md
    ├── references/       # 参考资料
    ├── templates/        # 模板文件
    ├── scripts/          # 脚本
    └── assets/           # 资源

4.2 渐进式披露 (Progressive Disclosure)

技能不是一次性全部加载的:

python
# agent/prompt_builder.py - build_skills_system_prompt()
# 默认只加载技能名称 + 描述摘要(几十字节/技能)
# 只有 Agent 判断相关时才加载完整内容
# 这保持了 token 使用量与技能数量无关(70+技能不膨胀)

4.3 技能自改进

技能不是只读的,Agent 可以通过 6 种操作修改技能:

python
# tools/skill_manager_tool.py
# Actions: create, edit, patch, delete, write_file, remove_file
# 默认使用 patch(精准替换)而非 edit(全量重写)

触发条件(从 prompt_builder.py 的 SKILLS_GUIDANCE 提取):

  • 5次以上工具调用的复杂任务完成后
  • 修复了一个棘手的错误
  • 发现了非显而易见的工作流

安全扫描: Agent 创建的技能会经过与社区技能相同的安全扫描(skills_guard.py),检测渗透、注入、破坏性命令等模式。

五、工具系统

5.1 注册表模式 (tools/registry.py)

python
class ToolRegistry:
    """单例注册表,收集来自工具文件的 schema + handler"""

    def register(self, name, toolset, schema, handler, check_fn=None, ...):
        """在模块导入时由每个工具文件调用"""

    def get_definitions(self, tool_names, quiet=False):
        """返回 OpenAI 格式的工具 schema(只包含 check_fn 通过的工具)"""

    def dispatch(self, name, args, **kwargs):
        """按名称执行工具 handler(自动桥接 async)"""

这种自注册模式解耦了工具实现和编排逻辑。每个工具文件在导入时调用 registry.register(),无需修改中央文件。

5.2 47 个内置工具 (20 个工具集)

工具集代表工具说明
terminalterminal6种后端执行命令
browserbrowser_* (11个)Playwright + Camofox 反检测浏览器
webweb_search, web_extract搜索和内容提取
fileread_file, write_file, patch, search_files文件操作
code_executionexecute_code沙盒化代码执行
visionvision_analyze图像分析
image_generationimage_generate图像生成 (fal.ai)
ttstext_to_speech语音合成 (edge-tts / ElevenLabs)
delegationdelegate_task子 Agent 派遣
memorymemory持久化记忆管理
skillsskills_list, skill_view, skill_manage技能系统
session_searchsession_search历史会话搜索
todotodo任务规划
croncron_*定时任务
mcp动态工具MCP 协议扩展

5.3 危险命令审批系统 (tools/approval.py)

python
DANGEROUS_PATTERNS = [
    (r'\brm\s+-[^\s]*r', "recursive delete"),
    (r'\bchmod\s+(-[^\s]*\s+)*(777|666|o\+[rwx]*w|a\+[rwx]*w)\b', "world-writable permissions"),
    (r'\bDROP\s+(TABLE|DATABASE)\b', "SQL DROP"),
    (r':\(\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;\s*:', "fork bomb"),
    (r'\b(curl|wget)\b.*\|\s*(ba)?sh\b', "pipe remote content to shell"),
    # ... 30+ 个模式
]

关键特性:

  • 命令归一化:先 strip ANSI 转义、null 字节、Unicode 全角字符,防止绕过
  • 三级审批:once(本次)/ session(会话内)/ always(永久白名单写入 config.yaml)
  • Gateway 异步审批:网关模式下通过 threading.Event 队列实现跨线程阻塞审批
  • Smart Approval:可选使用辅助 LLM 自动评估低风险命令

六、执行后端

6.1 策略模式 (tools/environments/base.py)

python
class BaseEnvironment(ABC):
    """所有 Hermes 执行后端的通用接口"""

    @abstractmethod
    def execute(self, command, cwd="", *, timeout=None, stdin_data=None) -> dict:
        """执行命令,返回 {"output": str, "returncode": int}"""

    @abstractmethod
    def cleanup(self):
        """释放后端资源(容器、实例、连接)"""

6 种后端通过配置切换,无需代码变更:

后端文件适用场景
Localenvironments/local.py直接宿主机执行(默认,最快)
Dockerenvironments/docker.py隔离容器(只读root,降权)
SSHenvironments/ssh.py远程服务器
Modalenvironments/modal.py无服务器云沙箱
Daytonaenvironments/daytona.py托管工作空间环境
Singularityenvironments/singularity.pyHPC/科研环境

6.2 Docker 安全默认值

Docker 后端的安全策略在源码中清晰可见:只读根文件系统、丢弃特权、命名空间隔离。

七、消息网关 (14+ 平台)

7.1 架构

python
# gateway/run.py - GatewayRunner
# 单进程管理多平台适配器
# 每个平台独立的 adapter 文件

支持平台(gateway/platforms/ 目录):

平台文件特性
Telegramtelegram.py语音转写、文件上传、贴纸缓存
Discorddiscord.py语音频道、线程
Slackslack.pyBolt 框架
WhatsAppwhatsapp.pyBusiness API
Signalsignal.py端到端加密
Matrixmatrix.pyE2E 加密 (nio)
Emailemail.pyIMAP/SMTP
SMSsms.py短信
DingTalkdingtalk.py钉钉
Feishufeishu.py飞书/Lark
WeComwecom.py企业微信
Home Assistanthomeassistant.py智能家居
Mattermostmattermost.py开源 Slack 替代
Webhookwebhook.py通用 webhook

所有平台共享同一个对话上下文,实现跨平台对话连续性。

八、Prompt 缓存优化

8.1 Anthropic 前缀缓存 (agent/prompt_caching.py)

python
def apply_anthropic_cache_control(api_messages, cache_ttl="5m", native_anthropic=False):
    """system_and_3 策略:系统提示词 + 最后3条非系统消息"""
    # Anthropic 最多允许 4 个 cache_control 断点
    # 1. 系统提示词(跨所有轮次稳定)
    # 2-4. 最后 3 条非系统消息(滚动窗口)

为什么系统提示词永不中途修改?

这是一条硬性架构规则。源码中多处体现:

  • _cached_system_prompt 只构建一次,后续复用
  • 继续会话时从 SessionDB 加载存储的系统提示词(而非重建)
  • 外部记忆上下文注入到用户消息而非系统提示词
  • 插件上下文同样注入到用户消息

效果:输入 token 成本降低约 75%。

九、上下文压缩 (agent/context_compressor.py)

python
class ContextCompressor:
    """算法:
    1. 裁剪旧工具结果(便宜,不需要 LLM)
    2. 保护头部消息(系统提示词 + 首次交互)
    3. 按 token 预算保护尾部消息(最近 ~20K tokens)
    4. 用结构化 LLM 提示词摘要中间轮次
    5. 后续压缩迭代式更新之前的摘要
    """

关键参数:

  • threshold_percent = 0.50 — 上下文使用 50% 时触发
  • _SUMMARY_RATIO = 0.20 — 摘要占压缩内容的 20%
  • _SUMMARY_TOKENS_CEILING = 12_000 — 摘要最大 token 数
  • _PRUNED_TOOL_PLACEHOLDER — 旧工具结果替换为占位符

摘要模板是结构化的:目标、进展、决策、文件、下一步。这比自由格式摘要保留了更多信息。

十、子 Agent 委派 (tools/delegate_tool.py)

python
DELEGATE_BLOCKED_TOOLS = frozenset([
    "delegate_task",   # 禁止递归委派
    "clarify",         # 禁止用户交互
    "memory",          # 禁止写共享 MEMORY.md
    "send_message",    # 禁止跨平台副作用
    "execute_code",    # 子 Agent 应逐步推理
])

MAX_CONCURRENT_CHILDREN = 3
MAX_DEPTH = 2  # parent(0) -> child(1) -> grandchild rejected(2)
DEFAULT_MAX_ITERATIONS = 50

子 Agent 设计要点:

  • 独立的上下文(不继承父 Agent 历史)
  • 受限工具集(可配置,但始终移除被封锁工具)
  • 独立的 IterationBudget
  • 父 Agent 只看到委派调用和摘要结果,不看中间步骤

十一、安全体系

11.1 多层防御

层级机制实现
输入Prompt 注入扫描prompt_builder.py — 10个威胁模式 + 不可见字符检测
记忆记忆内容扫描memory_tool.py — 注入/渗透模式检测
技能安装前安全扫描skills_guard.py — 信任级别 + 威胁模式
命令危险命令审批approval.py — 30+ 模式 + 命令归一化
工具输出大小限制100K 字符阈值,超限写文件
执行容器隔离Docker 只读根、降权
输出Secret 渗透检测浏览器 URL 和 LLM 响应扫描

11.2 不可见字符检测

python
_CONTEXT_INVISIBLE_CHARS = {
    '\u200b',  # Zero-width space
    '\u200c',  # Zero-width non-joiner
    '\u200d',  # Zero-width joiner
    '\u2060',  # Word joiner
    '\ufeff',  # Zero-width no-break space (BOM)
    '\u202a'-'\u202e',  # Bidi override characters
}

十二、Provider 支持与凭据池

12.1 18+ LLM Provider

Nous Portal, OpenRouter (200+ models), Anthropic, OpenAI, z.ai/GLM, Kimi/Moonshot, MiniMax, Alibaba/DashScope, DeepSeek, Hugging Face, 以及自定义 OpenAI 兼容端点。

12.2 凭据池 (agent/credential_pool.py)

python
STRATEGY_FILL_FIRST = "fill_first"
STRATEGY_ROUND_ROBIN = "round_robin"
STRATEGY_RANDOM = "random"
STRATEGY_LEAST_USED = "least_used"  # 默认

EXHAUSTED_TTL_429_SECONDS = 60 * 60      # 429 限速:冷却1小时
EXHAUSTED_TTL_DEFAULT_SECONDS = 24 * 60 * 60  # 其他故障:冷却24小时

同一 provider 可配置多个 API key,线程安全的 least_used 策略分发负载,401 故障自动切换到下一个凭据。

十三、技术栈

核心语言: Python 3.11+ (93.4%)
包管理: uv (Astral)
数据库: SQLite + FTS5
CLI UI: Rich + prompt_toolkit + KawaiiSpinner
LLM SDK: openai + anthropic
Web: httpx + requests + exa-py + firecrawl-py
浏览器: Playwright + Camoufox
TTS: edge-tts (免费) + ElevenLabs (付费)
STT: faster-whisper
配置: YAML (pyyaml)
MCP: mcp >= 1.2.0
测试: pytest (3,000+ test cases)
构建: Nix Flake (可复现构建)

十四、与竞品对比

维度Hermes AgentOpenClaw (OpenHands)Claude Code
定位自进化学习 Agent广生态集成开发者编码助手
记忆4层架构 (prompt/episodic/procedural/dialectic)基础上下文文件笔记
技能系统agentskills.io 可移植标准,自创建+自改进插件仅工具调用
消息平台14平台,单网关进程有限Telegram/Discord
执行后端6种 (local/Docker/SSH/Modal/Daytona/Singularity)主要本地本地
成本仅 LLM API 费用;可跑在 $5 VPS 上$59/月(云) 或自托管订阅制
安全命令审批 + 注入扫描 + Docker 沙盒 + Secret 检测标准权限提示
开源MIT开源非开源

十五、核心设计洞见

15.1 3,575 字符的 Prompt Memory 上限

这是最有趣的设计决策之一。memory_char_limit=2200 + user_char_limit=1375 = 3575 字符,约 900 tokens。

为什么这么小? 这强制 Agent 策展而非累积。如果无限增长,记忆会变成垃圾场。3,575 字符的约束迫使 Agent 只保留真正有价值的信息。

15.2 冻结快照 vs 实时更新

系统提示词中的记忆是会话开始时的快照,中途不变。工具调用可以修改磁盘上的记忆文件,但当前系统提示词保持不变。

权衡:牺牲了记忆的即时性,换取了 75% 的缓存成本节省。对于大多数场景,这是一个正确的权衡。

15.3 后台审查而非内联审查

记忆和技能的审查在后台线程中运行(_spawn_background_review),使用独立的 AIAgent 实例。这意味着:

  • 用户不需要等待审查完成
  • 审查不会打断当前任务的思路
  • 审查结果在下次会话才生效(因为冻结快照)

15.4 agentskills.io 标准

技能使用 YAML frontmatter + Markdown 格式,可在兼容的 Agent 框架间迁移。这是一个生态系统赌注 —— 如果被广泛采用,将成为 Agent 领域的"npm"。

15.5 Prompt Injection 的全链路防御

从上下文文件加载、记忆写入、技能安装到命令执行,每一层都有独立的注入检测。这不是事后加的安全补丁,而是从架构层面贯穿的设计理念。

十六、总结

Hermes Agent 的核心创新不是单个特性,而是一个完整的自我进化闭环:

任务执行 → 经验积累 → 记忆策展 → 技能创建
    ↑                                    ↓
    ← ← ← ← 技能改进 ← 技能检索 ← ← ←

这个闭环的每个环节都有精心的工程实现:

  • 记忆有容量约束和安全扫描
  • 技能有渐进披露和自改进
  • 审查在后台运行不阻塞用户
  • 缓存策略贯穿整个架构

在 5 周内发布 7 个版本、积累 30K Stars 和 242 名贡献者,说明这个项目击中了开源 AI Agent 领域的一个真实需求:一个不绑定特定 IDE、不锁定特定 LLM、能从使用中学习的通用 Agent 框架。


基于 v0.7.0 源码 (commit 2026-04-03) 深度阅读分析 | 分析日期: 2026-04-07

Linked from

Comments (0)

No comments yet

imfht
April 7, 2026