Hermes Agent
一、Hermes Agent 是什么
它不是依附于集成开发环境 (IDE) 的代码助手,也不是围绕单一 API 封装的聊天机器人。它是一个自主代理 ,运行时间越长,功能越强大。
主要特点
- 一个闭环学习系统 ——由智能体维护的记忆(附带定期提醒)、自主技能创建、使用过程中的技能自我改进、FTS5 跨会话回忆(结合 LLM 摘要)以及 Honcho 辩证用户建模
- 可在任何设备上运行,不仅限于笔记本电脑 ——支持 6 种终端后端:本地、Docker、SSH、Daytona、Singularity 和 Modal。Daytona 和 Modal 提供无服务器持久化功能——环境在空闲时会进入休眠状态,几乎不消耗任何资源。
- 随时随地,尽在掌握 ——CLI、Telegram、Discord、Slack、WhatsApp、Signal、Matrix、Mattermost、电子邮件、短信、钉钉、飞书、微商、BlueBubbles、Home Assistant——通过一个网关即可访问 15 个以上的平台。
- 由模型训练专家构建 ——由 Nous Research 实验室创建,该实验室也是 Hermes、Nomos 和 Psyche 的开发者。可与 Nous Portal 、 OpenRouter 、OpenAI 或任何端点配合使用。
- 定时自动化 —— 内置 cron 功能,可部署到任何平台
- 委托和并行化 — 为并行工作流生成隔离的子代理。通过 execute_code 进行程序化工具调用,可将多步骤管道合并为单个推理调用。
- 委托和并行化 — 为并行工作流生成隔离的子代理。通过 execute_code 进行程序化工具调用,可将多步骤管道合并为单个推理调用。
- 开放标准技能 ——与 agentskills.io 兼容。技能可移植、可共享,并通过技能中心由社区贡献。
- 完全网页控制 ——搜索、提取、浏览、视觉识别、图像生成、文本转语音
- MCP 支持 — 连接到任何 MCP 服务器以扩展工具功能
- 研究就绪 ——支持批量处理、轨迹导出和使用 Atropos 进行强化学习训练。由 Nous Research 构建——该实验室正是 Hermes、Nomos 和 Psyche 模型背后的研发者。
1.1 快速安装
1 | |
安装过程会让你配置模型和消息通道,安装好如下:

1 | |
如需稍后重新配置个别设置,请使用专用命令:
1 | |
只需一条命令即可更新到最新版本:
1 | |
通过即时通讯平台进行更新
1 | |
卸载
1 | |
1.2 使用Hermes
CLI
1 | |

TUI
1 | |

