Hermes 架构全解

191.8 万行 Python · 4,772 个文件 · 单系统深潜 · 不做任何对比

这篇文章的定位

这一篇只讲 Hermes 一个系统。不和任何其他项目对比,只回答:这个系统是怎么造出来的?

从 22 个聊天平台的消息入口,到全息记忆的向量运算,逐层拆开每一个可插拔子系统 —— 包括常驻网关进程、多身份路由、凭据池故障转移、定时任务、以及那套让它自称「自我改进」的技能演化机制。

阅读门槛:不需要人工智能背景。所有概念在首次出现时都会解释。如果你完全没接触过大语言模型,建议先读《合刊》那一篇的第 1 章(零基础前置知识),大约 20 分钟,之后再回来。

0 · 项目全景与代码地图

0.1 这个软件是什么

项目自己的定位写在 README 第一句:

「The self-improving AI agent built by Nous Research. It's the only agent with a built-in learning loop — it creates skills from experience, improves them during use, nudges itself to persist knowledge, searches its own past conversations, and builds a deepening model of who you are across sessions. Run it on a $5 VPS, a GPU cluster, or serverless infrastructure that costs nearly nothing when idle. It's not tied to your laptop — talk to it from Telegram while it works on a cloud VM.」

译:由 Nous Research 打造的自我改进型 AI 智能体。它是唯一内置学习闭环的智能体 —— 它从经验中创建技能、在使用中改进它们、提醒自己持久化知识、搜索自己过往的对话,并跨会话地建立一个对你越来越深入的认知模型。你可以把它跑在一台每月 5 美元的虚拟服务器上、跑在 GPU 集群上、或者跑在闲置时几乎零成本的无服务器基础设施上。它不绑定在你的笔记本上 —— 你可以从 Telegram 和它对话,而它在一台云端虚拟机上干活。

把这段话拆开,它声明了四个核心主张,而这四个主张各自对应了架构里的一大块:

主张对应的架构哪一章
不绑定你的笔记本
从 Telegram 对话,在云端干活
常驻网关进程 + 22 个平台适配器第 1 章
用任何你想用的模型
切换不改代码、不锁定
供应商适配层 + 凭据池第 11 章
跨会话建立对你的认知记忆提供者抽象 + 8 种后端第 8 章
内置学习闭环
从经验创建技能并改进
技能系统(81 个技能,近 9,000 行管理代码)第 13 章
属性
开发方Nous Research
编程语言Python 3.11
包管理uv —— 一个用 Rust 写的、比 pip 快很多的 Python 包管理器
许可证MIT(最宽松的开源许可证之一)
发布2026 年 2 月 25 日。8 周后在代码托管平台 GitHub 上获得约 9.9 万收藏,6 月突破 17.5 万
代码规模4,772 个 Python 文件,191.8 万行

0.2 目录地图

括号里是文件数,能直观看出体量分布:

