sidebar position: 7 title: "网关内部机制" description: "消息网关如何启动、授权用户、路由会话和投递消息" 消息网关是一个长运行进程,通过统一架构将 Hermes 连接到 14+ 个外部消息平台。 当消息从任何平台到达时: 1. 平台适配器 接收原始事件,将其规范化为 Mess

> 📖 本文档翻译自 Gateway Internals > 最后更新:2026-04-16


sidebar_position: 7 title: "网关内部机制" description: "消息网关如何启动、授权用户、路由会话和投递消息"

网关内部机制

消息网关是一个长运行进程,通过统一架构将 Hermes 连接到 14+ 个外部消息平台。

关键文件

文件用途
gateway/run.pyGatewayRunner——主循环、斜杠命令、消息分发(约 9,000 行)
gateway/session.pySessionStore——对话持久化和会话键构造
gateway/delivery.py向目标平台/频道发送出站消息
gateway/pairing.py用于用户授权的 DM 配对流程
gateway/channel_directory.py将聊天 ID 映射为人类可读名称,用于定时任务投递
gateway/hooks.py钩子发现、加载和生命周期事件分发
gateway/mirror.py用于 send_message 的跨会话消息镜像
gateway/status.py配置文件范围网关实例的 Token 锁管理
gateway/builtin_hooks/始终注册的钩子(例如 BOOT.md 系统提示词钩子)
gateway/platforms/平台适配器(每个消息平台一个)

架构概览

┌─────────────────────────────────────────────────┐
│                 GatewayRunner                     │
│                                                   │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐       │
│  │ Telegram  │  │ Discord  │  │  Slack   │  ...  │
│  │ Adapter   │  │ Adapter  │  │ Adapter  │       │
│  └─────┬─────┘  └─────┬────┘  └─────┬────┘       │
│        │              │              │             │
│        └──────────────┼──────────────┘             │
│                       ▼                            │
│              _handle_message()                     │
│                       │                            │
│          ┌────────────┼────────────┐               │
│          ▼            ▼            ▼               │
│   斜杠命令分发    AIAgent      队列/后台            │
│                   创建         会话                │
│                       │                            │
│                       ▼                            │
│              SessionStore                          │
│           (SQLite 持久化)                          │
└─────────────────────────────────────────────────┘

消息流

当消息从任何平台到达时:

  1. 平台适配器接收原始事件,将其规范化为 MessageEvent
  2. 基础适配器检查活动会话守卫:
    • 如果该会话有 Agent 正在运行 → 将消息排队,设置中断事件
    • 如果是 /approve/deny/stop → 绕过守卫(内联分发)
  3. GatewayRunner._handle_message() 接收事件:
    • 通过 _session_key_for_source() 解析会话键(格式:agent:main:{platform}:{chat_type}:{chat_id}
    • 检查授权(见下方授权部分)
    • 检查是否为斜杠命令 → 分发到命令处理器
    • 检查 Agent 是否已在运行 → 拦截 /stop/status 等命令
    • 否则 → 创建 AIAgent 实例并运行对话
  4. 响应通过平台适配器发送回去

会话键格式

会话键编码完整的路由上下文:

agent:main:{platform}:{chat_type}:{chat_id}

例如:agent:main:telegram:private:123456789

支持线程的平台(Telegram 论坛话题、Discord 线程、Slack 线程)可能在 chat_id 部分包含线程 ID。切勿手动构造会话键——始终使用 gateway/session.py 中的 build_session_key()

两级消息守卫

当 Agent 正在主动运行时,入站消息通过两个顺序守卫:

  1. 第 1 级——基础适配器gateway/platforms/base.py):检查 _active_sessions。如果会话处于活动状态,将消息排队到 _pending_messages 并设置中断事件。这在消息到达网关运行器之前捕获消息。

  2. 第 2 级——网关运行器gateway/run.py):检查 _running_agents。拦截特定命令(/stop/new/queue/status/approve/deny)并适当路由。其他所有消息触发 running_agent.interrupt()

必须在 Agent 阻塞时到达运行器的命令(如 /approve)通过 await self._message_handler(event) 内联分发——它们绕过后台任务系统以避免竞态条件。

授权

