开源自托管 Agent 项目 Hermes Agent 是什么:全景导读

2026-07-30

本文基于 hermes-agent 仓库 commit 2d40494(2026-07-29)梳理,该项目仍在高频迭代,具体行为以仓库 https://github.com/NousResearch/hermes-agent 最新代码与文档为准。

先把最容易搞混的一点摆在前面:Hermes Agent 跟你终端里那个帮你改代码的 Agent 不是同一类东西。 它是一个装在某台机器上、你关掉终端之后还在跑的进程;你从 Telegram、Discord、Slack 或者别的聊天窗口给它发消息,它在那台机器上开终端、跑命令、写文件,做完把结果推回你的聊天窗口。名字也得消歧一次:Hermes 这个词在 AI 圈里同时是 Nous Research 那套开源模型的系列名,在 AI 圈外还有一堆同名的品牌和软件库。本文从头到尾只说一件东西:GitHub 上 NousResearch/hermes-agent 这个仓库里的 Agent 程序本体,MIT 许可证,LICENSE 署名 Nous Research。它可以接任何模型供应商,用哪家模型跟仓库名里的 Hermes 没有关系。

站内已经有三篇相关的文章:开源终端 Agent 怎么选给的是选型流程,Agent 框架横向对比讲的是该看哪些维度,开源编程 Agent pi 是什么拆的是另一个项目的分层。这篇不重复那几套判断框架,它只做一件事:把 hermes-agent 这个仓库摊开,讲清哪块代码负责什么、它的设计取向是什么、以及在你自己的机器上跑起来要付哪些代价。方法论那几篇告诉你该问什么问题,这篇给的是这一个项目的具体答案。

一、它想解决的问题:Agent 不该只在你开着终端时才存在

大多数编码 Agent 的生命周期跟你那个终端窗口绑定:窗口关了,进程没了,上下文散了,下次从零开始。这个设定对”我现在要改这个仓库”完全够用,但对另一类需求就不行了 —— 每天早上八点帮我扫一遍某个页面有没有变、有人往仓库推了 PR 就来提醒我一句、我在地铁上想起一件事随手发条消息让它去做。这些活儿的共同点是:你不在场的时候它得还在。

hermes-agent 的做法是把同一套 Agent 内核挂在多个入口上。仓库自带的开发说明(AGENTS.md)第一段就写了这个定位:同一个 Agent 内核跑在一个 CLI、一个消息网关、一个 TUI 和一个 Electron 桌面端后面。CLI 是 hermes,网关是 hermes gateway,网关起来之后你就能从聊天软件里跟它说话。这里有个容易看错的地方:绝大多数聊天平台适配器并不在网关目录里,而是以随仓库发布的插件形式一个平台一个目录放在 plugins/platforms/ 下面,Telegram、Discord、Slack、Matrix、邮件、短信、钉钉、企业微信、飞书都在那儿;gateway/platforms/ 里留的是共享基类和一小批直连适配器(base.py、Signal、whatsapp_cloud.pyapi_server.pywebhook.py 等),发现和延迟加载由 gateway/platform_registry.py 负责。其中 webhookapi_server 是两个非人类入口。顺带提醒一句:AGENTS.md 里那张目录树把平台适配器统统画在了 gateway/platforms/ 下,跟当前文件系统已经不一致了,SECURITY.md 的外部接口那一节写的才是现状 —— 读这个仓库的时候,目录树注释永远比 ls 的结果旧。

跑在哪台机器上也是可配的。tools/environments/ 下面放的是终端后端实现:local.pydocker.pyssh.pysingularity.pymodal.pydaytona.pyvercel_sandbox.py。也就是说”Agent 进程在哪”和”命令在哪执行”是两件可以分开的事 —— 网关跑在一台小机器上,重活派到容器或远端去干。