hermes-agent/ │ ├── run_agent.py (425 KB) AIAgent 类 —— 智能体的核心对象 ├── cli.py (1.0 MB) 命令行界面 ├── model_tools.py (77 KB) ★ 工具的统一分发与参数矫正 → 第 4 章 ├── toolsets.py (39 KB) ★ 工具的分组与投放策略 → 第 4 章 ├── hermes_state.py (682 KB) ★ SQLite 状态存储 → 第 8 章 ├── hermes_state_search.py (116 KB) 全文检索 ├── hermes_state_schema.py (75 KB) 数据库结构 ├── hermes_constants.py (73 KB) 常量 ├── trajectory_compressor.py (70 KB) 轨迹压缩 ├── batch_runner.py (60 KB) 批量运行 ├── mcp_serve.py (38 KB) 把自己作为 MCP 服务暴露出去 │ ├── agent/ (209 个) ★ 智能体核心 │ ├── conversation_loop.py (475 KB) ★★ 主循环 → 第 3 章 │ ├── context_compressor.py (419 KB) 内置上下文引擎 → 第 7 章 │ ├── context_engine.py (16 KB) ★ 引擎抽象基类 → 第 7 章 │ ├── auxiliary_client.py (489 KB) 辅助模型调用 │ ├── turn_context.py 每轮的准备工作 → 第 3 章 │ ├── memory_provider.py ★ 记忆抽象基类 → 第 8 章 │ ├── credential_pool.py ★ 凭据池 → 第 11 章 │ ├── *_adapter.py 供应商适配器 → 第 11 章 │ └── prompt_builder.py 系统提示词组装 │ ├── gateway/ (99 个) ★ 常驻网关进程 → 第 1、2 章 │ ├── run.py (1.55 MB) ★★ 网关主循环 │ ├── platforms/base.py (333 KB) ★ 平台适配器抽象基类 │ ├── profile_routing.py ★ 多身份路由 → 第 2 章 │ ├── slash_commands.py (297 KB) 斜杠命令 │ └── ... 投递账本、重启守卫、内存监控 │ ├── tools/ (162 个) ★ 工具实现 → 第 4 章 │ ├── approval.py (5,802 行) ★ 安全审批 → 第 5 章 │ ├── environments/ (12 个) ★ 执行环境 → 第 6 章 │ ├── delegate_tool.py (5,071 行) 子智能体委派 → 第 10 章 │ ├── kanban_tools.py 看板协作 → 第 10 章 │ ├── skills_hub.py (4,956 行) 技能中枢 → 第 13 章 │ └── mcp_tool.py (378 KB) MCP 客户端 │ ├── plugins/ (351 个) ★ 可热插拔单元 → 第 9 章 │ ├── platforms/ (22 个平台适配器) │ ├── memory/ (8 种记忆后端) → 第 8 章 │ ├── context_engine/ → 第 7 章 │ ├── model-providers/ │ └── kanban / browser / image_gen / observability / ... │ ├── skills/ (484 个) 81 个 SKILL.md,15 个分类 → 第 13 章 ├── cron/ (14 个) 定时任务系统 → 第 12 章 ├── hermes_cli/ (299 个) 命令行子命令 ├── optional-mcps/ (65 个) 可选的外部 MCP 服务 ├── ui-tui/ (475 个) 终端界面(TypeScript 写的) ├── web/ (184 个) 网页版界面 ├── tui_gateway/ (30 个) 终端界面的网关 ├── acp_adapter/ (11 个) 编程软件对接协议 └── evals/ (38 个) 评测

0.3 从这张地图能读出的三件事

第一:外围远大于核心,而且外围就是产品本身

核心(智能体逻辑)外围(集成与扩展)
conversation_loop.py 主循环
model_tools.py 工具分发
context_engine.py 引擎抽象 —— 490 行
memory_provider.py 记忆抽象
plugins/ 351 个文件
hermes_cli/ 299 个文件
ui-tui/ 475 个文件
skills/ 484 个文件
gateway/ 99 个文件

注意 context_engine.py 只有 490 行,而它旁边的 context_compressor.py 有 419 KB。前者是接口(规定「一个上下文引擎必须提供哪些功能」),后者是内置的一个实现

这个比例关系贯穿全系统:抽象层薄,实现层厚,而且实现层可以整个换掉。

第二:有一层叫「网关」,而且它是最大的模块

gateway/run.py 单文件 1.55 MB —— 是整个项目最大的文件。

这一层解决的是一个很具体的问题:一个长期在线的智能体,怎么被 22 个不同的聊天软件以统一的方式触达。

它带来的能力是:你在电脑上用 Slack 和智能体聊到一半,出门换成手机上的 Telegram 继续聊,对话上下文完全连续。对智能体来说这始终是同一场会话,只是消息的进出口换了。

第三:几乎每个关键决策点都是一个抽象基类

「抽象基类」(Abstract Base Class,缩写 ABC)是 Python 里的一种「插座标准」:它规定「任何想接进来的东西必须提供哪几个功能」,但不规定这些功能怎么实现。

抽象基类规定了什么已有的实现
ContextEngine上下文怎么管理内置压缩器 + 第三方引擎
MemoryProvider长期记忆怎么存取8 种(内置全息记忆 + 7 种外部服务)
BasePlatformAdapter一个聊天平台怎么接入22 种
Environment工具在哪里执行7 种(本机 / Docker / 云沙箱 / SSH…)
Provider Adapter一个模型服务怎么调用Anthropic / OpenAI / Gemini / Bedrock / Vertex / Azure / Codex / Ollama…

