Hermes Agent 很容易被理解成“一个会记忆、会调工具的 CLI Agent”。但如果只看这一层,会漏掉它更关键的设计:它在做的是 harness 工程。
这里的 harness 不是某个具体执行器,也不是“把模型包一层工具调用”的薄壳。按照近期 Agent 论文里对 harness engineering 的定义,harness 指的是模型周围那套可治理的外部认知基础设施:memory 外部化长期状态,skills 外部化过程经验,protocols 外部化交互结构,tools/environments 外部化行动能力,evaluation/guardrails 外部化质量控制。harness 工程就是把这些模块协调成一个能长期运行、可观测、可改进的系统。
这篇基于 NousResearch/hermes-agent 源码分析,基线提交为 a7cdd413,提交时间是 2026-04-27T20:41:36-07:00。进化能力部分还结合了 NousResearch/hermes-agent-self-evolution 源码,基线提交为 4693c8f,提交时间是 2026-03-29T08:47:23-07:00。
01 总览:Hermes 的中心不是 Gateway,而是 Agent Loop
图 1:Hermes Agent 的整体结构。CLI、Gateway、Cron、批处理和 RL 环境最终都会把任务送进同一个 Python Agent Loop。
从目录结构看,Hermes 的模块分层非常直接:
| 模块 | 主要职责 | 关键源码 |
|---|---|---|
| CLI / TUI | 命令入口、模型选择、配置、登录、更新、交互界面启动 | hermes_cli/main.py、cli.py |
| Agent Core | 会话循环、模型调用、工具调度、上下文压缩、费用统计、失败恢复 | run_agent.py |
| Tool Registry | 工具发现、工具 schema 过滤、工具执行、MCP/插件工具接入 | model_tools.py、tools/registry.py |
| Memory / Skills | 文件记忆、外部记忆插件、会话搜索、技能加载与技能自改进 | agent/memory_manager.py、tools/memory_tool.py、agent/skill_commands.py |
| Gateway | Telegram、Discord、Slack、WhatsApp、Signal、Email 等消息入口 | gateway/run.py、gateway/session.py |
| Execution Backends | local、Docker、SSH、Modal、Daytona、Singularity 等终端环境 | tools/terminal_tool.py、tools/environments/ |
| Research / RL | 批量轨迹生成、Atropos 环境、工具调用 parser、训练数据压缩 | environments/、batch_runner.py |
Hermes 的核心判断可以概括成一句话:
Hermes Agent 是一个以
AIAgent为中心的长期运行 Agent 系统,Gateway 和 TUI 是入口,memory/skills/session_search/context compressor 是学习闭环,tools/environments 是行动层。
这和 OpenClaw 有明显差异。OpenClaw 的文章里我已经讲过,OpenClaw 的重心在 Gateway 控制面和嵌入式 Runtime 编排。Hermes 则把复杂度堆在 run_agent.py 这个厚执行核里,再用 Python 模块把工具、记忆和平台接进来。
02 启动路径:CLI 很厚,但真正运行会落到 AIAgent
Hermes 的用户入口看起来很多:
hermes:启动终端 TUI。hermes model:选择 provider 和 model。hermes gateway:启动消息平台网关。hermes setup:跑配置向导。hermes claw migrate:从 OpenClaw 迁移。batch_runner.py/environments/:研究和训练场景。
但这些入口最后基本都绕不开 AIAgent。
hermes_cli/main.py 是一个非常大的命令分发文件,负责模型配置、认证、TUI 构建、Gateway 启动、更新、日志、备份、profile、completion 等命令。它更像“产品壳层”,不是推理内核。
真正的 Agent 执行在 run_agent.py 的 AIAgent 类里。这个类的构造参数非常长,原因不是设计失控,而是它要同时服务 CLI、Gateway、Cron、subagent、ACP、batch eval 等多种场景:
provider/api_mode/model决定模型传输层。enabled_toolsets/disabled_toolsets决定工具面。platform/user_id/chat_id决定消息平台上下文。session_id/session_db决定会话持久化。skip_memory/skip_context_files决定是否加载长期上下文。iteration_budget/parent_session_id决定多 Agent 协作边界。- 各种 callback 把 streaming、tool progress、clarify、status 回传给 CLI 或 Gateway。
这说明 Hermes 没有把“交互界面”和“Agent 内核”分成两个完全独立产品,而是用一个 AIAgent 承载所有入口的实际执行。
03 Agent Loop:它不是一次请求,而是带预算和恢复逻辑的执行机器
图 2:Hermes 的一轮 Agent Loop。每一轮都会经过 prompt 构建、模型调用、工具解析、工具执行、上下文预算和持久化。
Hermes 的 Agent Loop 主要在 run_agent.py 中展开。代码量很大,但核心结构是稳定的:
- 初始化系统提示词、memory snapshot、context files、skills、platform hints。
- 组装当前 messages。
- 调模型接口。
- 解析模型返回的
tool_calls或 raw<tool_call>。 - 执行工具。
- 把工具结果写回 messages。
- 更新 token、费用、上下文压缩状态和 session DB。
- 如果模型还要继续调工具,进入下一轮。
- 如果模型返回最终文本,持久化并退出。
这个循环里最值得注意的不是“会调工具”,而是周边的防御逻辑非常多:
IterationBudget限制最大迭代次数,父 Agent 和子 Agent 可以共享或独立预算。_should_parallelize_tool_batch()判断哪些工具可以并发执行。_repair_tool_call_arguments()尝试修复模型生成的损坏 JSON 参数。- 对
length截断有 continuation retry。 - 对“思考耗尽输出 token”有专门提示。
ContextCompressor在接近上下文窗口时压缩中间消息。StreamingContextScrubber防止 memory context 片段通过 streaming 泄漏到用户侧。- session token 和费用会写入 DB,供
/usage、/insights查询。
Hermes 的执行循环更像一个“容错执行器”,不是简单的 while loop。它的目标不是跑通 demo,而是长期会话里尽可能不因为模型输出异常、工具输出过长、网络失败、上下文爆炸、pipe 断开或平台中断而崩掉。
04 模型层:Hermes 把 provider 差异吸收到 transport 和 adapter
Hermes 支持的模型入口非常多:OpenAI、OpenRouter、Nous Portal、Anthropic、Bedrock、Gemini、Copilot ACP、Kimi、Moonshot、xAI、custom endpoint 等。
源码里没有把所有 provider 分支都写成一堆散落的 if,而是逐步抽象出 transport:
agent/transports/base.pyagent/transports/chat_completions.pyagent/transports/anthropic.pyagent/transports/bedrock.pyagent/transports/codex.py
AIAgent.__init__() 会根据 provider、base_url、model、api_mode 自动判断使用哪条 API 路径:
chat_completionscodex_responsesanthropic_messagesbedrock_converse
这层判断非常工程化。例如 GPT-5/Codex 风格模型通常走 Responses API,但 Azure OpenAI 又是例外;Anthropic 原生和第三方兼容 Anthropic endpoint 又要走不同 adapter;Bedrock 则绕过 OpenAI client,直接走 AWS Converse API。
这套设计的核心不是“支持很多模型”,而是:把模型 API 差异压进 transport 层,让 Agent Loop 继续围绕统一的 message/tool/result 语义工作。
05 工具系统:registry 是核心,toolset 是可治理边界
图 3:Hermes 的工具注册和过滤链路。工具模块自注册,model_tools 负责发现、过滤、schema 动态改写和执行分发。
Hermes 的工具系统由两个文件托底:
tools/registry.py:工具注册表。model_tools.py:工具发现、过滤、schema 输出和调用分发。
工具不是集中写在一个大列表里,而是每个 tools/*.py 模块在 import 时调用 registry.register() 自注册。discover_builtin_tools() 会扫描工具文件 AST,只导入顶层存在 registry.register(...) 的模块,避免把无关 helper 全部拉进来。
get_tool_definitions() 做的事情很多:
- 根据
enabled_toolsets/disabled_toolsets解析有效工具。 - 运行工具可用性检查,例如依赖、环境变量、平台状态。
- 动态重写
execute_codeschema,只暴露当前真实可用的 sandbox tools。 - 动态重写 Discord 工具 schema,隐藏 bot 权限不支持的动作。
- 当
web_search/web_extract不可用时,去掉 browser tool 描述里的交叉引用,降低模型幻觉调用不存在工具的概率。 - 通过
schema_sanitizer清理不同后端不兼容的 JSON schema 形状。
这说明 Hermes 的工具系统不只是“给模型一组 function schema”。它在做一件更重要的事:让模型看到的工具说明尽量贴近当前 session 的真实能力。
工具执行时,model_tools.handle_function_call() 最终会走 registry dispatch。同步/异步桥接也做了专门处理:主线程有持久 event loop,worker 线程有 thread-local loop,避免 asyncio.run() 反复创建和关闭 event loop 导致缓存客户端出错。
这类细节看起来不醒目,但这是长期运行 Agent 的真实工程成本。
06 记忆系统:Hermes 的“自我学习循环”由四部分组成
图 4:Hermes 的记忆闭环。短期 context、文件记忆、会话搜索、外部 memory provider 和技能系统共同构成学习循环。
Hermes README 里强调它有 built-in learning loop。源码里这个 loop 不是一个单点功能,而是由四类机制拼出来的。
第一类是文件记忆。tools/memory_tool.py 管理两个文件:
MEMORY.md:环境事实、项目约定、工具经验、长期可复用观察。USER.md:用户偏好、沟通风格、稳定习惯。
它的设计很克制:使用 § 作为 entry delimiter,有字符上限,写入前扫描 prompt injection 和 exfiltration 模式,读写时加文件锁。最关键的是 frozen snapshot:session 开始时把记忆注入系统提示词,session 中途写入会落盘,但不会立刻改变当前系统提示词。这样可以稳定 prompt cache,也避免当前轮被刚写入的记忆反复扰动。
第二类是 memory provider。agent/memory_manager.py 把内置记忆和外部 provider 统一成 MemoryProvider 接口。内置 provider 永远存在,外部 provider 同时只允许一个,避免工具 schema 膨胀和后端冲突。
外部 provider 位于 plugins/memory/,包括 Honcho、Hindsight、Mem0、ByteRover、OpenViking、Supermemory、RetainDB、Holographic 等。每个 provider 可以实现:
prefetch():每轮前召回相关上下文。sync_turn():每轮后同步对话。get_tool_schemas():向模型暴露专属 memory 工具。on_pre_compress():上下文压缩前抽取重要信息。on_delegation():观察子 Agent 的结果。
第三类是 session search。tools/session_search_tool.py 不直接把历史聊天全塞给模型,而是先用 SQLite FTS5 搜索历史消息,再按 session 聚合,截取匹配附近的上下文,最后用辅助模型做摘要。这是长期记忆里很实用的一层:文件记忆存“稳定事实”,session search 找“过去发生过什么”。
第四类是技能系统。Hermes 的技能不是记忆文件,而是可复用工作流。agent/prompt_builder.py 里的 SKILLS_GUIDANCE 会鼓励模型在复杂任务后保存技能;agent/skill_commands.py 负责把 SKILL.md 变成 slash command;agent/skill_preprocessing.py 支持 ${HERMES_SKILL_DIR}、${HERMES_SESSION_ID} 模板变量和可选 inline shell 展开。
所以 Hermes 的“学习”不是神秘能力,而是几条明确的数据通路:
- 稳定事实进 memory。
- 历史过程进 session DB,再由 session_search 召回。
- 可复用流程进 skill。
- 长上下文过程由 compressor 保留摘要。
- 外部 memory provider 可替换长期用户模型。
07 Context Engine:压缩不是删历史,而是做安全交接
图 5:Hermes 默认 ContextCompressor 的压缩策略。它保护头部和尾部,中间区域经过工具输出裁剪和辅助模型摘要。
agent/context_engine.py 定义了可插拔的 ContextEngine 抽象。默认实现是 agent/context_compressor.py。
它的压缩流程大致是:
- 根据模型上下文长度和阈值判断是否需要压缩。
- 先裁剪旧工具结果,保留一行结构化摘要。
- 保护系统提示词和会话开头。
- 保护最近尾部消息,确保当前任务连续性。
- 对中间消息用辅助模型生成结构化摘要。
- 如果已经压缩过,再做 iterative summary update。
- 把摘要作为“参考信息”插入,而不是当成新的用户指令。
源码里 SUMMARY_PREFIX 的措辞很关键:它明确说明压缩摘要是旧上下文的 handoff,不是当前指令,也不要回答摘要里出现的问题。这解决了一个常见问题:压缩摘要如果写得像任务列表,模型会误以为那些旧任务仍然要执行。
Hermes 还在压缩前做了很多具体处理:
- 多模态内容按图片 token 估算加入预算。
- tool call arguments 用 JSON parse 后裁剪,避免把 JSON 字符串截坏。
- 对 terminal、read_file、search_files、browser、web_search 等工具结果生成有信息量的一行摘要。
- 对摘要失败设置 cooldown,避免每轮都重复失败。
这不是“上下文不够就总结一下”的简单实现,而是把压缩当成会话连续性工程来做。
08 Gateway:多平台入口,但不抢 Agent Core 的位置
图 6:Hermes Gateway。各平台 adapter 把消息规范化为 session event,再交给 GatewayRunner 调用 AIAgent。
Hermes 也有 Gateway,但它和 OpenClaw 的 Gateway 气质不同。
gateway/run.py 的 GatewayRunner 负责平台 adapter、session、delivery、interrupt、slash command、media placeholder、cron ticker 等。gateway/session.py 负责 session key、sender/chat hash、session context prompt、session store、shared multi-user session 等。
Gateway 的核心价值是把多个消息平台变成统一 Agent 输入:
- Telegram、Discord、Slack、WhatsApp、Signal、Email、WeCom、Feishu、Matrix、Mattermost 等平台各自有 adapter。
- 平台消息会被转换成统一 session event。
- 每个平台会注入不同 platform hints,例如 markdown 支持、媒体发送格式、群聊身份等。
/stop、/new、/reset、/model、/skills等命令在 messaging 场景复用 CLI 语义。- gateway session 可以有自己的
platform、user_id、chat_id、thread_id,这些会传给AIAgent。
OpenClaw 的 Gateway 更像系统控制面;Hermes 的 Gateway 更像多平台适配层。它很重要,但它不拥有 Agent Runtime 的底层协议。底层执行仍然是 AIAgent。
这也解释了两者架构差异:OpenClaw 把平台一致性放在 Gateway;Hermes 把执行一致性放在 Agent Loop。
09 执行环境:Hermes 把 terminal 当成可替换后端
Hermes 的 terminal tool 不只是 subprocess.run() 包一层。tools/terminal_tool.py 把执行后端抽象成多种环境:
- local:直接在本机执行。
- docker:容器隔离。
- ssh:远程机器。
- modal:云端 sandbox。
- daytona:持久云开发环境。
- singularity:HPC/集群常用容器。
这和 Hermes 的定位有关。它不是只在本地电脑上做代码助手,而是可以跑在 VPS、云环境、GPU 集群、serverless sandbox 上。terminal backend 的职责不仅是运行命令,还包括:
- foreground/background 任务。
- sudo 和危险命令审批。
- workdir 安全校验。
- interrupt 传播。
- container/VM 生命周期。
- persistent filesystem 与 idle cleanup。
这层能力和 Gateway 结合之后,Hermes 就变成了“你从 Telegram 发消息,它在云 VM 上跑任务”的长期 worker。
10 Subagent:Hermes 用 delegate_task 做上下文隔离和并行
tools/delegate_tool.py 是 Hermes 的子 Agent 实现。它的设计很清楚:
- 子 Agent 是新的
AIAgent实例。 - 子 Agent 不继承父会话历史。
- 每个子 Agent 有自己的
task_id和 terminal session。 - 子 Agent 默认不能再调用
delegate_task,防止递归失控。 - 子 Agent 默认不能写 memory,避免污染共享长期记忆。
- 子 Agent 默认不能
clarify或send_message,避免绕过父 Agent 与用户交互。 - 父 Agent 只看到子 Agent 的最终摘要,不吃下子 Agent 的中间工具轨迹。
这其实是一种很务实的多 Agent 协作:不追求复杂自治社会,而是把子 Agent 当成隔离工作线程。它可以并行处理任务,但上下文成本和副作用被控制在边界内。
这点和 OpenClaw 的多 Agent/Swarm 或可替换底层 runtime 抽象不是同一层概念。Hermes 的 subagent 是“同一执行内核下的新实例”,主要解决上下文隔离和并行工作。
11 Harness 工程:Hermes 把能力外部化为可维护系统
图 7:Hermes 的 harness 工程结构。模型不是独自完成任务,而是在 Agent Loop 协调下调用外部化的记忆、技能、协议、工具、评估和安全边界。
要理解 Hermes,关键不是问“它用了哪个模型”,而是问:模型周围有哪些外部结构在帮它稳定工作?
Externalization in LLM Agents 对这个趋势的概括很适合解释 Hermes:Agent 能力越来越少依赖“模型权重里本来会什么”,越来越多依赖运行时外部结构。memory 负责跨时间状态,skills 负责过程知识,protocols 负责交互结构,而 harness engineering 负责把这些外部结构协调进可治理执行。
Hermes 的源码正是这个定义的工程落地:
| Harness 组成 | Hermes 实现 | 作用 |
|---|---|---|
| 执行编排 | run_agent.py 的 AIAgent.run_conversation() | 把 prompt、tools、memory、skills、context、transport、session persistence 串成闭环 |
| 行为协议 | agent/prompt_builder.py | 把 identity、memory guidance、session search guidance、skills guidance、platform hints 组合成系统协议 |
| 行动词汇表 | tools/registry.py、model_tools.py | 用 tool registry、toolset、dynamic schema 控制模型真实可见能力 |
| 程序性记忆 | tools/skills_tool.py、tools/skill_manager_tool.py | 把可复用流程保存成 SKILL.md,按需加载,允许创建/patch/维护 |
| 长期状态 | tools/memory_tool.py、tools/session_search_tool.py | 用 MEMORY.md/USER.md 存稳定事实,用 FTS5 + 摘要召回历史会话 |
| 上下文治理 | agent/context_compressor.py | 不是简单截断,而是把历史压缩成安全 handoff |
| 环境接口 | gateway/run.py、cron/、tools/environments/ | 把聊天平台、定时任务、本地/远程/云执行环境接到同一个 Agent Core |
| 质量与安全边界 | path_security、approval callback、prompt injection scan、constraint validators | 防止工具越权、记忆污染、技能投毒、进化漂移 |
这也解释了为什么 Hermes 的“学习”不是单点能力。它不是模型权重在线训练,而是 harness 的外部资产在变化:
- 用户稳定偏好进入 memory。
- 可复用流程进入 skills。
- 历史任务进入 session DB。
- 长对话通过 compressor 变成可传递摘要。
- 工具 schema 根据当前环境动态裁剪。
- 技能和 prompt 可以被离线优化器迭代。
如果用 Natural-Language Agent Harnesses 的视角看,Hermes 里相当多的 harness 逻辑已经以自然语言 artifact 存在:SKILL.md、prompt sections、tool descriptions、platform hints、memory guidance 都是可读、可 patch、可评估的文本。区别是 Hermes 目前没有把它们统一声明成一个独立 harness DSL,而是分布在 Python 控制器、Markdown skill、tool schema 和配置文件里。
12 进化能力:在线学习闭环 + 离线 Self-Evolution 流水线
图 8:Hermes 的两层进化能力。在线层负责记忆和技能的低风险沉淀;离线层用 DSPy/GEPA 对 skill、tool description、prompt 和代码做评估驱动优化。
Hermes 的进化能力分成两层,不能混在一起讲。
第一层是主仓库里的在线自我维护。它发生在普通使用过程中,目标是低风险地积累经验,不直接改模型权重。
agent/prompt_builder.py 里有两段关键 guidance:
MEMORY_GUIDANCE:要求把用户偏好、环境事实、稳定约定存进 memory;但不要把任务进度、临时 TODO、完成记录塞进 memory,过程类知识应该沉淀成 skill。SKILLS_GUIDANCE:复杂任务、修复 tricky error、发现非平凡 workflow 后,用skill_manage保存技能;如果使用技能时发现它过时、不完整或错误,要立即 patch。
这不是只靠模型“自觉”。run_agent.py 里有明确触发机制:
- 每轮用户请求开始时,
_turns_since_memory递增,到达_memory_nudge_interval后触发 memory review。 - Agent Loop 中统计工具迭代次数,复杂任务后
_iters_since_skill到达_skill_nudge_interval后触发 skill review。 - 主响应返回给用户之后,
_spawn_background_review()在后台起一个新的AIAgentfork。 - 这个 review agent 只启用
memory和skillstoolset,继承父会话快照,但不改主会话历史。 - 它根据
_MEMORY_REVIEW_PROMPT、_SKILL_REVIEW_PROMPT或_COMBINED_REVIEW_PROMPT决定是否写 memory、创建 skill、patch skill。 - 后台 review 线程安装 auto-deny approval callback,危险命令默认拒绝,避免复盘阶段越权执行。
这套设计很重要:用户任务先完成,学习动作后置到后台,且只允许写入低风险外部资产。它避免了很多“Agent 边工作边自改导致不可控”的问题。
技能的写入由 tools/skill_manager_tool.py 承担。skill_manage 支持:
create:创建完整SKILL.md。patch:用old_string/new_string做局部更新,优先用于修复。edit:完整重写,适合大改。write_file/remove_file:维护 skill 目录下的references/、templates/、scripts/、assets/。
成功修改技能后,它会调用 clear_skills_system_prompt_cache(clear_snapshot=True),清理 skill prompt snapshot。也就是说,技能变化不会假装立刻改写当前轮系统提示词,而是通过缓存失效让后续会话拿到新技能索引。
第二层是独立仓库 hermes-agent-self-evolution 的离线进化流水线。这个仓库的定位写得很清楚:它“operates ON hermes-agent — not part of it”。也就是说,它不是运行时热改 Agent,而是在外部读取 Hermes 资产,生成候选版本,评估后产出可审查修改。
当前实现最完整的是 Phase 1:skill evolution。主入口是 evolution/skills/evolve_skill.py,流程如下:
find_skill()在 Hermes 仓库的skills/目录里定位目标SKILL.md。load_skill()拆出 frontmatter 和 body,frontmatter 保持不变,只让 body 参与进化。SyntheticDatasetBuilder、GoldenDatasetLoader或build_dataset_from_external()构造 eval dataset。SkillModule把 skill body 包装成 DSPy module,把 skill text 作为可优化参数。- 首选
dspy.GEPA,不可用时 fallback 到dspy.MIPROv2。 ConstraintValidator检查尺寸、增长率、非空、skill 结构;可选跑 pytest。- 在 holdout set 上对 baseline 和 evolved module 做对比。
- 把
baseline_skill.md、evolved_skill.md、metrics.json保存到output/<skill>/<timestamp>/。
这就是 Hermes “进化能力”的工程本质:不是在线训练模型,而是把 harness artifact 变成可优化对象,再用评估数据和约束门控选择更好的版本。
当前源码也有几个边界需要讲清楚:
- README/PLAN 规划了 PR 自动生成,但当前
evolve_skill.py主流程实际是保存 output 和 metrics,并没有完整实现pr_builder.py。 LLMJudge已经定义了多维 rubric scoring,但skill_fitness_metric()当前优化时主要用关键词重合的快速启发式分数;这说明 Phase 1 仍是早期实现,不是成熟自动评审系统。- tool description、system prompt、code evolution、continuous loop 在 PLAN 里设计完整,但仓库当前只实现了 skill evolution 的主路径。
- 约束门控是必要的,因为进化文本很容易向“更长、更泛化、更像口号”的方向漂移;Hermes 用 size limit、growth limit、semantic preservation 规划、pytest、holdout、人工 review 来压住风险。
从 harness 工程角度看,hermes-agent-self-evolution 的价值不在于“自动写得更好看”,而在于它把 Agent 的外部认知结构变成了可实验对象:
- skill 可以作为 prompt artifact 被优化。
- tool description 可以作为工具选择策略被优化。
- system prompt section 可以作为行为协议被优化。
- tool implementation code 可以作为可测试软件被优化。
- SessionDB、Claude Code、Copilot、Hermes 历史都可以成为 eval data 来源。
所以 Hermes 的进化能力是一个“外部化能力进化”的路径:模型本身可以不变,但模型周围的记忆、技能、工具说明、上下文协议和执行 guardrails 会被持续改进。
13 研究训练路径:Hermes 不只是产品 Agent,也在服务数据生成
Hermes 还有一条很重要但容易被忽略的线:研究和训练。
environments/agent_loop.py 实现了可复用的 HermesAgentLoop,用于标准 OpenAI 工具调用格式。它服务于 Atropos/RL 环境,支持:
- server 抽象调用
chat_completion()。 - tool schemas 和 valid tool names。
- raw
<tool_call>fallback parser。 - 每轮 reasoning 抽取。
- tool error 记录。
- 大并发 eval 的 thread pool。
environments/tool_call_parsers/ 里有很多模型格式 parser,例如 Hermes、DeepSeek、GLM、Kimi、Llama、Mistral、Qwen 等。这说明 Hermes 不只是消费工具调用模型,也在为“训练能稳定调工具的模型”准备环境。
batch_runner.py、mini_swe_runner.py、scripts/sample_and_compress.py 这些文件进一步说明它有数据生产和评测用途。产品 Agent 和训练环境共享一部分工具调用语义,这是 Hermes 与普通 CLI Agent 的另一个区别。
14 总结:Hermes 是一套可进化的 Agent Harness 工程
读完 Hermes 和 self-evolution 两个仓库后,我觉得它最值得关注的不是“支持很多模型”或“支持很多聊天平台”,而是它把长期运行 Agent 的 harness 工程问题放在同一个系统里解决:
- 模型 API 差异:用 transport/adapter 吸收。
- 工具能力膨胀:用 registry + toolset + dynamic schema 控制。
- 长期记忆:用文件记忆、session search、memory provider 拆分职责。
- 可复用经验:用 skills 从任务中沉淀流程。
- 上下文爆炸:用 ContextEngine 和压缩摘要做安全交接。
- 多入口:用 CLI/TUI/Gateway/Cron 共享同一个 Agent Core。
- 多环境:用 terminal backend 支持本机、容器、远程和云 sandbox。
- 多任务:用 delegate_task 隔离子 Agent。
- 在线学习:用后台 memory/skill review 把经验沉淀到外部资产。
- 离线进化:用 DSPy/GEPA 对 skills 等 harness artifact 做评估驱动优化。
- 研究训练:用 environments 和 parser 把工具调用轨迹变成可评测数据。
Hermes 的 harness 不是单个 executor,而是一整套外部认知工程:AIAgent 是协调器,memory 是状态层,skills 是程序性经验层,tool registry 是行动边界,context compressor 是上下文治理,Gateway/Cron/terminal backend 是环境接口,self-evolution 是离线优化管线。
它的进化能力也不是玄学:在线层通过 background review 维护 memory/skills,离线层通过 eval dataset、GEPA/MIPRO、constraint gate、holdout comparison 去优化 SKILL.md 等 artifact。当前实现还没有达到“完全自动持续进化”的成熟阶段,但架构方向已经很明确:不训练模型权重,而是持续进化模型周围的 harness。
参考源码
NousResearch/hermes-agentrun_agent.pymodel_tools.pytools/registry.pyagent/memory_manager.pytools/memory_tool.pyagent/context_compressor.pygateway/run.pytools/skills_tool.pytools/skill_manager_tool.pyNousResearch/hermes-agent-self-evolutionhermes-agent-self-evolution/PLAN.mdevolution/skills/evolve_skill.pyevolution/skills/skill_module.pyevolution/core/dataset_builder.pyevolution/core/constraints.pyExternalization in LLM AgentsNatural-Language Agent Harnesses