架构
本文介绍 Hermes Agent 的内部架构,帮助开发者理解系统的工作原理和各模块之间的关系。
整体概览
Hermes 由三个主要入口点、一个核心 Agent 引擎和多个支撑子系统组成:
┌─────────────────────────────────────────────────────────┐
│ 入口点层 │
│ ┌───────────┐ ┌──────────────────┐ ┌──────────────┐ │
│ │ CLI │ │ Gateway │ │ ACP 适配器 │ │
│ │ (cli.py) │ │ (gateway/run.py) │ │ │ │
│ └─────┬─────┘ └────────┬─────────┘ └──────┬───────┘ │
└────────┼────────────────┼────────────────────┼──────────┘
│ │ │
└────────────────┼────────────────────┘
│
┌─────────────────────────▼─────────────────────────────┐
│ 核心 Agent 引擎 │
│ AIAgent (run_agent.py) │
│ ┌────────────────┐ ┌──────────────────┐ │
│ │ Prompt Builder│ │ Provider Resolution│ │
│ └────────────────┘ └──────────────────┘ │
│ ┌────────────────────────────────────────┐ │
│ │ Tool Dispatch │ │
│ └────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────┘
│ │ │
┌────────▼────────┐ ┌────▼──────┐ ┌───────▼──────────┐
│ Tool Registry │ │ Config │ │ Memory System │
│ (47 tools, │ │ System │ │ (长期记忆+画像) │
│ 37 toolsets) │ │ │ │ │
└─────────────────┘ └───────────┘ └──────────────────┘入口点
1. CLI(cli.py)
命令行交互入口,负责:
- 解析命令行参数和子命令
- 初始化 Rich 终端界面(状态栏、格式化输出)
- 管理快捷键绑定(keybindings)
- 将用户输入传递给
AIAgent - 流式展示 Agent 的输出和工具调用过程
CLI 使用 Rich 库实现彩色输出、进度条、代码语法高亮等界面效果。
2. 网关(gateway/run.py)
消息平台接入入口,负责:
- 监听来自各平台(Telegram、Discord、Slack 等)的消息
- 将平台消息格式标准化后传给
AIAgent - 将 Agent 响应转换为平台特定格式发送回去
- 管理多用户会话隔离
- 系统服务生命周期管理
每个平台有对应的适配器模块(gateway/adapters/telegram.py 等),实现平台特定的 API 调用逻辑。
3. ACP 适配器
ACP(Agent Communication Protocol)适配器,用于多 Agent 协作场景:
- 将 Hermes 暴露为标准 ACP 服务
- 接受来自其他 Agent 或编排系统的调用
- 支持 Agent 间工具共享和能力委托
核心 Agent 引擎
AIAgent(run_agent.py)是 Hermes 的核心,实现完整的 ReAct(推理-行动)循环:
用户输入
│
▼
┌─────────────────┐
│ Prompt Builder │ ← 注入系统提示、记忆、工具描述
└────────┬────────┘
│
▼
┌─────────────────┐
│ Provider Resolution│ ← 选择模型和提供商,处理 fallback
└────────┬────────┘
│
▼
┌─────────────────┐
│ LLM API 调用 │ ← 流式或非流式请求
└────────┬────────┘
│
┌────▼────┐
│有工具调用?│
└────┬────┘
是 │ │ 否
▼ ▼
┌──────────┐ 返回最终
│Tool Dispatch│ 响应给用户
└──────────┘
│
▼
执行工具
│
▼
回到循环顶部Prompt Builder
负责构建每次 LLM 请求的完整提示词,按优先级注入:
- 系统提示词(人格配置)
- 用户记忆和画像(来自记忆系统)
- 当前工具列表描述
- 对话历史(经过压缩处理)
- 用户当前输入
Provider Resolution
模型和提供商选择逻辑:
- 读取配置中的默认模型和提供商
- 支持按会话临时切换(
-m参数) - 处理提供商不可用时的 fallback 逻辑
- 管理 API 密钥轮换
Tool Dispatch
工具调用分发器:
- 接收 LLM 返回的工具调用请求(tool use)
- 查询工具注册表定位对应处理函数
- 根据审批配置决定是否需要用户确认
- 执行工具并将结果返回给 LLM
- 处理工具执行超时和错误
工具注册表
工具注册表(tools/registry.py)采用自注册模式,管理 Hermes 的所有工具:
- 47 个内置工具,分属 37 个工具集(toolsets)
- 每个工具文件通过装饰器自动注册到全局注册表
- 工具集按功能分组(文件操作、网络请求、代码执行、系统管理等)
- MCP 服务器的工具动态注册,与内置工具统一管理
工具集分类
| 工具集类别 | 包含工具示例 |
|---|---|
| 文件系统 | 读文件、写文件、列目录、搜索文件 |
| Shell 执行 | 运行命令、脚本执行 |
| 网络 | HTTP 请求、网页抓取、下载文件 |
| 代码分析 | 语法检查、代码搜索 |
| 系统信息 | 进程管理、环境变量 |
| 记忆管理 | 保存记忆、查询记忆 |
| 媒体处理 | 图片分析、文件转换 |
| 日历/时间 | 获取时间、提醒设置 |
CLI 编排层
CLI 层负责将 Agent 执行过程可视化呈现给用户:
- Rich 格式化:Markdown 渲染、代码语法高亮、表格显示
- 状态栏:实时显示当前模型、token 用量、执行状态
- 工具调用预览:展示每个工具调用的输入/输出摘要
- 快捷键处理:
Ctrl+C(中断)、Tab(补全)等 - 流式输出:LLM 生成内容实时逐字显示
配置系统
Hermes 采用双层配置:
~/.hermes/
├── config.yaml ← 功能配置(模型、显示、记忆等)
├── .env ← 敏感信息(API 密钥、Token)
├── sessions/ ← 会话历史数据库
├── memory/ ← 长期记忆存储
└── logs/ ← 运行日志- YAML 配置(
config.yaml):结构化功能配置,支持热重载 - 环境变量(
.env):API 密钥等敏感信息,不纳入版本控制 - 迁移机制:版本升级时通过
hermes config migrate自动迁移旧格式
数据流
CLI 数据流
用户键盘输入
→ CLI 输入处理(快捷键、多行、图片粘贴)
→ AIAgent.run()
→ Prompt 构建(注入记忆、工具列表)
→ LLM API 请求(流式)
→ 流式输出渲染(Rich)
→ 工具调用处理(审批 → 执行 → 结果注入)
→ 继续 LLM 生成直到完成
→ 会话保存 + 记忆提取网关数据流
平台消息(Telegram/Discord/...)
→ 平台适配器接收
→ 用户身份验证(授权检查)
→ 会话上下文加载(用户隔离)
→ AIAgent.run()(同 CLI 流程)
→ 响应格式化(适配平台 API 限制)
→ 平台 API 发送回复
→ 会话保存Cron 数据流
定时任务触发(hermes cron tick)
→ 加载任务配置(提示词、技能、模型)
→ 创建无头 Agent 会话
→ AIAgent.run()(无交互式 UI)
→ 结果保存到会话历史
→ 可选:通过网关平台投递结果设计原则
提示词稳定性
Prompt Builder 设计为确定性的:相同输入(用户消息 + 记忆 + 工具列表)始终产生相同提示词结构。这使得行为可预测、可测试,便于调试。
可观测执行
Agent 的每个步骤(工具调用、LLM 请求、结果)都有完整日志,存储在 ~/.hermes/logs/。CLI 状态栏实时显示执行状态,用户随时了解 Agent 在做什么。
平台无关核心
AIAgent 核心不依赖任何特定平台(CLI、Telegram、Discord 等)。平台差异完全封装在入口点层和适配器中,使得核心逻辑可被任意方式调用。