这是 Hermes 最核心的架构立场:把每一个「可能有多种做法」的决策点,都定义成接口交出去。

代价是显而易见的:接口必须照顾所有实现的最低公分母,拿不到任何单一实现的深度优化。
收益也是显而易见的:1,000 多位贡献者可以并行地往这些插座上接东西,而不需要碰核心代码。

0.4 一条消息的完整旅程

Hermes 分层架构总览
Hermes 分层架构总览 — 从最上层的 22 个平台入口,经过身份路由、智能体循环、工具与审批,一直到最下层的 7 种执行环境。右侧那些竖向贯穿的模块(插件、记忆、上下文引擎)是横切关注点,它们不属于任何一层,而是穿过所有层点击放大
你在手机 Telegram 上发了一句「帮我看看昨天那个报错」 │ ▼ 【第 1 章】网关层 Telegram 适配器收到消息 → 归一化成统一的 MessageEvent → 检查授权 → 文本消息去抖动(避免连发多条时重复触发) │ ▼ 【第 2 章】身份路由 profile_routing 判断这条消息属于哪个"身份" (四级路由:显式规则 → 服务器 → 频道 → 会话线程 → 默认) → 每个身份有自己的模型、工具、记忆、人格 │ ▼ 会话路由:找到(或创建)对应的 AIAgent 实例 ★ 关键:如果你上次是在 Slack 上聊的,这里会命中同一个会话 │ ▼ 【第 3 章】主循环 run_conversation │ ├─ build_turn_context() 每轮的准备工作 │ 系统提示词组装 · 预检压缩 · 外部记忆预取 · 崩溃恢复持久化 │ ├─【第 7 章】ContextEngine.select_context() 每轮上下文选择 │ ├─ 调用模型(可能中途切换供应商)→【第 11 章】 │ ├─【第 4 章】工具调用分发 handle_function_call │ 参数强制矫正 →【第 5 章】审批 →【第 6 章】在选定环境里执行 │ └─【第 10 章】如果是 delegate_task → 派生子智能体 │ ├─ /steer 中途插话(用户可以在模型思考时插一句) │ └─【第 7 章】ContextEngine.on_turn_complete() 后置观察 │ ▼ 【第 8 章】状态与记忆 SQLite 落盘 · FTS5 全文索引 · HRR 向量 · 信任分反馈 │ ▼ 【第 13 章】技能演化 这次用到的技能被记录使用情况;系统可能提议改进它 │ ▼ 回复从 Telegram 发出(流式更新同一条消息) │ 【第 12 章】另外还有定时任务系统在后台按计划自主触发智能体 【第 9 章】以上每一层都可以被插件替换或扩展

0.5 全文章节索引

标题核心内容
1网关层常驻进程、22 平台适配器抽象、能力声明式设计、投递账本、重启守卫
2身份与会话路由Profile 多身份、四级路由、SOUL.md 人格文件、跨平台会话连续性
3主循环★ 预算驱动的循环、宽限调用、中途插话、每轮 prologue
4工具系统TOOLSETS 投放策略、中心分发、参数强制矫正层、错误净化
5审批与安全红线★ 12 条硬红线、命令位置锚定、引号遮蔽、反混淆、路径归一化
6执行环境7 种可插拔环境、本机默认无沙箱的审计发现
7上下文引擎★ 抽象基类、select 与 compress 双动词、缓存契约
8记忆系统★ HRR 全息记忆、SQLite + FTS5、信任分衰减、8 种可插拔后端
9插件系统3 个发现来源、可叠加能力与互斥策略的区分
10委派与看板子智能体、实时干预(插话/中止/暂停)、看板协作、心跳
11供应商适配十余种后端、凭据池故障转移、按供应商重打缓存断点
12定时任务自主触发、失败连击提醒、事故记录、注入防护
13技能系统81 个技能、渐进式披露、使用记录、自我改进闭环