Hermes 101|08|Extensions

Extensions 让 Agent 不必把所有能力写进核心。插件、MCP、平台和 provider 共同构成可扩展边界。

Hermes 101|08|Extensions

一个 Agent 框架如果把所有能力都写进核心,很快会变得臃肿。今天加 GitHub,明天加 Slack,后天加内部数据库,再后来要支持新的模型 provider、新的 memory backend、新的上下文管理策略。核心代码越大,升级越慢,风险也越高。

Hermes 的做法是把核心运行时和外部能力分开:Agent Loop、Session、Tool Runtime、Context Builder 保持相对稳定;外部能力通过 Extensions 接入。

这里的 Extensions 不是单一机制,而是一组扩展边界:plugins、MCP servers、provider plugins、gateway platforms、hooks、skills 等。

Extensions 把外部能力接入核心运行时

读完本文,你应该能回答

  • 为什么 Agent 不应该把所有能力写进核心?
  • 插件、MCP、provider、平台入口分别扩展什么?
  • 显式启用扩展解决了哪些安全和可维护性问题?
  • mini-agent-harness 应该怎样设计扩展点而不失控?

本篇在系列中的位置

上一篇讲可复用流程,本篇讲能力边界如何外接。它把核心 Runtime 和外部生态连接起来,也为后面的 Observability、Gateway、Provider Runtime 做铺垫。

贯穿案例

贯穿这个系列,可以一直带着同一个任务来读:用户说“帮我修复这个 repo 里的 failing tests”。不同章节会回答同一个任务在运行时的不同问题:入口怎样进入、上下文怎样准备、模型怎样决定下一步、工具怎样执行、状态怎样保存、失败后怎样恢复。

定义

Extension 是在不修改 Agent 核心循环的前提下,为系统增加工具、平台、模型、记忆、上下文引擎或生命周期行为的机制。

它解决的是 Agent 系统的长期演化问题。一个好的扩展系统不只是“能加功能”,还要回答:功能怎样发现、怎样授权、怎样隔离、怎样禁用、怎样调试,以及它在模型上下文中如何呈现。

Hermes 的插件系统

Hermes 的插件可以放在用户目录、项目目录、内置目录,也可以通过 pip entry point 分发。一个最小插件通常包含 manifest、注册函数、schema 和 handler。

插件在 register(ctx) 中声明能力:

可迁移伪实现:Extension Plugin

下面的伪代码是机制抽象,不对应 Hermes 的真实 API 或文件结构。

type PluginContext = {
  registerTool(entry: ToolEntry): void
  registerHook(event: string, callback: Hook): void
  registerCommand(name: string, handler: CommandHandler): void
  registerPlatform(entry: PlatformEntry): void
  registerSkill(name: string, path: string): void
  registerContextEngine(engine: ContextEngine): void
}

这套接口背后的思想是:扩展不应该绕过核心运行时。插件注册工具后,工具仍然进入 Tool Runtime 的过滤、schema 生成、调用和结果回填流程;注册 hook 后,hook 也在明确生命周期点执行,而不是随意劫持对话。

扩展点选择表

不是所有扩展都应该做成插件,也不是所有外部能力都应该接成 MCP。一个实用判断方式是先看它扩展的是哪一层。

需求 更适合的扩展点 原因
增加一个本地可执行能力 Tool / Plugin tool 需要进入工具 schema,由 Agent 显式调用
接入外部标准工具服务器 MCP 让外部工具按统一协议暴露
新增模型供应商 Provider plugin / config 影响模型调用路径,不应写进 Tool Runtime
改变消息平台入口 Gateway adapter 入口事件、session key、delivery 都在平台层
在执行前后记录审计信息 Hook 不改变核心逻辑,只观察或拦截生命周期
给某类任务增加流程知识 Skill 这是经验,不是新能力

这个区分能避免一个常见失控:把所有东西都塞进核心 Agent Loop。Hermes 的思路是让核心循环尽量稳定,把变化放到边界上。

扩展点不是一种

Hermes 把扩展分成多类,是因为不同能力的生命周期不同。

一般插件可以添加工具、hooks、slash commands 和 CLI commands。这类插件通常是多选的,用户可以同时启用多个。

平台插件负责 gateway 通道,例如 Discord、Telegram 之外的其他消息平台。它们要处理消息接收、鉴权、投递和会话映射。

Provider 插件解决模型、图像、视频、memory、context engine 这类“底层后端”替换问题。比如 model provider 可以新增一个 OpenAI-compatible 供应商;memory provider 可以替换长期记忆后端;context engine 可以替换内置压缩器。

MCP 则是另一种连接层。它让 Hermes 可以把外部 MCP server 暴露的工具、资源和 prompts 接入工具系统,不必为每个服务都写一个内置工具。

不同扩展点解决不同层的问题

为什么需要显式启用

扩展系统的风险在于:它运行的是代码,不只是文本。

Hermes 因此对许多第三方插件采用 opt-in 模式。用户插件可以被发现,但不会默认执行;需要加入 plugins.enabled,或通过 hermes plugins enable 显式开启。项目本地插件默认也不开启,除非用户设置允许项目插件。

这种设计把便利性和安全边界分开:系统可以展示“有哪些扩展可用”,但不会在用户没有意识到的情况下执行任意插件代码。

plugins:
  enabled:
    - my-tool-plugin
  disabled:
    - noisy-plugin

当然,也有一些基础后端需要自动发现。例如内置平台、模型 provider、memory provider、context engine backend 等,如果完全走同一层 opt-in,基础功能会很难启动。Hermes 的做法是按插件种类区分加载策略,而不是用一个开关管理所有扩展。

Hooks:扩展运行时行为

Hooks 是 Extensions 中很重要的一类。它们不是给模型调用的工具,而是在生命周期点运行的代码。

例如:

  • pre_tool_call 可以在工具执行前做审计或阻止;
  • post_tool_call 可以记录结果或上报指标;
  • pre_llm_call 可以注入额外上下文;
  • on_session_start / on_session_end 可以做会话级初始化和清理;
  • gateway hook 可以在消息平台上记录、告警或触发外部 webhook。

这让扩展系统不仅能增加“动作”,也能增加“治理”。企业内部使用 Agent 时,经常需要审计、成本归因、数据边界和告警;hook 是把这些横切关注点接进运行时的方式。

MCP 和插件的关系

MCP server 与 Hermes plugin 的边界不同。

MCP 更像外部服务协议。它适合把已经存在的工具服务接进来,例如 GitHub、数据库、内部 API、浏览器自动化服务。Hermes 负责连接 server、读取工具列表、把 schema 暴露给模型,再把调用转发出去。

Plugin 更像本地扩展机制。它适合深度接入 Hermes:注册 hooks、添加 gateway 平台、打包 skills、接入新的 context engine 或 provider。

在生产系统里,两者经常并存:MCP 负责跨应用互操作,plugin 负责本地运行时集成。

小结

Extensions 的核心价值,是让 Agent 框架保持小而稳定,同时允许能力边界持续增长。Hermes 的扩展系统不是一个“大插件口”,而是一组按生命周期和风险分层的入口:工具、平台、provider、hooks、MCP、skills 各有位置。这样的设计让 Agent 能适应真实环境,而不是把每个新需求都硬塞进核心。