网关使用多层授权检查,按顺序评估:

  1. 按平台允许全部标志(例如 TELEGRAM_ALLOW_ALL_USERS)——如果设置,该平台上所有用户被授权
  2. 平台白名单(例如 TELEGRAM_ALLOWED_USERS)——逗号分隔的用户 ID
  3. DM 配对——已认证用户可以通过配对码配对新用户
  4. 全局允许全部GATEWAY_ALLOW_ALL_USERS)——如果设置,所有平台的所有用户被授权
  5. 默认:拒绝——未授权用户被拒绝

DM 配对流程

管理员: /pair
网关: "Pairing code: ABC123. Share with the user."
新用户: ABC123
网关: "Paired! You're now authorized."

配对状态持久化在 gateway/pairing.py 中,在重启后仍然保留。

斜杠命令分发

网关中所有斜杠命令通过相同的解析管道:

  1. hermes_cli/commands.py 中的 resolve_command() 将输入映射到规范名称(处理别名、前缀匹配)
  2. 规范名称与 GATEWAY_KNOWN_COMMANDS 对照检查
  3. _handle_message() 中的处理器根据规范名称分发
  4. 某些命令有配置门控(CommandDef 上的 gateway_config_gate

运行中 Agent 守卫

在 Agent 处理时不得执行的命令会被提前拒绝:

if _quick_key in self._running_agents:
    if canonical == "model":
        return "⏳ Agent is running — wait for it to finish or /stop first."

绕过命令(/stop/new/approve/deny/queue/status)有特殊处理。

配置来源

网关从多个来源读取配置:

来源提供的内容
~/.hermes/.envAPI 密钥、机器人令牌、平台凭据
~/.hermes/config.yaml模型设置、工具配置、显示选项
环境变量覆盖以上任何配置

与 CLI(使用带硬编码默认值的 load_cli_config())不同,网关通过 YAML 加载器直接读取 config.yaml。这意味着 CLI 默认值字典中存在但用户配置文件中不存在的配置键,在 CLI 和网关之间可能表现不同。

平台适配器

每个消息平台在 gateway/platforms/ 中有一个适配器:

gateway/platforms/
├── base.py              # BaseAdapter — 所有平台的共享逻辑
├── telegram.py          # Telegram Bot API(长轮询或 Webhook)
├── discord.py           # Discord bot via discord.py
├── slack.py             # Slack Socket Mode
├── whatsapp.py          # WhatsApp Business Cloud API
├── signal.py            # Signal via signal-cli REST API
├── matrix.py            # Matrix via mautrix(可选 E2EE)
├── mattermost.py        # Mattermost WebSocket API
├── email.py             # Email via IMAP/SMTP
├── sms.py               # SMS via Twilio
├── dingtalk.py          # DingTalk WebSocket
├── feishu.py            # Feishu/Lark WebSocket 或 Webhook
├── wecom.py             # WeCom (企业微信) 回调
├── weixin.py            # Weixin (个人微信) via iLink Bot API
├── bluebubbles.py       # Apple iMessage via BlueBubbles macOS server
├── qqbot.py             # QQ Bot (腾讯 QQ) via Official API v2
├── webhook.py           # 入站/出站 Webhook 适配器
├── api_server.py        # REST API 服务器适配器
└── homeassistant.py     # Home Assistant 对话集成

适配器实现通用接口:

  • connect() / disconnect()——生命周期管理
  • send_message()——出站消息发送
  • on_message()——入站消息规范化 → MessageEvent

Token 锁

使用唯一凭据连接的适配器在 connect() 中调用 acquire_scoped_lock(),在 disconnect() 中调用 release_scoped_lock()。这防止两个配置文件同时使用相同的机器人令牌。

投递路径

出站投递(gateway/delivery.py)处理:

  • 直接回复——将响应发送回原始聊天
  • 主频道投递——将定时任务输出和后台结果路由到配置的主频道
  • 显式目标投递——send_message 工具指定 telegram:-1001234567890
  • 跨平台投递——投递到与原始消息不同的平台

定时任务投递不会镜像到网关会话历史——它们只存在于自己的定时任务会话中。这是一个有意的设计选择,以避免消息交替违规。

钩子

网关钩子是响应生命周期事件的 Python 模块:

网关钩子事件

事件触发时机
gateway:startup网关进程启动
session:start新对话会话开始
session:end会话完成或超时
session:reset用户使用 /new 重置会话
agent:startAgent 开始处理消息
agent:stepAgent 完成一次工具调用迭代
agent:endAgent 完成并返回响应
command:*执行任何斜杠命令

钩子从 gateway/builtin_hooks/(始终激活)和 ~/.hermes/hooks/(用户安装)发现。每个钩子是一个包含 HOOK.yaml 清单和 handler.py 的目录。

内存 Provider 集成

当启用内存 Provider 插件(例如 Honcho)时:

  1. 网关为每条消息创建一个带会话 ID 的 AIAgent
  2. MemoryManager 用会话上下文初始化 Provider
  3. Provider 工具(例如 honcho_profileviking_search)通过以下路径路由:
AIAgent._invoke_tool()
  → self._memory_manager.handle_tool_call(name, args)
    → provider.handle_tool_call(name, args)
  1. 在会话结束/重置时,on_session_end() 触发以进行清理和最终数据刷新

内存刷新生命周期

当会话被重置、恢复或过期时:

  1. 内置内存刷新到磁盘
  2. 内存 Provider 的 on_session_end() 钩子触发
  3. 临时的 AIAgent 运行一个仅内存的对话轮次
  4. 然后上下文被丢弃或归档

后台维护

网关在处理消息的同时运行定期维护:

  • 定时任务滴答——检查作业计划并触发到期的作业
  • 会话过期——在超时后清理被遗弃的会话
  • 内存刷新——在会话过期前主动刷新内存
  • 缓存刷新——刷新模型列表和 Provider 状态

进程管理

网关作为长生命周期进程运行,通过以下方式管理:

  • hermes gateway start / hermes gateway stop——手动控制
  • systemctl(Linux)或 launchctl(macOS)——服务管理
  • PID 文件位于 ~/.hermes/gateway.pid——配置文件范围的进程跟踪

配置文件范围 vs 全局start_gateway() 使用配置文件范围的 PID 文件。hermes gateway stop 只停止当前配置文件的网关。hermes gateway stop --all 使用全局 ps aux 扫描来杀死所有网关进程(用于更新期间)。

相关文档

Continue Exploring

继续探索

这不是课程式的上一篇下一篇,而是从当前节点向外继续漫游。

开发者指南

会话存储

Hermes Agent 使用 SQLite 数据库( /.hermes/state.db)来持久化会话元数据、完整消息历史和模型配置,覆盖 CLI 和网关会话。这取代了早期基于每个会话 JSONL 文件的方式。 源文件:hermes state.py 关键设计决策: - WAL 模式 用于并发读取 + 单个写入器(网

开发者指南

Cron 内部机制

原文链接:Cron Internals sidebar position: 11 title: "Cron Internals" description: "How Hermes stores, schedules, edits, pauses, skill-loads, and delivers cron jobs"

开发者指南

ACP 内部机制

原文链接:ACP Internals sidebar position: 2 title: "ACP Internals" description: "How the ACP adapter works: lifecycle, sessions, event bridge, approvals, and tool re

开发者指南

Agent 循环内部机制

sidebar position: 3 title: "Agent 循环内部机制" description: "AIAgent 执行、API 模式、工具、回调和回退行为的详细解析" 核心编排引擎是 run agent.py 中的 AIAgent 类——大约 10,700 行代码,负责从 Prompt(提示词)组装到工具

开发者指南

架构

本页面是 Hermes Agent 内部结构的顶层地图. 使用它来了解代码库的整体结构,然后深入子系统文档获取实现细节。 如果你是首次接触此代码库: 1. 本页面 — 了解整体结构 2. Agent 循环内部机制 — AIAgent 如何工作 3. 提示词组装 — 系统提示词构建

开发者指南

贡献指南

感谢你对 Hermes Agent 的贡献!本指南涵盖开发环境设置、理解代码库以及如何让你的 PR 被合并。 我们按以下顺序重视贡献: 1. Bug 修复 — 崩溃、不正确行为、数据丢失 2. 跨平台兼容性 — macOS、不同 Linux 发行版、WSL2 3. 安全加固 — Shell 注入、Prompt 注入、路

Developer Guide

开发者指南

面向二次开发者,解释架构、运行时、上下文引擎、插件、工具与扩展机制。

20 篇文档20 个节点

当前节点

网关内部机制

同主题继续探索

架构

本页面是 Hermes Agent 内部结构的顶层地图. 使用它来了解代码库的整体结构,然后深入子系统文档获取实现细节。 如果你是首次接触此代码库: 1. 本页面 — 了解整体结构 2. Agent 循环内部机制 — AIAgent 如何工作 3. 提示词组装 — 系统提示词构建

贡献指南

感谢你对 Hermes Agent 的贡献!本指南涵盖开发环境设置、理解代码库以及如何让你的 PR 被合并。 我们按以下顺序重视贡献: 1. Bug 修复 — 崩溃、不正确行为、数据丢失 2. 跨平台兼容性 — macOS、不同 Linux 发行版、WSL2 3. 安全加固 — Shell 注入、Prompt 注入、路

Agent 循环内部机制

sidebar position: 3 title: "Agent 循环内部机制" description: "AIAgent 执行、API 模式、工具、回调和回退行为的详细解析" 核心编排引擎是 run agent.py 中的 AIAgent 类——大约 10,700 行代码,负责从 Prompt(提示词)组装到工具

提示词组装

sidebar position: 5 title: "提示词组装" description: "Hermes 如何构建系统提示词、保持缓存稳定性和注入临时层" Hermes 刻意将以下两者分离: - 缓存的系统提示词状态 - 临时的 API 调用时添加内容 这是项目中最关键的设计决策之一,因为它影响:

上下文压缩与缓存

Hermes Agent 使用双重压缩系统和 Anthropic 提示词缓存,在长对话中高效管理上下文窗口的使用。 源文件:agent/context engine.py(ABC)、agent/context compressor.py(默认引擎)、agent/prompt caching.py、gateway/run

会话存储

Hermes Agent 使用 SQLite 数据库( /.hermes/state.db)来持久化会话元数据、完整消息历史和模型配置,覆盖 CLI 和网关会话。这取代了早期基于每个会话 JSONL 文件的方式。 源文件:hermes state.py 关键设计决策: - WAL 模式 用于并发读取 + 单个写入器(网

相关节点

会话存储

Hermes Agent 使用 SQLite 数据库( /.hermes/state.db)来持久化会话元数据、完整消息历史和模型配置,覆盖 CLI 和网关会话。这取代了早期基于每个会话 JSONL 文件的方式。 源文件:hermes state.py 关键设计决策: - WAL 模式 用于并发读取 + 单个写入器(网

Cron 内部机制

原文链接:Cron Internals sidebar position: 11 title: "Cron Internals" description: "How Hermes stores, schedules, edits, pauses, skill-loads, and delivers cron jobs"

ACP 内部机制

原文链接:ACP Internals sidebar position: 2 title: "ACP Internals" description: "How the ACP adapter works: lifecycle, sessions, event bridge, approvals, and tool re

Agent 循环内部机制

sidebar position: 3 title: "Agent 循环内部机制" description: "AIAgent 执行、API 模式、工具、回调和回退行为的详细解析" 核心编排引擎是 run agent.py 中的 AIAgent 类——大约 10,700 行代码,负责从 Prompt(提示词)组装到工具

架构

本页面是 Hermes Agent 内部结构的顶层地图. 使用它来了解代码库的整体结构,然后深入子系统文档获取实现细节。 如果你是首次接触此代码库: 1. 本页面 — 了解整体结构 2. Agent 循环内部机制 — AIAgent 如何工作 3. 提示词组装 — 系统提示词构建

贡献指南

感谢你对 Hermes Agent 的贡献!本指南涵盖开发环境设置、理解代码库以及如何让你的 PR 被合并。 我们按以下顺序重视贡献: 1. Bug 修复 — 崩溃、不正确行为、数据丢失 2. 跨平台兼容性 — macOS、不同 Linux 发行版、WSL2 3. 安全加固 — Shell 注入、Prompt 注入、路