Hermes Agent 项目学习指南
Hermes Agent 是由 Nous Research 开发的自我进化 AI 智能体——它能从经验中创建技能(Skills)、在使用中自我改进,并可运行在终端、Telegram、Discord、Slack 等多种平台上。
Hermes Agent 项目学习指南
面向从未接触过该项目的开发者,帮助你快速上手并深入理解 Hermes Agent。
1. 项目简介
一句话说明
Hermes Agent 是由 Nous Research 开发的自我进化 AI 智能体——它能从经验中创建技能(Skills)、在使用中自我改进,并可运行在终端、Telegram、Discord、Slack 等多种平台上。
核心功能列表
- 交互式终端 CLI:全功能 TUI,支持多行编辑、斜杠命令自动补全、流式工具输出
- 多平台消息网关:Telegram、Discord、Slack、WhatsApp、Signal、钉钉、飞书等,单进程统一管理
- 闭环学习系统:自动创建技能、FTS5 全文搜索历史会话、LLM 摘要跨会话召回、Honcho 用户建模
- 40+ 内置工具:终端执行、文件操作、网页搜索/抓取、浏览器自动化、代码执行、图像生成、TTS 等
- MCP 协议支持:通过 Model Context Protocol 接入任意外部工具服务器
- 多终端后端:本地、Docker、SSH、Modal(Serverless)、Daytona、Singularity 六种执行环境
- 定时任务(Cron):自然语言描述的定时自动化,结果推送到任意平台
- 子智能体委托:并行派生隔离子 Agent,支持 Python RPC 调用工具
- RL 研究支持:批量轨迹生成、Atropos RL 环境、轨迹压缩用于训练下一代工具调用模型
- 多 Profile 隔离:多实例完全隔离,各自独立配置、记忆、技能
技术栈总览
| 类别 | 技术 / 依赖 | 版本 |
|---|---|---|
| 语言 | Python | ≥ 3.11 |
| LLM SDK | openai(兼容 OpenAI 格式) | ≥ 2.21.0 |
| LLM SDK | anthropic(原生 Anthropic) | ≥ 0.39.0 |
| CLI 渲染 | rich(终端富文本) | ≥ 14.3.3 |
| CLI 交互 | prompt_toolkit(输入框/自动补全) | ≥ 3.0.52 |
| 配置 | pyyaml、python-dotenv | ≥ 6.0.2 / ≥ 1.2.1 |
| HTTP | httpx、requests | ≥ 0.28.1 / ≥ 2.33.0 |
| 数据验证 | pydantic | ≥ 2.12.5 |
| 重试 | tenacity | ≥ 9.1.4 |
| 模板 | jinja2 | ≥ 3.1.5 |
| 数据库 | SQLite(内置,FTS5 扩展) | stdlib |
| 消息平台 | python-telegram-bot、discord.py、slack-bolt | ≥ 22.6 / ≥ 2.7.1 / ≥ 1.18.0 |
| MCP | mcp | ≥ 1.2.0 |
| 定时任务 | croniter | ≥ 6.0.0 |
| 网页工具 | firecrawl-py、parallel-web、exa-py | ≥ 4.16.0 / ≥ 0.4.2 / ≥ 2.9.0 |
| TTS | edge-tts(免费)、elevenlabs(可选) | ≥ 7.2.7 |
| 语音识别 | faster-whisper(可选) | ≥ 1.0.0 |
| 测试 | pytest、pytest-asyncio、pytest-xdist | ≥ 9.0.2 |
| 包管理 | setuptools / uv(推荐) | — |
2. 目录结构说明
hermes-agent/
│
├── hermes # CLI 启动脚本(入口包装器)
├── hermes_constants.py # 全局常量:HERMES_HOME 路径、环境检测工具函数
├── hermes_state.py # SQLite 会话存储(FTS5 全文搜索)
├── hermes_logging.py # 日志配置
├── hermes_time.py # 时间工具函数
├── model_tools.py # 工具编排层:发现工具、分发工具调用
├── toolsets.py # 工具集定义:_HERMES_CORE_TOOLS 列表
├── utils.py # 通用工具函数(原子写文件等)
│
├── run_agent.py # AIAgent 核心类:对话循环主体
├── cli.py # HermesCLI 类:交互式 CLI 编排器
│
├── hermes_cli/ # CLI 子命令与配置
│ ├── main.py # 所有 `hermes` 子命令入口(Profile 覆盖在此处理)
│ ├── config.py # DEFAULT_CONFIG、OPTIONAL_ENV_VARS、配置迁移
│ ├── commands.py # 斜杠命令定义 + SlashCommandCompleter
│ ├── callbacks.py # 终端回调(clarify、sudo、approval)
│ ├── setup.py # 交互式安装向导
│ ├── skin_engine.py # 皮肤/主题引擎
│ ├── models.py # 模型目录、提供商模型列表
│ ├── model_switch.py # /model 切换流水线(CLI + Gateway 共用)
│ ├── auth.py # 提供商凭证解析
│ ├── skills_hub.py # /skills 斜杠命令(搜索、浏览、安装)
│ ├── skills_config.py # `hermes skills` — 按平台启用/禁用技能
│ ├── tools_config.py # `hermes tools` — 按平台启用/禁用工具
│ ├── banner.py # 启动横幅渲染
│ └── doctor.py # 诊断配置和依赖
│
├── agent/ # Agent 内部机制
│ ├── prompt_builder.py # 系统提示词组装(身份、平台提示、技能索引、上下文文件)
│ ├── context_compressor.py # 自动上下文压缩(长对话摘要)
│ ├── context_engine.py # 上下文引擎基类
│ ├── memory_manager.py # 记忆管理器(内置 + 外部插件)
│ ├── memory_provider.py # 记忆提供商抽象基类
│ ├── auxiliary_client.py # 辅助 LLM 客户端(视觉、摘要)
│ ├── prompt_caching.py # Anthropic Prompt Caching 支持
│ ├── model_metadata.py # 模型上下文长度、Token 估算
│ ├── models_dev.py # models.dev 注册表集成
│ ├── display.py # KawaiiSpinner、工具预览格式化
│ ├── skill_commands.py # 技能斜杠命令(CLI/Gateway 共用)
│ ├── skill_utils.py # 技能文件解析工具函数
│ ├── smart_model_routing.py # 智能模型路由
│ ├── usage_pricing.py # Token 用量与费用追踪
│ └── trajectory.py # 轨迹保存辅助函数
│
├── tools/ # 工具实现(每个工具一个文件)
│ ├── registry.py # 中央工具注册表(Schema、Handler、分发)
│ ├── terminal_tool.py # 终端执行(本地/Docker/Modal/SSH/Singularity/Daytona)
│ ├── file_tools.py # 文件读写/搜索/Patch
│ ├── web_tools.py # 网页搜索/抓取(并行 + Firecrawl)
│ ├── browser_tool.py # 浏览器自动化(Browserbase)
│ ├── mcp_tool.py # MCP 客户端(~1050 行)
│ ├── memory_tool.py # 记忆工具
│ ├── todo_tool.py # 待办事项工具(Agent 级别拦截)
│ ├── delegate_tool.py # 子 Agent 委托
│ ├── code_execution_tool.py # 代码执行沙箱
│ ├── vision_tools.py # 图像分析
│ ├── image_generation_tool.py # 图像生成(fal.ai)
│ ├── tts_tool.py # 文字转语音
│ ├── session_search_tool.py # 会话历史搜索
│ ├── skill_manager_tool.py # 技能管理工具
│ ├── approval.py # 危险命令检测
│ ├── process_registry.py # 后台进程管理
│ ├── path_security.py # 路径安全检查
│ └── environments/ # 终端后端实现
│ ├── local.py # 本地执行
│ ├── docker.py # Docker 容器
│ ├── ssh.py # SSH 远程
│ ├── modal.py # Modal Serverless
│ ├── daytona.py # Daytona 云开发环境
│ └── singularity.py # Singularity HPC 容器
│
├── gateway/ # 消息平台网关
│ ├── run.py # 主循环、斜杠命令、消息分发
│ ├── session.py # SessionStore — 对话持久化
│ ├── config.py # 网关配置
│ └── platforms/ # 平台适配器
│ ├── telegram.py # Telegram Bot
│ ├── discord.py # Discord Bot
│ ├── slack.py # Slack App
│ ├── whatsapp.py # WhatsApp
│ ├── signal.py # Signal
│ ├── dingtalk.py # 钉钉
│ ├── feishu.py # 飞书
│ ├── wecom.py # 企业微信
│ ├── matrix.py # Matrix 协议
│ └── homeassistant.py # Home Assistant
│
├── cron/ # 定时任务调度器
│ ├── scheduler.py # 调度器主体
│ └── jobs.py # 任务定义与管理
│
├── acp_adapter/ # ACP 服务器(VS Code / Zed / JetBrains 集成)
├── environments/ # RL 训练环境(Atropos)
├── plugins/ # 插件系统(memory 等)
├── tests/ # Pytest 测试套件(~3000 个测试)
├── batch_runner.py # 并行批处理
├── trajectory_compressor.py # 轨迹压缩(用于 RL 训练数据)
├── pyproject.toml # 项目元数据与依赖声明(权威来源)
└── AGENTS.md # 开发者指南(AI 编码助手专用)
3. 架构设计
整体架构模式
Hermes Agent 采用分层 + 插件注册的架构:
- 分层:入口层(CLI/Gateway)→ 编排层(AIAgent)→ 工具层(Tools)→ 存储层(SQLite/文件系统)
- 插件注册:每个工具文件在模块导入时自动向中央注册表(
tools/registry.py)注册,无需手动维护工具列表 - 同步优先:核心 Agent 循环完全同步(
run_conversation),异步工具通过_run_async()桥接
核心模块划分与职责
┌─────────────────────────────────────────────────────────────┐
│ 入口层 (Entry) │
│ hermes_cli/main.py ←→ cli.py ←→ gateway/run.py │
│ (子命令路由) (交互 TUI) (消息平台网关) │
└────────────────────────┬────────────────────────────────────┘
│
┌────────────────────────▼────────────────────────────────────┐
│ 编排层 (Orchestration) │
│ run_agent.py │
│ AIAgent.run_conversation() │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │prompt_builder│ │context_comp- │ │ memory_manager │ │
│ │(系统提示组装) │ │ressor(压缩) │ │ (记忆管理) │ │
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
└────────────────────────┬────────────────────────────────────┘
│
┌────────────────────────▼────────────────────────────────────┐
│ 工具层 (Tools) │
│ model_tools.py → tools/registry.py → tools/*.py │
│ (工具发现/分发) (中央注册表) (具体工具实现) │
└────────────────────────┬────────────────────────────────────┘
│
┌────────────────────────▼────────────────────────────────────┐
│ 存储层 (Storage) │
│ hermes_state.py(SQLite) ~/.hermes/(文件系统) │
│ 会话/消息/FTS5搜索 config/memory/skills/logs │
└─────────────────────────────────────────────────────────────┘
模块间调用关系与数据流向
工具注册链(导入时):
tools/registry.py(无依赖)
↑ 被导入
tools/*.py(各自调用 registry.register())
↑ 被导入
model_tools.py(触发工具发现)
↑ 被导入
run_agent.py / cli.py / batch_runner.py
对话数据流(运行时):
用户输入
→ cli.py / gateway/run.py(接收消息)
→ AIAgent.run_conversation()(主循环)
→ prompt_builder.py(组装系统提示)
→ memory_manager.prefetch_all()(召回记忆)
→ LLM API 调用(OpenAI/Anthropic 格式)
→ 若有工具调用 → model_tools.handle_function_call()
→ tools/registry.dispatch()
→ 具体工具实现(terminal/file/web 等)
→ 工具结果追加到 messages
→ 循环直到无工具调用
→ memory_manager.sync_all()(持久化记忆)
→ hermes_state.py(保存会话到 SQLite)
→ 返回最终响应给用户
4. 核心流程解析
4.1 应用启动流程
hermes(shell 命令)
→ hermes_cli/main.py: main()
→ _apply_profile_override() # 1. 最先执行:解析 --profile/-p,设置 HERMES_HOME 环境变量
→ argparse 解析子命令
→ 若无子命令 → 启动 CLI 模式
→ cli.py: HermesCLI.__init__()
→ load_cli_config() # 2. 加载 ~/.hermes/config.yaml
→ load_hermes_dotenv() # 3. 加载 ~/.hermes/.env(API Keys)
→ AIAgent.__init__() # 4. 初始化 Agent
→ _discover_tools() # 5. 导入所有 tools/*.py,触发 registry.register()
→ MemoryManager 初始化 # 6. 初始化记忆管理器
→ HermesCLI.run() # 7. 进入交互循环(prompt_toolkit)
关键点:
_apply_profile_override()必须在所有模块导入之前执行,因为许多模块在导入时就会缓存HERMES_HOME路径。
4.2 对话主循环(最核心流程)
# run_agent.py: AIAgent.run_conversation()
while api_call_count < self.max_iterations:
# 1. 调用 LLM API(OpenAI 格式)
response = client.chat.completions.create(
model=model,
messages=messages,
tools=tool_schemas
)
# 2. 若模型请求工具调用
if response.tool_calls:
for tool_call in response.tool_calls:
# 3. 分发到对应工具实现
result = handle_function_call(
tool_call.name,
tool_call.args,
task_id
)
# 4. 将工具结果追加到消息历史
messages.append(tool_result_message(result))
api_call_count += 1
else:
# 5. 无工具调用 → 返回最终响应
return response.content
消息格式遵循 OpenAI 标准:{"role": "system/user/assistant/tool", "content": "..."}
4.3 工具注册与调用流程
注册(模块导入时,一次性):
# tools/terminal_tool.py(示例)
from tools.registry import registry
registry.register(
name="terminal",
toolset="terminal",
schema={...}, # JSON Schema,传给 LLM
handler=lambda args, **kw: ..., # 实际执行函数
check_fn=check_requirements, # 可用性检查(如检查环境变量)
requires_env=["TERMINAL_ENV"],
)
调用(运行时):
# model_tools.py: handle_function_call()
def handle_function_call(function_name, function_args, task_id):
entry = registry.get(function_name)
if entry.is_async:
return _run_async(entry.handler(function_args, task_id=task_id))
return entry.handler(function_args, task_id=task_id)
# 所有 handler 必须返回 JSON 字符串
4.4 上下文压缩流程
当对话历史接近模型上下文窗口限制时自动触发:
检测 Token 用量 > 阈值(默认 context_length × 0.8)
→ ContextCompressor.compress()
→ 1. 剪枝旧工具输出(廉价预处理,无 LLM 调用)
→ 2. 保护头部消息(系统提示 + 首轮对话)
→ 3. 保护尾部消息(最近 ~20K tokens)
→ 4. 用辅助 LLM(便宜/快速)摘要中间轮次
→ 5. 若已有摘要,迭代更新(保留跨多次压缩的信息)
→ 压缩后的 messages 替换原始 messages
注意:压缩是唯一允许修改历史上下文的操作,其他任何修改都会破坏 Prompt Caching。
4.5 记忆系统流程
每轮对话结束后:
MemoryManager.sync_all(user_msg, assistant_response)
→ BuiltinMemoryProvider.sync()
→ 检测 Agent 是否调用了 memory 工具
→ 若有 → 更新 ~/.hermes/MEMORY.md
→ 外部插件 Provider.sync()(如 Honcho)
下一轮对话开始前:
MemoryManager.prefetch_all(user_message)
→ 从 MEMORY.md 读取相关记忆
→ 注入到系统提示(用 <memory-context> 标签包裹)
5. 关键设计与实现
5.1 使用的设计模式
| 模式 | 应用场景 | 代码位置 |
|---|---|---|
| 注册表模式(Registry) | 工具自注册,解耦工具实现与编排层 | tools/registry.py |
| 策略模式(Strategy) | 终端后端可替换(local/docker/ssh/modal) | tools/environments/ |
| 模板方法(Template Method) | 上下文引擎基类定义压缩流程骨架 | agent/context_engine.py |
| 观察者/回调(Callback) | 终端 UI 回调(clarify、sudo 审批) | hermes_cli/callbacks.py |
| 单例(Singleton) | 工具注册表全局唯一实例 | tools/registry.py: registry |
| 适配器(Adapter) | 各消息平台统一接口 | gateway/platforms/base.py |
| 数据驱动(Data-Driven) | 皮肤/主题系统纯数据配置,无需改代码 | hermes_cli/skin_engine.py |
5.2 数据模型 / 数据库设计
Hermes 使用 SQLite + FTS5 存储会话数据,文件位于 ~/.hermes/state.db:
-- 会话表:存储每次对话的元数据
CREATE TABLE sessions (
id TEXT PRIMARY KEY,
source TEXT NOT NULL, -- 来源平台:'cli', 'telegram', 'discord' 等
model TEXT, -- 使用的模型名称
started_at REAL NOT NULL, -- 开始时间(Unix 时间戳)
message_count INTEGER,
input_tokens INTEGER,
output_tokens INTEGER,
estimated_cost_usd REAL, -- 估算费用
title TEXT, -- 会话标题(自动生成)
...
);
-- 消息表:存储每条消息
CREATE TABLE messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_id TEXT REFERENCES sessions(id),
role TEXT NOT NULL, -- 'user', 'assistant', 'tool'
content TEXT,
tool_name TEXT,
timestamp REAL NOT NULL,
...
);
-- FTS5 虚拟表:全文搜索
CREATE VIRTUAL TABLE messages_fts USING fts5(...);
文件系统存储(~/.hermes/):
~/.hermes/
├── config.yaml # 所有配置项
├── .env # API Keys(不提交到 git)
├── state.db # SQLite 会话数据库
├── MEMORY.md # 持久化记忆
├── USER.md # 用户画像
├── SOUL.md # Agent 人格定义
├── skills/ # 用户技能目录
├── logs/ # 日志文件
└── profiles/ # 多 Profile 隔离目录
└── <name>/ # 每个 Profile 有独立的上述所有文件
5.3 状态管理 / 数据流方案
- 对话历史:存储在内存中的
messages列表(OpenAI 格式),每轮结束后持久化到 SQLite - 记忆:通过
MemoryManager管理,支持内置(文件)和外部(Honcho)两种提供商 - 配置:
config.yaml(设置项)+.env(密钥),通过load_cli_config()加载到内存 - 工具状态:无状态设计,每次工具调用独立执行;后台进程通过
process_registry.py追踪
5.4 错误处理与日志策略
- 工具调用错误:所有工具 handler 必须返回 JSON 字符串,错误通过
tool_error()包装返回给 LLM,而非抛出异常 - LLM API 重试:通过
tenacity库实现指数退避重试(agent/retry_utils.py) - 上下文压缩失败:有 600 秒冷却期,避免频繁失败
- 日志:使用 Python 标准
logging模块,日志文件存储在~/.hermes/logs/ - 危险命令检测:
tools/approval.py检测高风险命令,触发用户审批流程
5.5 安全机制
- 命令审批:危险命令(如
rm -rf、sudo等)需用户确认,可配置白名单 - 路径安全:
tools/path_security.py防止路径穿越攻击 - Prompt 注入检测:
agent/prompt_builder.py扫描上下文文件中的注入模式(隐形 Unicode、ignore previous instructions等) - MCP 凭证保护:MCP 工具调用错误信息中自动剥离凭证信息
- DM 配对:消息平台通过配对机制限制访问用户
- 环境变量过滤:MCP stdio 子进程的环境变量经过白名单过滤
6. 环境搭建与运行
环境依赖与前置条件
- Python 3.11+(必须)
- uv(推荐,速度更快)或 pip
- Git
- 至少一个 LLM API Key(OpenAI、Anthropic、OpenRouter 等任选其一)
安装步骤
方式一:一键安装(推荐)
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
source ~/.bashrc # 或 source ~/.zshrc
hermes # 启动!
方式二:开发者安装(贡献代码用)
# 1. 克隆仓库
git clone https://github.com/NousResearch/hermes-agent.git
cd hermes-agent
# 2. 安装 uv(Rust 编写的极速 Python 包管理器)
curl -LsSf https://astral.sh/uv/install.sh | sh
# 3. 创建虚拟环境(必须 Python 3.11+)
uv venv venv --python 3.11
source venv/bin/activate # Linux/macOS
# venv\Scripts\activate # Windows(不支持,请用 WSL2)
# 4. 安装所有依赖(含开发依赖)
uv pip install -e ".[all,dev]"
# 5. 运行测试验证安装
python -m pytest tests/ -q
# 6. 启动
hermes
方式三:最小安装(仅核心功能)
uv pip install -e "." # 仅安装核心依赖
配置步骤
# 运行交互式配置向导(推荐首次使用)
hermes setup
# 或手动配置
hermes model # 选择 LLM 提供商和模型
hermes tools # 配置启用哪些工具
hermes config set model.name "anthropic/claude-opus-4.6"
启动命令
# 交互式 CLI(最常用)
hermes
# 启动消息平台网关(后台服务)
hermes gateway start
# 查看网关状态
hermes gateway status
# 运行诊断
hermes doctor
# 批量处理(研究用)
python batch_runner.py --input tasks.jsonl --output results.jsonl
关键环境变量说明
| 变量名 | 说明 | 示例 |
|---|---|---|
HERMES_HOME | Hermes 数据目录(默认 ~/.hermes) | /opt/hermes-data |
OPENAI_API_KEY | OpenAI API Key | sk-... |
ANTHROPIC_API_KEY | Anthropic API Key | sk-ant-... |
OPENROUTER_API_KEY | OpenRouter API Key(200+ 模型) | sk-or-... |
TERMINAL_ENV | 终端后端(local/docker/modal/ssh) | local |
TELEGRAM_BOT_TOKEN | Telegram Bot Token(网关用) | 123456:ABC... |
DISCORD_BOT_TOKEN | Discord Bot Token(网关用) | MTI... |
EXA_API_KEY | Exa 搜索 API Key | exa-... |
FIRECRAWL_API_KEY | Firecrawl 网页抓取 API Key | fc-... |
FAL_KEY | fal.ai 图像生成 API Key | ... |
所有 API Key 存储在
~/.hermes/.env,不要提交到 git。
7. 推荐学习路线
阶段一:入门(1-2 天)
目标:理解项目是什么、能做什么,跑通基本流程
-
先读文档
README.md— 了解项目定位和核心功能AGENTS.md— 开发者指南,理解整体架构
-
理解配置系统
hermes_constants.py— 理解get_hermes_home()的设计(Profile 隔离的基础)hermes_cli/config.py— 了解DEFAULT_CONFIG有哪些配置项
-
跑通启动流程
hermes_cli/main.py前 100 行 — 理解_apply_profile_override()为何必须最先执行- 实际运行
hermes setup和hermes,感受 CLI 交互
理解的核心概念:
HERMES_HOME是所有数据的根目录- Profile 是多实例隔离的机制
config.yaml+.env是两套配置(设置 vs 密钥)
阶段二:进阶(3-5 天)
目标:深入理解 Agent 核心循环和工具系统
-
工具注册机制(最重要)
tools/registry.py— 完整阅读,理解ToolRegistry和ToolEntrytools/terminal_tool.py前 80 行 — 看一个具体工具如何注册model_tools.py— 理解工具发现(_discover_tools())和分发(handle_function_call())
-
Agent 主循环
run_agent.py— 重点阅读AIAgent.__init__()和run_conversation()- 理解
messages列表的结构和工具调用的消息格式
-
系统提示组装
agent/prompt_builder.py— 理解系统提示由哪些部分组成agent/prompt_caching.py— 理解为何不能随意修改历史上下文
-
上下文压缩
agent/context_compressor.py— 理解长对话如何被摘要压缩
-
工具集系统
toolsets.py— 理解_HERMES_CORE_TOOLS和工具集组合
动手实践:
# 查看当前工具列表
hermes tools
# 在 Python 中直接使用 AIAgent
python -c "
from run_agent import AIAgent
agent = AIAgent(model='openai/gpt-4o-mini')
print(agent.chat('Hello! What tools do you have?'))
"
阶段三:实践(1 周+)
目标:能够扩展项目功能,理解所有核心机制
-
添加一个新工具(最佳实践练习)
- 参考
AGENTS.md的”Adding New Tools”章节 - 在
tools/下创建新文件,调用registry.register() - 在
model_tools.py的_discover_tools()中添加 import - 在
toolsets.py的_HERMES_CORE_TOOLS中添加工具名
- 参考
-
添加一个斜杠命令
- 参考
AGENTS.md的”Adding a Slash Command”章节 - 在
hermes_cli/commands.py的COMMAND_REGISTRY中添加CommandDef - 在
cli.py的process_command()中添加处理逻辑
- 参考
-
理解消息网关
gateway/run.py— 网关主循环gateway/platforms/telegram.py— 一个平台适配器的完整实现gateway/platforms/ADDING_A_PLATFORM.md— 如何添加新平台
-
记忆系统深入
agent/memory_manager.py— 记忆管理器设计agent/memory_provider.py— 提供商抽象基类tools/memory_tool.py— 记忆工具实现
-
运行测试套件
source venv/bin/activate python -m pytest tests/ -q # 全量测试 python -m pytest tests/test_model_tools.py -q # 工具集解析 python -m pytest tests/tools/ -q # 工具级测试 python -m pytest tests/gateway/ -q # 网关测试
8. 常见问题与注意事项
容易踩的坑
1. 忘记激活虚拟环境
# 每次开发前必须执行
source venv/bin/activate
2. 硬编码 ~/.hermes 路径
# ❌ 错误:破坏 Profile 隔离
config_path = Path.home() / ".hermes" / "config.yaml"
# ✅ 正确:使用 get_hermes_home()
from hermes_constants import get_hermes_home
config_path = get_hermes_home() / "config.yaml"
3. 工具 handler 抛出异常而非返回错误 JSON
# ❌ 错误:会导致整个 Agent 循环崩溃
def my_tool(args):
raise ValueError("something went wrong")
# ✅ 正确:返回 JSON 字符串,让 LLM 处理错误
def my_tool(args):
return json.dumps({"error": "something went wrong"})
4. 在对话中途修改工具集或系统提示
- 这会破坏 Anthropic Prompt Caching,导致费用大幅增加
- 唯一允许的例外是上下文压缩
5. 使用 simple_term_menu 做交互菜单
- 在 tmux/iTerm2 中有渲染 bug(滚动时残影)
- 应使用
curses(标准库),参考hermes_cli/tools_config.py
6. 在 Spinner/Display 代码中使用 \033[K(ANSI 清除到行尾)
- 在
prompt_toolkit的patch_stdout下会泄漏为字面量?[K - 应使用空格填充:
f"\r{line}{' ' * pad}"
代码中的特殊约定
- 所有工具 handler 必须返回 JSON 字符串,不能是 Python 对象
todo和memory工具是 Agent 级别工具,在run_agent.py中被拦截,不经过handle_function_call()_last_resolved_tool_names是进程全局变量,子 Agent 执行期间会临时修改,注意并发安全- 工具 Schema 描述中不能跨工具集引用工具名(如
browser_navigate不能提到web_search),因为对方工具集可能未启用 - 测试不能写入
~/.hermes/,tests/conftest.py的_isolate_hermes_homefixture 会重定向到临时目录
值得注意的技术债务
model_tools.py注释提到原始版本有 2400 行,已重构为薄编排层,但历史包袱仍存在- MCP 客户端(
tools/mcp_tool.py)约 1050 行,是代码库中最复杂的单文件 hermes_cli/目录文件数量较多(30+ 文件),功能边界有时不够清晰- 异步桥接(
_run_async())的多线程事件循环管理较复杂,是潜在的并发问题来源 [待确认]部分 RL 训练相关代码(environments/、rl_cli.py)与主流程耦合度较低,文档较少
附录:快速参考
常用命令速查
hermes # 启动交互式 CLI
hermes setup # 配置向导
hermes model # 切换模型
hermes tools # 管理工具
hermes gateway start # 启动消息网关
hermes doctor # 诊断问题
hermes update # 更新版本
hermes -p <name> # 使用指定 Profile
斜杠命令速查(CLI 内使用)
/new, /reset # 开始新对话
/model # 切换模型
/compress # 手动压缩上下文
/usage # 查看 Token 用量
/skills # 浏览技能
/retry # 重试上一轮
/undo # 撤销上一轮
/help # 查看所有命令
关键文件速查
| 想了解什么 | 看哪个文件 |
|---|---|
| 如何添加新工具 | AGENTS.md + tools/terminal_tool.py(参考) |
| 如何添加斜杠命令 | hermes_cli/commands.py |
| 配置项有哪些 | hermes_cli/config.py: DEFAULT_CONFIG |
| Agent 主循环 | run_agent.py |
| 工具注册机制 | tools/registry.py |
| 系统提示如何组装 | agent/prompt_builder.py |
| 会话数据库结构 | hermes_state.py: SCHEMA_SQL |
| 如何添加消息平台 | gateway/platforms/ADDING_A_PLATFORM.md |