Hermes Agent 深度解读
Hermes Agent 深度解读
一、项目概述
Hermes Agent 是由 Nous Research 开发的一个全功能 AI Agent 框架,支持 CLI、Telegram、Discord、Slack、WhatsApp、Signal、Home Assistant 等多个平台。它不仅仅是一个聊天机器人,而是一个能实际执行任务的智能代理——可以写代码、操作文件、运行命令、浏览网页、管理定时任务、调用外部服务等。
项目核心代码约 5 万行 Python,包含约 3000 个测试,工具数量超过 40 个。
二、核心架构分层
┌─────────────────────────────────────────────────────┐
│ 用户交互层 │
│ cli.py (CLI TUI) │ gateway/run.py (多平台网关) │
│ acp_adapter/ (VSCode/Zed 插件) │ cron/ (定时) │
├─────────────────────────────────────────────────────┤
│ Agent 核心层 │
│ run_agent.py → AIAgent 类(对话循环 + 工具调度) │
│ agent/ 子包(prompt构建、上下文压缩、缓存、显示等) │
├─────────────────────────────────────────────────────┤
│ 工具编排层 │
│ model_tools.py(薄编排层)│ toolsets.py(工具集定义) │
│ tools/registry.py(中央注册表) │
├─────────────────────────────────────────────────────┤
│ 工具实现层 │
│ tools/*.py 每个文件一个工具,自动注册 │
│ tools/environments/ 终端后端(local/docker/ssh/modal)│
├─────────────────────────────────────────────────────┤
│ 持久化层 │
│ hermes_state.py(SQLite + FTS5 全文搜索) │
│ memory_tool / skills / config.yaml │
└─────────────────────────────────────────────────────┘
三、每个文件/模块的详细作用
3.1 核心文件
run_agent.py(~11600 行,项目最大的文件)
AIAgent 类的完整实现,是整个项目的引擎。关键职责:
- 初始化阶段:解析配置、建立 LLM 客户端(支持 OpenRouter、Anthropic、OpenAI、AWS Bedrock 等多种 provider)、加载工具集、初始化上下文压缩器、内存系统、checkpoint 管理器
- 对话循环:核心 loop——发送消息给 LLM → 如果有 tool_calls 则执行工具 → 把结果返回给 LLM → 重复直到 LLM 给出纯文本回复或达到最大迭代次数
- 多 API 模式:自动检测并适配
chat_completions(OpenAI 兼容)、anthropic_messages(原生 Anthropic SDK)、codex_responses(OpenAI Responses API)、bedrock_converse(AWS Bedrock) - Provider 回退链:主 provider 遇到限流/过载时自动切换到备用 provider
- Prompt 缓存:对 Claude 模型自动启用 Anthropic 的 prompt caching(system_and_3 策略),多轮对话输入成本降低约 75%
- 上下文压缩:当接近模型上下文窗口限制时,自动压缩中间对话
- 安全包装:SafeWriter 包装 stdout/stderr 防止管道断裂导致崩溃
- 预算控制:IterationBudget 控制最大工具调用次数(默认 90)
toolsets.py(~700 行)
工具集定义系统。核心是 _HERMES_CORE_TOOLS 列表(定义所有核心工具)和 TOOLSETS 字典(将工具分组为 web、terminal、file、browser、skills 等类别)。支持工具集的嵌套组合。
model_tools.py(~560 行)
薄编排层,位于 registry 和 run_agent 之间。负责:
- 导入所有工具模块触发自动注册(
discover_builtin_tools()) - 发现 MCP 工具和插件工具
- 提供
get_tool_definitions()按 toolset 过滤 - 提供
handle_function_call()分派工具调用 - 管理异步桥接(
_run_async)——解决 asyncio 事件生命周期问题
cli.py(~10200 行)
CLI 交互式终端界面。使用 Rich + prompt_toolkit 构建精美的 TUI:
- 动态输入补全(slash 命令)
- KawaiiSpinner 动画(API 调用时显示)
- Skin 引擎(主题定制)
- 管理所有 slash 命令(/model、/skills、/tools、/usage 等)
- TUI 布局:固定输入区 + 滚动输出区
hermes_state.py(~1200 行)
SQLite 会话存储,替代了旧的 JSONL 文件方案:
- WAL 模式支持并发读写
- FTS5 虚拟表实现全文搜索
- 压缩触发会话分裂(parent_session_id 链)
- 随机抖动重试解决写竞争问题
3.2 agent/ 子包(Agent 内部组件)
| 文件 | 作用 |
|---|---|
prompt_builder.py |
系统提示词组装——Agent 身份、平台提示、技能索引、上下文文件注入、提示词注入检测 |
context_compressor.py |
自动上下文压缩——当对话接近窗口限制时,用便宜的辅助模型总结中间轮次,保护头部和尾部 |
prompt_caching.py |
Anthropic prompt caching 实现——system_and_3 策略(系统提示词 + 最近 3 条消息),4 个 cache_control 断点 |
auxiliary_client.py |
辅助 LLM 客户端——用于视觉分析、网页提取、审批判断等辅助任务,独立于主模型 |
model_metadata.py |
模型元数据管理——上下文长度、token 估算、价格信息,带 1 小时缓存 |
display.py |
KawaiiSpinner 动画、工具预览格式化、工具 emoji |
skill_commands.py |
技能斜杠命令(CLI/gateway 共享) |
trajectory.py |
对话轨迹保存(JSONL 格式) |
memory_manager.py |
内存提供者插件系统(支持 Honcho 等外部内存后端) |
anthropic_adapter.py |
Anthropic 原生 SDK 适配层 |
usage_pricing.py |
用量和费用估算 |
model_normalize.py |
模型名称归一化 |
retry_utils.py |
带抖动的退避重试 |
error_classifier.py |
API 错误分类(限流、过载、连接失败等) |
redact.py |
敏感信息脱敏 |
checkpoint_manager.py |
文件系统 checkpoint(快照/回滚) |
3.3 tools/ 目录(工具实现)
每个工具文件通过调用 registry.register() 在模块导入时自动注册:
| 文件 | 工具名 | 作用 |
|---|---|---|
registry.py |
- | 中央注册表——ToolEntry + ToolRegistry,线程安全的工具元数据存储,支持 AST 扫描自动发现 |
file_tools.py |
read_file, write_file, patch, search_files | 文件读写、模糊匹配替换、内容搜索。包含敏感路径保护、设备路径黑名单、重复读取检测 |
terminal_tool.py |
terminal | 命令执行,支持多种后端(local/docker/ssh/modal/daytona/singularity) |
process.py |
process | 后台进程管理(启动/轮询/写入/关闭) |
web_tools.py |
web_search, web_extract | 网页搜索和内容提取(Parallel + Firecrawl) |
browser_tool.py |
browser_*(12 个工具) | 浏览器自动化(Browserbase/Firecrawl/browser-use 多 provider) |
code_execution_tool.py |
execute_code | 程序化工具调用(PTC)——让 LLM 写 Python 脚本批量调用工具,多步操作合并为一轮推理 |
delegate_tool.py |
delegate_task | 子代理委派——创建隔离上下文的子 Agent,支持最多 3 个并行子代理 |
mcp_tool.py |
MCP 工具(动态) | MCP(Model Context Protocol)客户端——连接外部 MCP 服务器,发现其工具并注册 |
mcp_oauth.py |
- | MCP OAuth 认证 |
memory_tool.py |
memory | 持久化内存(MEMORY.md + USER.md) |
todo_tool.py |
todo | 任务列表管理 |
session_search_tool.py |
session_search | 历史会话搜索(基于 FTS5) |
clarify_tool.py |
clarify | 向用户提问(多选/开放) |
cronjob_tools.py |
cronjob | 定时任务管理 |
skills_hub.py |
skills_list, skill_view, skill_manage | 技能系统——创建/查看/管理技能文档 |
tts_tool.py |
text_to_speech | 文本转语音(Edge TTS / ElevenLabs / OpenAI / xAI) |
vision_tools.py |
vision_analyze, image_generate | 图像分析和生成 |
skills_sync.py |
- | 技能同步 |
budget_config.py |
- | 预算配置 |
fuzzy_match.py |
- | 模糊匹配(用于 patch 工具的字符串匹配) |
path_security.py |
- | 路径安全检查 |
url_safety.py |
- | URL 安全检查 |
tirith_security.py |
- | 安全策略检查 |
osv_check.py |
- | 开源漏洞检查 |
interrupt.py |
- | 中断机制 |
approval.py |
- | 危险命令检测 |
credential_files.py |
- | 凭证文件管理 |
debug_helpers.py |
- | 调试工具 |
ansi_strip.py |
- | ANSI 转义码剥离 |
openrouter_client.py |
- | OpenRouter 客户端封装 |
transcription_tools.py |
- | 语音转录 |
tools/voice_mode.py |
- | 语音模式 |
tools/mixture_of_agents_tool.py |
mixture_of_agents | 多模型集成推理 |
3.4 tools/environments/ 目录(终端后端)
| 文件 | 作用 |
|---|---|
base.py |
环境基类(抽象接口) |
local.py |
本地终端环境 |
docker.py |
Docker 容器后端 |
ssh.py |
SSH 远程后端 |
modal.py |
Modal 云 GPU 后端 |
managed_modal.py |
托管 Modal 环境 |
daytona.py |
Daytona 沙箱后端 |
singularity.py |
Singularity 容器后端 |
file_sync.py |
文件同步(本地与远程之间) |
modal_utils.py |
Modal 工具函数 |
3.5 gateway/ 目录(消息平台网关)
| 文件 | 作用 |
|---|---|
run.py |
网关主循环、斜杠命令处理、消息分发 |
session.py |
会话存储——对话持久化 |
platforms/ |
各平台适配器(Telegram、Discord、Slack、WhatsApp、Home Assistant、Signal、QQBot) |
3.6 其他重要目录
| 目录/文件 | 作用 |
|---|---|
hermes_cli/ |
CLI 子命令和设置向导(main.py, config.py, commands.py, setup.py, skin_engine.py 等) |
acp_adapter/ |
ACP 服务器(VS Code / Zed / JetBrains 编辑器集成) |
cron/ |
调度器(jobs.py, scheduler.py) |
environments/ |
RL 训练环境(Atropos) |
plugins/ |
插件系统(内存提供者、上下文引擎等) |
packaging/homebrew/ |
Homebrew 打包 |
batch_runner.py |
并行批处理 |
hermes_constants.py |
全局常量(路径、URL、版本等) |
四、为什么速度这么快
Hermes Agent 的速度优势来自多个层面的优化,不是单一技巧的结果:
4.1 程序化工具调用(PTC)—— execute_code 工具
这是最大的速度优化。传统的 AI Agent 每执行一步操作都需要:
LLM 推理 → 工具调用 → 等待结果 → LLM 推理 → 下一个工具调用 → ...
每一步都是一次完整的 API 往返,延迟通常在 1-5 秒之间。
Hermes Agent 的 execute_code 工具让 LLM 写一个 Python 脚本,脚本中直接调用工具(通过 Unix Domain Socket RPC 或文件 RPC):
# LLM 一次性写出:
results = search_files("def handle_")
for match in results['matches']:
content = read_file(match['path'])
patch(match['path'], "old", "new")
这个脚本在子进程中运行,7 个工具(web_search, web_extract, read_file, write_file, search_files, patch, terminal)可以顺序执行而不需要回到 LLM。中间结果不进入上下文窗口。
效果:原本需要 6-10 轮 API 调用的任务,现在只需 1-2 轮。
4.2 并行工具调用
当 LLM 返回多个独立的工具调用时(如同时读取 3 个不同文件),Hermes Agent 会并行执行它们:
_PARALLEL_SAFE_TOOLS定义了可安全并发的只读工具(read_file, search_files, web_search, web_extract 等)_PATH_SCOPED_TOOLS对文件工具做路径级冲突检测——不同路径可以并行_NEVER_PARALLEL_TOOLS定义绝对不能并发的工具(如 clarify)- 最多 8 个工作线程并发执行
4.3 Anthropic Prompt Caching
对 Claude 模型启用 system_and_3 缓存策略:
- 系统提示词(不变的部分)被缓存
- 最近 3 条非系统消息被缓存
- 多轮对话中,大部分输入 token 命中缓存
- 输入成本降低约 75%,同时缓存命中的 token 处理速度远快于全新 token
4.4 自动上下文压缩(Context Compressor)
当对话接近模型上下文窗口限制时:
- 先做廉价修剪:用规则替换旧的工具输出为简短摘要(无需 LLM 调用)
- 保护头部:系统提示词和前几条对话保留
- 保护尾部:最近的 ~20K token 保留(预算驱动)
- 用辅助模型总结中间部分:用便宜的快速模型做摘要
- 迭代更新:后续压缩时保留之前摘要中的待解决问题
这避免了频繁遇到上下文溢出,也避免了每次都重传大量历史。
4.5 子代理委派(Delegate Task)
对于独立子任务,可以创建隔离的子 Agent:
- 子 Agent 有独立的对话上下文(不携带父 Agent 的历史)
- 独立的终端会话和工具集
- 最多 3 个子代理并行执行
- 父 Agent 的上下文只看到委派调用和最终摘要
这避免了长上下文的 token 浪费,也实现了真正的并行工作。
4.6 辅助模型分离
视觉分析、网页提取、审批判断等辅助任务使用独立的辅助模型(通常是更便宜的模型),不占用主模型的 token 预算和推理时间。
4.7 高效的异步桥接
model_tools.py 中的 _run_async 解决了 Python 异步事件循环的生命周期问题:
- 主线程使用持久的事件循环(而非每次都
asyncio.run()创建-销毁) - 工作线程使用线程本地的持久循环
- 避免 “Event loop is closed” 错误和缓存客户端的重复初始化
4.8 智能的 Provider 路由
通过 OpenRouter 或直接连接多个 provider:
- 自动选择最快/最便宜的 provider
- 限流时自动回退到备用 provider
- 不同任务使用不同模型(主任务用强模型,辅助任务用快模型)
4.9 SQLite 状态存储 + FTS5
会话数据存储在 SQLite 中而非 JSONL 文件:
- WAL 模式支持并发
- FTS5 全文索引实现毫秒级搜索
- 随机抖动重试避免写竞争
五、为什么效果好
5.1 精心设计的系统提示词
- Agent 身份:明确的角色定义和行为准则
- 工具使用强制执行:对特定模型家族(GPT、Gemini、Gemma、Grok)注入额外的工具使用纪律指导
- 平台适配提示:根据运行平台(CLI/Telegram/Discord)注入不同的格式化指导
- 上下文文件注入:自动发现并注入
.hermes.md、AGENTS.md、SOUL.md、.cursorrules等项目级配置 - 提示词注入防护:扫描上下文文件中的注入模式(“ignore previous instructions” 等)
5.2 工具设计哲学
- 一个工具一个文件:职责清晰,易于维护
- 自动注册:工具通过
registry.register()自注册,不需要手动维护列表 - 丰富的描述:每个工具的 schema 包含详细的描述和参数说明,帮助 LLM 正确使用
- 错误恢复:工具调用失败时有清晰的错误信息反馈给 LLM
- 安全保护:敏感路径保护、设备路径黑名单、危险命令检测
5.3 技能系统(Skills)
Skills 是可重用的专业知识和工作流文档:
- 每个 skill 是一个包含 YAML frontmatter + Markdown 的目录
- 支持引用文件、模板、脚本
- Agent 被指导在完成复杂任务后自动创建 skill
- 使用 skill 时发现过时或不完整,立即 patch 更新
- 目前有 50+ 预置技能(GitHub、MCP、ML 模型、创意工具等)
5.4 持久化记忆
- MEMORY.md 存储项目级记忆(环境事实、工具怪癖、工作流约定)
- USER.md 存储用户级记忆(偏好、角色、沟通风格)
- 每次对话自动注入相关记忆
- 支持外部内存提供者插件(如 Honcho)
5.5 多平台一致性
CLI、Telegram、Discord、Slack、WhatsApp、Signal、Home Assistant 等平台共享同一套 Agent 核心,确保跨平台体验一致。
5.6 MCP 集成
通过 MCP(Model Context Protocol)可以连接任意外部 MCP 服务器,发现并使用其工具。这使得 Hermes Agent 的能力可以无限扩展。
六、数据流示例:用户输入 “帮我重构这个项目”
1. cli.py 接收用户输入 → 创建 AIAgent 实例
2. AIAgent.__init__():
- 解析 config.yaml,确定模型/provider
- 初始化 OpenAI/Anthropic 客户端
- 加载工具定义(过滤启用的 toolset)
- 构建系统提示词(身份 + 记忆 + 技能 + 上下文文件)
- 初始化上下文压缩器、SQLite 存储、todo 存储
3. run_conversation() 主循环:
a. 发送 [系统提示词 + 用户消息] 给 LLM
b. LLM 返回 tool_calls: [search_files("TODO"), read_file("src/main.py")]
c. 并行执行两个工具(因为都是只读文件操作)
d. 把结果附加到消息列表
e. 再次发送给 LLM
f. LLM 返回 tool_calls: [execute_code(...)] — 一个 Python 脚本
g. 在子进程中运行脚本,脚本内部调用 read_file/patch/terminal
h. 脚本输出作为工具结果返回
i. LLM 继续推理...
j. 直到 LLM 返回纯文本(最终回复)
4. 回复展示给用户,会话保存到 SQLite
七、关键设计理念总结
- 模块化:每个关注点独立模块,通过注册表解耦
- 自动发现:工具自注册、MCP 动态发现、插件系统
- 多层优化:PTC 减少 API 往返、并行执行、prompt 缓存、上下文压缩
- 安全第一:路径保护、注入检测、凭证脱敏、危险命令识别
- 可扩展:plugin 系统、MCP 集成、memory provider、context engine 插件
- 生产就绪:~3000 测试、WAL 并发、随机抖动重试、SafeWriter 防崩溃
- 多模型支持:OpenRouter、Anthropic、OpenAI、Bedrock、Ollama、Copilot 等
- 多平台:CLI + 7 个消息平台 + ACP 编辑器集成
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)