定时和事件触发也是内置的。cron/jobs.py 是任务存储,cron/scheduler.py 是滴答循环,用户侧用 hermes cron 管,Agent 侧有一个 cronjob 工具可以自己排任务。仓库里那篇 hermes-already-has-routines.md 给了可以照抄的形态,比如一个带前置脚本的定时任务:

hermes cron create "every 1h" \
  "If CHANGE DETECTED, summarize what changed. If NO_CHANGE, respond with [SILENT]." \
  --script ~/.hermes/scripts/watch-site.py \
  --name "Pricing monitor" \
  --deliver telegram

值得单独说一句的是 --script:脚本先跑,标准输出被当成上下文塞给 Agent。机械活(抓取、比对、计算)交给确定性的代码,判断留给模型。这个分工比”让模型自己去抓自己去比”稳得多,也便宜得多。

二、仓库里这几块各自负责什么

仓库根目录的文件数量一直在变,AGENTS.md 自己也提醒别把目录树当成穷举清单。下面这张表只列你真会打开的那几个入口点,路径都能在仓库里直接对上。

组成部分它负责什么仓库位置你什么时候会碰到它
会话主循环AIAgent 类,工具调用循环、中断检查、预算跟踪run_agent.py想搞清一轮对话到底怎么走完
工具编排工具发现与分发、工具集定义model_tools.pytoolsets.py想加工具,或想知道某个能力属于哪个工具集
交互式命令行终端 CLI 编排、斜杠命令注册表cli.pyhermes_cli/commands.py改命令行行为、加一个斜杠命令
终端 UIInk(React)写的 TUI 与它的 Python 后端ui-tui/tui_gateway/hermes --tui,或改界面
消息网关会话生命周期、消息排队、平台发现gateway/run.pygateway/session.pygateway/platform_registry.py接聊天软件、排查”消息进来了没反应”
平台适配器一个聊天平台一个目录plugins/platforms/(少数直连的在 gateway/platforms/想知道某个平台支持到什么程度
会话存储与检索SQLite 会话库,全文/三元组/中日韩检索hermes_state.pyhermes_state_search.py想让它翻自己的历史对话
技能按需加载的知识文档skills/optional-skills/教它一套固定流程
技能维护后台评审、归档、备份、使用遥测agent/curator.pyagent/curator_backup.pytools/skill_usage.py技能攒多了,想知道谁在动它们
定时任务任务存储与调度滴答cron/jobs.pycron/scheduler.py排无人值守的活
插件记忆后端、模型供应商、其它扩展plugins/(含 memory/model-providers/换记忆后端、接一个新的推理后端
终端后端命令实际在哪执行tools/environments/想把执行环境隔离出去
委派派子 Agent 干并行活tools/delegate_tool.py一个任务想拆成几条并行线

用户侧的状态不在仓库里。配置是 ~/.hermes/config.yaml,密钥单独放 ~/.hermes/.env,日志在 ~/.hermes/logs/ 下面分 agent.logerrors.loggateway.log。这个 .env 只放密钥的规矩是硬的,后面会讲为什么。

三、“把经验写成技能”这条线具体怎么走

这是这个项目最容易被说成宣传语、也最值得看代码的一块。它不是一个黑盒的”自我进化”,而是几个能分别核对的机制拼起来的。

技能是文件,不是状态。 skills/ 下面 14 个分类目录、共 70 份 SKILL.mdoptional-skills/ 下面 21 个分类目录、共 111 份 SKILL.md,后者是随仓库发布但默认不激活的重型或小众技能,要显式装。每份 SKILL.md 是带 frontmatter 的 markdown:namedescriptionversionauthorlicenseplatforms,加上 metadata.hermes 下面的标签、分类、关联技能。装上的技能自动变成一个斜杠命令,你打 /<技能名> 就能点着用。

新技能怎么来的。 有一条 /learn 路径,实现在 agent/learn_prompt.py。它的做法很克制 —— 不新增任何模型工具,只是构造一段提示词,让 Agent 用它已有的读文件、搜文件、抽网页那几个工具去收集素材,然后通过 skill_manage 写出一份 SKILL.md。所以你在本地、Docker 还是远端后端上跑,行为都一样。除了你主动喊,Agent 也会被提醒去沉淀:agent/agent_init.py 里读两个按用户轮次计数的提醒间隔,skills.creation_nudge_interval 管”该不该把这套流程写成技能”,memory.nudge_interval 管”该不该记一笔”。两个都在 config.yaml 里可调,嫌它啰嗦就调大,设成 0 直接关掉。这里还有个能省你半小时的细节:代码里的兜底默认值和仓库自带的示例配置给的不是同一个数,别照着示例文件推断实际行为,要看你自己那份 config.yaml

技能的描述有一条看着像洁癖的硬规则:description 不超过 60 个字符。 agent/learn_prompt.py 里把原因写明白了 —— 系统提示里的技能索引会把描述截断到 60 字符,而且每个会话都要载入一次。超出的部分不是难看,是根本不参与路由。这条规则解释了这个项目大量的取舍逻辑:系统提示里的每一个字节都是你每轮对话都在付的钱。

攒下来的技能谁管。 agent/curator.py 是一个后台维护器,用辅助模型跑,不碰主会话的提示缓存。它按空闲触发,去看 Agent 自己创建的那些技能的活跃度,该固定的固定、该归档的归档、该合并的合并。它的不变量写得很清楚:只动 created_by: "agent" 来源的技能,内置的和从技能站装的一律不碰;永不删除,最狠的动作是归档到 ~/.hermes/skills/.archive/,可恢复;被固定(pinned)的技能豁免所有自动流转。使用数据放在 ~/.hermes/skills/.usage.json 里,由 tools/skill_usage.py 维护,记的是使用次数、查看次数、修改次数、最后活跃时间和状态。用户侧有 hermes curator 一串动词管它:statusrunpauseresumepinunpinarchiverestoreprunebackuprollback

不过这条”内置不碰”你得亲自核一遍,因为仓库内部口径不一致:AGENTS.md 的不变量清单说内置和技能站装的都是禁区,但 agent/curator.py 里有一个 prune_builtins 开关是默认打开的,注释明确写着开着的时候内置技能同样会进入候选、按同样的不活跃期被归档,只有技能站装的那批任何情况下都不碰。两处说法冲突时,代码里的默认值才是你机器上真正发生的事。这也顺便说明了读这类高频迭代仓库的姿势:文档是意图,代码是行为,冲突就以代码为准 —— 本文后面还会再遇到一次同样的情况。

跨会话的记忆分两层。 一层是文件式的,MEMORY.mdUSER.md,由 tools/memory_tool.py 里的存储类管,两个文件各有字符上限;另一层是外部记忆后端,做成插件放在 plugins/memory/ 下面,同一时刻只激活一个。另外 hermes_state_search.py 给会话库加了全文检索,配合 session_search 工具集,Agent 可以回头翻自己以前的对话。

这几块合起来才是那句”自带学习回路”的实际含义:技能是可读可改可版本化的文件,沉淀有提醒,维护有后台任务且只敢归档不敢删,历史可检索。它不是模型权重在变,是磁盘上的文档在变 —— 这个区别在你评估风险时很重要。常驻型 Agent 为什么需要这种可回滚的状态设计,可以对着Agent 检查点与常驻状态一起看。

四、两条贯穿全项目的设计取向

读这个仓库的时候,有两条原则值得先记住,因为它们能解释掉你八成的”为什么要设计成这样”。AGENTS.md 把它们放在了最前面。

第一条:每个会话的提示缓存不能破。 一个长对话每轮复用同一段缓存前缀,任何在对话中途改动历史上下文、切换工具集、重建系统提示的行为都会让缓存失效,用户的成本随即翻倍。所以这个项目不做这些事,唯一的例外是上下文压缩。这条原则甚至规定了斜杠命令的行为方式:会改动系统提示状态的命令默认延迟生效(下个会话才生效),要立刻生效得显式加参数。

第二条:核心是窄腰,能力长在边缘。 每一个模型工具都会在每次 API 调用时被发送出去,所以新增核心工具的门槛被刻意抬得很高。仓库里给了一条”足迹阶梯”,六级,从上往下足迹越来越大,要求你选能正确解决问题的最上面那一级:扩展已有代码 → CLI 命令加技能 → 有前置条件门控的工具 → 插件 → 放进目录的 MCP 服务 → 最后才是新的核心工具。

这两条一摆出来,很多现象就顺了。为什么定时任务和 webhook 订阅的主入口是 hermes cron / hermes webhook 这样的命令行子命令,配一份技能教 Agent 怎么调,而不是给模型开一排新工具?因为这类”管配置、管状态、管基础设施”的能力落在阶梯第二级,仓库把它俩连同 hermes tools 一起列成了这一级的范例。定时任务确实还留了一个 cronjob 模型工具让 Agent 自己排活,但那是被单独论证过的例外,不是默认做法。为什么 plugins/ 下面有 18 个顶层插件目录、optional-mcps/ 下面还另外放着 6 个可选 MCP 服务?因为能力被有意往外推。为什么记忆后端做成插件而不是核心的一部分?同一个原因。

顺带说一句,这个仓库对”什么不该合进来”写得比”什么该合”更细:没有具体使用方的预留扩展点不要;非密钥的行为配置一律不许新开环境变量;给指令性工具加分页读取的口子不要(模型会只读第一页);把别人家的产品集成塞进主仓库不要,让它自己发一个独立插件仓库。tests/ 目录下 test_ 开头的测试文件有 2499 个。

五、边界与代价:它放弃了什么、什么它不管

这一节是全文最该慢读的部分。一个常驻在你机器上、有终端权限、连着你聊天账号的程序,代价必须摊开讲。

你多了一台要运维的机器。 常驻的另一面是”崩了得有人管”。项目自己把这块做得挺细:docs/session-lifecycle.md 里写了一整套重启恢复流程 —— 优雅退出会写一个 .clean_shutdown 标记,下次启动看到它就跳过恢复;没看到就说明上次是崩的,于是把最近活跃过的会话标记成待恢复,保留原会话 ID 让用户接着聊;如果同一个会话连着 3 次重启都还在活跃,就判定它卡住了,强制给个干净的开始。这套机制的存在恰恰证明了问题真实存在:进程会崩,会话会卡,你得知道它崩了。

上下文不是永久的。 网关按会话键维护一个有容量上限的 Agent 实例缓存,满了按最近最少使用淘汰,闲置超过设定时长的也会被清掉;后台还有一个定期跑的过期巡检任务,负责收尾过期会话、调插件的收尾钩子、关掉工具占用的资源、把太老的会话记录剪掉。会话重置策略本身可配,有 noneidledailyboth 四种模式,还能按平台和会话类型分别设 —— 顺便说,这套模式的默认值在 docs/session-lifecycle.md 里前后写了两个不同的答案,真要依赖它就自己读一遍配置。换句话说,你不能假设”我三个月前跟它说过的事它还记得在上下文里”—— 记得住的是写进文件和数据库的那部分,不是对话缓冲区。

它有终端权限,这件事没法绕过。而且项目自己把这件事说得比多数使用者以为的更狠。 SECURITY.md 的信任模型一节写得非常直白:唯一的安全边界是操作系统,Agent 进程内部没有任何东西构成隔离 —— 不是审批门,不是输出脱敏,不是任何模式扫描器,也不是工具允许名单;凡是在进程内筛查模型输出的组件,处理的都是一段被攻击者影响过的字符串,文档把它们统一归为”启发式,不是边界”。它给出的两种真正的隔离姿势是:把终端后端换成容器或远端(只约束经由 shell 和文件工具的动作,约束不到代码执行工具、MCP 子进程、插件与技能加载这些跑在 Agent 自己解释器里的路径),或者把整个进程树包进沙箱(所有路径同一套策略)。

审批门本身还是要配的,只是要理解它的定位:approvals.modesmartmanualoff 三档,默认 smart 用辅助模型评估被判为破坏性的 shell 命令,低风险放行一次、高风险直接拒、拿不准的问你;off 等价于 --yolo,一键关掉所有提示。定时任务这种无人值守的场景另有 approvals.cron_mode,默认值是遇到危险命令就拒。还有一条要记住:文件写入不走审批提示,只有 shell 命令走。所以默认配置下它就在你机器上执行命令,你把 approvals.mode 关掉就是自己承担后果,而即使不关,你拿到的也只是”防手滑”,不是”防越狱”。仓库贡献者指南里有一个很说明问题的细节 —— 建虚拟环境别建在 Agent 操作的那个目录里面,因为 Agent 跑一条相对路径的命令就可能把自己的运行时删掉。这条对普通用户同样成立:它对自己所在的目录也是有写权限的。相关的权限收敛思路可以参考最小权限怎么设计

装第三方技能和插件,等于把代码请进 Agent 进程。 这一点在 SECURITY.md 里说得毫不含糊:插件加载进 Agent 进程、以 Agent 的全部权限运行,能读同一份凭据、调同一批工具、注册同一批钩子;技能在导入时就会执行任意 Python,所以”审一个技能”意味着读它的 Python 代码和脚本,不是读一眼 SKILL.md 的描述就完事。仓库自带的技能扫描器只是评审辅助,文档明说它不是边界,第三方内容的边界就是你装之前那次人工审查。恶意插件搞出来的破坏,项目不把它算成自己的漏洞。反过来说,这条也解释了为什么”随仓库发布但默认不激活”这个设计是对的 —— 默认不激活的那批要显式 hermes skills install 才进来,装的动作就是你的确认。

连聊天账号意味着授权面变大。 谁能跟它说话由允许名单和私聊配对管;多人场景的隔离规则默认值需要你自己确认清楚 —— 群组和频道会话默认按人隔离,而话题/线程会话默认是共享的(同一个线程里所有参与者看同一份上下文,发言人名字加在每条消息前面)。这不是漏洞,是有意的默认值,但如果你在公司群里挂一个,最好先确认这个默认符合你的预期。

它明确不管的几件事。 它不给你模型 —— 你自带供应商和密钥,用哪家由你选,各家的计费、额度和限流规则不同且会调整,以官方最新说明为准。它不是 IDE 里的内联补全工具,也不试图做那件事。后台委派有个明确的耐久性红线:后台的子 Agent 任务虽然脱离了当前这轮对话,但仍然是进程内的,进程重启就没了;要活过重启,得用定时任务或者带完成通知的后台终端命令。并发也有上限,子 Agent 的并发数由配置控制,默认值不高。

最后一条不是技术边界而是态度边界:这是别人的开源项目,迭代很快,仓库里的策略条款自己就标着”某年某月起的政策”。今天读到的默认值明天可能就变了,任何时候都该回仓库核一遍,而不是照抄一篇文章(包括这一篇)。

六、上手清单:为什么会踩,怎么避

1. 把它当终端编码 Agent 用。 会踩是因为它确实有 TUI、也确实能改代码,看着跟你熟悉的那类工具一样。但它的价值不在你盯着屏幕的那半小时。怎么避:第一天别拿它写业务代码,先起网关,排一个每天固定跑的任务,观察它在你不在场时的表现,再决定要不要往下投入。

2. 一上手就把审批关掉。 会踩是因为审批提示确实打断流程,尤其是你在批量试东西的时候。怎么避:把执行环境隔离出去,而不是把审批关掉 —— tools/environments/ 里的容器和远端后端就是干这个的。审批留在默认那档,让辅助模型帮你过滤掉大部分噪音。

3. 直接装在生产机器上,或者装在你重要文件旁边。 会踩是因为安装脚本一条命令就跑完了,顺手就装在手边的机器上。怎么避:给它一台便宜的独立机器,或者让终端后端指向容器。记住上面那个 venv 的例子 —— 它对自己工作目录的写权限是真实的。

4. 把行为配置写进 .env 会踩是因为环境变量看着最快最直接。但这个项目的规矩是 .env 只放密钥,超时、阈值、开关、显示偏好全部走 config.yaml;文档里也点明了旧的消息工作目录环境变量已经移除,工作目录现在看 config.yamlterminal.cwd 这一项。怎么避:找配置的时候先翻 config.yaml 的段落列表,modelagentterminaldisplaymemorysecuritydelegationskillsgatewaycron 这些段落里放着绝大多数你想调的东西。

5. 假设群里所有人共享一个上下文(或者假设一定不共享)。 会踩是因为群组和线程的默认值不一样,一个按人隔离一个共享。怎么避:接群之前先把这两个开关的当前值确认一遍,再决定这个 Agent 是”团队共用的一个大脑”还是”每人一个私有助手”。

6. 指望技能自己越来越好而完全不看。 会踩是因为后台维护器确实在跑,容易产生”有人管了”的错觉。但它的动作范围跟你以为的不一样:文档说只动 Agent 自己创建的技能,代码里的 prune_builtins 默认却把内置技能也纳入了不活跃归档。好消息是它永不删除、只归档且可恢复。怎么避:把”翻一遍技能列表”当成月度动作,看看哪些是 Agent 攒的、哪些被归档了、哪些该固定住;真有不能被动的技能,直接 hermes curator pin 钉住,固定过的豁免所有自动流转。

7. 自己写技能时描述写长了。 会踩是因为写文档的本能是把事情说清楚,一句话很容易过 60 字符。后果不是难看,是这份技能在系统提示的索引里被截断、路由不到,等于写了不生效。怎么避:写完数一遍字符数,超了就砍,别指望”应该没事”。

8. Windows 上装完被杀毒软件拦住。 会踩是因为安装器会带一个用来管 Python 环境的 Rust 写的包管理器二进制,基于机器学习的杀毒引擎经常把这类未签名二进制判成恶意。README 里给了完整的校验步骤(比对官方发布产物的哈希)和加白名单的方法,并且特别提醒白名单要加目录而不是文件哈希,因为这个二进制每次更新哈希都会变。

收个尾:接下来该读哪几个文件

如果你决定往下深挖,按这个顺序读效率最高:先看 AGENTS.md,尤其是贡献规则和那条足迹阶梯,它是理解全项目取舍的钥匙;再看 docs/session-lifecycle.md,会话怎么产生、怎么过期、怎么在重启后恢复都在里面,这决定了你的使用体验;然后翻一份 skills/ 下面的 SKILL.md,看清技能文件的真实格式再动手写自己的;最后看 SECURITY.md 的信任模型那一节,把”唯一边界是操作系统”这句话读进去,再决定给它哪台机器、哪个隔离姿势、哪个聊天账号。

给自己的四个自检问题:这台常驻机器崩了我能多久发现?它现在有权限动哪些目录、能不能删到我不想被删的东西?我要它记住的东西是落在文件里了,还是只活在某个会话的上下文里?它攒出来的技能,最近一个月我看过一次吗?这四个问题答不上来,说明你还没真正接管这个进程 —— 常驻的意思是它一直在,也意味着责任一直在你这边。

这个系列的其余文章

这篇是总览。想往下挖,按下面两条线走:先把它跑起来,或者直接读代码

上手与使用

结构与机制

全部文章也汇总在 Hermes Agent 开源专题。另一类形态的开源 Agent——专门操作浏览器的那种——见 browser-use 是什么,两者的取舍差别不小。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。