1.3 配置
所有设置都存储在 ~/.hermes/ 目录中,以便于访问。
目录结构
1 | |
管理配置
1 | |
配置优先级
- CLI 参数 — 例如, hermes chat –model anthropic/claude-sonnet-4 (每次调用覆盖)
- ~/.hermes/config.yaml — 所有非机密设置的主要配置文件
- ~/.hermes/.env — 环境变量的备用文件;密钥(API 密钥、令牌、密码) 必需 。
- 内置默认值 ——当没有其他设置时,硬编码的安全默认值
1.4 Sessions
Hermes Agent 会自动将每次对话保存为一个会话。会话支持对话恢复、跨会话搜索和完整的对话历史记录管理。
会话如何运作
无论对话来自命令行界面 (CLI)、Telegram、Discord、Slack、WhatsApp、Signal、Matrix 还是任何其他消息平台,所有对话都会以会话的形式存储,并包含完整的消息历史记录。会话在两个互补的系统中进行跟踪:
- SQLite 数据库 (
~/.hermes/state.db)——包含结构化会话元数据和 FTS5 全文搜索 - JSONL 转录 (
~/.hermes/sessions/)— 包含工具调用(网关)的原始对话转录
使用 --continue 或 --resume 从 CLI
恢复之前的对话:
1 | |
这会从 SQLite 数据库中查找最近的 cli 会话,并加载其完整的对话历史记录。
如果您已为会话指定了标题(请参阅下文 “会话命名 ”),则可以按名称恢复会话:
1 | |
恢复特定会话
1 | |
退出 CLI 会话时会显示会话 ID,可以使用
hermes sessions list 找到它们。
1.5 运行多个Agents (Profiles)
通过 Profiles 功能,你可以在同一台机器上运行多个相互独立的 Hermes
Agent,例如一个编码助手、一个私人管家或一个研究专员。每个 Profile
都拥有自己完全独立的配置 (config.yaml)、API 密钥
(.env)、系统提示词
(SOUL.md)、记忆、会话历史、技能库以及网关状态,互不干扰。
快速上手与别名命令
创建一个 Profile 时,系统会自动为其生成一个专属的别名命令:
1
2
3hermes profile create coder # 创建名为 coder 的 profile,并自动生成 "coder" 命令
coder setup # 独立配置该 agent 的 API keys 和模型
coder chat # 开始与该专属 agent 聊天coder 代替
hermes 执行任何命令,如
coder gateway start、coder skills list。你也可以在常规命令中使用
-p 参数指定:hermes -p coder chat。
创建与克隆策略
- 创建空白
Profile:
hermes profile create mybot - 仅克隆配置:
hermes profile create work --clone(复制当前配置、密钥和系统提示词,但不复制历史记忆和会话,适合干净开局) - 全量克隆
(快照):
hermes profile create backup --clone-all(复制所有数据,包括记忆、完整历史记录和插件,非常适合备份或从现有上下文中“分叉”出一个新 Agent)
多网关独立运行
由于每个 Profile 的状态是隔离的,你可以同时运行多个 Agent
的后台网关服务,且它们可以分别接入不同的通讯平台: 1
2
3
4
5# 在 ~/.hermes/profiles/coder/.env 中配置 Telegram Bot A
coder gateway start
# 在 ~/.hermes/profiles/assistant/.env 中配置 Discord Bot B
assistant gateway start
此外,你还可以为每个 Agent
独立注册后台守护服务:coder gateway install。
底层原理解析
Profiles 的本质是改变了工作目录。当你运行 coder chat
时,系统在底层将其 HERMES_HOME 环境变量指向了
~/.hermes/profiles/coder,使所有的日志、记忆、数据库操作全部隔离在此目录下。
注意:Profile 隔离的是“大脑状态”,而不是文件系统沙盒。Agent 执行代码的实际工作区依然由
terminal.cwd决定。如果你希望特定的 Profile 始终在某个项目目录中启动,请在配置中指定:
1coder config set terminal.cwd /absolute/path/to/project
1.6 Git Worktrees 隔离工作区
在大型、长生命周期的代码仓库中,如果你需要: 1. 在同一个项目上并行运行多个 Agent。 2. 让 Agent 进行实验性的重构,而不污染你的主分支。
使用 Git Worktrees(工作树) 是最安全的做法。它可以为每个 Agent 提供独立的目录和分支,而无需重新克隆整个庞大的代码库。
为什么需要隔离? Hermes 会将你当前运行
hermes 的目录视为“项目根目录”。如果多个 Agent
在同一个目录下并发运行,它们可能会互相覆盖或删除对方正在修改的文件。
而通过 Git Worktrees,每个 Agent 都能获得: -
独立的分支和工作目录。 - 独立的 Checkpoint
(检查点) 历史,调用 /rollback 时互不影响。
自动 Worktree 模式 (hermes -w)
Hermes 内置了极简的自动处理机制。你完全不需要手动配置 git
树,只需在你的仓库根目录下加上 -w 参数:
1 | |
此时 Hermes 会在底层自动执行以下操作: 1. 在仓库的
.worktrees/ 目录下创建一个临时的独立工作区。 2.
自动切出一个隔离的分支(例如 hermes/hermes-<hash>)。
3. 在这个独立且干净的环境中启动交互式会话。
如果你想并行运行多个 Agent,只需打开多个终端窗口,在每个窗口都运行
hermes -w,它们就能在各自独立的分支互不干扰地工作。
你也可以结合单次查询使用: 1
hermes -w -q "帮忙修复一下 Issue #123 的 bug"
手动管理 Worktree
如果你希望完全手动掌控,也可以使用原生的 git 命令:
1
2
3
4
5# 在上一级目录创建一个名为 repo-feature 的工作区,并绑定新分支
git worktree add ../repo-feature feature/hermes-experiment
cd ../repo-feature
hermes # 此时 Agent 已经被完美隔离在这个新目录下
当实验结束后,如果你觉得 Agent 写的代码很好,可以直接将该分支 merge
回主分支。如果搞砸了,直接丢弃该分支并执行
git worktree remove ../repo-feature 清理即可。
1.7 Security 安全机制
作为一款能够自动执行命令的 Agent,Hermes 在底层设计了极为严苛的 七层防御纵深安全模型 (Defense-in-depth),确保你的系统、隐私和凭据绝对安全。
1. 危险命令审批 (Dangerous Command Approval)
在执行任何终端命令前,Hermes
会使用内置拦截器扫描命令是否包含破坏性模式(如 rm -rf,
chmod 777, DROP TABLE, > /etc/
等数十种高危操作)。 - 拦截模式 (Mode):默认为
manual(手动确认)。你也可以开启 smart
模式,让辅助 LLM 帮你评估风险,低风险自动放行,高危操作强制拦截。 -
YOLO 模式:如果你在跑极其信任的全自动化流水线,可以使用
/yolo 命令或 --yolo
标志彻底关闭安全弹窗(请在隔离的 Docker 环境中使用)。 -
云端免审批:如果你的后端沙盒配置为
docker、modal 或
daytona,系统会自动跳过危险命令检查,因为容器本身就是最完美的物理安全边界。
2. 网关用户授权与配对 (User Authorization & DM Pairing)
当你把 Hermes 挂载到 Telegram、Discord
或微信等公开平台上时,它默认是全封闭的(默认 Deny)。 -
白名单机制:只有在 ~/.hermes/.env 中配置了
TELEGRAM_ALLOWED_USERS 等白名单 ID 的用户才能唤醒 Agent。 -
DM Pairing
(私信配对系统):为方便向朋友分享,系统内置了动态验证码机制。未授权用户发消息时会收到一个
8 位验证码,你可以直接在 CLI 中运行
hermes pairing approve telegram <code> 为其放行。
3. 沙盒强化隔离 (Container Hardening)
当使用 docker 作为代码执行沙盒时,Hermes
绝不会使用默认的弱隔离容器。它在底层强制注入了极其严酷的安全参数: -
--cap-drop ALL:移除所有 Linux 内核特权。 -
--security-opt no-new-privileges:彻底阻断提权攻击。 -
--tmpfs /run:rw,noexec,nosuid:防止在运行时挂载点执行恶意脚本。
4. 环境变量与凭据穿透 (Env & Credential Passthrough)
在大模型自动生成的代码中,绝不允许直接读取宿主机的环境变量(防止窃取你的
AWS Key 或 SSH Key)。 - 只有被明确定义在技能(如
required_environment_variables)或 config.yaml
(env_passthrough) 中的环境变量才会被精确注入到执行沙盒中。
- OAuth 文件穿透:对于 Google Workspace 这类需要
token.json 文件的场景,系统只将其以只读 (ro)
形式挂载进容器。
5. SSRF 防御与 Tirith 深度扫描
- 防 SSRF
攻击:内置的浏览器和网络工具强制拦截对本地内网 (如
192.168.0.0/16)、回环地址 (127.0.0.1) 和云服务元数据 (169.254.169.254) 的探测。 - Tirith 扫描:在执行前,除了正则匹配,Hermes
会调用外部的 tirith
工具扫描混淆的恶意终端代码(例如检测管道投毒
curl | bash或 Unicode 欺骗攻击)。
6. 提示词注入防御 (Context File Injection)
当 Agent 读取工作区中庞大的 AGENTS.md 或
.cursorrules 文件时,底层会扫描隐藏的 HTML
注释、忽略指令(Ignore prior instructions)以及隐形 Unicode
字符,防止被投毒的开源仓库挟持你的 Agent 去窃取本地秘钥。
7. MCP 凭据屏蔽
当挂载第三方 MCP (Model Context Protocol) 服务器时,所有 LLM
的输出以及 MCP 抛出的报错日志都会被强行擦除敏感的 API Key
(sk-..., ghp_...) 并替换为
[REDACTED]。
二、Features 核心特性概览
Hermes Agent 提供了一套极其丰富的特性矩阵,远超普通的聊天机器人。以下是它核心能力的全面概览:
2.1 核心基石 (Core)
- Tools & Toolsets (工具集):按模块划分的底层能力扩展,涵盖网页搜索、终端控制、文件编辑等。你可以针对不同平台按需启停特定的工具集。
- Skills System (技能系统):兼容
agentskills.io开放标准的动态知识库。Agent 会在需要时按需加载技能,极大节省 Token 开销。 - Persistent Memory
(持久化记忆):跨会话的记忆系统。Agent 会通过
MEMORY.md和USER.md记住你的偏好、项目背景和它曾学到的知识。 - Context Files
(上下文文件):自动感知并加载项目目录下的
.hermes.md,AGENTS.md,.cursorrules等规范文件,塑造 Agent 的特定项目行为。 - Context References (上下文引用):在对话中输入
@即可直接注入文件、文件夹、Git Diffs 或 URLs,系统会自动解析并附加内容。 - Checkpoints
(检查点与回滚):在修改文件前自动为工作区创建快照,如果代码改崩了,随时可以使用
/rollback完美恢复。
2.2 自动化与后台守护 (Automation)
- Cronjobs (定时任务):支持通过自然语言或 Cron 表达式调度后台任务。任务可以附带专属技能,并将结果推送到任何消息平台。
- Subagent Delegation (多智能体委派):使用
delegate_task工具孵化具有隔离上下文、受限工具和独立终端的子 Agent 实例。默认支持 3 个并发子 Agent 执行多线任务。 - Code Execution (代码沙盒执行):允许 Agent 编写 Python 脚本并通过沙盒 RPC 编排调用 Hermes 工具,将复杂的多步工作流压缩为单次 LLM 推理。
- Event Hooks (生命周期钩子):支持在网关层面或工具拦截点注入自定义代码逻辑,用于日志记录、安全扫描或告警。
- Batch Processing (批处理):并发处理成百上千个 Prompts,并生成标准的 ShareGPT 格式轨迹数据,用于评估或构建训练集。
2.3 媒体与全能浏览器 (Media & Web)
- Browser Automation (浏览器自动化):支持本地 Chromium 控制以及 Browserbase 云端引擎。能够导航网页、穿透 Cloudflare、填写表单并提取核心数据。
- Voice Mode (全双工语音):支持 CLI 和跨平台的语音交互。甚至可以加入 Discord 语音频道进行实时语音对谈。
- Vision (视觉感知):支持剪贴板图片直接粘贴。Agent 可利用视觉模型分析截图、还原 UI 或读取报错信息。
- Image Generation (图像生成):内置集成 FAL.ai,支持 Flux 2 Pro、Recraft V4 等 8 种顶级文生图模型。
- TTS (文本转语音):内置 5 种语音提供商 (包括免费的 Edge TTS 和顶级的 ElevenLabs),让 Agent 发送高保真语音消息。
2.4 生态集成 (Integrations)
- MCP Integration (模型上下文协议):原生接入任何外部 MCP 服务器,无缝打通内部数据库、GitHub 或专有系统工具。
- Provider Routing (智能路由):精细化控制哪个模型处理哪个任务,实现成本、速度与质量的极致平衡。
- Fallback Providers (灾备降级):主模型宕机时,自动切换至备用模型,确保后台定时任务万无一失。
- Credential Pools (凭据池):配置多个 API Key,系统会在触发 Rate Limit 时自动轮询切换,保证服务不中断。
- Memory Providers (记忆提供商):支持接入外部记忆后端 (如 Honcho, Mem0, RetainDB 等),实现跨会话的深度用户建模与个性化。
- API Server (兼容 OpenAI API):将 Hermes 暴露为标准 HTTP 接口,可作为 Open WebUI、LobeChat 等前端的强化版底座。
- IDE ACP 协议:支持直接接入 VS Code、Zed 和 JetBrains 编辑器,在 IDE 内部渲染差异并控制光标。
- RL Training (强化学习训练):自动从 Agent 会话中收集并生成标准格式的轨迹数据,用于大模型的强化学习 (RL) 与微调训练。
2.5 深度定制 (Customization)
- Personality & SOUL (人格塑造):通过编写
SOUL.md,从系统级重塑 Agent 的身份认知与表达语气。你还可以在会话中使用/personality动态切换人设预设。 - Skins & Themes (皮肤与主题):深度自定义 CLI 的视觉呈现效果。你可以修改横幅颜色、加载动画 (Spinner)、响应框标签、品牌文本以及工具活动的特定前缀标识。
- Plugins UI (插件市场):一个统一的交互式 UI 界面
(
hermes plugins),无需修改核心代码即可无缝安装第三方自定义工具、生命周期钩子和外部记忆库。 ## 三、Integrations
Hermes Agent 可以连接到外部系统,用于 AI 推理、工具服务器、IDE 工作流、编程式访问等。这些集成扩展了 Hermes 的能力以及它可以运行的场景。
3.1 AI 提供商与路由 (AI Providers & Routing)
Hermes 开箱即用地支持多个 AI 推理提供商。你可以使用
hermes model 进行交互式配置,或者在
config.yaml 中进行设置。
- AI 提供商 — 支持 OpenRouter, Anthropic, OpenAI, Google 以及任何兼容 OpenAI 格式的端点。Hermes 会针对每个提供商自动检测其能力(如视觉能力、流式输出以及工具调用)。
- 提供商路由 (Provider Routing) — 对 OpenRouter 请求进行细粒度控制。你可以通过排序、白名单、黑名单以及明确的优先级顺序,来优化成本、速度或生成质量。
- 灾备降级 (Fallback Providers) — 当你的主模型遇到错误时,自动故障转移到备用 LLM 提供商。这不仅包括主模型的降级,还包括为视觉、上下文压缩和网页提取等辅助任务设置独立的备用模型。
3.2 工具服务器 (MCP)
- MCP 服务器 — 通过 Model Context Protocol
(模型上下文协议) 将 Hermes 连接到外部工具服务器。无需编写原生的 Hermes
工具,即可访问来自 GitHub、数据库、文件系统、浏览器堆栈、内部 API
等的外部工具。支持
stdio和SSE两种传输方式、按服务器级别的工具过滤,以及感知能力的资源/提示词注册。
3.3 网页搜索后端 (Web Search Backends)
web_search 和 web_extract 工具支持 4
种后端提供商,可通过 config.yaml 或
hermes tools 进行配置:
| Backend (后端) | Env Var (环境变量) | Search (搜索) | Extract (提取) | Crawl (爬取) |
|---|---|---|---|---|
| Firecrawl (默认) | FIRECRAWL_API_KEY |
✔ | ✔ | ✔ |
| Parallel | PARALLEL_API_KEY |
✔ | ✔ | — |
| Tavily | TAVILY_API_KEY |
✔ | ✔ | ✔ |
| Exa | EXA_API_KEY |
✔ | ✔ | — |
快速配置示例:
1 | |
如果未设置 web.backend,系统将根据可用的 API
密钥自动检测后端。同时,通过配置 FIRECRAWL_API_URL
也支持自托管的 Firecrawl。
3.4 浏览器自动化 (Browser Automation)
Hermes 包含了全功能的浏览器自动化,提供多个后端选项来导航网站、填写表单并提取信息:
- Browserbase — 托管的云端浏览器,内置反爬虫绕过、验证码 (CAPTCHA) 破解以及住宅代理池。
- Browser Use — 另一种云端浏览器提供商方案。
- 本地 Chrome (通过 CDP) — 使用
/browser connect命令连接到你本地正在运行的 Chrome 实例。 - 本地 Chromium — 通过
agent-browserCLI 运行的无头本地浏览器。
3.5 语音与 TTS 提供商 (Voice & TTS Providers)
跨所有消息平台支持文本转语音 (TTS) 与语音转文本 (STT):
| Provider (提供商) | Quality (质量) | Cost (成本) | API Key (密钥) |
|---|---|---|---|
| Edge TTS (默认) | Good (良好) | Free (免费) | 不需要 |
| ElevenLabs | Excellent (极佳) | Paid (付费) | ELEVENLABS_API_KEY |
| OpenAI TTS | Good (良好) | Paid (付费) | VOICE_TOOLS_OPENAI_KEY |
| MiniMax | Good (良好) | Paid (付费) | MINIMAX_API_KEY |
| NeuTTS | Good (良好) | Free (免费) | 不需要 |
语音转文本 (Speech-to-text) 支持三种提供商:本地 Whisper (免费,在设备上运行)、Groq (极速云端) 以及 OpenAI Whisper API。语音消息转录在 Telegram, Discord, WhatsApp 等各大消息平台上均可用。
3.6 IDE 与编辑器集成 (IDE & Editor Integration)
- IDE 集成 (ACP) — 在兼容 ACP (Agent Context Protocol) 的编辑器(如 VS Code, Zed 和 JetBrains)中使用 Hermes Agent。Hermes 作为一个 ACP 服务器运行,直接在你的编辑器内部渲染聊天消息、工具活动、文件差异 (diffs) 以及终端命令。
3.7 编程式访问 (Programmatic Access)
- API Server — 将 Hermes 暴露为一个兼容 OpenAI 格式的 HTTP 端点。任何支持 OpenAI 格式的前端 —— 如 Open WebUI, LobeChat, LibreChat, NextChat, ChatBox —— 都可以连接并把 Hermes 作为带有完整工具集的底层后端来使用。
3.8 记忆与个性化 (Memory & Personalization)
- 内置记忆 (Built-in Memory) — 通过
MEMORY.md和USER.md文件实现持久化的精选记忆。Agent 维护着一个有界限的个人笔记和用户画像存储,并在不同的会话之间持久生效。 - 记忆提供商 (Memory Providers) — 接入外部的记忆后端以获得更深度的个性化。目前支持 7 种提供商:Honcho (辩证推理), OpenViking (分层检索), Mem0 (云端提取), Hindsight (知识图谱), Holographic (本地 SQLite), RetainDB (混合搜索), 以及 ByteRover (基于 CLI)。
3.9 消息平台 (Messaging Platforms)
Hermes 作为一个网关机器人 (Gateway bot) 可以运行在 15+
种消息平台上,全部通过同一个 gateway 子系统进行配置:
- Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Mattermost, Email, SMS, DingTalk (钉钉), Feishu/Lark (飞书), WeCom (企业微信), WeCom Callback, Weixin (微信个人号), BlueBubbles, QQ Bot, Home Assistant, Webhooks
3.10 智能家居 (Home Automation)
- Home Assistant — 通过四个专用工具
(
ha_list_entities,ha_get_state,ha_list_services,ha_call_service) 控制智能家居设备。配置HASS_TOKEN后,Home Assistant 工具集将自动激活。
3.11 插件系统 (Plugins)
- 插件系统 (Plugin System) —
通过自定义工具、生命周期钩子和 CLI 命令来扩展
Hermes,而无需修改核心代码。插件会自动从
~/.hermes/plugins/、项目本地的.hermes/plugins/以及 pip 安装的入口点中被发现和加载。 - 构建插件 — 提供了详细的分步指南,教你如何创建包含工具、钩子和 CLI 命令的 Hermes 插件。
3.12 训练与评估 (Training & Evaluation)
- 强化学习训练 (RL Training) — 从 Agent 会话中生成轨迹 (trajectory) 数据,用于强化学习和大模型微调。支持具有自定义奖励函数 (reward functions) 的 Atropos 环境。
- 批处理 (Batch Processing) — 并行地跨数百个提示词运行 Agent,生成结构化的 ShareGPT 格式轨迹数据,用于训练数据生成或模型评估。
四、Architecture
4.1 Architecture 架构解析
本页面是 Hermes Agent 内部构件的顶层地图。你可以通过它来了解代码库的全貌,随后再深入具体子系统的文档以了解实现细节。
1. System Overview (系统总览)
1 | |
2. Directory Structure (目录结构)
1 | |
3. Data Flow (数据流向)
CLI Session (终端交互会话) 1
2
3
4
5
6
7用户输入 → HermesCLI.process_input()
→ AIAgent.run_conversation()
→ prompt_builder.build_system_prompt()
→ runtime_provider.resolve_runtime_provider()
→ API 调用 (chat_completions / codex_responses / anthropic_messages)
→ 产生工具调用? → model_tools.handle_function_call() → 循环继续
→ 最终响应 → display 渲染 → 保存至 SessionDB 数据库
Gateway Message (网关消息处理) 1
2
3
4
5
6
7平台事件回调 → Adapter.on_message() → 构造 MessageEvent
→ GatewayRunner._handle_message()
→ 验证用户授权
→ 解析 Session Key
→ 带有历史记录实例化 AIAgent
→ AIAgent.run_conversation()
→ 通过 Adapter 将响应投递给用户
Cron Job (定时任务) 1
2
3
4
5
6调度器触发 (Scheduler tick) → 从 jobs.json 加载到期的任务
→ 实例化全新的 AIAgent (无上下文历史)
→ 将任务绑定的技能注入到上下文中
→ 运行任务 Prompt
→ 将响应投递到目标平台
→ 更新任务状态与 next_run (下次运行时间)
4. Major Subsystems (核心子系统)
- Agent Loop (核心对话循环):同步的编排引擎
(
run_agent.py中的AIAgent)。处理提供商选择、提示词组装、工具执行、重试、降级、回调、上下文压缩和持久化。支持三种 API 模式来对接不同的后端。 - Prompt System
(提示词系统):在对话生命周期内维护和构建 Prompt。
prompt_builder.py:从人格 (SOUL.md)、记忆 (MEMORY.md, USER.md)、技能、项目上下文文件、工具指南等组装出系统提示词。prompt_caching.py:应用 Anthropic 缓存断点以实现前缀缓存 (Prefix Caching)。context_compressor.py:当上下文超出阈值时,对中间的回合进行摘要压缩。
- Provider Resolution
(提供商解析):一个共享的运行时解析器,被 CLI、网关、Cron、ACP
共享。将
(提供商, 模型)映射为(API 模式, API Key, Base URL),处理了 18+ 提供商的别名和凭据池轮询。 - Tool System (工具系统):中央工具注册表
(
tools/registry.py)。包含 19 个工具集中的 47 个注册工具。在导入时利用装饰器完成自我注册。支持终端环境后端的无缝挂载。 - Session Persistence (会话持久化):基于 SQLite 和 FTS5 的对话存储。具有谱系追踪 (追踪跨压缩产生的分支会话)、跨平台隔离和处理写竞争的原子操作机制。
- Messaging Gateway (消息网关):常驻内存的长进程,包含 18 种适配器,提供统一的对话路由、用户授权 (白名单与私信配对)、钩子系统以及 Cron 的后台心跳维护。
- Plugin System (插件系统):从系统目录和项目本地热发现插件,以注入工具或钩子。特殊的插件如“记忆提供商”和“上下文引擎”只能单选激活。
- RL / Environments (强化学习轨迹):用于大模型微调和评估的环境框架,自动生成 ShareGPT 格式的轨迹数据集。
5. Design Principles (设计哲学)
| 原则 (Principle) | 工程实践 (What it means in practice) |
|---|---|
| Prompt stability (提示词稳定性) | 系统提示词 (System Prompt) 在对话中途绝不改变。除非用户显式触发(如
/model),否则禁止发生任何会破坏缓存 (Cache-breaking)
的修改。 |
| Observable execution (可观测的执行) | 每一次工具调用都必须通过回调向用户展示。在 CLI 中体现为 Spinner,在网关中体现为实时的 Chat 状态消息。 |
| Interruptible (可中断性) | API 调用和底层工具执行均可随时被用户的键盘信号打断。 |
| Platform-agnostic core (平台无关的内核) | 唯一的 AIAgent 类同时驱动 CLI、网关、ACP、批处理和 API
服务器。各个平台的差异只存在于入口点,绝不在 Agent 内部。 |
| Loose coupling (松耦合) | 可选子系统(如 MCP、插件、外部记忆提供商)一律采用注册表模式,而不是硬编码依赖。 |
| Profile isolation (环境隔离) | 每个 Profile (hermes -p <name>) 都有独立的
HERMES_HOME、配置、记忆库和 PID。多个 Profile
可完全独立并发运行。 |
6. File Dependency Chain (文件依赖链)
1 | |
这套极其优雅的依赖链意味着:工具的注册是发生在其被 import
时的。所有的工具都不需要在中心文件中写长长的 import
列表,只要工具脚本内有一句
registry.register(),它就会被底层引擎自动发现并热加载!
4.2 Agent Loop Internals (核心对话循环)
核心的编排引擎是位于 run_agent.py 中的
AIAgent 类 —— 大约 10,700
行代码,处理了从系统提示词组装、工具调度分发到提供商灾备切换的所有核心逻辑。
1. Core Responsibilities (核心职责)
AIAgent 的主要职责包括:
- 通过
prompt_builder.py组装有效的系统提示词 (System Prompt) 与工具 Schema。 - 选择正确的提供商 / API 模式 (chat_completions, codex_responses, anthropic_messages)。
- 发起可被用户键盘输入或信号中断 (Interruptible) 的大模型 API 调用。
- 执行工具调用(顺序执行或通过线程池并发执行)。
- 以 OpenAI Message 格式维护整条对话历史记录。
- 处理上下文压缩、重试以及后备模型的自动切换。
- 跟踪主 Agent 与子 Agent (Subagents) 的迭代预算 (Iteration budgets)。
- 在上下文丢失之前将临时记忆持久化刷新到磁盘。
2. Two Entry Points (两大入口点)
1 | |
chat() 只是一个轻量级的包装器,其内部调用了
run_conversation() 并提取了返回字典中的
final_response 字段。
3. API Modes (API 模式)
Hermes 支持三种 API 执行模式,这些模式由“提供商选择”、“显式参数”和“Base URL 探测启发式算法”共同解析得出:
| API mode (模式) | Used for (适用场景) | Client type (客户端类型) |
|---|---|---|
chat_completions |
兼容 OpenAI 的端点 (如 OpenRouter,自定义模型以及大多数提供商) | openai.OpenAI |
codex_responses |
OpenAI Codex / Responses API | 使用 Responses 格式的 openai.OpenAI |
anthropic_messages |
原生的 Anthropic Messages API | 通过适配器转接的 anthropic.Anthropic |
这些模式决定了:消息应如何格式化、工具调用如何结构化、响应如何解析,以及缓存/流式传输
(Streaming) 如何工作。无论是调用前还是调用后,这三种模式在
Hermes 内部都会统一收敛为原生的 OpenAI 风格字典格式
(role / content /
tool_calls)。
模式解析优先级排序: 1. 显式的 api_mode
构造函数传参(最高优先级) 2.
特定提供商的自动探测(例如:anthropic 提供商 →
anthropic_messages) 3. Base URL
启发式探测(例如:api.anthropic.com →
anthropic_messages) 4.
默认回退值:chat_completions
4. Turn Lifecycle (单轮回合生命周期)
Agent 核心循环的每一次迭代均遵循以下序列:
1 | |
Message Format (内部消息格式)
所有的消息在系统内部统一使用 OpenAI 兼容格式表示:
1 | |
深度思考内容 (来自支持 Extended Thinking 的模型,如 R1/o3) 被储存在
assistant_msg["reasoning"] 中,并可通过
reasoning_callback 回调渲染给用户。
Message Alternation Rules (消息交替规则)
Agent Loop 强制执行极其严格的消息角色交替规则(为了迎合诸如 Anthropic 等苛刻的模型):
- 在系统消息 (System) 之后:必须是
User → Assistant → User → Assistant → ... - 在工具调用期间:必须是
Assistant (携带 tool_calls) → Tool → Tool → ... → Assistant - 绝不允许出现两个连续的 Assistant 消息。
- 绝不允许出现两个连续的 User 消息。
- 只有
tool角色允许连续出现(代表并行的工具执行结果)。
如果底层提供商发现历史记录违反上述格式,会直接抛出 400 拒绝请求,因此 Hermes 内部做了严格的规范化。
5. Interruptible API Calls (可中断的 API 调用)
API 请求被包裹在 _api_call_with_interrupt()
闭包中,实际的 HTTP
网络请求会在一个后台线程中执行,同时主线程负责监听中断事件:
1 | |
当被中断时(用户发送了新消息、输入了 /stop 命令或按下了
Ctrl+C): - 后台网络线程会被直接遗弃(丢弃迟来的响应)。 - Agent
可以立刻去处理用户的新指令或优雅关机。 -
绝不会有残缺的响应被塞入当前对话历史中污染上下文。
6. Tool Execution (工具执行逻辑)
Sequential vs Concurrent (顺序执行 vs 并发执行)
当模型返回了工具调用时:
- 单一的工具调用 (Single tool call) → 直接在主线程中顺序执行。
- 多个工具调用 (Multiple tool calls) → 通过
ThreadPoolExecutor线程池并发执行。- 特例:被标记为“交互式”的工具(如
clarify要求用户补充输入)会强制降级为顺序执行。 - 无论完成顺序如何,结果都会被严格地按照原始工具调用 (tool call) 的排序插回历史记录中。
- 特例:被标记为“交互式”的工具(如
Execution Flow (执行链路)
1 | |
Agent-Level Tools (Agent 级特权工具)
有些特殊的工具会在到达 handle_function_call()
之前 就被 run_agent.py 半路拦截:
| Tool (工具名) | Why intercepted (为什么需要拦截处理) |
|---|---|
todo |
需要读取/写入当前 Agent 实例局部的任务状态。 |
memory |
需要向带有字符限制的磁盘记忆文件中刷新内容。 |
session_search |
需要越过沙盒,直接查询当前 Agent 的 SQLite 历史会话数据库。 |
delegate_task |
需要孵化出具备隔离上下文的子 Agent (Subagents) 实例。 |
这些工具直接修改 Agent 的内部状态,并在不经过通用工具注册表的情况下,伪造合成 (synthetic) 的工具结果返回给大模型。
7. Callback Surfaces (回调接口集)
AIAgent 支持特定于平台的回调 (Callbacks),这些回调驱动了
CLI、Gateway 和 ACP 中的实时进度渲染:
| Callback (回调名称) | When fired (何时触发) | Used by (使用者) |
|---|---|---|
tool_progress_callback |
在每个工具执行之前/之后 | CLI 的 Spinner 动画, 网关的进度卡片 |
thinking_callback |
模型开始/停止思考时 | CLI 的 “thinking…” 占位符 |
reasoning_callback |
模型流式返回深度思考内容时 | CLI 的思考框展示, 网关的 |
clarify_callback |
调用了 clarify 工具时 |
CLI 的输入框, 网关的交互式提问弹窗 |
step_callback |
每个完整的 Agent 回合结束时 | 网关的回合步骤追踪, ACP 状态反馈 |
stream_delta_callback |
每一个流式输出的 Token (如开启流式) | CLI 的流式打字机效果 |
tool_gen_callback |
在流式输出中解析出工具名称时 | CLI Spinner 中的工具前瞻预览 |
status_callback |
Agent 内部大状态变化时 (思考中、执行中等) | ACP (IDE) 的状态更新 |
8. Budget and Fallback Behavior (迭代预算与灾备降级)
Iteration Budget (迭代预算)
Agent 通过 IterationBudget 严密监控死循环: - 默认:90
次迭代(可通过 agent.max_turns 配置)。 - 每一个 Agent
拥有独立的预算。子 Agent 有自己的独立预算上限
delegation.max_iterations (默认 50) —— 父子 Agent
的总迭代次数可能会超过父级的限制。 - 达到 100% 阈值时,Agent
会强制熔断,并生成一份截至目前的工作总结。
Fallback Model (灾备模型)
当主模型彻底崩溃(如 429 速率限制,5xx 厂商服务器宕机,401/403
秘钥鉴权失败)时: 1. 检查 config.yaml 中的
fallback_providers 后备列表。 2.
按照顺序依次尝试每一个备用模型。 3.
成功后,带着新的提供商身份无缝继续当前的对话。 4. 遇到 401/403
错误时,系统在降级前会先尝试进行 OAuth 凭据的热刷新。
降级系统对旁路任务(视觉、压缩、网页信息提取、本地搜索)依然适用 ——
可以在 auxiliary.*
配置文件块中为它们各自指定独立的备用链条。
9. Compression and Persistence (压缩与持久化)
When Compression Triggers (压缩何时触发)
- Preflight (飞行前检查) (在发起 API 之前): 如果对话历史长度超出了当前模型总上下文窗口的 50%。
- Gateway auto-compression (网关自动压缩): 如果超出了 85%(这是一个更激进的阈值,运行在两个回合的空隙中)。
What Happens During Compression (压缩期间发生了什么)
- 强制将 Memory 闪存至磁盘(防止数据丢失)。
- 将中间的对话回合送入摘要引擎,压缩为精简的摘要字符串。
- 原封不动地保留最后 N 条消息(由
compression.protect_last_n控制,默认保留最后 20 条)。 - 强绑定工具调用与结果的消息对 (永远不会被拦腰拆分)。
- 生成一个新的 Session 谱系 ID(发生压缩意味着当前会话分裂出了一个“Child 子会话”)。
Session Persistence (会话持久化)
在每个回合结束之后: - 所有的 Message 会被存储进底层的 Session 数据库
(通过 hermes_state.py 写入 SQLite)。 - 记忆的改动会被闪存进
MEMORY.md / USER.md。 -
该会话在未来可以随时通过发送 /resume 命令或
hermes chat --resume 被完美恢复。
10. Key Source Files (核心源码指引)
| File (源码文件) | Purpose (作用) |
|---|---|
run_agent.py |
AIAgent 类的主阵地 — 核心对话循环的全部实现 (~10,700 行)。 |
agent/prompt_builder.py |
负责从记忆、技能、项目规范文件、人格中组装系统大提示词。 |
agent/context_engine.py |
ContextEngine 的抽象基类 — 使得上下文管理可热插拔。 |
agent/context_compressor.py |
默认的上下文引擎 — 实现了有损的摘要压缩算法。 |
agent/prompt_caching.py |
负责计算并注入 Anthropic 缓存断点以及分析缓存命中率。 |
agent/auxiliary_client.py |
辅助的 LLM 客户端,处理旁路小任务 (如视觉识别或长文本摘要)。 |
model_tools.py |
工具 Schema 的集中打包以及 handle_function_call()
中央分发调度。 |
4.3 Prompt Assembly (提示词组装机制)
Hermes 在设计上刻意将提示词分为了两部分: - cached system prompt state (被缓存的静态系统提示词状态) - ephemeral API-call-time additions (随 API 调用动态注入的短暂附加层)
这是整个项目中最核心的架构设计选择之一,因为它直接影响到: - Token 消耗量 - 提示词缓存 (Prompt Caching) 的命中率 - 会话的连续性 - 记忆的正确性
主要涉及的文件: - run_agent.py -
agent/prompt_builder.py -
tools/memory_tool.py
1. Cached system prompt layers (静态系统提示词的分层组装)
被缓存的 System Prompt 大致按照以下 10 层顺序进行组装:
- Agent 人格身份 — 优先加载
HERMES_HOME下的SOUL.md,若不存在则回退至内置的DEFAULT_AGENT_IDENTITY。 - 带有工具感知能力的行为准则。
- Honcho 静态上下文块 (当激活时)。
- 可选的自定义系统消息 (System message)。
- 被冻结的 MEMORY (系统记忆) 快照。
- 被冻结的 USER (用户画像) 快照。
- Skills index (技能索引目录)。
- Context files (项目级上下文文件,如
AGENTS.md,.cursorrules等) — 如果第一步已经加载了 SOUL.md,它不会在这里被重复加载。 - 当前时间戳 / 可选的 Session ID。
- Platform hint (针对不同平台的特定提示,如 CLI 或 Discord)。
当系统设置了 skip_context_files (例如在孵化子 Agent
委派任务时),SOUL.md 不会被加载,取而代之的是硬编码的
DEFAULT_AGENT_IDENTITY。
Concrete example: assembled system prompt (具体示例:组装后的终态)
下面是一个简化版的、包含所有层的终态 System Prompt 示例(注释说明了每个区块的来源):
1 | |
2. How SOUL.md appears in the prompt (SOUL.md 的注入逻辑)
SOUL.md 存放在 ~/.hermes/SOUL.md,充当
Agent 的顶级身份认知 —— 它是 System Prompt 的绝对第一部分。在
prompt_builder.py 中的加载逻辑如下:
1 | |
当 load_soul_md()
返回有效内容时,它会替换掉硬编码的身份认知。随后在调用
build_context_files_prompt() 时,会传入
skip_soul=True 标志,以防止 SOUL.md
出现两次(一次作为身份,一次作为普通上下文文件)。如果文件不存在,将回退到默认的热心
AI 助手人设。
3. How context files are injected (项目上下文文件的注入逻辑)
build_context_files_prompt() 使用了严格的
优先级系统 (Priority system) ——
每次只会加载一种项目级上下文(命中第一个即停止寻找):
1 | |
Context file discovery details (上下文发现细节)
| Priority (优先级) | Files (文件名) | Search scope (搜索范围) | Notes (备注) |
|---|---|---|---|
| 1 | .hermes.md, HERMES.md |
当前目录向上遍历直到 git root | Hermes 原生的项目级配置 |
| 2 | AGENTS.md |
仅限当前目录 | 通用的 Agent 指令规范标准 |
| 3 | CLAUDE.md |
仅限当前目录 | 兼容 Claude Code |
| 4 | .cursorrules, .cursor/rules/*.mdc |
仅限当前目录 | 兼容 Cursor 编辑器 |
所有的上下文文件在加载时都会经过: - 安全扫描 (Security
scanned) — 检查提示词注入攻击(如隐形 unicode
字符,“忽略之前的指令”的话术,窃取凭据的企图)。 - 暴力截断
(Truncated) — 使用 70/20 的头尾比例截断至最高 20,000
个字符,并带有截断标记。 - YAML 前置物剥离 —
.hermes.md 顶部的配置块会被抹除。
4. API-call-time-only layers (仅 API 调用时的短暂附加层)
以下这些内容被刻意排除在了被缓存的 System Prompt 之外:
- 临时的
ephemeral_system_prompt(例如迭代上限警告)。 - Prefill (大模型预填充) 消息。
- 网关 (Gateway) 衍生的会话状态覆盖层。
- 外部 Honcho 记忆引擎在当前回合动态检索并注入到用户输入中的召回片段。
这种严格的物理隔离确保了“稳定的静态前缀”永远不被污染,从而最大化 Anthropic Prompt Caching 的省钱效果。
5. Memory snapshots (记忆快照机制)
本地记忆和用户画像数据是在 Session 启动时以“被冻结的快照 (Frozen snapshots)”的形式注入的。如果 Agent 在中途使用记忆工具写入了新知识,它只会更新磁盘文件,绝对不会去修改当前已经构建好的 System Prompt(除非发起了一个全新的 Session 或触发了强行重建),这也同样是为了保护缓存的命中率。
6. Why prompt assembly is split this way (为什么架构要如此分离?)
整个架构的分离设计是在极致优化以下几个核心指标: - 极致保护提供商侧的 Prompt Caching 命中率(每一分钱都是刀刃)。 - 避免在历史记录中发生不必要的状态突变。 - 保持“记忆”的语义可预测性和稳定。 - 允许外部网关、ACP、CLI 等接入端动态追加上下文,却绝不会“弄脏”底层持续运作的提示词大盘状态。
4.4 Context Compression and Caching (上下文压缩与缓存)
Hermes Agent 使用“双重压缩系统”以及 Anthropic 的“提示词缓存 (Prompt caching)”技术,在超长对话中极其高效地管理上下文窗口。
主要涉及源码:agent/context_engine.py (抽象基类),
agent/context_compressor.py (默认引擎),
agent/prompt_caching.py, gateway/run.py
(会话卫生清理), run_agent.py (搜索
_compress_context)
1. Pluggable Context Engine (可插拔的上下文引擎)
上下文管理建立在 ContextEngine 抽象基类之上。内置的
ContextCompressor
是默认的实现,但插件可以用其他引擎(例如无损上下文管理
LCM)来替换它。
1 | |
引擎负责处理: - 决定何时应触发紧凑化
(should_compress()) - 执行紧凑化 (compress())
- (可选)暴露 Agent 可调用的专属工具 (如 lcm_grep) - 从
API 响应中追踪 Token 消耗
引擎选择由 config.yaml 中的 context.engine
驱动。解析顺序: 1. 检查
plugins/context_engine/<name>/ 目录 2.
检查通用插件系统 (register_context_engine()) 3.
回退到内置的 ContextCompressor
插件引擎永远不会自动激活 — 用户必须显式地将
context.engine 设置为插件名称。默认的
"compressor" 始终使用内置逻辑。
2. Dual Compression System (双重压缩系统)
Hermes 拥有两个独立运行的隔离压缩层:
1 | |
2.1 Gateway Session Hygiene (网关卫生检查, 85% 阈值)
位于 gateway/run.py。这是在 Agent
处理消息前运行的安全网。它能防止在回合之间(比如
Telegram 隔夜积累的消息群)因会话过于臃肿而导致 API 彻底崩溃。 -
阈值: 固定为模型上下文长度的 85% -
触发条件: 只有当 len(history) >= 4
且启用了压缩时 - 目的: 兜底捕捉那些侥幸逃过 Agent
内部压缩器的超级长对话。阈值被刻意定得比 Agent
高,以防止在网关聊天中每个回合都被错误地频繁压缩。
2.2 Agent ContextCompressor (Agent内部压缩器, 50%
阈值) 位于
agent/context_compressor.py。这是主力压缩系统,运行在
Agent 工具循环内部,拥有最准确的 API 上报 Token 计数。
3. Configuration (参数配置)
1 | |
4. Compression Algorithm (压缩算法核心4步)
ContextCompressor.compress()
方法遵循严格的四阶段算法:
Phase 1: Prune Old Tool Results (修剪旧工具结果 ——
极低成本,无需 LLM) 保护区之外的大型工具输出 (>200 字符)
会被直接替换为:[Old tool output cleared to save context space]。这可以在不调用
LLM 的情况下从冗长的文件读取或搜索结果中榨出大量 Token。
Phase 2: Determine Boundaries (划定边界)
1
2
3
4
5
6
7
8┌─────────────────────────────────────────────────────────────┐
│ Message list (消息列表) │
│ │
│ [0..2] ← protect_first_n (系统提示词 + 最初第一轮对话永不删除) │
│ [3..N] ← 中间回合 (middle turns) → 将被送去 LLM 生成摘要 │
│ [N..end] ← 尾部保护区 (由 target_ratio 预算 或 protect_last_n 决定)│
│ │
└─────────────────────────────────────────────────────────────┘
Phase 3: Generate Structured Summary (生成结构化摘要) > [!WARNING] > 负责生成摘要的旁路模型 (Summary model) 的上下文长度必须至少等于主模型的长度。如果它被塞爆了,压缩器会直接静默丢弃中间的所有对话(无摘要),导致“失忆”。
将把中间对话发送给辅助 LLM,按照以下模板强制生成摘要: - Goal (用户最终目标) - Constraints & Preferences (约束与偏好) - Progress (进度:Done 已完成, In Progress 进行中, Blocked 阻塞) - Key Decisions (关键技术决策) - Relevant Files (相关文件) - Next Steps (下一步)
Phase 4: Assemble Compressed Messages (重组上下文) 新的压缩消息列表变为: 1. 头部消息 (首次压缩时会在系统提示词末尾加上说明) 2. 摘要消息 (Role 会根据防同角色连续规则智能挑选) 3. 尾部消息 (原封不动)
如果是连续多次压缩,系统会将“上一次的旧摘要”喂给 LLM,要求它只进行“更新 (update)”而不是重新总结。这让任务卡片能动态从 “In Progress” 流转到 “Done”。
5. Before/After Example (压缩前后震撼对比)
Before (压缩前: 45条消息, ~95K Tokens) 充满了漫长的
terminal: mkdir, write_file: main.py,
terminal: pytest 报错与修补……
After (压缩后: 25条消息, ~45K Tokens) 中间 30
多个回合的枯燥试错全部消失了!变成了一张精准的进度卡: 1
2
3
4
5
6
7
8
9
10
11
12[CONTEXT COMPACTION] Earlier turns were compacted...
## Goal
Set up a FastAPI project with tests and error handling
## Progress
### Done
- Created project structure... 8/10 tests passing
### In Progress
- Fixing 2 failing tests (test_create_user...)
## Relevant Files
- main.py, tests/test_api.py...
## Next Steps
- Fix failing test fixtures
6. Prompt Caching (Anthropic 提示词缓存系统)
通过缓存对话前缀,长对话的输入 Token 成本暴跌 ~75%。使用的是
Anthropic 的 cache_control 断点系统。
Strategy: system_and_3 (系统+尾部3连断点策略) Anthropic 每次请求最多允许打 4 个断点。Hermes 的排布是: - 断点 1:System Prompt (所有回合绝对稳定命中!) - 断点 2:倒数第 3 条非系统消息 - 断点 3:倒数第 2 条非系统消息 - 断点 4:最后 1 条非系统消息 (形成滚动缓存窗口)
缓存系统的默认 TTL 存活时间是 5m (5分钟),可以在
config.yaml 中配置为 1h 适合那些“边喝茶边跟 AI
结对编程”的用户。
4.5 Gateway Internals (消息网关内部机制)
Messaging Gateway 是一个常驻内存的长进程,通过统一的架构将 Hermes 接入 14+ 种外部聊天平台(如 Telegram, Discord, Slack 等)。
1. Key Files (核心目录结构)
gateway/run.py:GatewayRunner— 网关主循环、斜杠命令解析与调度 (~9,000行)gateway/session.py:会话存储持久化与 Session Key 构造gateway/delivery.py:负责将响应投递 (Delivery) 回目标平台gateway/pairing.py:私信 (DM) 配对授权逻辑gateway/platforms/:平台适配器目录 (一平台一文件)
2. Message Flow (核心消息流)
- 平台适配器 (Platform adapter) 收到底层 API
事件,将其标准化为
MessageEvent。 - 基类适配器 (Base adapter) 进行第一道拦截:如果当前
Session 的 Agent 正在运行,则直接将新消息扔进队列。如果是
/stop则放行。 - GatewayRunner 接收事件:
- 组装 Session Key
(
agent:main:{platform}:{chat_type}:{chat_id})。 - 检查用户权限 (Authorization)。
- 解析是否是斜杠命令并分发。
- 如果是一般对话,实例化一个携带历史记录的
AIAgent。
- 组装 Session Key
(
- Agent 疯狂运转,随后将生成的 Response 通过平台适配器投递给用户。
3. Authorization (多级安全鉴权)
网关使用了严格的“五层降级拦截”来防止黑客白嫖你的 API Key: 1.
全局平台放行:例如
TELEGRAM_ALLOW_ALL_USERS=true。 2.
平台白名单:配置文件中配置的特定用户 ID 列表。 3.
DM 动态配对 (Pairing):管理员在群里敲
/pair 生成一个配对码
ABC123,新用户私信机器人输入该码即可动态提权。 4.
全局跨平台放行:GATEWAY_ALLOW_ALL_USERS=true。
5. 默认兜底:直接拒绝 (Deny) 未授权访客。
4. Platform Adapters (18大平台适配器)
所有的适配器都在 gateway/platforms/
下,实现了公共基类的三个方法 (connect,
disconnect, send_message): -
Telegram (长轮询/Webhook) - Discord
(discord.py) - Slack (Socket Mode) - WhatsApp,
Signal, Matrix, Mattermost - Email (IMAP), SMS
(Twilio) - DingTalk (钉钉), Feishu (飞书), WeCom
(企业微信), Weixin (个人微信通过 iLink) - BlueBubbles
(接入苹果 iMessage) - QQ Bot (官方 API v2)
由于某些平台(如 Telegram Bot
API)不允许两个进程同时使用同一个 Token,所有的适配器在
connect() 时都会请求获取跨进程的 Token Locks,防止多
Profile 冲突。
5. Hooks (生命周期钩子)
网关提供了一整套基于目录的热插拔 Hooks: -
gateway:startup, session:start,
agent:step, agent:end, command:*
所有的 Hook 脚本只要放在 ~/.hermes/hooks/
目录下,网关会在启动时自动扫描并注册,实现如“在 Agent
工作完毕后发送一封邮件通知”这样的能力。
4.6 Session Storage (SQLite 会话存储系统)
Hermes Agent 使用单一的 SQLite 数据库
(~/.hermes/state.db) 来持久化跨 CLI
和网关会话的所有消息历史、Token 开销和模型配置。这彻底取代了早期粗糙的
JSONL 文件流。
主要代码:hermes_state.py
1. Architecture Overview (架构总览)
1 | |
关键设计决策: - WAL
模式:允许网关在应对并发聊天时,实现“多读一写”不锁死。 -
FTS5 虚拟表:支持对本地百万字的 Agent
生成的代码和对话进行毫秒级全文检索。 - Session lineage
(会话谱系):通过
parent_session_id,将因上下文压缩而断裂分裂出的新会话像 Git
树一样连接起来。
2. Write Contention Handling (史诗级的写入竞争处理)
由于可能有网关后台、CLI 前台、Cron 任务、甚至是 Git Worktree
沙盒等几十个进程同时想要写入同一个
state.db。SessionDB
类做出了教科书级别的锁争用优化: - 缩短 SQLite
的死锁超时 从原生的 30 秒剧烈缩减到 1 秒。 - 带有
Jitter 的应用层重试:在 20ms 到 150ms 之间随机退避,最高重试 15
次。 - BEGIN IMMEDIATE
强事务:在进入事务的第一秒就立刻暴露锁竞争,而不是等到最后
commit 时才报错。 - 周期性 WAL 检查点
(Checkpoint):每成功写入 50 次,就静默触发一次 PASSIVE
检查点。
这完美地避开了 SQLite 臭名昭著的“护航效应 (Convoy effect)”,让几十个智能体并发不卡顿。
3. Full-Text Search (支持黑魔法的 FTS5 检索)
Hermes 提供了一个极其强大的 db.search_messages()
接口。
| FTS5 语法 | 示例 | 意义 |
|---|---|---|
| 关键词 | docker deployment |
同时包含两词 (隐式 AND) |
| 精确短语 | "exact phrase" |
精确匹配完整短语 |
| 布尔 OR | docker OR kubernetes |
包含其一即可 |
| 布尔 NOT | python NOT java |
排除干扰词 |
| 前缀匹配 | deploy* |
匹配 deploy, deployment 等 |
底层做了极端的自动
Sanitization:剥离没闭合的引号、将带连字符的单词(如
chat-send)用引号保护、自动清理尾部的残缺布尔符,防止搜素引擎直接语法报错崩溃。
4. Session Lineage & Export (会话谱系与导出)
你可以通过 SQL 中的 WITH RECURSIVE CTE
递归查询语句,顺藤摸瓜找出一个会话的全部“祖宗”与“子孙”。系统也提供了原生的
Python 接口 db.export_session() 和清理陈旧僵尸会话的
db.prune_sessions(older_than_days=90) 方法。
4.7 Provider Runtime Resolution (大模型提供商运行时解析)
由于 Hermes 面向 CLI、Gateway、Cron 和旁路工具提供统一的服务,它实现了一个底层的共享运行时解析器 (Shared runtime resolver),决定每一次 LLM 调用到底走哪条高速公路。
核心逻辑位于:hermes_cli/runtime_provider.py 和
hermes_cli/auth.py。
1. Resolution precedence (解析优先级)
提供商解析遵循严格的层叠覆盖原则: 1. CLI 或参数显式指定
(--provider, --model) 2.
config.yaml 中保存的历史模型/提供商状态 3. 环境变量的覆盖
(OPENAI_API_KEY, 等等) 4. 厂商特有的默认规则兜底
Hermes 把保存的 config.yaml
视为真正的“单点事实”。这防止了用户昨天在 hermes model
里切成了 Anthropic,结果今天开了一个配置有 OPENAI_API_KEY
的破 Shell 就导致模型静默跳回 GPT-4 的惨剧。
2. Native Anthropic path (原生的 Anthropic 链路)
现在的 Anthropic 模型不再只是通过 OpenRouter 的兼容接口访问了!
当解析器选中 anthropic 时,引擎会彻底切换形态: -
api_mode = anthropic_messages - 直接连线原生 Anthropic
Messages API - 通过 agent/anthropic_adapter.py
进行数据结构转换
它甚至接入了 Claude Code (也就是著名的 mcp-cli) 的底层刷新凭据链!如果存在 Claude Code 的 OAuth 刷新 Token,它会比写死的环境变量拥有更高优先级,并在触发 401 Unauthorized 前自动静默刷新凭证,永远不断联。
3. OpenAI-compatible and Isolation (自定义网关的绝密隔离)
当环境中同时存在
OPENROUTER_API_KEY、AI_GATEWAY_API_KEY 和
OPENAI_API_KEY 时,Hermes 绝不会“乱甩秘钥导致泄露”。
OPENROUTER_API_KEY绝对且只会被发送到openrouter.aiAI_GATEWAY_API_KEY绝对只送往 Vercel 的ai-gateway.vercel.shOPENAI_API_KEY作为 fallback 发送给所有自定义的基础 URL。
4. Fallback models (无缝灾备降级机制)
当你的主模型(比如 OpenRouter 的 4.5 Sonnet)因官方宕机而爆出
5xx,或者你的余额不足爆出 402 时,Hermes
绝不会让任务中断:
- 触发点:当遇到非重试的致命错误(如 401 鉴权失效)或
429触碰上限时。 - 激活降级 (Activation):它会立刻读取
config.yaml中的fallback_model。 - 无缝热拔插:在内存中瞬间替换掉主循环里的
self.provider,self.base_url, 和底层的 HTTP Client。 - 再启程:带着最新的 Token 和新的模型,继续刚才未尽的 Tool 调用循环!
而且这一切在 Gateway、CLI 等所有入口点全面生效!旁路小模型(如视觉摘要器)也拥有这套独立且完整的灾备降级逻辑。